1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <xmlbahdl.hxx>
22 #include <XMLNumberWithAutoForVoidPropHdl.hxx>
23 #include <sal/log.hxx>
24 #include <o3tl/any.hxx>
25 #include <o3tl/safeint.hxx>
26 #include <o3tl/string_view.hxx>
27 #include <sax/tools/converter.hxx>
28 #include <xmloff/xmluconv.hxx>
29 #include <com/sun/star/uno/Any.hxx>
30 #include <com/sun/star/beans/Pair.hpp>
31 #include <xmloff/xmltoken.hxx>
35 using namespace ::com::sun::star::uno
;
36 using namespace ::xmloff::token
;
38 static void lcl_xmloff_setAny( Any
& rValue
, sal_Int32 nValue
, sal_Int8 nBytes
)
43 if( nValue
< SCHAR_MIN
)
45 else if( nValue
> SCHAR_MAX
)
47 rValue
<<= static_cast<sal_Int8
>(nValue
);
50 if( nValue
< SHRT_MIN
)
52 else if( nValue
> SHRT_MAX
)
54 rValue
<<= static_cast<sal_Int16
>(nValue
);
62 static bool lcl_xmloff_getAny( const Any
& rValue
, sal_Int32
& nValue
,
72 bRet
= rValue
>>= nValue8
;
78 sal_Int16 nValue16
= 0;
79 bRet
= rValue
>>= nValue16
;
84 bRet
= rValue
>>= nValue
;
92 XMLNumberPropHdl::~XMLNumberPropHdl()
97 bool XMLNumberPropHdl::importXML( const OUString
& rStrImpValue
, Any
& rValue
, const SvXMLUnitConverter
& ) const
100 bool bRet
= ::sax::Converter::convertNumber( nValue
, rStrImpValue
);
101 lcl_xmloff_setAny( rValue
, nValue
, nBytes
);
106 bool XMLNumberPropHdl::exportXML( OUString
& rStrExpValue
, const Any
& rValue
, const SvXMLUnitConverter
& ) const
111 if( lcl_xmloff_getAny( rValue
, nValue
, nBytes
) )
113 rStrExpValue
= OUString::number( nValue
);
122 XMLNumberNonePropHdl::XMLNumberNonePropHdl( sal_Int8 nB
) :
123 sZeroStr( GetXMLToken(XML_NO_LIMIT
) ),
128 XMLNumberNonePropHdl::XMLNumberNonePropHdl( enum XMLTokenEnum eZeroString
, sal_Int8 nB
) :
129 sZeroStr( GetXMLToken( eZeroString
) ),
134 XMLNumberNonePropHdl::~XMLNumberNonePropHdl()
139 bool XMLNumberNonePropHdl::importXML( const OUString
& rStrImpValue
, Any
& rValue
, const SvXMLUnitConverter
& ) const
143 sal_Int32 nValue
= 0;
144 if( rStrImpValue
== sZeroStr
)
150 bRet
= ::sax::Converter::convertNumber( nValue
, rStrImpValue
);
152 lcl_xmloff_setAny( rValue
, nValue
, nBytes
);
157 bool XMLNumberNonePropHdl::exportXML( OUString
& rStrExpValue
, const Any
& rValue
, const SvXMLUnitConverter
& ) const
162 if( lcl_xmloff_getAny( rValue
, nValue
, nBytes
) )
166 rStrExpValue
= sZeroStr
;
170 rStrExpValue
= OUString::number( nValue
);
180 XMLMeasurePropHdl::~XMLMeasurePropHdl()
185 bool XMLMeasurePropHdl::importXML( const OUString
& rStrImpValue
, Any
& rValue
, const SvXMLUnitConverter
& rUnitConverter
) const
187 sal_Int32 nValue
= 0;
188 bool bRet
= rUnitConverter
.convertMeasureToCore( nValue
, rStrImpValue
);
189 lcl_xmloff_setAny( rValue
, nValue
, nBytes
);
193 bool XMLMeasurePropHdl::exportXML( OUString
& rStrExpValue
, const Any
& rValue
, const SvXMLUnitConverter
& rUnitConverter
) const
198 if( lcl_xmloff_getAny( rValue
, nValue
, nBytes
) )
201 rUnitConverter
.convertMeasureToXML( aOut
, nValue
);
202 rStrExpValue
= aOut
.makeStringAndClear();
211 bool XMLUnitMeasurePropHdl::importXML( const OUString
& rStrImpValue
, Any
& rValue
, const SvXMLUnitConverter
& ) const
214 std::optional
<sal_Int16
> nValueUnit
;
216 auto bRet
= ::sax::Converter::convertMeasureUnit( fValue
, nValueUnit
, rStrImpValue
);
220 // This importer may only accept font-relative units.
221 // Discard all other units to allow fall-through to other attributes.
222 if (css::util::MeasureUnit::FONT_EM
!= nValueUnit
223 && css::util::MeasureUnit::FONT_CJK_ADVANCE
!= nValueUnit
)
228 css::beans::Pair
<double, sal_Int16
> stValue
{fValue
, nValueUnit
.value()};
235 bool XMLUnitMeasurePropHdl::exportXML( OUString
& rStrExpValue
, const Any
& rValue
, const SvXMLUnitConverter
& ) const
238 css::beans::Pair
<double, sal_Int16
> stValue
{0.0, css::util::MeasureUnit::MM_100TH
};
240 if( rValue
>>= stValue
)
242 auto [fValue
, nValueUnit
] = stValue
;
244 // This exporter may only produce font-relative units.
245 // Discard all other units to allow fall-through to other attributes.
246 if (css::util::MeasureUnit::FONT_EM
!= nValueUnit
247 && css::util::MeasureUnit::FONT_CJK_ADVANCE
!= nValueUnit
)
253 ::sax::Converter::convertMeasureUnit( aOut
, fValue
, nValueUnit
);
254 rStrExpValue
= aOut
.makeStringAndClear();
263 XMLBoolFalsePropHdl::~XMLBoolFalsePropHdl()
268 bool XMLBoolFalsePropHdl::importXML( const OUString
&, Any
&, const SvXMLUnitConverter
& ) const
273 bool XMLBoolFalsePropHdl::exportXML( OUString
& rStrExpValue
, const Any
& /*rValue*/, const SvXMLUnitConverter
& rCnv
) const
275 return XMLBoolPropHdl::exportXML( rStrExpValue
, Any( false ), rCnv
);
279 XMLBoolPropHdl::~XMLBoolPropHdl()
284 bool XMLBoolPropHdl::importXML( const OUString
& rStrImpValue
, Any
& rValue
, const SvXMLUnitConverter
& ) const
287 bool const bRet
= ::sax::Converter::convertBool( bValue
, rStrImpValue
);
293 bool XMLBoolPropHdl::exportXML( OUString
& rStrExpValue
, const Any
& rValue
, const SvXMLUnitConverter
& ) const
298 if (rValue
>>= bValue
)
301 ::sax::Converter::convertBool( aOut
, bValue
);
302 rStrExpValue
= aOut
.makeStringAndClear();
311 XMLNBoolPropHdl::~XMLNBoolPropHdl()
316 bool XMLNBoolPropHdl::importXML( const OUString
& rStrImpValue
, Any
& rValue
, const SvXMLUnitConverter
& ) const
319 bool const bRet
= ::sax::Converter::convertBool( bValue
, rStrImpValue
);
325 bool XMLNBoolPropHdl::exportXML( OUString
& rStrExpValue
, const Any
& rValue
, const SvXMLUnitConverter
& ) const
330 if (rValue
>>= bValue
)
333 ::sax::Converter::convertBool( aOut
, !bValue
);
334 rStrExpValue
= aOut
.makeStringAndClear();
343 XMLPercentPropHdl::~XMLPercentPropHdl()
348 bool XMLPercentPropHdl::importXML( const OUString
& rStrImpValue
, Any
& rValue
, const SvXMLUnitConverter
& ) const
350 sal_Int32 nValue
= 0;
351 bool const bRet
= ::sax::Converter::convertPercent( nValue
, rStrImpValue
);
352 lcl_xmloff_setAny( rValue
, nValue
, nBytes
);
357 bool XMLPercentPropHdl::exportXML( OUString
& rStrExpValue
, const Any
& rValue
, const SvXMLUnitConverter
& ) const
362 if( lcl_xmloff_getAny( rValue
, nValue
, nBytes
) )
365 ::sax::Converter::convertPercent( aOut
, nValue
);
366 rStrExpValue
= aOut
.makeStringAndClear();
375 bool XMLDoublePercentPropHdl::importXML( const OUString
& rStrImpValue
, Any
& rValue
, const SvXMLUnitConverter
& ) const
381 if( rStrImpValue
.indexOf( '%' ) == -1 )
383 fValue
= rStrImpValue
.toDouble();
387 sal_Int32 nValue
= 0;
388 bRet
= ::sax::Converter::convertPercent( nValue
, rStrImpValue
);
389 fValue
= static_cast<double>(nValue
) / 100.0;
396 bool XMLDoublePercentPropHdl::exportXML( OUString
& rStrExpValue
, const Any
& rValue
, const SvXMLUnitConverter
& ) const
401 if( rValue
>>= fValue
)
404 if( fValue
> 0 ) fValue
+= 0.5; else fValue
-= 0.5;
406 sal_Int32 nValue
= static_cast<sal_Int32
>(fValue
);
409 ::sax::Converter::convertPercent( aOut
, nValue
);
410 rStrExpValue
= aOut
.makeStringAndClear();
418 bool XML100thPercentPropHdl::importXML(const OUString
& rStrImpValue
, Any
& rValue
,
419 const SvXMLUnitConverter
&) const
423 sal_Int32 nValue
= 0;
424 bRet
= sax::Converter::convertPercent(nValue
, rStrImpValue
);
425 rValue
<<= static_cast<sal_Int16
>(nValue
* 100);
430 bool XML100thPercentPropHdl::exportXML(OUString
& rStrExpValue
, const Any
& rValue
,
431 const SvXMLUnitConverter
&) const
434 sal_Int16 nValue
= 0;
436 if (rValue
>>= nValue
)
438 nValue
= std::round(static_cast<double>(nValue
) / 100);
440 sax::Converter::convertPercent(aOut
, nValue
);
441 rStrExpValue
= aOut
.makeStringAndClear();
449 XMLNegPercentPropHdl::~XMLNegPercentPropHdl()
454 bool XMLNegPercentPropHdl::importXML( const OUString
& rStrImpValue
, Any
& rValue
, const SvXMLUnitConverter
& ) const
456 sal_Int32 nValue
= 0;
457 bool bRet
= ::sax::Converter::convertPercent( nValue
, rStrImpValue
);
459 bRet
= !o3tl::checked_sub
<sal_Int32
>(100, nValue
, nValue
);
461 lcl_xmloff_setAny( rValue
, nValue
, nBytes
);
465 bool XMLNegPercentPropHdl::exportXML( OUString
& rStrExpValue
, const Any
& rValue
, const SvXMLUnitConverter
& ) const
470 if( lcl_xmloff_getAny( rValue
, nValue
, nBytes
) )
473 ::sax::Converter::convertPercent( aOut
, 100-nValue
);
474 rStrExpValue
= aOut
.makeStringAndClear();
482 XMLMeasurePxPropHdl::~XMLMeasurePxPropHdl()
487 bool XMLMeasurePxPropHdl::importXML( const OUString
& rStrImpValue
, Any
& rValue
, const SvXMLUnitConverter
& ) const
489 sal_Int32 nValue
= 0;
490 bool bRet
= ::sax::Converter::convertMeasurePx( nValue
, rStrImpValue
);
491 lcl_xmloff_setAny( rValue
, nValue
, nBytes
);
495 bool XMLMeasurePxPropHdl::exportXML( OUString
& rStrExpValue
, const Any
& rValue
, const SvXMLUnitConverter
& ) const
500 if( lcl_xmloff_getAny( rValue
, nValue
, nBytes
) )
503 ::sax::Converter::convertMeasurePx( aOut
, nValue
);
504 rStrExpValue
= aOut
.makeStringAndClear();
513 XMLColorPropHdl::~XMLColorPropHdl()
518 bool XMLColorPropHdl::importXML( const OUString
& rStrImpValue
, Any
& rValue
, const SvXMLUnitConverter
& ) const
522 if( rStrImpValue
.matchIgnoreAsciiCase( "hsl" ) )
524 sal_Int32 nOpen
= rStrImpValue
.indexOf( '(' );
525 sal_Int32 nClose
= rStrImpValue
.lastIndexOf( ')' );
527 if( (nOpen
!= -1) && (nClose
> nOpen
) )
529 const std::u16string_view
aTmp( rStrImpValue
.subView( nOpen
+1, nClose
- nOpen
-1) );
531 sal_Int32 nIndex
= 0;
533 Sequence
< double > aHSL
535 o3tl::toDouble(o3tl::getToken(aTmp
, 0, ',', nIndex
)),
536 o3tl::toDouble(o3tl::getToken(aTmp
, 0, ',', nIndex
)) / 100.0,
537 o3tl::toDouble(o3tl::getToken(aTmp
, 0, ',', nIndex
)) / 100.0
546 bRet
= ::sax::Converter::convertColor( nColor
, rStrImpValue
);
553 bool XMLColorPropHdl::exportXML( OUString
& rStrExpValue
, const Any
& rValue
, const SvXMLUnitConverter
& ) const
556 sal_Int32 nColor
= 0;
559 if( rValue
>>= nColor
)
561 ::sax::Converter::convertColor( aOut
, nColor
);
562 rStrExpValue
= aOut
.makeStringAndClear();
568 Sequence
< double > aHSL
;
569 if( (rValue
>>= aHSL
) && (aHSL
.getLength() == 3) )
571 rStrExpValue
= "hsl(" + OUString::number(aHSL
[0]) + "," +
572 OUString::number(aHSL
[1] * 100.0) + "%," +
573 OUString::number(aHSL
[2] * 100.0) + "%)";
583 XMLHexPropHdl::~XMLHexPropHdl()
588 bool XMLHexPropHdl::importXML( const OUString
& rStrImpValue
, Any
& rValue
, const SvXMLUnitConverter
& ) const
591 bool bRet
= SvXMLUnitConverter::convertHex( nRsid
, rStrImpValue
);
597 bool XMLHexPropHdl::exportXML( OUString
& rStrExpValue
, const Any
& rValue
, const SvXMLUnitConverter
& ) const
600 sal_uInt32 nRsid
= 0;
602 if( rValue
>>= nRsid
)
605 SvXMLUnitConverter::convertHex( aOut
, nRsid
);
606 rStrExpValue
= aOut
.makeStringAndClear();
619 XMLStringPropHdl::~XMLStringPropHdl()
624 bool XMLStringPropHdl::importXML( const OUString
& rStrImpValue
, Any
& rValue
, const SvXMLUnitConverter
& ) const
626 rValue
<<= rStrImpValue
;
630 bool XMLStringPropHdl::exportXML( OUString
& rStrExpValue
, const Any
& rValue
, const SvXMLUnitConverter
& ) const
634 if( rValue
>>= rStrExpValue
)
641 XMLStyleNamePropHdl::~XMLStyleNamePropHdl()
646 bool XMLStyleNamePropHdl::exportXML( OUString
& rStrExpValue
, const Any
& rValue
, const SvXMLUnitConverter
& rUnitConverter
) const
650 if( rValue
>>= rStrExpValue
)
652 rStrExpValue
= rUnitConverter
.encodeStyleName( rStrExpValue
);
660 XMLDoublePropHdl::~XMLDoublePropHdl()
665 bool XMLDoublePropHdl::importXML( const OUString
& rStrImpValue
, Any
& rValue
, const SvXMLUnitConverter
& ) const
667 double fDblValue(0.0);
668 bool const bRet
= ::sax::Converter::convertDouble(fDblValue
, rStrImpValue
);
669 rValue
<<= fDblValue
;
673 bool XMLDoublePropHdl::exportXML( OUString
& rStrExpValue
, const Any
& rValue
, const SvXMLUnitConverter
& ) const
679 if( rValue
>>= fValue
)
682 ::sax::Converter::convertDouble( aOut
, fValue
);
683 rStrExpValue
= aOut
.makeStringAndClear();
691 XMLColorTransparentPropHdl::XMLColorTransparentPropHdl(
692 enum XMLTokenEnum eTransparent
) :
693 sTransparent( GetXMLToken(
694 eTransparent
!= XML_TOKEN_INVALID
? eTransparent
: XML_TRANSPARENT
) )
699 XMLColorTransparentPropHdl::~XMLColorTransparentPropHdl()
704 bool XMLColorTransparentPropHdl::importXML( const OUString
& rStrImpValue
, Any
& rValue
, const SvXMLUnitConverter
& ) const
708 if( rStrImpValue
!= sTransparent
)
711 bRet
= ::sax::Converter::convertColor( nColor
, rStrImpValue
);
718 bool XMLColorTransparentPropHdl::exportXML( OUString
& rStrExpValue
, const Any
& rValue
, const SvXMLUnitConverter
& ) const
721 sal_Int32 nColor
= 0;
723 if( rStrExpValue
== sTransparent
)
725 else if( rValue
>>= nColor
)
728 ::sax::Converter::convertColor( aOut
, nColor
);
729 rStrExpValue
= aOut
.makeStringAndClear();
738 XMLIsTransparentPropHdl::XMLIsTransparentPropHdl(
739 enum XMLTokenEnum eTransparent
, bool bTransPropVal
) :
740 sTransparent( GetXMLToken(
741 eTransparent
!= XML_TOKEN_INVALID
? eTransparent
: XML_TRANSPARENT
) ),
742 bTransPropValue( bTransPropVal
)
746 XMLIsTransparentPropHdl::~XMLIsTransparentPropHdl()
751 bool XMLIsTransparentPropHdl::importXML( const OUString
& rStrImpValue
, Any
& rValue
, const SvXMLUnitConverter
& ) const
753 bool bValue
= ( (rStrImpValue
== sTransparent
) == bTransPropValue
);
759 bool XMLIsTransparentPropHdl::exportXML( OUString
& rStrExpValue
, const Any
& rValue
, const SvXMLUnitConverter
& ) const
763 // MIB: This looks a bit strange, because bTransPropValue == bValue should
764 // do the same, but this only applies if 'true' is represented by the same
765 // 8 bit value in bValue and bTransPropValue. Who will ensure this?
766 bool bValue
= *o3tl::doAccess
<bool>(rValue
);
767 bool bIsTrans
= bTransPropValue
? bValue
: !bValue
;
771 rStrExpValue
= sTransparent
;
779 XMLColorAutoPropHdl::XMLColorAutoPropHdl()
784 XMLColorAutoPropHdl::~XMLColorAutoPropHdl()
789 bool XMLColorAutoPropHdl::importXML( const OUString
& rStrImpValue
, Any
& rValue
, const SvXMLUnitConverter
& ) const
793 // This is a multi property: the value might be set to AUTO_COLOR
794 // already by the XMLIsAutoColorPropHdl!
795 sal_Int32 nColor
= 0;
796 if( !(rValue
>>= nColor
) || -1 != nColor
)
798 bRet
= ::sax::Converter::convertColor( nColor
, rStrImpValue
);
806 bool XMLColorAutoPropHdl::exportXML( OUString
& rStrExpValue
, const Any
& rValue
, const SvXMLUnitConverter
& ) const
810 sal_Int32 nColor
= 0;
811 if( (rValue
>>= nColor
) && -1 != nColor
)
814 ::sax::Converter::convertColor( aOut
, nColor
);
815 rStrExpValue
= aOut
.makeStringAndClear();
824 XMLIsAutoColorPropHdl::XMLIsAutoColorPropHdl()
828 XMLIsAutoColorPropHdl::~XMLIsAutoColorPropHdl()
833 bool XMLIsAutoColorPropHdl::importXML( const OUString
& rStrImpValue
, Any
& rValue
, const SvXMLUnitConverter
& ) const
835 // An auto color overrides any other color set!
837 bool const bRet
= ::sax::Converter::convertBool( bValue
, rStrImpValue
);
839 rValue
<<= sal_Int32(-1);
844 bool XMLIsAutoColorPropHdl::exportXML( OUString
& rStrExpValue
, const Any
& rValue
, const SvXMLUnitConverter
& ) const
847 sal_Int32 nColor
= 0;
849 if( (rValue
>>= nColor
) && -1 == nColor
)
852 ::sax::Converter::convertBool( aOut
, true );
853 rStrExpValue
= aOut
.makeStringAndClear();
862 XMLCompareOnlyPropHdl::~XMLCompareOnlyPropHdl()
867 bool XMLCompareOnlyPropHdl::importXML( const OUString
&, Any
&, const SvXMLUnitConverter
& ) const
869 SAL_WARN( "xmloff", "importXML called for compare-only-property" );
873 bool XMLCompareOnlyPropHdl::exportXML( OUString
&, const Any
&, const SvXMLUnitConverter
& ) const
875 SAL_WARN( "xmloff", "exportXML called for compare-only-property" );
880 XMLNumberWithoutZeroPropHdl::XMLNumberWithoutZeroPropHdl( sal_Int8 nB
) :
885 XMLNumberWithoutZeroPropHdl::~XMLNumberWithoutZeroPropHdl()
889 bool XMLNumberWithoutZeroPropHdl::importXML(
890 const OUString
& rStrImpValue
,
892 const SvXMLUnitConverter
& ) const
894 sal_Int32 nValue
= 0;
895 bool const bRet
= ::sax::Converter::convertNumber( nValue
, rStrImpValue
);
897 lcl_xmloff_setAny( rValue
, nValue
, nBytes
);
901 bool XMLNumberWithoutZeroPropHdl::exportXML( OUString
& rStrExpValue
, const Any
& rValue
, const SvXMLUnitConverter
& ) const
904 sal_Int32 nValue
= 0;
905 bool bRet
= lcl_xmloff_getAny( rValue
, nValue
, nBytes
);
910 rStrExpValue
= OUString::number(nValue
);
917 XMLNumberWithAutoForVoidPropHdl::~XMLNumberWithAutoForVoidPropHdl()
921 bool XMLNumberWithAutoForVoidPropHdl::importXML(
922 const OUString
& rStrImpValue
,
924 const SvXMLUnitConverter
& ) const
926 sal_Int32 nValue
= 0;
927 bool bRet
= ::sax::Converter::convertNumber( nValue
, rStrImpValue
);
929 lcl_xmloff_setAny( rValue
, nValue
, 2 );
930 else if( rStrImpValue
== GetXMLToken( XML_AUTO
) )
932 rValue
.clear(); // void
938 bool XMLNumberWithAutoForVoidPropHdl::exportXML(
939 OUString
& rStrExpValue
, const Any
& rValue
, const SvXMLUnitConverter
&) const
942 sal_Int32 nValue
= 0;
943 bool bRet
= lcl_xmloff_getAny( rValue
, nValue
, 2 );
945 // note: 0 is a valid value here, see CTF_PAGENUMBEROFFSET for when it isn't
948 rStrExpValue
= GetXMLToken( XML_AUTO
);
951 rStrExpValue
= OUString::number(nValue
);
957 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */