| /************************************************************** |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| *************************************************************/ |
| |
| |
| |
| // MARKER(update_precomp.py): autogen include statement, do not remove |
| #include "precompiled_xmloff.hxx" |
| #include <com/sun/star/util/DateTime.hpp> |
| #include <com/sun/star/util/Date.hpp> |
| #include <com/sun/star/util/Time.hpp> |
| #include <tools/debug.hxx> |
| #include <rtl/ustrbuf.hxx> |
| #include "xmlehelp.hxx" |
| #include <xmloff/xmlement.hxx> |
| #include <xmloff/xmluconv.hxx> |
| #include <xmloff/xmltoken.hxx> |
| #include <rtl/math.hxx> |
| #include <rtl/logfile.hxx> |
| |
| #ifndef _TOOLS_DATE_HXX |
| #include <tools/date.hxx> |
| |
| #include <tools/string.hxx> |
| |
| #endif |
| |
| #include <tools/time.hxx> |
| #include <tools/fldunit.hxx> |
| |
| // #110680# |
| //#ifndef _COMPHELPER_PROCESSFACTORY_HXX_ |
| //#include <comphelper/processfactory.hxx> |
| //#endif |
| #include <com/sun/star/util/XNumberFormatsSupplier.hpp> |
| #include <com/sun/star/style/NumberingType.hpp> |
| #include <com/sun/star/text/XNumberingTypeInfo.hpp> |
| #include <com/sun/star/lang/XMultiServiceFactory.hpp> |
| #include <com/sun/star/i18n/XCharacterClassification.hpp> |
| #include <com/sun/star/i18n/UnicodeType.hpp> |
| #include <basegfx/vector/b3dvector.hxx> |
| |
| using namespace rtl; |
| using namespace com::sun::star; |
| using namespace com::sun::star::uno; |
| using namespace com::sun::star::lang; |
| using namespace com::sun::star::text; |
| using namespace com::sun::star::style; |
| using namespace ::com::sun::star::i18n; |
| using namespace ::xmloff::token; |
| |
| const sal_Int8 XML_MAXDIGITSCOUNT_TIME = 11; |
| const sal_Int8 XML_MAXDIGITSCOUNT_DATETIME = 6; |
| #define XML_NULLDATE "NullDate" |
| |
| OUString SvXMLUnitConverter::msXML_true; |
| OUString SvXMLUnitConverter::msXML_false; |
| |
| void SvXMLUnitConverter::initXMLStrings() |
| { |
| if( msXML_true.getLength() == 0 ) |
| { |
| msXML_true = GetXMLToken(XML_TRUE); |
| msXML_false = GetXMLToken(XML_FALSE); |
| } |
| } |
| |
| void SvXMLUnitConverter::createNumTypeInfo() const |
| { |
| // #110680# |
| //Reference< lang::XMultiServiceFactory > xServiceFactory = |
| // comphelper::getProcessServiceFactory(); |
| //OSL_ENSURE( xServiceFactory.is(), |
| // "XMLUnitConverter: got no service factory" ); |
| |
| if( mxServiceFactory.is() ) |
| { |
| ((SvXMLUnitConverter *)this)->xNumTypeInfo = |
| Reference < XNumberingTypeInfo > ( |
| mxServiceFactory->createInstance( |
| OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.DefaultNumberingProvider") ) ), UNO_QUERY ); |
| } |
| } |
| |
| /** constructs a SvXMLUnitConverter. The core measure unit is the |
| default unit for numerical measures, the XML measure unit is |
| the default unit for textual measures |
| */ |
| |
| // #110680# |
| //SvXMLUnitConverter::SvXMLUnitConverter( MapUnit eCoreMeasureUnit, |
| // MapUnit eXMLMeasureUnit ) : |
| SvXMLUnitConverter::SvXMLUnitConverter( |
| MapUnit eCoreMeasureUnit, |
| MapUnit eXMLMeasureUnit, |
| const uno::Reference<lang::XMultiServiceFactory>& xServiceFactory ) : |
| aNullDate(30, 12, 1899), |
| mxServiceFactory( xServiceFactory ) |
| { |
| DBG_ASSERT( mxServiceFactory.is(), "got no service manager" ); |
| |
| meCoreMeasureUnit = eCoreMeasureUnit; |
| meXMLMeasureUnit = eXMLMeasureUnit; |
| } |
| |
| SvXMLUnitConverter::~SvXMLUnitConverter() |
| { |
| } |
| |
| MapUnit SvXMLUnitConverter::GetMapUnit(sal_Int16 nFieldUnit) |
| { |
| MapUnit eUnit = MAP_INCH; |
| switch( nFieldUnit ) |
| { |
| case FUNIT_MM: |
| eUnit = MAP_MM; |
| break; |
| case FUNIT_CM: |
| case FUNIT_M: |
| case FUNIT_KM: |
| eUnit = MAP_CM; |
| break; |
| case FUNIT_TWIP: |
| eUnit = MAP_TWIP; |
| break; |
| case FUNIT_POINT: |
| case FUNIT_PICA: |
| eUnit = MAP_POINT; |
| break; |
| // case FUNIT_INCH: |
| // case FUNIT_FOOT: |
| // case FUNIT_MILE: |
| // eUnit = MAP_INCH; |
| // break; |
| case FUNIT_100TH_MM: |
| eUnit = MAP_100TH_MM; |
| break; |
| } |
| return eUnit; |
| } |
| |
| /** convert string to measure using optional min and max values*/ |
| sal_Bool SvXMLUnitConverter::convertMeasure( sal_Int32& nValue, |
| const OUString& rString, |
| sal_Int32 nMin, sal_Int32 nMax ) const |
| { |
| return SvXMLUnitConverter::convertMeasure( nValue, rString, |
| meCoreMeasureUnit, |
| nMin, nMax ); |
| } |
| |
| /** convert measure to string */ |
| void SvXMLUnitConverter::convertMeasure( OUStringBuffer& rString, |
| sal_Int32 nMeasure ) const |
| { |
| SvXMLUnitConverter::convertMeasure( rString, nMeasure, |
| meCoreMeasureUnit, |
| meXMLMeasureUnit ); |
| } |
| |
| /** convert measure with given unit to string */ |
| void SvXMLUnitConverter::convertMeasure( OUStringBuffer& rString, |
| sal_Int32 nMeasure, |
| MapUnit eSrcUnit ) const |
| { |
| SvXMLUnitConverter::convertMeasure( rString, nMeasure, |
| eSrcUnit, |
| meXMLMeasureUnit ); |
| } |
| |
| /** convert the value from the given string to an int value |
| with the given map unit using optional min and max values |
| */ |
| sal_Bool SvXMLUnitConverter::convertMeasure( sal_Int32& rValue, |
| const OUString& rString, |
| MapUnit eDstUnit, |
| sal_Int32 nMin, sal_Int32 nMax ) |
| { |
| sal_Bool bNeg = sal_False; |
| double nVal = 0; |
| |
| sal_Int32 nPos = 0; |
| const sal_Int32 nLen = rString.getLength(); |
| |
| // skip white space |
| while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) ) |
| nPos++; |
| |
| if( nPos < nLen && sal_Unicode('-') == rString[nPos] ) |
| { |
| bNeg = sal_True; |
| ++nPos; |
| } |
| |
| // get number |
| while( nPos < nLen && |
| sal_Unicode('0') <= rString[nPos] && |
| sal_Unicode('9') >= rString[nPos] ) |
| { |
| // TODO: check overflow! |
| nVal *= 10; |
| nVal += (rString[nPos] - sal_Unicode('0')); |
| ++nPos; |
| } |
| double nDiv = 1.; |
| if( nPos < nLen && sal_Unicode('.') == rString[nPos] ) |
| { |
| ++nPos; |
| |
| while( nPos < nLen && |
| sal_Unicode('0') <= rString[nPos] && |
| sal_Unicode('9') >= rString[nPos] ) |
| { |
| // TODO: check overflow! |
| nDiv *= 10; |
| nVal += ( ((double)(rString[nPos] - sal_Unicode('0'))) / nDiv ); |
| ++nPos; |
| } |
| } |
| |
| // skip white space |
| while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) ) |
| ++nPos; |
| |
| if( nPos < nLen ) |
| { |
| |
| if( MAP_RELATIVE == eDstUnit ) |
| { |
| if( sal_Unicode('%') != rString[nPos] ) |
| return sal_False; |
| } |
| else if( MAP_PIXEL == eDstUnit ) |
| { |
| if( nPos + 1 >= nLen || |
| (sal_Unicode('p') != rString[nPos] && |
| sal_Unicode('P') != rString[nPos])|| |
| (sal_Unicode('x') != rString[nPos+1] && |
| sal_Unicode('X') != rString[nPos+1]) ) |
| return sal_False; |
| } |
| else |
| { |
| DBG_ASSERT( MAP_TWIP == eDstUnit || MAP_POINT == eDstUnit || |
| MAP_100TH_MM == eDstUnit || MAP_10TH_MM == eDstUnit, "unit is not supported"); |
| const sal_Char *aCmpsL[2] = { 0, 0 }; |
| const sal_Char *aCmpsU[2] = { 0, 0 }; |
| double aScales[2] = { 1., 1. }; |
| |
| if( MAP_TWIP == eDstUnit ) |
| { |
| switch( rString[nPos] ) |
| { |
| case sal_Unicode('c'): |
| case sal_Unicode('C'): |
| aCmpsL[0] = "cm"; |
| aCmpsU[0] = "CM"; |
| aScales[0] = (72.*20.)/2.54; // twip |
| break; |
| case sal_Unicode('e'): |
| case sal_Unicode('E'): |
| // pCmp1 = sXML_unit_em; |
| // nToken1 = CSS1_EMS; |
| |
| // pCmp2 = sXML_unit_ex; |
| // nToken2 = CSS1_EMX; |
| break; |
| case sal_Unicode('i'): |
| case sal_Unicode('I'): |
| aCmpsL[0] = "in"; |
| aCmpsU[0] = "IN"; |
| aScales[0] = 72.*20.; // twip |
| break; |
| case sal_Unicode('m'): |
| case sal_Unicode('M'): |
| aCmpsL[0] = "mm"; |
| aCmpsU[0] = "MM"; |
| aScales[0] = (72.*20.)/25.4; // twip |
| break; |
| case sal_Unicode('p'): |
| case sal_Unicode('P'): |
| aCmpsL[0] = "pt"; |
| aCmpsU[0] = "PT"; |
| aScales[0] = 20.; // twip |
| |
| aCmpsL[1] = "pc"; |
| aCmpsU[1] = "PC"; |
| aScales[1] = 12.*20.; // twip |
| |
| // pCmp3 = sXML_unit_px; |
| // nToken3 = CSS1_PIXLENGTH; |
| break; |
| } |
| } |
| else if( MAP_100TH_MM == eDstUnit || MAP_10TH_MM == eDstUnit ) |
| { |
| double nScaleFactor = (MAP_100TH_MM == eDstUnit) ? 100.0 : 10.0; |
| switch( rString[nPos] ) |
| { |
| case sal_Unicode('c'): |
| case sal_Unicode('C'): |
| aCmpsL[0] = "cm"; |
| aCmpsU[0] = "CM"; |
| aScales[0] = 10.0 * nScaleFactor; // mm/100 |
| break; |
| case sal_Unicode('e'): |
| case sal_Unicode('E'): |
| // pCmp1 = sXML_unit_em; |
| // nToken1 = CSS1_EMS; |
| |
| // pCmp2 = sXML_unit_ex; |
| // nToken2 = CSS1_EMX; |
| break; |
| case sal_Unicode('i'): |
| case sal_Unicode('I'): |
| aCmpsL[0] = "in"; |
| aCmpsU[0] = "IN"; |
| aScales[0] = 1000.*2.54; // mm/100 |
| break; |
| case sal_Unicode('m'): |
| case sal_Unicode('M'): |
| aCmpsL[0] = "mm"; |
| aCmpsU[0] = "MM"; |
| aScales[0] = 1.0 * nScaleFactor; // mm/100 |
| break; |
| case sal_Unicode('p'): |
| case sal_Unicode('P'): |
| aCmpsL[0] = "pt"; |
| aCmpsU[0] = "PT"; |
| aScales[0] = (10.0 * nScaleFactor*2.54)/72.; // mm/100 |
| |
| aCmpsL[1] = "pc"; |
| aCmpsU[1] = "PC"; |
| aScales[1] = (10.0 * nScaleFactor*2.54)/12.; // mm/100 |
| |
| // pCmp3 = sXML_unit_px; |
| // nToken3 = CSS1_PIXLENGTH; |
| break; |
| } |
| } |
| else if( MAP_POINT == eDstUnit ) |
| { |
| if( rString[nPos] == 'p' || rString[nPos] == 'P' ) |
| { |
| aCmpsL[0] = "pt"; |
| aCmpsU[0] = "PT"; |
| aScales[0] = 1; |
| } |
| } |
| |
| if( aCmpsL[0] == NULL ) |
| return sal_False; |
| |
| double nScale = 0.; |
| for( sal_uInt16 i= 0; i < 2; ++i ) |
| { |
| const sal_Char *pL = aCmpsL[i]; |
| if( pL ) |
| { |
| const sal_Char *pU = aCmpsU[i]; |
| while( nPos < nLen && *pL ) |
| { |
| sal_Unicode c = rString[nPos]; |
| if( c != *pL && c != *pU ) |
| break; |
| ++pL; |
| ++pU; |
| ++nPos; |
| } |
| if( !*pL && (nPos == nLen || ' ' == rString[nPos]) ) |
| { |
| nScale = aScales[i]; |
| break; |
| } |
| } |
| } |
| |
| if( 0. == nScale ) |
| return sal_False; |
| |
| // TODO: check overflow |
| if( nScale != 1. ) |
| nVal *= nScale; |
| } |
| } |
| |
| nVal += .5; |
| if( bNeg ) |
| nVal = -nVal; |
| |
| if( nVal <= (double)nMin ) |
| rValue = nMin; |
| else if( nVal >= (double)nMax ) |
| rValue = nMax; |
| else |
| rValue = (sal_Int32)nVal; |
| |
| return sal_True; |
| } |
| |
| /** convert measure in given unit to string with given unit */ |
| void SvXMLUnitConverter::convertMeasure( OUStringBuffer& rBuffer, |
| sal_Int32 nMeasure, |
| MapUnit eSrcUnit, |
| MapUnit eDstUnit ) |
| { |
| if( eSrcUnit == MAP_RELATIVE ) |
| { |
| DBG_ASSERT( eDstUnit == MAP_RELATIVE, |
| "MAP_RELATIVE only maps to MAP_RELATIVE!" ); |
| |
| rBuffer.append( nMeasure ); |
| rBuffer.append( sal_Unicode('%' ) ); |
| } |
| else |
| { |
| SvXMLExportHelper::AddLength( nMeasure, eSrcUnit, |
| rBuffer, eDstUnit ); |
| } |
| } |
| |
| /** convert string to boolean */ |
| sal_Bool SvXMLUnitConverter::convertBool( sal_Bool& rBool, |
| const OUString& rString ) |
| { |
| rBool = IsXMLToken(rString, XML_TRUE); |
| |
| return rBool || IsXMLToken(rString, XML_FALSE); |
| } |
| |
| /** convert boolean to string */ |
| void SvXMLUnitConverter::convertBool( OUStringBuffer& rBuffer, |
| sal_Bool bValue ) |
| { |
| rBuffer.append( GetXMLToken( bValue ? XML_TRUE : XML_FALSE ) ); |
| } |
| |
| /** convert string to percent */ |
| sal_Bool SvXMLUnitConverter::convertPercent( sal_Int32& rPercent, |
| const OUString& rString ) |
| { |
| return convertMeasure( rPercent, rString, MAP_RELATIVE ); |
| } |
| |
| /** convert percent to string */ |
| void SvXMLUnitConverter::convertPercent( OUStringBuffer& rBuffer, |
| sal_Int32 nValue ) |
| { |
| rBuffer.append( nValue ); |
| rBuffer.append( sal_Unicode('%' ) ); |
| } |
| |
| /** convert string to pixel measure */ |
| sal_Bool SvXMLUnitConverter::convertMeasurePx( sal_Int32& rPixel, |
| const OUString& rString ) |
| { |
| return convertMeasure( rPixel, rString, MAP_PIXEL ); |
| } |
| |
| /** convert pixel measure to string */ |
| void SvXMLUnitConverter::convertMeasurePx( OUStringBuffer& rBuffer, |
| sal_Int32 nValue ) |
| { |
| rBuffer.append( nValue ); |
| rBuffer.append( sal_Unicode('p' ) ); |
| rBuffer.append( sal_Unicode('x' ) ); |
| } |
| |
| /** convert string to enum using given enum map, if the enum is |
| not found in the map, this method will return false |
| */ |
| sal_Bool SvXMLUnitConverter::convertEnum( sal_uInt16& rEnum, |
| const OUString& rValue, |
| const SvXMLEnumStringMapEntry *pMap ) |
| { |
| while( pMap->pName ) |
| { |
| if( rValue.equalsAsciiL( pMap->pName, pMap->nNameLength ) ) |
| { |
| rEnum = pMap->nValue; |
| return sal_True; |
| } |
| ++pMap; |
| } |
| |
| return sal_False; |
| } |
| |
| /** convert string to enum using given token map, if the enum is |
| not found in the map, this method will return false */ |
| sal_Bool SvXMLUnitConverter::convertEnum( |
| sal_uInt16& rEnum, |
| const OUString& rValue, |
| const SvXMLEnumMapEntry *pMap ) |
| { |
| while( pMap->eToken != XML_TOKEN_INVALID ) |
| { |
| if( IsXMLToken( rValue, pMap->eToken ) ) |
| { |
| rEnum = pMap->nValue; |
| return sal_True; |
| } |
| ++pMap; |
| } |
| return sal_False; |
| } |
| |
| /** convert enum to string using given enum map with optional |
| default string. If the enum is not found in the map, |
| this method will either use the given default or return |
| false if not default is set |
| */ |
| sal_Bool SvXMLUnitConverter::convertEnum( OUStringBuffer& rBuffer, |
| sal_uInt16 nValue, |
| const SvXMLEnumStringMapEntry *pMap, |
| sal_Char * pDefault /* = NULL */ ) |
| { |
| const sal_Char *pStr = pDefault; |
| |
| while( pMap->pName ) |
| { |
| if( pMap->nValue == nValue ) |
| { |
| pStr = pMap->pName; |
| break; |
| } |
| ++pMap; |
| } |
| |
| if( NULL == pStr ) |
| pStr = pDefault; |
| |
| if( NULL != pStr ) |
| rBuffer.appendAscii( pStr ); |
| |
| return NULL != pStr; |
| } |
| |
| /** convert enum to string using given token map with an optional |
| default token. If the enum is not found in the map, |
| this method will either use the given default or return |
| false if no default is set */ |
| sal_Bool SvXMLUnitConverter::convertEnum( |
| OUStringBuffer& rBuffer, |
| unsigned int nValue, |
| const SvXMLEnumMapEntry *pMap, |
| enum XMLTokenEnum eDefault) |
| { |
| enum XMLTokenEnum eTok = eDefault; |
| |
| while( pMap->eToken != XML_TOKEN_INVALID ) |
| { |
| if( pMap->nValue == nValue ) |
| { |
| eTok = pMap->eToken; |
| break; |
| } |
| ++pMap; |
| } |
| |
| // the map may have contained XML_TOKEN_INVALID |
| if( eTok == XML_TOKEN_INVALID ) |
| eTok = eDefault; |
| |
| if( eTok != XML_TOKEN_INVALID ) |
| rBuffer.append( GetXMLToken(eTok) ); |
| |
| return (eTok != XML_TOKEN_INVALID); |
| } |
| |
| int lcl_gethex( int nChar ) |
| { |
| if( nChar >= '0' && nChar <= '9' ) |
| return nChar - '0'; |
| else if( nChar >= 'a' && nChar <= 'f' ) |
| return nChar - 'a' + 10; |
| else if( nChar >= 'A' && nChar <= 'F' ) |
| return nChar - 'A' + 10; |
| else |
| return 0; |
| } |
| |
| /** convert string to color */ |
| sal_Bool SvXMLUnitConverter::convertColor( Color& rColor, |
| const OUString& rValue ) |
| { |
| if( rValue.getLength() != 7 || rValue[0] != '#' ) |
| return sal_False; |
| |
| rColor.SetRed( |
| sal::static_int_cast< sal_uInt8 >( |
| lcl_gethex( rValue[1] ) * 16 + lcl_gethex( rValue[2] ) ) ); |
| |
| rColor.SetGreen( |
| sal::static_int_cast< sal_uInt8 >( |
| lcl_gethex( rValue[3] ) * 16 + lcl_gethex( rValue[4] ) ) ); |
| |
| rColor.SetBlue( |
| sal::static_int_cast< sal_uInt8 >( |
| lcl_gethex( rValue[5] ) * 16 + lcl_gethex( rValue[6] ) ) ); |
| |
| return sal_True; |
| } |
| |
| static sal_Char aHexTab[] = "0123456789abcdef"; |
| |
| /** convert color to string */ |
| void SvXMLUnitConverter::convertColor( OUStringBuffer& rBuffer, |
| const Color& rCol ) |
| { |
| rBuffer.append( sal_Unicode( '#' ) ); |
| |
| sal_uInt8 nCol = rCol.GetRed(); |
| rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) ); |
| rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) ); |
| |
| nCol = rCol.GetGreen(); |
| rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) ); |
| rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) ); |
| |
| nCol = rCol.GetBlue(); |
| rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) ); |
| rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) ); |
| } |
| |
| /** convert number to string */ |
| void SvXMLUnitConverter::convertNumber( OUStringBuffer& rBuffer, |
| sal_Int32 nNumber ) |
| { |
| rBuffer.append( sal_Int32( nNumber ) ); |
| } |
| |
| /** convert string to number with optional min and max values */ |
| sal_Bool SvXMLUnitConverter::convertNumber( sal_Int32& rValue, |
| const OUString& rString, |
| sal_Int32 nMin, sal_Int32 nMax ) |
| { |
| rValue = 0; |
| sal_Int64 nNumber = 0; |
| sal_Bool bRet = convertNumber64(nNumber,rString,nMin,nMax); |
| if ( bRet ) |
| rValue = static_cast<sal_Int32>(nNumber); |
| return bRet; |
| } |
| |
| /** convert 64-bit number to string */ |
| void SvXMLUnitConverter::convertNumber64( OUStringBuffer& rBuffer, |
| sal_Int64 nNumber ) |
| { |
| rBuffer.append( nNumber ); |
| } |
| |
| /** convert string to 64-bit number with optional min and max values */ |
| sal_Bool SvXMLUnitConverter::convertNumber64( sal_Int64& rValue, |
| const OUString& rString, |
| sal_Int64 nMin, sal_Int64 nMax ) |
| { |
| sal_Bool bNeg = sal_False; |
| rValue = 0; |
| |
| sal_Int32 nPos = 0; |
| const sal_Int32 nLen = rString.getLength(); |
| |
| // skip white space |
| while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) ) |
| ++nPos; |
| |
| if( nPos < nLen && sal_Unicode('-') == rString[nPos] ) |
| { |
| bNeg = sal_True; |
| ++nPos; |
| } |
| |
| // get number |
| while( nPos < nLen && |
| sal_Unicode('0') <= rString[nPos] && |
| sal_Unicode('9') >= rString[nPos] ) |
| { |
| // TODO: check overflow! |
| rValue *= 10; |
| rValue += (rString[nPos] - sal_Unicode('0')); |
| ++nPos; |
| } |
| |
| if( bNeg ) |
| rValue *= -1; |
| |
| return ( nPos == nLen && rValue >= nMin && rValue <= nMax ); |
| } |
| |
| /** convert double number to string (using ::rtl::math) */ |
| void SvXMLUnitConverter::convertDouble(::rtl::OUStringBuffer& rBuffer, |
| double fNumber, sal_Bool bWriteUnits) const |
| { |
| SvXMLUnitConverter::convertDouble(rBuffer, fNumber, |
| bWriteUnits, meCoreMeasureUnit, meXMLMeasureUnit); |
| } |
| |
| /** convert double number to string (using ::rtl::math) */ |
| void SvXMLUnitConverter::convertDouble( ::rtl::OUStringBuffer& rBuffer, |
| double fNumber, sal_Bool bWriteUnits, MapUnit eCoreUnit, MapUnit eDstUnit) |
| { |
| if(MAP_RELATIVE == eCoreUnit) |
| { |
| DBG_ASSERT(eDstUnit == MAP_RELATIVE, "MAP_RELATIVE only maps to MAP_RELATIVE!" ); |
| ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', sal_True); |
| if(bWriteUnits) |
| rBuffer.append(sal_Unicode('%')); |
| } |
| else |
| { |
| OUStringBuffer sUnit; |
| double fFactor = SvXMLExportHelper::GetConversionFactor(sUnit, eCoreUnit, eDstUnit); |
| if(fFactor != 1.0) |
| fNumber *= fFactor; |
| ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', sal_True); |
| if(bWriteUnits) |
| rBuffer.append(sUnit); |
| } |
| } |
| |
| /** convert double number to string (using ::rtl::math) */ |
| void SvXMLUnitConverter::convertDouble( ::rtl::OUStringBuffer& rBuffer, double fNumber) |
| { |
| ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', sal_True); |
| } |
| |
| /** convert string to double number (using ::rtl::math) */ |
| sal_Bool SvXMLUnitConverter::convertDouble(double& rValue, |
| const ::rtl::OUString& rString, sal_Bool bLookForUnits) const |
| { |
| if(bLookForUnits) |
| { |
| MapUnit eSrcUnit = SvXMLExportHelper::GetUnitFromString(rString, meCoreMeasureUnit); |
| |
| return SvXMLUnitConverter::convertDouble(rValue, rString, |
| eSrcUnit, meCoreMeasureUnit); |
| } |
| else |
| { |
| return SvXMLUnitConverter::convertDouble(rValue, rString); |
| } |
| } |
| |
| /** convert string to double number (using ::rtl::math) */ |
| sal_Bool SvXMLUnitConverter::convertDouble(double& rValue, |
| const ::rtl::OUString& rString, MapUnit eSrcUnit, MapUnit eCoreUnit) |
| { |
| rtl_math_ConversionStatus eStatus; |
| rValue = ::rtl::math::stringToDouble( rString, (sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL ); |
| |
| if(eStatus == rtl_math_ConversionStatus_Ok) |
| { |
| OUStringBuffer sUnit; |
| const double fFactor = SvXMLExportHelper::GetConversionFactor(sUnit, eCoreUnit, eSrcUnit); |
| if(fFactor != 1.0 && fFactor != 0.0) |
| rValue /= fFactor; |
| } |
| |
| return ( eStatus == rtl_math_ConversionStatus_Ok ); |
| } |
| |
| /** convert string to double number (using ::rtl::math) */ |
| sal_Bool SvXMLUnitConverter::convertDouble(double& rValue, const ::rtl::OUString& rString) |
| { |
| rtl_math_ConversionStatus eStatus; |
| rValue = ::rtl::math::stringToDouble( rString, (sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL ); |
| return ( eStatus == rtl_math_ConversionStatus_Ok ); |
| } |
| |
| /** get the Null Date of the XModel and set it to the UnitConverter */ |
| sal_Bool SvXMLUnitConverter::setNullDate(const com::sun::star::uno::Reference <com::sun::star::frame::XModel>& xModel) |
| { |
| com::sun::star::uno::Reference <com::sun::star::util::XNumberFormatsSupplier> xNumberFormatsSupplier (xModel, com::sun::star::uno::UNO_QUERY); |
| if (xNumberFormatsSupplier.is()) |
| { |
| const com::sun::star::uno::Reference <com::sun::star::beans::XPropertySet> xPropertySet = xNumberFormatsSupplier->getNumberFormatSettings(); |
| return xPropertySet.is() && (xPropertySet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(XML_NULLDATE))) >>= aNullDate); |
| } |
| return sal_False; |
| } |
| |
| /** convert double to ISO Time String; negative durations allowed */ |
| void SvXMLUnitConverter::convertTime( ::rtl::OUStringBuffer& rBuffer, |
| const double& fTime) |
| { |
| |
| double fValue = fTime; |
| |
| // take care of negative durations as specified in: |
| // XML Schema, W3C Working Draft 07 April 2000, section 3.2.6.1 |
| if (fValue < 0.0) |
| { |
| rBuffer.append(sal_Unicode('-')); |
| fValue = - fValue; |
| } |
| |
| rBuffer.appendAscii(RTL_CONSTASCII_STRINGPARAM( "PT" )); |
| fValue *= 24; |
| double fHoursValue = ::rtl::math::approxFloor (fValue); |
| fValue -= fHoursValue; |
| fValue *= 60; |
| double fMinsValue = ::rtl::math::approxFloor (fValue); |
| fValue -= fMinsValue; |
| fValue *= 60; |
| double fSecsValue = ::rtl::math::approxFloor (fValue); |
| fValue -= fSecsValue; |
| double f100SecsValue; |
| if (fValue > 0.00001) |
| f100SecsValue = ::rtl::math::round( fValue, XML_MAXDIGITSCOUNT_TIME - 5); |
| else |
| f100SecsValue = 0.0; |
| |
| if (f100SecsValue == 1.0) |
| { |
| f100SecsValue = 0.0; |
| fSecsValue += 1.0; |
| } |
| if (fSecsValue >= 60.0) |
| { |
| fSecsValue -= 60.0; |
| fMinsValue += 1.0; |
| } |
| if (fMinsValue >= 60.0) |
| { |
| fMinsValue -= 60.0; |
| fHoursValue += 1.0; |
| } |
| |
| if (fHoursValue < 10) |
| rBuffer.append( sal_Unicode('0')); |
| rBuffer.append( sal_Int32( fHoursValue)); |
| rBuffer.append( sal_Unicode('H')); |
| if (fMinsValue < 10) |
| rBuffer.append( sal_Unicode('0')); |
| rBuffer.append( sal_Int32( fMinsValue)); |
| rBuffer.append( sal_Unicode('M')); |
| if (fSecsValue < 10) |
| rBuffer.append( sal_Unicode('0')); |
| rBuffer.append( sal_Int32( fSecsValue)); |
| if (f100SecsValue > 0.0) |
| { |
| ::rtl::OUString a100th( ::rtl::math::doubleToUString( fValue, |
| rtl_math_StringFormat_F, XML_MAXDIGITSCOUNT_TIME - 5, '.', |
| sal_True)); |
| if ( a100th.getLength() > 2 ) |
| { |
| rBuffer.append( sal_Unicode('.')); |
| rBuffer.append( a100th.copy( 2 ) ); // strip 0. |
| } |
| } |
| rBuffer.append( sal_Unicode('S')); |
| } |
| |
| /** convert ISO Time String to double; negative durations allowed */ |
| static bool lcl_convertTime( const ::rtl::OUString& rString, sal_Int32& o_rDays, sal_Int32& o_rHours, sal_Int32& o_rMins, |
| sal_Int32& o_rSecs, sal_Bool& o_rIsNegativeTime, double& o_rFractionalSecs ) |
| { |
| rtl::OUString aTrimmed = rString.trim().toAsciiUpperCase(); |
| const sal_Unicode* pStr = aTrimmed.getStr(); |
| |
| // negative time duration? |
| if ( sal_Unicode('-') == (*pStr) ) |
| { |
| o_rIsNegativeTime = sal_True; |
| pStr++; |
| } |
| |
| if ( *(pStr++) != sal_Unicode('P') ) // duration must start with "P" |
| return false; |
| |
| ::rtl::OUString sDoubleStr; |
| sal_Bool bSuccess = true; |
| sal_Bool bDone = sal_False; |
| sal_Bool bTimePart = sal_False; |
| sal_Bool bIsFraction = sal_False; |
| sal_Int32 nTemp = 0; |
| |
| while ( bSuccess && !bDone ) |
| { |
| sal_Unicode c = *(pStr++); |
| if ( !c ) // end |
| bDone = sal_True; |
| else if ( sal_Unicode('0') <= c && sal_Unicode('9') >= c ) |
| { |
| if ( nTemp >= SAL_MAX_INT32 / 10 ) |
| bSuccess = false; |
| else |
| { |
| if ( !bIsFraction ) |
| { |
| nTemp *= 10; |
| nTemp += (c - sal_Unicode('0')); |
| } |
| else |
| { |
| sDoubleStr += OUString::valueOf(c); |
| } |
| } |
| } |
| else if ( bTimePart ) |
| { |
| if ( c == sal_Unicode('H') ) |
| { |
| o_rHours = nTemp; |
| nTemp = 0; |
| } |
| else if ( c == sal_Unicode('M') ) |
| { |
| o_rMins = nTemp; |
| nTemp = 0; |
| } |
| else if ( (c == sal_Unicode(',')) || (c == sal_Unicode('.')) ) |
| { |
| o_rSecs = nTemp; |
| nTemp = 0; |
| bIsFraction = sal_True; |
| sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0.")); |
| } |
| else if ( c == sal_Unicode('S') ) |
| { |
| if ( !bIsFraction ) |
| { |
| o_rSecs = nTemp; |
| nTemp = 0; |
| sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0.0")); |
| } |
| } |
| else |
| bSuccess = false; // invalid character |
| } |
| else |
| { |
| if ( c == sal_Unicode('T') ) // "T" starts time part |
| bTimePart = sal_True; |
| else if ( c == sal_Unicode('D') ) |
| { |
| o_rDays = nTemp; |
| nTemp = 0; |
| } |
| else if ( c == sal_Unicode('Y') || c == sal_Unicode('M') ) |
| { |
| //! how many days is a year or month? |
| |
| DBG_ERROR("years or months in duration: not implemented"); |
| bSuccess = false; |
| } |
| else |
| bSuccess = false; // invalid character |
| } |
| } |
| |
| if ( bSuccess ) |
| o_rFractionalSecs = sDoubleStr.toDouble(); |
| return bSuccess; |
| } |
| |
| sal_Bool SvXMLUnitConverter::convertTime( double& fTime, |
| const ::rtl::OUString& rString) |
| { |
| sal_Int32 nDays = 0; |
| sal_Int32 nHours = 0; |
| sal_Int32 nMins = 0; |
| sal_Int32 nSecs = 0; |
| sal_Bool bIsNegativeDuration = sal_False; |
| double fFractionalSecs = 0.0; |
| if ( lcl_convertTime( rString, nDays, nHours, nMins, nSecs, bIsNegativeDuration, fFractionalSecs ) ) |
| { |
| if ( nDays ) |
| nHours += nDays * 24; // add the days to the hours part |
| double fTempTime = 0.0; |
| double fHour = nHours; |
| double fMin = nMins; |
| double fSec = nSecs; |
| double fSec100 = 0.0; |
| fTempTime = fHour / 24; |
| fTempTime += fMin / (24 * 60); |
| fTempTime += fSec / (24 * 60 * 60); |
| fTempTime += fSec100 / (24 * 60 * 60 * 60); |
| fTempTime += fFractionalSecs / (24 * 60 * 60); |
| |
| // negative duration? |
| if ( bIsNegativeDuration ) |
| { |
| fTempTime = -fTempTime; |
| } |
| |
| fTime = fTempTime; |
| return sal_True; |
| } |
| return sal_False; |
| } |
| |
| /** convert util::DateTime to ISO Time String */ |
| void SvXMLUnitConverter::convertTime( ::rtl::OUStringBuffer& rBuffer, |
| const ::com::sun::star::util::DateTime& rDateTime ) |
| { |
| double fHour = rDateTime.Hours; |
| double fMin = rDateTime.Minutes; |
| double fSec = rDateTime.Seconds; |
| double fSec100 = rDateTime.HundredthSeconds; |
| double fTempTime = fHour / 24; |
| fTempTime += fMin / (24 * 60); |
| fTempTime += fSec / (24 * 60 * 60); |
| fTempTime += fSec100 / (24 * 60 * 60 * 100); |
| convertTime( rBuffer, fTempTime ); |
| } |
| |
| /** convert ISO Time String to util::DateTime */ |
| sal_Bool SvXMLUnitConverter::convertTime( ::com::sun::star::util::DateTime& rDateTime, |
| const ::rtl::OUString& rString ) |
| { |
| sal_Int32 nDays = 0, nHours = 0, nMins = 0, nSecs = 0; |
| sal_Bool bIsNegativeDuration = sal_False; |
| double fFractionalSecs = 0.0; |
| if ( lcl_convertTime( rString, nDays, nHours, nMins, nSecs, bIsNegativeDuration, fFractionalSecs ) ) |
| { |
| rDateTime.Year = 0; |
| rDateTime.Month = 0; |
| rDateTime.Day = 0; |
| rDateTime.Hours = static_cast < sal_uInt16 > ( nHours ); |
| rDateTime.Minutes = static_cast < sal_uInt16 > ( nMins ); |
| rDateTime.Seconds = static_cast < sal_uInt16 > ( nSecs ); |
| rDateTime.HundredthSeconds = static_cast < sal_uInt16 > ( fFractionalSecs * 100.0 ); |
| |
| return sal_True; |
| } |
| return sal_False; |
| } |
| |
| /** convert double to ISO Date Time String */ |
| void SvXMLUnitConverter::convertDateTime( ::rtl::OUStringBuffer& rBuffer, |
| const double& fDateTime, |
| const com::sun::star::util::Date& aTempNullDate, |
| sal_Bool bAddTimeIf0AM ) |
| { |
| double fValue = fDateTime; |
| sal_Int32 nValue = static_cast <sal_Int32> (::rtl::math::approxFloor (fValue)); |
| Date aDate (aTempNullDate.Day, aTempNullDate.Month, aTempNullDate.Year); |
| aDate += nValue; |
| fValue -= nValue; |
| double fCount; |
| if (nValue > 0) |
| fCount = ::rtl::math::approxFloor (log10((double)nValue)) + 1; |
| else if (nValue < 0) |
| fCount = ::rtl::math::approxFloor (log10((double)(nValue * -1))) + 1; |
| else |
| fCount = 0.0; |
| sal_Int16 nCount = sal_Int16(fCount); |
| sal_Bool bHasTime(sal_False); |
| double fHoursValue = 0; |
| double fMinsValue = 0; |
| double fSecsValue = 0; |
| double f100SecsValue = 0; |
| if (fValue > 0.0) |
| { |
| bHasTime = sal_True; |
| fValue *= 24; |
| fHoursValue = ::rtl::math::approxFloor (fValue); |
| fValue -= fHoursValue; |
| fValue *= 60; |
| fMinsValue = ::rtl::math::approxFloor (fValue); |
| fValue -= fMinsValue; |
| fValue *= 60; |
| fSecsValue = ::rtl::math::approxFloor (fValue); |
| fValue -= fSecsValue; |
| if (fValue > 0.0) |
| f100SecsValue = ::rtl::math::round( fValue, XML_MAXDIGITSCOUNT_TIME - nCount); |
| else |
| f100SecsValue = 0.0; |
| |
| if (f100SecsValue == 1.0) |
| { |
| f100SecsValue = 0.0; |
| fSecsValue += 1.0; |
| } |
| if (fSecsValue >= 60.0) |
| { |
| fSecsValue -= 60.0; |
| fMinsValue += 1.0; |
| } |
| if (fMinsValue >= 60.0) |
| { |
| fMinsValue -= 60.0; |
| fHoursValue += 1.0; |
| } |
| if (fHoursValue >= 24.0) |
| { |
| fHoursValue -= 24.0; |
| aDate += 1; |
| } |
| } |
| rBuffer.append( sal_Int32( aDate.GetYear())); |
| rBuffer.append( sal_Unicode('-')); |
| sal_uInt16 nTemp = aDate.GetMonth(); |
| if (nTemp < 10) |
| rBuffer.append( sal_Unicode('0')); |
| rBuffer.append( sal_Int32( nTemp)); |
| rBuffer.append( sal_Unicode('-')); |
| nTemp = aDate.GetDay(); |
| if (nTemp < 10) |
| rBuffer.append( sal_Unicode('0')); |
| rBuffer.append( sal_Int32( nTemp)); |
| if(bHasTime || bAddTimeIf0AM) |
| { |
| rBuffer.append( sal_Unicode('T')); |
| if (fHoursValue < 10) |
| rBuffer.append( sal_Unicode('0')); |
| rBuffer.append( sal_Int32( fHoursValue)); |
| rBuffer.append( sal_Unicode(':')); |
| if (fMinsValue < 10) |
| rBuffer.append( sal_Unicode('0')); |
| rBuffer.append( sal_Int32( fMinsValue)); |
| rBuffer.append( sal_Unicode(':')); |
| if (fSecsValue < 10) |
| rBuffer.append( sal_Unicode('0')); |
| rBuffer.append( sal_Int32( fSecsValue)); |
| if (f100SecsValue > 0.0) |
| { |
| ::rtl::OUString a100th( ::rtl::math::doubleToUString( fValue, |
| rtl_math_StringFormat_F, |
| XML_MAXDIGITSCOUNT_TIME - nCount, '.', sal_True)); |
| if ( a100th.getLength() > 2 ) |
| { |
| rBuffer.append( sal_Unicode('.')); |
| rBuffer.append( a100th.copy( 2 ) ); // strip 0. |
| } |
| } |
| } |
| } |
| |
| /** convert ISO Date Time String to double */ |
| sal_Bool SvXMLUnitConverter::convertDateTime( double& fDateTime, |
| const ::rtl::OUString& rString, const com::sun::star::util::Date& aTempNullDate) |
| { |
| com::sun::star::util::DateTime aDateTime; |
| sal_Bool bSuccess = convertDateTime(aDateTime,rString); |
| |
| if (bSuccess) |
| { |
| double fTempDateTime = 0.0; |
| const Date aTmpNullDate(aTempNullDate.Day, aTempNullDate.Month, aTempNullDate.Year); |
| const Date aTempDate((sal_uInt16)aDateTime.Day, (sal_uInt16)aDateTime.Month, (sal_uInt16)aDateTime.Year); |
| const sal_Int32 nTage = aTempDate - aTmpNullDate; |
| fTempDateTime = nTage; |
| double Hour = aDateTime.Hours; |
| double Min = aDateTime.Minutes; |
| double Sec = aDateTime.Seconds; |
| double Sec100 = aDateTime.HundredthSeconds; |
| fTempDateTime += Hour / 24; |
| fTempDateTime += Min / (24 * 60); |
| fTempDateTime += Sec / (24 * 60 * 60); |
| fTempDateTime += Sec100 / (24 * 60 * 60 * 100); |
| fDateTime = fTempDateTime; |
| } |
| return bSuccess; |
| } |
| |
| /** convert util::DateTime to ISO Date String */ |
| void SvXMLUnitConverter::convertDateTime( |
| ::rtl::OUStringBuffer& rBuffer, |
| const com::sun::star::util::DateTime& rDateTime, |
| sal_Bool bAddTimeIf0AM ) |
| { |
| String aString( String::CreateFromInt32( rDateTime.Year ) ); |
| aString += '-'; |
| if( rDateTime.Month < 10 ) |
| aString += '0'; |
| aString += String::CreateFromInt32( rDateTime.Month ); |
| aString += '-'; |
| if( rDateTime.Day < 10 ) |
| aString += '0'; |
| aString += String::CreateFromInt32( rDateTime.Day ); |
| |
| if( rDateTime.Seconds != 0 || |
| rDateTime.Minutes != 0 || |
| rDateTime.Hours != 0 || |
| bAddTimeIf0AM ) |
| { |
| aString += 'T'; |
| if( rDateTime.Hours < 10 ) |
| aString += '0'; |
| aString += String::CreateFromInt32( rDateTime.Hours ); |
| aString += ':'; |
| if( rDateTime.Minutes < 10 ) |
| aString += '0'; |
| aString += String::CreateFromInt32( rDateTime.Minutes ); |
| aString += ':'; |
| if( rDateTime.Seconds < 10 ) |
| aString += '0'; |
| aString += String::CreateFromInt32( rDateTime.Seconds ); |
| if ( rDateTime.HundredthSeconds > 0) |
| { |
| aString += '.'; |
| if (rDateTime.HundredthSeconds < 10) |
| aString += '0'; |
| aString += String::CreateFromInt32( rDateTime.HundredthSeconds ); |
| } |
| } |
| |
| rBuffer.append( aString ); |
| } |
| |
| /** convert ISO Date String to util::DateTime */ |
| sal_Bool SvXMLUnitConverter::convertDateTime( com::sun::star::util::DateTime& rDateTime, |
| const ::rtl::OUString& rString ) |
| { |
| sal_Bool bSuccess = sal_True; |
| |
| rtl::OUString aDateStr, aTimeStr, sDoubleStr; |
| sal_Int32 nPos = rString.indexOf( (sal_Unicode) 'T' ); |
| sal_Int32 nPos2 = rString.indexOf( (sal_Unicode) ',' ); |
| if (nPos2 < 0) |
| nPos2 = rString.indexOf( (sal_Unicode) '.' ); |
| if ( nPos >= 0 ) |
| { |
| aDateStr = rString.copy( 0, nPos ); |
| if ( nPos2 >= 0 ) |
| { |
| aTimeStr = rString.copy( nPos + 1, nPos2 - nPos - 1 ); |
| sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0.")); |
| sDoubleStr += rString.copy( nPos2 + 1 ); |
| } |
| else |
| { |
| aTimeStr = rString.copy(nPos + 1); |
| sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0.0")); |
| } |
| } |
| else |
| aDateStr = rString; // no separator: only date part |
| |
| sal_Int32 nYear = 1899; |
| sal_Int32 nMonth = 12; |
| sal_Int32 nDay = 30; |
| sal_Int32 nHour = 0; |
| sal_Int32 nMin = 0; |
| sal_Int32 nSec = 0; |
| |
| const sal_Unicode* pStr = aDateStr.getStr(); |
| sal_Int32 nDateTokens = 1; |
| while ( *pStr ) |
| { |
| if ( *pStr == '-' ) |
| nDateTokens++; |
| pStr++; |
| } |
| if ( nDateTokens > 3 || aDateStr.getLength() == 0 ) |
| bSuccess = sal_False; |
| else |
| { |
| sal_Int32 n = 0; |
| if ( !convertNumber( nYear, aDateStr.getToken( 0, '-', n ), 0, 9999 ) ) |
| bSuccess = sal_False; |
| if ( nDateTokens >= 2 ) |
| if ( !convertNumber( nMonth, aDateStr.getToken( 0, '-', n ), 0, 12 ) ) |
| bSuccess = sal_False; |
| if ( nDateTokens >= 3 ) |
| if ( !convertNumber( nDay, aDateStr.getToken( 0, '-', n ), 0, 31 ) ) |
| bSuccess = sal_False; |
| } |
| |
| if ( aTimeStr.getLength() > 0 ) // time is optional |
| { |
| pStr = aTimeStr.getStr(); |
| sal_Int32 nTimeTokens = 1; |
| while ( *pStr ) |
| { |
| if ( *pStr == ':' ) |
| nTimeTokens++; |
| pStr++; |
| } |
| if ( nTimeTokens > 3 ) |
| bSuccess = sal_False; |
| else |
| { |
| sal_Int32 n = 0; |
| if ( !convertNumber( nHour, aTimeStr.getToken( 0, ':', n ), 0, 23 ) ) |
| bSuccess = sal_False; |
| if ( nTimeTokens >= 2 ) |
| if ( !convertNumber( nMin, aTimeStr.getToken( 0, ':', n ), 0, 59 ) ) |
| bSuccess = sal_False; |
| if ( nTimeTokens >= 3 ) |
| if ( !convertNumber( nSec, aTimeStr.getToken( 0, ':', n ), 0, 59 ) ) |
| bSuccess = sal_False; |
| } |
| } |
| |
| if (bSuccess) |
| { |
| rDateTime.Year = (sal_uInt16)nYear; |
| rDateTime.Month = (sal_uInt16)nMonth; |
| rDateTime.Day = (sal_uInt16)nDay; |
| rDateTime.Hours = (sal_uInt16)nHour; |
| rDateTime.Minutes = (sal_uInt16)nMin; |
| rDateTime.Seconds = (sal_uInt16)nSec; |
| rDateTime.HundredthSeconds = (sal_uInt16)(sDoubleStr.toDouble() * 100); |
| } |
| return bSuccess; |
| } |
| |
| /** gets the position of the first comma after npos in the string |
| rStr. Commas inside '"' pairs are not matched */ |
| sal_Int32 SvXMLUnitConverter::indexOfComma( const OUString& rStr, |
| sal_Int32 nPos ) |
| { |
| sal_Unicode cQuote = 0; |
| sal_Int32 nLen = rStr.getLength(); |
| for( ; nPos < nLen; nPos++ ) |
| { |
| sal_Unicode c = rStr[nPos]; |
| switch( c ) |
| { |
| case sal_Unicode('\''): |
| if( 0 == cQuote ) |
| cQuote = c; |
| else if( '\'' == cQuote ) |
| cQuote = 0; |
| break; |
| |
| case sal_Unicode('"'): |
| if( 0 == cQuote ) |
| cQuote = c; |
| else if( '\"' == cQuote ) |
| cQuote = 0; |
| break; |
| |
| case sal_Unicode(','): |
| if( 0 == cQuote ) |
| return nPos; |
| break; |
| } |
| } |
| |
| return -1; |
| } |
| |
| // --- |
| |
| SvXMLTokenEnumerator::SvXMLTokenEnumerator( const OUString& rString, sal_Unicode cSeperator /* = sal_Unicode(' ') */ ) |
| : maTokenString( rString ), mnNextTokenPos(0), mcSeperator( cSeperator ) |
| { |
| } |
| |
| sal_Bool SvXMLTokenEnumerator::getNextToken( OUString& rToken ) |
| { |
| if( -1 == mnNextTokenPos ) |
| return sal_False; |
| |
| int nTokenEndPos = maTokenString.indexOf( mcSeperator, mnNextTokenPos ); |
| if( nTokenEndPos != -1 ) |
| { |
| rToken = maTokenString.copy( mnNextTokenPos, |
| nTokenEndPos - mnNextTokenPos ); |
| mnNextTokenPos = nTokenEndPos + 1; |
| |
| // if the mnNextTokenPos is at the end of the string, we have |
| // to deliver an empty token |
| if( mnNextTokenPos > maTokenString.getLength() ) |
| mnNextTokenPos = -1; |
| } |
| else |
| { |
| rToken = maTokenString.copy( mnNextTokenPos ); |
| mnNextTokenPos = -1; |
| } |
| |
| return sal_True; |
| } |
| |
| // --- |
| bool lcl_getPositions(const OUString& _sValue,OUString& _rContentX,OUString& _rContentY,OUString& _rContentZ) |
| { |
| if(!_sValue.getLength() || _sValue[0] != '(') |
| return false; |
| |
| sal_Int32 nPos(1L); |
| sal_Int32 nFound = _sValue.indexOf(sal_Unicode(' '), nPos); |
| |
| if(nFound == -1 || nFound <= nPos) |
| return false; |
| |
| _rContentX = _sValue.copy(nPos, nFound - nPos); |
| |
| nPos = nFound + 1; |
| nFound = _sValue.indexOf(sal_Unicode(' '), nPos); |
| |
| if(nFound == -1 || nFound <= nPos) |
| return false; |
| |
| _rContentY = _sValue.copy(nPos, nFound - nPos); |
| |
| nPos = nFound + 1; |
| nFound = _sValue.indexOf(sal_Unicode(')'), nPos); |
| |
| if(nFound == -1 || nFound <= nPos) |
| return false; |
| |
| _rContentZ = _sValue.copy(nPos, nFound - nPos); |
| return true; |
| |
| } |
| /** convert string to ::basegfx::B3DVector */ |
| sal_Bool SvXMLUnitConverter::convertB3DVector( ::basegfx::B3DVector& rVector, const OUString& rValue ) |
| { |
| OUString aContentX,aContentY,aContentZ; |
| if ( !lcl_getPositions(rValue,aContentX,aContentY,aContentZ) ) |
| return sal_False; |
| |
| rtl_math_ConversionStatus eStatus; |
| |
| rVector.setX(::rtl::math::stringToDouble(aContentX, sal_Unicode('.'), |
| sal_Unicode(','), &eStatus, NULL)); |
| |
| if( eStatus != rtl_math_ConversionStatus_Ok ) |
| return sal_False; |
| |
| rVector.setY(::rtl::math::stringToDouble(aContentY, sal_Unicode('.'), |
| sal_Unicode(','), &eStatus, NULL)); |
| |
| if( eStatus != rtl_math_ConversionStatus_Ok ) |
| return sal_False; |
| |
| rVector.setZ(::rtl::math::stringToDouble(aContentZ, sal_Unicode('.'), |
| sal_Unicode(','), &eStatus, NULL)); |
| |
| |
| return ( eStatus == rtl_math_ConversionStatus_Ok ); |
| } |
| |
| /** convert ::basegfx::B3DVector to string */ |
| void SvXMLUnitConverter::convertB3DVector( OUStringBuffer &rBuffer, const ::basegfx::B3DVector& rVector ) |
| { |
| rBuffer.append(sal_Unicode('(')); |
| convertDouble(rBuffer, rVector.getX()); |
| rBuffer.append(sal_Unicode(' ')); |
| convertDouble(rBuffer, rVector.getY()); |
| rBuffer.append(sal_Unicode(' ')); |
| convertDouble(rBuffer, rVector.getZ()); |
| rBuffer.append(sal_Unicode(')')); |
| } |
| |
| /** convert string to Position3D */ |
| sal_Bool SvXMLUnitConverter::convertPosition3D( drawing::Position3D& rPosition, |
| const OUString& rValue ) |
| { |
| OUString aContentX,aContentY,aContentZ; |
| if ( !lcl_getPositions(rValue,aContentX,aContentY,aContentZ) ) |
| return sal_False; |
| |
| if ( !convertDouble( rPosition.PositionX, aContentX, sal_True ) ) |
| return sal_False; |
| if ( !convertDouble( rPosition.PositionY, aContentY, sal_True ) ) |
| return sal_False; |
| return convertDouble( rPosition.PositionZ, aContentZ, sal_True ); |
| } |
| |
| /** convert Position3D to string */ |
| void SvXMLUnitConverter::convertPosition3D( OUStringBuffer &rBuffer, |
| const drawing::Position3D& rPosition ) |
| { |
| rBuffer.append( sal_Unicode('(') ); |
| convertDouble( rBuffer, rPosition.PositionX, sal_True ); |
| rBuffer.append( sal_Unicode(' ') ); |
| convertDouble( rBuffer, rPosition.PositionY, sal_True ); |
| rBuffer.append( sal_Unicode(' ') ); |
| convertDouble( rBuffer, rPosition.PositionZ, sal_True ); |
| rBuffer.append( sal_Unicode(')') ); |
| } |
| |
| const |
| sal_Char aBase64EncodeTable[] = |
| { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', |
| 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', |
| 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', |
| 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', |
| '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; |
| |
| const |
| sal_uInt8 aBase64DecodeTable[] = |
| { 62,255,255,255, 63, // 43-47 |
| // + / |
| |
| 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255, // 48-63 |
| // 0 1 2 3 4 5 6 7 8 9 = |
| |
| 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79 |
| // A B C D E F G H I J K L M N O |
| |
| 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255, // 80-95 |
| // P Q R S T U V W X Y Z |
| |
| 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111 |
| // a b c d e f g h i j k l m n o |
| |
| 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 }; // 112-123 |
| // p q r s t u v w x y z |
| |
| |
| |
| void ThreeByteToFourByte (const sal_Int8* pBuffer, const sal_Int32 nStart, const sal_Int32 nFullLen, rtl::OUStringBuffer& sBuffer) |
| { |
| sal_Int32 nLen(nFullLen - nStart); |
| if (nLen > 3) |
| nLen = 3; |
| if (nLen == 0) |
| { |
| sBuffer.setLength(0); |
| return; |
| } |
| |
| sal_Int32 nBinaer; |
| switch (nLen) |
| { |
| case 1: |
| { |
| nBinaer = ((sal_uInt8)pBuffer[nStart + 0]) << 16; |
| } |
| break; |
| case 2: |
| { |
| nBinaer = (((sal_uInt8)pBuffer[nStart + 0]) << 16) + |
| (((sal_uInt8)pBuffer[nStart + 1]) << 8); |
| } |
| break; |
| default: |
| { |
| nBinaer = (((sal_uInt8)pBuffer[nStart + 0]) << 16) + |
| (((sal_uInt8)pBuffer[nStart + 1]) << 8) + |
| ((sal_uInt8)pBuffer[nStart + 2]); |
| } |
| break; |
| } |
| |
| sBuffer.appendAscii("===="); |
| |
| sal_uInt8 nIndex (static_cast<sal_uInt8>((nBinaer & 0xFC0000) >> 18)); |
| sBuffer.setCharAt(0, aBase64EncodeTable [nIndex]); |
| |
| nIndex = static_cast<sal_uInt8>((nBinaer & 0x3F000) >> 12); |
| sBuffer.setCharAt(1, aBase64EncodeTable [nIndex]); |
| if (nLen == 1) |
| return; |
| |
| nIndex = static_cast<sal_uInt8>((nBinaer & 0xFC0) >> 6); |
| sBuffer.setCharAt(2, aBase64EncodeTable [nIndex]); |
| if (nLen == 2) |
| return; |
| |
| nIndex = static_cast<sal_uInt8>((nBinaer & 0x3F)); |
| sBuffer.setCharAt(3, aBase64EncodeTable [nIndex]); |
| } |
| |
| void SvXMLUnitConverter::encodeBase64(rtl::OUStringBuffer& aStrBuffer, const uno::Sequence<sal_Int8>& aPass) |
| { |
| sal_Int32 i(0); |
| sal_Int32 nBufferLength(aPass.getLength()); |
| const sal_Int8* pBuffer = aPass.getConstArray(); |
| while (i < nBufferLength) |
| { |
| rtl::OUStringBuffer sBuffer; |
| ThreeByteToFourByte (pBuffer, i, nBufferLength, sBuffer); |
| aStrBuffer.append(sBuffer); |
| i += 3; |
| } |
| } |
| |
| void SvXMLUnitConverter::decodeBase64(uno::Sequence<sal_Int8>& aBuffer, const rtl::OUString& sBuffer) |
| { |
| sal_Int32 nCharsDecoded = decodeBase64SomeChars( aBuffer, sBuffer ); |
| OSL_ENSURE( nCharsDecoded == sBuffer.getLength(), |
| "some bytes left in base64 decoding!" ); |
| (void)nCharsDecoded; |
| } |
| |
| sal_Int32 SvXMLUnitConverter::decodeBase64SomeChars( |
| uno::Sequence<sal_Int8>& rOutBuffer, |
| const rtl::OUString& rInBuffer) |
| { |
| sal_Int32 nInBufferLen = rInBuffer.getLength(); |
| sal_Int32 nMinOutBufferLen = (nInBufferLen / 4) * 3; |
| if( rOutBuffer.getLength() < nMinOutBufferLen ) |
| rOutBuffer.realloc( nMinOutBufferLen ); |
| |
| const sal_Unicode *pInBuffer = rInBuffer.getStr(); |
| sal_Int8 *pOutBuffer = rOutBuffer.getArray(); |
| sal_Int8 *pOutBufferStart = pOutBuffer; |
| sal_Int32 nCharsDecoded = 0; |
| |
| sal_uInt8 aDecodeBuffer[4]; |
| sal_Int32 nBytesToDecode = 0; |
| sal_Int32 nBytesGotFromDecoding = 3; |
| sal_Int32 nInBufferPos= 0; |
| while( nInBufferPos < nInBufferLen ) |
| { |
| sal_Unicode cChar = *pInBuffer; |
| if( cChar >= '+' && cChar <= 'z' ) |
| { |
| sal_uInt8 nByte = aBase64DecodeTable[cChar-'+']; |
| if( nByte != 255 ) |
| { |
| // We have found a valid character! |
| aDecodeBuffer[nBytesToDecode++] = nByte; |
| |
| // One '=' character at the end means 2 out bytes |
| // Two '=' characters at the end mean 1 out bytes |
| if( '=' == cChar && nBytesToDecode > 2 ) |
| nBytesGotFromDecoding--; |
| if( 4 == nBytesToDecode ) |
| { |
| // Four characters found, so we may convert now! |
| sal_uInt32 nOut = (aDecodeBuffer[0] << 18) + |
| (aDecodeBuffer[1] << 12) + |
| (aDecodeBuffer[2] << 6) + |
| aDecodeBuffer[3]; |
| |
| *pOutBuffer++ = (sal_Int8)((nOut & 0xff0000) >> 16); |
| if( nBytesGotFromDecoding > 1 ) |
| *pOutBuffer++ = (sal_Int8)((nOut & 0xff00) >> 8); |
| if( nBytesGotFromDecoding > 2 ) |
| *pOutBuffer++ = (sal_Int8)(nOut & 0xff); |
| nCharsDecoded = nInBufferPos + 1; |
| nBytesToDecode = 0; |
| nBytesGotFromDecoding = 3; |
| } |
| } |
| else |
| { |
| nCharsDecoded++; |
| } |
| } |
| else |
| { |
| nCharsDecoded++; |
| } |
| |
| nInBufferPos++; |
| pInBuffer++; |
| } |
| if( (pOutBuffer - pOutBufferStart) != rOutBuffer.getLength() ) |
| rOutBuffer.realloc( pOutBuffer - pOutBufferStart ); |
| |
| return nCharsDecoded; |
| } |
| |
| sal_Bool SvXMLUnitConverter::convertNumFormat( |
| sal_Int16& rType, |
| const OUString& rNumFmt, |
| const OUString& rNumLetterSync, |
| sal_Bool bNumberNone ) const |
| { |
| sal_Bool bRet = sal_True; |
| sal_Bool bExt = sal_False; |
| |
| sal_Int32 nLen = rNumFmt.getLength(); |
| if( 0 == nLen ) |
| { |
| if( bNumberNone ) |
| rType = NumberingType::NUMBER_NONE; |
| else |
| bRet = sal_False; |
| } |
| else if( 1 == nLen ) |
| { |
| switch( rNumFmt[0] ) |
| { |
| case sal_Unicode('1'): rType = NumberingType::ARABIC; break; |
| case sal_Unicode('a'): rType = NumberingType::CHARS_LOWER_LETTER; break; |
| case sal_Unicode('A'): rType = NumberingType::CHARS_UPPER_LETTER; break; |
| case sal_Unicode('i'): rType = NumberingType::ROMAN_LOWER; break; |
| case sal_Unicode('I'): rType = NumberingType::ROMAN_UPPER; break; |
| default: bExt = sal_True; break; |
| } |
| if( !bExt && IsXMLToken( rNumLetterSync, XML_TRUE ) ) |
| { |
| switch( rType ) |
| { |
| case NumberingType::CHARS_LOWER_LETTER: |
| rType = NumberingType::CHARS_LOWER_LETTER_N; |
| break; |
| case NumberingType::CHARS_UPPER_LETTER: |
| rType = NumberingType::CHARS_UPPER_LETTER_N; |
| break; |
| } |
| } |
| } |
| else |
| { |
| bExt = sal_True; |
| } |
| if( bExt ) |
| { |
| Reference < XNumberingTypeInfo > xInfo = getNumTypeInfo(); |
| if( xInfo.is() && xInfo->hasNumberingType( rNumFmt ) ) |
| { |
| rType = xInfo->getNumberingType( rNumFmt ); |
| } |
| else |
| { |
| rType = NumberingType::ARABIC; |
| } |
| } |
| |
| return bRet; |
| } |
| |
| void SvXMLUnitConverter::convertNumFormat( OUStringBuffer& rBuffer, |
| sal_Int16 nType ) const |
| { |
| enum XMLTokenEnum eFormat = XML_TOKEN_INVALID; |
| sal_Bool bExt = sal_False; |
| switch( nType ) |
| { |
| case NumberingType::CHARS_UPPER_LETTER: eFormat = XML_A_UPCASE; break; |
| case NumberingType::CHARS_LOWER_LETTER: eFormat = XML_A; break; |
| case NumberingType::ROMAN_UPPER: eFormat = XML_I_UPCASE; break; |
| case NumberingType::ROMAN_LOWER: eFormat = XML_I; break; |
| case NumberingType::ARABIC: eFormat = XML_1; break; |
| case NumberingType::CHARS_UPPER_LETTER_N: eFormat = XML_A_UPCASE; break; |
| case NumberingType::CHARS_LOWER_LETTER_N: eFormat = XML_A; break; |
| case NumberingType::NUMBER_NONE: eFormat = XML__EMPTY; break; |
| |
| case NumberingType::CHAR_SPECIAL: |
| case NumberingType::PAGE_DESCRIPTOR: |
| case NumberingType::BITMAP: |
| DBG_ASSERT( eFormat != XML_TOKEN_INVALID, "invalid number format" ); |
| break; |
| default: |
| bExt = sal_True; |
| break; |
| } |
| |
| if( eFormat != XML_TOKEN_INVALID ) |
| { |
| rBuffer.append( GetXMLToken(eFormat) ); |
| } |
| else |
| { |
| Reference < XNumberingTypeInfo > xInfo = getNumTypeInfo(); |
| if( xInfo.is() ) |
| rBuffer.append( xInfo->getNumberingIdentifier( nType ) ); |
| } |
| } |
| |
| void SvXMLUnitConverter::convertNumLetterSync( OUStringBuffer& rBuffer, |
| sal_Int16 nType ) const |
| { |
| enum XMLTokenEnum eSync = XML_TOKEN_INVALID; |
| switch( nType ) |
| { |
| case NumberingType::CHARS_UPPER_LETTER: |
| case NumberingType::CHARS_LOWER_LETTER: |
| case NumberingType::ROMAN_UPPER: |
| case NumberingType::ROMAN_LOWER: |
| case NumberingType::ARABIC: |
| case NumberingType::NUMBER_NONE: |
| // default |
| // eSync = XML_FALSE; |
| break; |
| |
| case NumberingType::CHARS_UPPER_LETTER_N: |
| case NumberingType::CHARS_LOWER_LETTER_N: |
| eSync = XML_TRUE; |
| break; |
| |
| case NumberingType::CHAR_SPECIAL: |
| case NumberingType::PAGE_DESCRIPTOR: |
| case NumberingType::BITMAP: |
| DBG_ASSERT( eSync != XML_TOKEN_INVALID, "invalid number format" ); |
| break; |
| } |
| if( eSync != XML_TOKEN_INVALID ) |
| rBuffer.append( GetXMLToken(eSync) ); |
| } |
| |
| void SvXMLUnitConverter::convertPropertySet(uno::Sequence<beans::PropertyValue>& rProps, |
| const uno::Reference<beans::XPropertySet>& aProperties) |
| { |
| uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = aProperties->getPropertySetInfo(); |
| if (xPropertySetInfo.is()) |
| { |
| uno::Sequence< beans::Property > aProps = xPropertySetInfo->getProperties(); |
| const sal_Int32 nCount(aProps.getLength()); |
| if (nCount) |
| { |
| rProps.realloc(nCount); |
| beans::PropertyValue* pProps = rProps.getArray(); |
| for (sal_Int32 i = 0; i < nCount; i++, ++pProps) |
| { |
| pProps->Name = aProps[i].Name; |
| pProps->Value = aProperties->getPropertyValue(aProps[i].Name); |
| } |
| } |
| } |
| } |
| |
| void SvXMLUnitConverter::convertPropertySet(uno::Reference<beans::XPropertySet>& rProperties, |
| const uno::Sequence<beans::PropertyValue>& aProps) |
| { |
| sal_Int32 nCount(aProps.getLength()); |
| if (nCount) |
| { |
| uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = rProperties->getPropertySetInfo(); |
| if (xPropertySetInfo.is()) |
| { |
| for (sal_Int32 i = 0; i < nCount; i++) |
| { |
| if (xPropertySetInfo->hasPropertyByName(aProps[i].Name)) |
| rProperties->setPropertyValue(aProps[i].Name, aProps[i].Value); |
| } |
| } |
| } |
| } |
| |
| void SvXMLUnitConverter::clearUndefinedChars(rtl::OUString& rTarget, const rtl::OUString& rSource) |
| { |
| sal_uInt32 nLength(rSource.getLength()); |
| rtl::OUStringBuffer sBuffer(nLength); |
| for (sal_uInt32 i = 0; i < nLength; i++) |
| { |
| sal_Unicode cChar = rSource[i]; |
| if (!(cChar < 0x0020) || |
| (cChar == 0x0009) || // TAB |
| (cChar == 0x000A) || // LF |
| (cChar == 0x000D)) // legal character |
| sBuffer.append(cChar); |
| } |
| rTarget = sBuffer.makeStringAndClear(); |
| } |
| |
| OUString SvXMLUnitConverter::encodeStyleName( |
| const OUString& rName, |
| sal_Bool *pEncoded ) const |
| { |
| if( pEncoded ) |
| *pEncoded = sal_False; |
| |
| sal_Int32 nLen = rName.getLength(); |
| OUStringBuffer aBuffer( nLen ); |
| |
| for( sal_Int32 i = 0; i < nLen; i++ ) |
| { |
| sal_Unicode c = rName[i]; |
| sal_Bool bValidChar = sal_False; |
| if( c < 0x00ffU ) |
| { |
| bValidChar = |
| (c >= 0x0041 && c <= 0x005a) || |
| (c >= 0x0061 && c <= 0x007a) || |
| (c >= 0x00c0 && c <= 0x00d6) || |
| (c >= 0x00d8 && c <= 0x00f6) || |
| (c >= 0x00f8 && c <= 0x00ff) || |
| ( i > 0 && ( (c >= 0x0030 && c <= 0x0039) || |
| c == 0x00b7 || c == '-' || c == '.') ); |
| } |
| else |
| { |
| if( (c >= 0xf900U && c <= 0xfffeU) || |
| (c >= 0x20ddU && c <= 0x20e0U)) |
| { |
| bValidChar = sal_False; |
| } |
| else if( (c >= 0x02bbU && c <= 0x02c1U) || c == 0x0559 || |
| c == 0x06e5 || c == 0x06e6 ) |
| { |
| bValidChar = sal_True; |
| } |
| else if( c == 0x0387 ) |
| { |
| bValidChar = i > 0; |
| } |
| else |
| { |
| if( !xCharClass.is() ) |
| { |
| if( mxServiceFactory.is() ) |
| { |
| try |
| { |
| const_cast < SvXMLUnitConverter * >(this) |
| ->xCharClass = |
| Reference < XCharacterClassification >( |
| mxServiceFactory->createInstance( |
| OUString::createFromAscii( |
| "com.sun.star.i18n.CharacterClassification_Unicode") ), |
| UNO_QUERY ); |
| |
| OSL_ENSURE( xCharClass.is(), |
| "can't instantiate character clossification component" ); |
| } |
| catch( com::sun::star::uno::Exception& ) |
| { |
| } |
| } |
| } |
| if( xCharClass.is() ) |
| { |
| sal_Int16 nType = xCharClass->getType( rName, i ); |
| |
| switch( nType ) |
| { |
| case UnicodeType::UPPERCASE_LETTER: // Lu |
| case UnicodeType::LOWERCASE_LETTER: // Ll |
| case UnicodeType::TITLECASE_LETTER: // Lt |
| case UnicodeType::OTHER_LETTER: // Lo |
| case UnicodeType::LETTER_NUMBER: // Nl |
| bValidChar = sal_True; |
| break; |
| case UnicodeType::NON_SPACING_MARK: // Ms |
| case UnicodeType::ENCLOSING_MARK: // Me |
| case UnicodeType::COMBINING_SPACING_MARK: //Mc |
| case UnicodeType::MODIFIER_LETTER: // Lm |
| case UnicodeType::DECIMAL_DIGIT_NUMBER: // Nd |
| bValidChar = i > 0; |
| break; |
| } |
| } |
| } |
| } |
| if( bValidChar ) |
| { |
| aBuffer.append( c ); |
| } |
| else |
| { |
| aBuffer.append( static_cast< sal_Unicode >( '_' ) ); |
| if( c > 0x0fff ) |
| aBuffer.append( static_cast< sal_Unicode >( |
| aHexTab[ (c >> 12) & 0x0f ] ) ); |
| if( c > 0x00ff ) |
| aBuffer.append( static_cast< sal_Unicode >( |
| aHexTab[ (c >> 8) & 0x0f ] ) ); |
| if( c > 0x000f ) |
| aBuffer.append( static_cast< sal_Unicode >( |
| aHexTab[ (c >> 4) & 0x0f ] ) ); |
| aBuffer.append( static_cast< sal_Unicode >( |
| aHexTab[ c & 0x0f ] ) ); |
| aBuffer.append( static_cast< sal_Unicode >( '_' ) ); |
| if( pEncoded ) |
| *pEncoded = sal_True; |
| } |
| } |
| |
| // check for length |
| if( aBuffer.getLength() > ((1<<15)-1) ) |
| { |
| aBuffer = rName; |
| if( pEncoded ) |
| *pEncoded = sal_False; |
| } |
| |
| |
| return aBuffer.makeStringAndClear(); |
| } |
| |
| // static |
| rtl::OUString SvXMLUnitConverter::convertTimeDuration( const Time& rTime, sal_Int32 nSecondsFraction ) |
| { |
| // return ISO time period string |
| rtl::OUStringBuffer sTmp; |
| sTmp.append( sal_Unicode('P') ); // "period" |
| |
| sal_uInt16 nHours = rTime.GetHour(); |
| sal_Bool bHasHours = ( nHours > 0 ); |
| if ( nHours >= 24 ) |
| { |
| // add days |
| |
| sal_uInt16 nDays = nHours / 24; |
| sTmp.append( (sal_Int32) nDays ); |
| sTmp.append( sal_Unicode('D') ); // "days" |
| |
| nHours -= nDays * 24; |
| } |
| sTmp.append( sal_Unicode('T') ); // "time" |
| |
| if ( bHasHours ) |
| { |
| sTmp.append( (sal_Int32) nHours ); |
| sTmp.append( sal_Unicode('H') ); // "hours" |
| } |
| sal_uInt16 nMinutes = rTime.GetMin(); |
| if ( bHasHours || nMinutes > 0 ) |
| { |
| sTmp.append( (sal_Int32) nMinutes ); |
| sTmp.append( sal_Unicode('M') ); // "minutes" |
| } |
| sal_uInt16 nSeconds = rTime.GetSec(); |
| sTmp.append( (sal_Int32) nSeconds ); |
| if ( nSecondsFraction ) |
| { |
| sTmp.append( sal_Unicode( '.' ) ); |
| ::rtl::OUStringBuffer aFractional; |
| convertNumber( aFractional, nSecondsFraction ); |
| sTmp.append( aFractional.getStr() ); |
| } |
| sTmp.append( sal_Unicode('S') ); // "seconds" |
| |
| return sTmp.makeStringAndClear(); |
| } |
| |
| // static |
| bool SvXMLUnitConverter::convertTimeDuration( const rtl::OUString& rString, Time& rTime, sal_Int32* pSecondsFraction ) |
| { |
| rtl::OUString aTrimmed = rString.trim().toAsciiUpperCase(); |
| const sal_Unicode* pStr = aTrimmed.getStr(); |
| |
| if ( *(pStr++) != sal_Unicode('P') ) // duration must start with "P" |
| return false; |
| |
| bool bSuccess = true; |
| sal_Bool bDone = sal_False; |
| sal_Bool bTimePart = sal_False; |
| sal_Bool bFractional = sal_False; |
| sal_Int32 nDays = 0; |
| sal_Int32 nHours = 0; |
| sal_Int32 nMins = 0; |
| sal_Int32 nSecs = 0; |
| sal_Int32 nTemp = 0; |
| sal_Int32 nSecondsFraction = 0; |
| |
| while ( bSuccess && !bDone ) |
| { |
| sal_Unicode c = *(pStr++); |
| if ( !c ) // end |
| bDone = sal_True; |
| else if ( sal_Unicode('0') <= c && sal_Unicode('9') >= c ) |
| { |
| if ( bFractional ) |
| { |
| if ( nSecondsFraction >= SAL_MAX_INT32 / 10 ) |
| bSuccess = false; |
| else |
| { |
| nSecondsFraction *= 10; |
| nSecondsFraction += (c - sal_Unicode('0')); |
| } |
| } |
| else |
| { |
| if ( nTemp >= SAL_MAX_INT32 / 10 ) |
| bSuccess = false; |
| else |
| { |
| nTemp *= 10; |
| nTemp += (c - sal_Unicode('0')); |
| } |
| } |
| } |
| else if ( bTimePart ) |
| { |
| if ( c == sal_Unicode('H') ) |
| { |
| nHours = nTemp; |
| nTemp = 0; |
| } |
| else if ( c == sal_Unicode('M') ) |
| { |
| nMins = nTemp; |
| nTemp = 0; |
| } |
| else if ( c == sal_Unicode('S') ) |
| { |
| nSecs = nTemp; |
| nTemp = 0; |
| } |
| else if ( c == '.' ) |
| { |
| bFractional = sal_True; |
| } |
| else |
| bSuccess = false; // invalid characted |
| } |
| else |
| { |
| if ( c == sal_Unicode('T') ) // "T" starts time part |
| bTimePart = sal_True; |
| else if ( c == sal_Unicode('D') ) |
| { |
| nDays = nTemp; |
| nTemp = 0; |
| } |
| else if ( c == sal_Unicode('Y') || c == sal_Unicode('M') ) |
| { |
| //! how many days is a year or month? |
| |
| DBG_ERROR("years or months in duration: not implemented"); |
| bSuccess = false; |
| } |
| else |
| bSuccess = false; // invalid characted |
| } |
| } |
| |
| if ( bSuccess ) |
| { |
| if ( nDays ) |
| nHours += nDays * 24; // add the days to the hours part |
| rTime = Time( nHours, nMins, nSecs ); |
| if ( pSecondsFraction ) |
| *pSecondsFraction = nSecondsFraction % 1000; |
| } |
| return bSuccess; |
| } |
| |
| sal_Bool SvXMLUnitConverter::convertAny( ::rtl::OUStringBuffer& sValue, |
| ::rtl::OUStringBuffer& sType , |
| const com::sun::star::uno::Any& aValue) |
| { |
| sal_Bool bConverted = sal_False; |
| |
| sValue.setLength(0); |
| sType.setLength (0); |
| |
| switch(aValue.getValueTypeClass()) |
| { |
| case com::sun::star::uno::TypeClass_BYTE : |
| case com::sun::star::uno::TypeClass_SHORT : |
| case com::sun::star::uno::TypeClass_UNSIGNED_SHORT : |
| case com::sun::star::uno::TypeClass_LONG : |
| case com::sun::star::uno::TypeClass_UNSIGNED_LONG : |
| { |
| sal_Int32 nTempValue = 0; |
| if (aValue >>= nTempValue) |
| { |
| sType.appendAscii("integer"); |
| bConverted = sal_True; |
| SvXMLUnitConverter::convertNumber(sValue, nTempValue); |
| } |
| } |
| break; |
| |
| case com::sun::star::uno::TypeClass_BOOLEAN : |
| { |
| sal_Bool bTempValue = sal_False; |
| if (aValue >>= bTempValue) |
| { |
| sType.appendAscii("boolean"); |
| bConverted = sal_True; |
| SvXMLUnitConverter::convertBool(sValue, bTempValue); |
| } |
| } |
| break; |
| |
| case com::sun::star::uno::TypeClass_FLOAT : |
| case com::sun::star::uno::TypeClass_DOUBLE : |
| { |
| double fTempValue = 0.0; |
| if (aValue >>= fTempValue) |
| { |
| sType.appendAscii("float"); |
| bConverted = sal_True; |
| SvXMLUnitConverter::convertDouble(sValue, fTempValue); |
| } |
| } |
| break; |
| |
| case com::sun::star::uno::TypeClass_STRING : |
| { |
| ::rtl::OUString sTempValue; |
| if (aValue >>= sTempValue) |
| { |
| sType.appendAscii("string"); |
| bConverted = sal_True; |
| sValue.append(sTempValue); |
| } |
| } |
| break; |
| |
| case com::sun::star::uno::TypeClass_STRUCT : |
| { |
| com::sun::star::util::Date aDate ; |
| com::sun::star::util::Time aTime ; |
| com::sun::star::util::DateTime aDateTime; |
| |
| if (aValue >>= aDate) |
| { |
| sType.appendAscii("date"); |
| bConverted = sal_True; |
| com::sun::star::util::DateTime aTempValue; |
| aTempValue.Day = aDate.Day; |
| aTempValue.Month = aDate.Month; |
| aTempValue.Year = aDate.Year; |
| aTempValue.HundredthSeconds = 0; |
| aTempValue.Seconds = 0; |
| aTempValue.Minutes = 0; |
| aTempValue.Hours = 0; |
| SvXMLUnitConverter::convertDateTime(sValue, aTempValue); |
| } |
| else |
| if (aValue >>= aTime) |
| { |
| sType.appendAscii("time"); |
| bConverted = sal_True; |
| com::sun::star::util::DateTime aTempValue; |
| aTempValue.Day = 0; |
| aTempValue.Month = 0; |
| aTempValue.Year = 0; |
| aTempValue.HundredthSeconds = aTime.HundredthSeconds; |
| aTempValue.Seconds = aTime.Seconds; |
| aTempValue.Minutes = aTime.Minutes; |
| aTempValue.Hours = aTime.Hours; |
| SvXMLUnitConverter::convertTime(sValue, aTempValue); |
| } |
| else |
| if (aValue >>= aDateTime) |
| { |
| sType.appendAscii("date"); |
| bConverted = sal_True; |
| SvXMLUnitConverter::convertDateTime(sValue, aDateTime); |
| } |
| } |
| break; |
| default: |
| break; |
| } |
| |
| return bConverted; |
| } |
| |
| sal_Bool SvXMLUnitConverter::convertAny( com::sun::star::uno::Any& aValue, |
| const ::rtl::OUString& sType , |
| const ::rtl::OUString& sValue) |
| { |
| sal_Bool bConverted = sal_False; |
| |
| if (sType.equalsAscii("boolean")) |
| { |
| sal_Bool bTempValue = sal_False; |
| SvXMLUnitConverter::convertBool(bTempValue, sValue); |
| aValue <<= bTempValue; |
| bConverted = sal_True; |
| } |
| else |
| if (sType.equalsAscii("integer")) |
| { |
| sal_Int32 nTempValue = 0; |
| SvXMLUnitConverter::convertNumber(nTempValue, sValue); |
| aValue <<= nTempValue; |
| bConverted = sal_True; |
| } |
| else |
| if (sType.equalsAscii("float")) |
| { |
| double fTempValue = 0.0; |
| SvXMLUnitConverter::convertDouble(fTempValue, sValue); |
| aValue <<= fTempValue; |
| bConverted = sal_True; |
| } |
| else |
| if (sType.equalsAscii("string")) |
| { |
| aValue <<= sValue; |
| bConverted = sal_True; |
| } |
| else |
| if (sType.equalsAscii("date")) |
| { |
| com::sun::star::util::DateTime aTempValue; |
| SvXMLUnitConverter::convertDateTime(aTempValue, sValue); |
| aValue <<= aTempValue; |
| bConverted = sal_True; |
| } |
| else |
| if (sType.equalsAscii("time")) |
| { |
| com::sun::star::util::DateTime aTempValue; |
| com::sun::star::util::Time aConvValue; |
| SvXMLUnitConverter::convertTime(aTempValue, sValue); |
| aConvValue.HundredthSeconds = aTempValue.HundredthSeconds; |
| aConvValue.Seconds = aTempValue.Seconds; |
| aConvValue.Minutes = aTempValue.Minutes; |
| aConvValue.Hours = aTempValue.Hours; |
| aValue <<= aConvValue; |
| bConverted = sal_True; |
| } |
| |
| return bConverted; |
| } |