diff options
author | Oliver Bolte <obo@openoffice.org> | 2008-01-10 11:52:53 +0000 |
---|---|---|
committer | Oliver Bolte <obo@openoffice.org> | 2008-01-10 11:52:53 +0000 |
commit | 0ffd29c77a849d6b44b31ac1d022d5a10a98fcb3 (patch) | |
tree | e7d698bee5847a60ede8d8d5e37a75110b93b653 /sax | |
parent | f290458774d7680f3324604dc8d2fa03e165e229 (diff) |
INTEGRATION: CWS xmlfilter02 (1.1.2); FILE ADDED
2007/05/10 15:50:14 hub 1.1.2.8: follow drr suggestion and use SAL_INT32_MAX instead of std::numeric_limits<>
2007/05/10 12:12:37 hub 1.1.2.7: Reviewed by: sj
Fix a 64-bits bugs: LONG_MIN and LONG_MAX were out of range for sal_Int32.
2007/03/20 14:51:06 dr 1.1.2.6: comment out tools dependent code
2007/03/20 14:01:19 dr 1.1.2.5: remove tools/debug
2007/01/24 16:03:55 cl 1.1.2.4: fixed unix compiler warnings
2007/01/24 15:45:34 cl 1.1.2.3: fixed compiler warning
2007/01/24 14:31:40 cl 1.1.2.2: added new fast parser, removed prototyp saxparser
2006/02/14 18:38:06 cl 1.1.2.1: added initial libxml2 wrapper
Diffstat (limited to 'sax')
-rw-r--r-- | sax/source/tools/converter.cxx | 1603 |
1 files changed, 1603 insertions, 0 deletions
diff --git a/sax/source/tools/converter.cxx b/sax/source/tools/converter.cxx new file mode 100644 index 000000000000..02ac59ecea22 --- /dev/null +++ b/sax/source/tools/converter.cxx @@ -0,0 +1,1603 @@ +/************************************************************************* + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: converter.cxx,v $ + * + * $Revision: 1.2 $ + * + * last change: $Author: obo $ $Date: 2008-01-10 12:52:53 $ + * + * The Contents of this file are made available subject to + * the terms of GNU Lesser General Public License Version 2.1. + * + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2005 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + ************************************************************************/ + + +#ifndef _COM_SUN_STAR_I18N_UNICODETYPE_HPP_ +#include <com/sun/star/i18n/UnicodeType.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_DATETIME_HPP_ +#include <com/sun/star/util/DateTime.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_DATE_HPP_ +#include <com/sun/star/util/Date.hpp> +#endif +#ifndef _COM_SUN_STAR_UTIL_TIME_HPP_ +#include <com/sun/star/util/Time.hpp> +#endif +#ifndef _COM_SUN_STAR_UNO_SEQUENCE_HXX_ +#include <com/sun/star/uno/Sequence.hxx> +#endif + +#ifndef _RTL_USTRBUF_HXX_ +#include <rtl/ustrbuf.hxx> +#endif +#ifndef INCLUDED_RTL_MATH_HXX +#include <rtl/math.hxx> +#endif + +#ifndef _SAX_CONVERTER_HXX +#include "sax/tools/converter.hxx" +#endif + +using namespace rtl; +using namespace com::sun::star; +using namespace com::sun::star::uno; +using namespace com::sun::star::util; +//using namespace com::sun::star::text; +//using namespace com::sun::star::style; +using namespace ::com::sun::star::i18n; + +namespace sax { + +static const sal_Char* gpsMM = "mm"; +static const sal_Char* gpsCM = "cm"; +static const sal_Char* gpsPT = "pt"; +static const sal_Char* gpsINCH = "in"; +static const sal_Char* gpsPC = "pc"; + +const sal_Int8 XML_MAXDIGITSCOUNT_TIME = 11; +const sal_Int8 XML_MAXDIGITSCOUNT_DATETIME = 6; +#define XML_NULLDATE "NullDate" + +/** convert string to measure using optional min and max values*/ +bool Converter::convertMeasure( sal_Int32& rValue, + const OUString& rString, + sal_Int16 nTargetUnit /* = MeasureUnit::MM_100TH */, + sal_Int32 nMin /* = SAL_MIN_INT32 */, + sal_Int32 nMax /* = SAL_MAX_INT32 */ ) +{ + bool bNeg = false; + double nVal = 0; + + sal_Int32 nPos = 0L; + sal_Int32 nLen = rString.getLength(); + + // skip white space + while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) ) + nPos++; + + if( nPos < nLen && sal_Unicode('-') == rString[nPos] ) + { + bNeg = 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( MeasureUnit::PERCENT == nTargetUnit ) + { + if( sal_Unicode('%') != rString[nPos] ) + return false; + } + else if( MeasureUnit::PIXEL == nTargetUnit ) + { + 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 false; + } + else + { + OSL_ENSURE( MeasureUnit::TWIP == nTargetUnit || MeasureUnit::POINT == nTargetUnit || + MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit, "unit is not supported"); + const sal_Char *aCmpsL[2] = { 0, 0 }; + const sal_Char *aCmpsU[2] = { 0, 0 }; + double aScales[2] = { 1., 1. }; + + if( MeasureUnit::TWIP == nTargetUnit ) + { + 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('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 + break; + } + } + else if( MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit ) + { + double nScaleFactor = (MeasureUnit::MM_100TH == nTargetUnit) ? 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('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 + break; + } + } + else if( MeasureUnit::POINT == nTargetUnit ) + { + if( rString[nPos] == 'p' || rString[nPos] == 'P' ) + { + aCmpsL[0] = "pt"; + aCmpsU[0] = "PT"; + aScales[0] = 1; + } + } + + if( aCmpsL[0] == NULL ) + return 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 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 true; +} + +/** convert measure in given unit to string with given unit */ +void Converter::convertMeasure( OUStringBuffer& rBuffer, + sal_Int32 nMeasure, + sal_Int16 nSourceUnit /* = MeasureUnit::MM_100TH */, + sal_Int16 nTargetUnit /* = MeasureUnit::INCH */ ) +{ + OSL_ENSURE( false, "Converter::convertMeasure - not implemented, tools/BigInt needs replacement" ); + (void)rBuffer; + (void)nMeasure; + (void)nSourceUnit; + (void)nTargetUnit; +#if 0 + if( nSourceUnit == MeasureUnit::PERCENT ) + { + OSL_ENSURE( nTargetUnit == MeasureUnit::PERCENT, + "MeasureUnit::PERCENT only maps to MeasureUnit::PERCENT!" ); + + rBuffer.append( nMeasure ); + rBuffer.append( sal_Unicode('%' ) ); + } + else + { + // the sign is processed seperatly + if( nMeasure < 0 ) + { + nMeasure = -nMeasure; + rBuffer.append( sal_Unicode('-') ); + } + + // The new length is (nVal * nMul)/(nDiv*nFac*10) + long nMul = 1000; + long nDiv = 1; + long nFac = 100; + const sal_Char* psUnit = 0; + switch( nSourceUnit ) + { + case MeasureUnit::TWIP: + switch( nTargetUnit ) + { + case MeasureUnit::MM_100TH: + case MeasureUnit::MM_10TH: + OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,"output unit not supported for twip values" ); + case MeasureUnit::MM: + // 0.01mm = 0.57twip (exactly) + nMul = 25400; // 25.4 * 1000 + nDiv = 1440; // 72 * 20; + nFac = 100; + psUnit = gpsMM; + break; + + case MeasureUnit::CM: + // 0.001cm = 0.57twip (exactly) + nMul = 25400; // 2.54 * 10000 + nDiv = 1440; // 72 * 20; + nFac = 1000; + psUnit = gpsCM; + break; + + case MeasureUnit::POINT: + // 0.01pt = 0.2twip (exactly) + nMul = 1000; + nDiv = 20; + nFac = 100; + psUnit = gpsPT; + break; + + case MeasureUnit::INCH: + default: + OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, + "output unit not supported for twip values" ); + // 0.0001in = 0.144twip (exactly) + nMul = 100000; + nDiv = 1440; // 72 * 20; + nFac = 10000; + psUnit = gpsINCH; + break; + } + break; + + case MeasureUnit::POINT: + // 1pt = 1pt (exactly) + OSL_ENSURE( MeasureUnit::POINT == nTargetUnit, + "output unit not supported for pt values" ); + nMul = 10; + nDiv = 1; + nFac = 1; + psUnit = gpsPT; + break; + case MeasureUnit::MM_10TH: + case MeasureUnit::MM_100TH: + { + long nFac2 = (MeasureUnit::MM_100TH == nSourceUnit) ? 100 : 10; + switch( nTargetUnit ) + { + case MeasureUnit::MM_100TH: + case MeasureUnit::MM_10TH: + OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, + "output unit not supported for 1/100mm values" ); + case MeasureUnit::MM: + // 0.01mm = 1 mm/100 (exactly) + nMul = 10; + nDiv = 1; + nFac = nFac2; + psUnit = gpsMM; + break; + + case MeasureUnit::CM: + // 0.001mm = 1 mm/100 (exactly) + nMul = 10; + nDiv = 1; // 72 * 20; + nFac = 10*nFac2; + psUnit = gpsCM; + break; + + case MeasureUnit::POINT: + // 0.01pt = 0.35 mm/100 (exactly) + nMul = 72000; + nDiv = 2540; + nFac = nFac2; + psUnit = gpsPT; + break; + + case MeasureUnit::INCH: + default: + OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, + "output unit not supported for 1/100mm values" ); + // 0.0001in = 0.254 mm/100 (exactly) + nMul = 100000; + nDiv = 2540; + nFac = 100*nFac2; + psUnit = gpsINCH; + break; + } + break; + } + } + + long nLongVal = 0; + bool bOutLongVal = true; + if( nMeasure > SAL_INT32_MAX / nMul ) + { + // A big int is required for calculation + BigInt nBigVal( nMeasure ); + BigInt nBigFac( nFac ); + nBigVal *= nMul; + nBigVal /= nDiv; + nBigVal += 5; + nBigVal /= 10; + + if( nBigVal.IsLong() ) + { + // To convert the value into a string a long is sufficient + nLongVal = (long)nBigVal; + } + else + { + BigInt nBigFac2( nFac ); + BigInt nBig10( 10 ); + rBuffer.append( (sal_Int32)(nBigVal / nBigFac2) ); + if( !(nBigVal % nBigFac2).IsZero() ) + { + rBuffer.append( sal_Unicode('.') ); + while( nFac > 1 && !(nBigVal % nBigFac2).IsZero() ) + { + nFac /= 10; + nBigFac2 = nFac; + rBuffer.append( (sal_Int32)((nBigVal / nBigFac2) % nBig10 ) ); + } + } + bOutLongVal = false; + } + } + else + { + nLongVal = nMeasure * nMul; + nLongVal /= nDiv; + nLongVal += 5; + nLongVal /= 10; + } + + if( bOutLongVal ) + { + rBuffer.append( (sal_Int32)(nLongVal / nFac) ); + if( nFac > 1 && (nLongVal % nFac) != 0 ) + { + rBuffer.append( sal_Unicode('.') ); + while( nFac > 1 && (nLongVal % nFac) != 0 ) + { + nFac /= 10; + rBuffer.append( (sal_Int32)((nLongVal / nFac) % 10) ); + } + } + } + + if( psUnit ) + rBuffer.appendAscii( psUnit ); + } +#endif +} + +static const OUString& getTrueString() +{ + static const OUString sTrue( RTL_CONSTASCII_USTRINGPARAM( "true" ) ); + return sTrue; +} + +static const OUString& getFalseString() +{ + static const OUString sFalse( RTL_CONSTASCII_USTRINGPARAM( "false" ) ); + return sFalse; +} + +/** convert string to boolean */ +bool Converter::convertBool( bool& rBool, const OUString& rString ) +{ + rBool = rString == getTrueString(); + + return rBool || (rString == getFalseString()); +} + +/** convert boolean to string */ +void Converter::convertBool( OUStringBuffer& rBuffer, bool bValue ) +{ + rBuffer.append( bValue ? getTrueString() : getFalseString() ); +} + +/** convert string to percent */ +bool Converter::convertPercent( sal_Int32& rPercent, const OUString& rString ) +{ + return convertMeasure( rPercent, rString, MeasureUnit::PERCENT ); +} + +/** convert percent to string */ +void Converter::convertPercent( OUStringBuffer& rBuffer, sal_Int32 nValue ) +{ + rBuffer.append( nValue ); + rBuffer.append( sal_Unicode('%' ) ); +} + +/** convert string to pixel measure */ +bool Converter::convertMeasurePx( sal_Int32& rPixel, const OUString& rString ) +{ + return convertMeasure( rPixel, rString, MeasureUnit::PIXEL ); +} + +/** convert pixel measure to string */ +void Converter::convertMeasurePx( OUStringBuffer& rBuffer, sal_Int32 nValue ) +{ + rBuffer.append( nValue ); + rBuffer.append( sal_Unicode('p' ) ); + rBuffer.append( sal_Unicode('x' ) ); +} + +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 */ +bool Converter::convertColor( sal_Int32& rColor, const OUString& rValue ) +{ + if( rValue.getLength() != 7 || rValue[0] != '#' ) + return false; + + rColor = lcl_gethex( rValue[1] ) * 16 + lcl_gethex( rValue[2] ); + rColor <<= 8; + + rColor |= ( lcl_gethex( rValue[3] ) * 16 + lcl_gethex( rValue[4] ) ); + rColor <<= 8; + + rColor |= ( lcl_gethex( rValue[5] ) * 16 + lcl_gethex( rValue[6] ) ); + + return true; +} + +static sal_Char aHexTab[] = "0123456789abcdef"; + +/** convert color to string */ +void Converter::convertColor( OUStringBuffer& rBuffer, sal_Int32 nColor ) +{ + rBuffer.append( sal_Unicode( '#' ) ); + + sal_uInt8 nCol = (sal_uInt8)(nColor >> 16); + rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) ); + rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) ); + + nCol = (sal_uInt8)(nColor >> 8); + rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) ); + rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) ); + + nCol = (sal_uInt8)nColor; + rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) ); + rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) ); +} + +/** convert number to string */ +void Converter::convertNumber( OUStringBuffer& rBuffer, sal_Int32 nNumber ) +{ + rBuffer.append( nNumber ); +} + +/** convert string to number with optional min and max values */ +bool Converter::convertNumber( sal_Int32& rValue, + const OUString& rString, + sal_Int32 nMin, sal_Int32 nMax ) +{ + bool bNeg = false; + rValue = 0; + + sal_Int32 nPos = 0L; + sal_Int32 nLen = rString.getLength(); + + // skip white space + while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) ) + nPos++; + + if( nPos < nLen && sal_Unicode('-') == rString[nPos] ) + { + bNeg = 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; + + if( rValue < nMin ) + rValue = nMin; + else if( rValue > nMax ) + rValue = nMax; + + return nPos == nLen; +} + +/** convert double number to string (using ::rtl::math) */ +void Converter::convertDouble( OUStringBuffer& rBuffer, + double fNumber, + bool bWriteUnits, + sal_Int16 nSourceUnit, + sal_Int16 nTargetUnit) +{ + if(MeasureUnit::PERCENT == nSourceUnit) + { + OSL_ENSURE( nTargetUnit == MeasureUnit::PERCENT, "MeasureUnit::PERCENT only maps to MeasureUnit::PERCENT!" ); + ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true); + if(bWriteUnits) + rBuffer.append(sal_Unicode('%')); + } + else + { + OUStringBuffer sUnit; + double fFactor = GetConversionFactor(sUnit, nSourceUnit, nTargetUnit); + if(fFactor != 1.0) + fNumber *= fFactor; + ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true); + if(bWriteUnits) + rBuffer.append(sUnit); + } +} + +/** convert double number to string (using ::rtl::math) */ +void Converter::convertDouble( ::rtl::OUStringBuffer& rBuffer, double fNumber) +{ + ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true); +} + +/** convert string to double number (using ::rtl::math) */ +bool Converter::convertDouble(double& rValue, + const ::rtl::OUString& rString, sal_Int16 nTargetUnit) +{ + sal_Int16 nSourceUnit = GetUnitFromString(rString, nTargetUnit); + + return convertDouble(rValue, rString, nSourceUnit, nTargetUnit ); +} + +/** convert string to double number (using ::rtl::math) */ +bool Converter::convertDouble(double& rValue, + const ::rtl::OUString& rString, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit) +{ + rtl_math_ConversionStatus eStatus; + rValue = ::rtl::math::stringToDouble( rString, (sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL ); + + if(eStatus == rtl_math_ConversionStatus_Ok) + { + OUStringBuffer sUnit; + double fFactor = GetConversionFactor(sUnit, nSourceUnit, nTargetUnit); + if(fFactor != 1.0 && fFactor != 0.0) + rValue /= fFactor; + } + + return ( eStatus == rtl_math_ConversionStatus_Ok ); +} + +/** convert string to double number (using ::rtl::math) */ +bool Converter::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 ); +} + +/** convert double to ISO Time String; negative durations allowed */ +void Converter::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, '.', + 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 */ +bool Converter::convertTime( double& fTime, + const ::rtl::OUString& rString) +{ + rtl::OUString aTrimmed = rString.trim().toAsciiUpperCase(); + const sal_Unicode* pStr = aTrimmed.getStr(); + + // negative time duration? + bool bIsNegativeDuration = false; + if ( sal_Unicode('-') == (*pStr) ) + { + bIsNegativeDuration = true; + pStr++; + } + + if ( *(pStr++) != sal_Unicode('P') ) // duration must start with "P" + return false; + + rtl::OUString sDoubleStr; + bool bSuccess = true; + bool bDone = false; + bool bTimePart = false; + bool bIsFraction = false; + sal_Int32 nDays = 0; + sal_Int32 nHours = 0; + sal_Int32 nMins = 0; + sal_Int32 nSecs = 0; + sal_Int32 nTemp = 0; + + while ( bSuccess && !bDone ) + { + sal_Unicode c = *(pStr++); + if ( !c ) // end + bDone = 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') ) + { + nHours = nTemp; + nTemp = 0; + } + else if ( c == sal_Unicode('M') ) + { + nMins = nTemp; + nTemp = 0; + } + else if ( (c == sal_Unicode(',')) || (c == sal_Unicode('.')) ) + { + nSecs = nTemp; + nTemp = 0; + bIsFraction = true; + sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0.")); + } + else if ( c == sal_Unicode('S') ) + { + if ( !bIsFraction ) + { + nSecs = 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 = 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? + + OSL_ENSURE( false, "years or months in duration: not implemented"); + bSuccess = false; + } + else + bSuccess = false; // invalid character + } + } + + if ( bSuccess ) + { + 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; + double fFraction = sDoubleStr.toDouble(); + fTempTime = fHour / 24; + fTempTime += fMin / (24 * 60); + fTempTime += fSec / (24 * 60 * 60); + fTempTime += fSec100 / (24 * 60 * 60 * 60); + fTempTime += fFraction / (24 * 60 * 60); + + // negative duration? + if ( bIsNegativeDuration ) + { + fTempTime = -fTempTime; + } + + fTime = fTempTime; + } + return bSuccess; +} + +/** convert util::DateTime to ISO Time String */ +void Converter::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 */ +bool Converter::convertTime( ::com::sun::star::util::DateTime& rDateTime, + const ::rtl::OUString& rString ) +{ + double fCalculatedTime = 0.0; + if( convertTime( fCalculatedTime, rString ) ) + { + // #101357# declare as volatile to prevent optimization + // (gcc 3.0.1 Linux) + volatile double fTempTime = fCalculatedTime; + fTempTime *= 24; + double fHoursValue = ::rtl::math::approxFloor (fTempTime); + fTempTime -= fHoursValue; + fTempTime *= 60; + double fMinsValue = ::rtl::math::approxFloor (fTempTime); + fTempTime -= fMinsValue; + fTempTime *= 60; + double fSecsValue = ::rtl::math::approxFloor (fTempTime); + fTempTime -= fSecsValue; + double f100SecsValue = 0.0; + + if( fTempTime > 0.00001 ) + f100SecsValue = fTempTime; + + rDateTime.Year = 0; + rDateTime.Month = 0; + rDateTime.Day = 0; + rDateTime.Hours = static_cast < sal_uInt16 > ( fHoursValue ); + rDateTime.Minutes = static_cast < sal_uInt16 > ( fMinsValue ); + rDateTime.Seconds = static_cast < sal_uInt16 > ( fSecsValue ); + rDateTime.HundredthSeconds = static_cast < sal_uInt16 > ( f100SecsValue * 100.0 ); + + return true; + } + return false; +} + +/** convert util::DateTime to ISO Date String */ +void Converter::convertDateTime( + ::rtl::OUStringBuffer& rBuffer, + const com::sun::star::util::DateTime& rDateTime, + bool bAddTimeIf0AM ) +{ + OSL_ENSURE( false, "Converter::convertDateTime - not implemented, tools/String needs replacement" ); + (void)rBuffer; + (void)rDateTime; + (void)bAddTimeIf0AM; +#if 0 + 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 ); +#endif +} + +/** convert ISO Date String to util::DateTime */ +bool Converter::convertDateTime( com::sun::star::util::DateTime& rDateTime, + const ::rtl::OUString& rString ) +{ + bool bSuccess = 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 = false; + else + { + sal_Int32 n = 0; + if ( !convertNumber( nYear, aDateStr.getToken( 0, '-', n ), 0, 9999 ) ) + bSuccess = false; + if ( nDateTokens >= 2 ) + if ( !convertNumber( nMonth, aDateStr.getToken( 0, '-', n ), 0, 12 ) ) + bSuccess = false; + if ( nDateTokens >= 3 ) + if ( !convertNumber( nDay, aDateStr.getToken( 0, '-', n ), 0, 31 ) ) + bSuccess = 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 = false; + else + { + sal_Int32 n = 0; + if ( !convertNumber( nHour, aTimeStr.getToken( 0, ':', n ), 0, 23 ) ) + bSuccess = false; + if ( nTimeTokens >= 2 ) + if ( !convertNumber( nMin, aTimeStr.getToken( 0, ':', n ), 0, 59 ) ) + bSuccess = false; + if ( nTimeTokens >= 3 ) + if ( !convertNumber( nSec, aTimeStr.getToken( 0, ':', n ), 0, 59 ) ) + bSuccess = 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 Converter::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; +} + +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 Converter::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 Converter::decodeBase64(uno::Sequence<sal_Int8>& aBuffer, const rtl::OUString& sBuffer) +{ +#if OSL_DEBUG_LEVEL > 0 + sal_Int32 nCharsDecoded = +#endif + decodeBase64SomeChars( aBuffer, sBuffer ); + OSL_ENSURE( nCharsDecoded == sBuffer.getLength(), "some bytes left in base64 decoding!" ); +} + +sal_Int32 Converter::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; +} + +void Converter::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(); +} + +double Converter::GetConversionFactor(::rtl::OUStringBuffer& rUnit, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit) +{ + double fRetval(1.0); + rUnit.setLength(0L); + + const sal_Char* psUnit = 0; + + if(nSourceUnit != nTargetUnit) + { + switch(nSourceUnit) + { + case MeasureUnit::TWIP: + { + switch(nTargetUnit) + { + case MeasureUnit::MM_100TH: + case MeasureUnit::MM_10TH: + { + OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for twip values"); + } + case MeasureUnit::MM: + { + // 0.01mm = 0.57twip (exactly) + fRetval = ((25400.0 / 1440.0) / 1000.0); + psUnit = gpsMM; + break; + } + case MeasureUnit::CM: + { + // 0.001cm = 0.57twip (exactly) + fRetval = ((25400.0 / 1440.0) / 10000.0); + psUnit = gpsCM; + break; + } + case MeasureUnit::POINT: + { + // 0.01pt = 0.2twip (exactly) + fRetval = ((1000.0 / 20.0) / 1000.0); + psUnit = gpsPT; + break; + } + case MeasureUnit::INCH: + default: + { + OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for twip values"); + // 0.0001in = 0.144twip (exactly) + fRetval = ((100000.0 / 1440.0) / 100000.0); + psUnit = gpsINCH; + break; + } + } + break; + } + case MeasureUnit::POINT: + { + switch(nTargetUnit) + { + case MeasureUnit::MM: + // 1mm = 72 / 25.4 pt (exactly) + fRetval = ( 25.4 / 72.0 ); + psUnit = gpsMM; + break; + + case MeasureUnit::CM: + // 1cm = 72 / 2.54 pt (exactly) + fRetval = ( 2.54 / 72.0 ); + psUnit = gpsCM; + break; + + case MeasureUnit::TWIP: + // 1twip = 72 / 1440 pt (exactly) + fRetval = 20.0; // 1440.0 / 72.0 + psUnit = gpsPC; + break; + + case MeasureUnit::INCH: + default: + OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for pt values"); + // 1in = 72 pt (exactly) + fRetval = ( 1.0 / 72.0 ); + psUnit = gpsINCH; + break; + } + break; + } + case MeasureUnit::MM_10TH: + { + switch(nTargetUnit) + { + case MeasureUnit::MM_100TH: + case MeasureUnit::MM_10TH: + { + OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values"); + } + case MeasureUnit::MM: + { + // 0.01mm = 1 mm/100 (exactly) + fRetval = ((10.0 / 1.0) / 100.0); + psUnit = gpsMM; + break; + } + case MeasureUnit::CM: + { + // 0.001mm = 1 mm/100 (exactly) + fRetval = ((10.0 / 1.0) / 1000.0); + psUnit = gpsCM; + break; + } + case MeasureUnit::POINT: + { + // 0.01pt = 0.35 mm/100 (exactly) + fRetval = ((72000.0 / 2540.0) / 100.0); + psUnit = gpsPT; + break; + } + case MeasureUnit::INCH: + default: + { + OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values"); + // 0.0001in = 0.254 mm/100 (exactly) + fRetval = ((100000.0 / 2540.0) / 10000.0); + psUnit = gpsINCH; + break; + } + } + break; + } + case MeasureUnit::MM_100TH: + { + switch(nTargetUnit) + { + case MeasureUnit::MM_100TH: + case MeasureUnit::MM_10TH: + { + OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values"); + } + case MeasureUnit::MM: + { + // 0.01mm = 1 mm/100 (exactly) + fRetval = ((10.0 / 1.0) / 1000.0); + psUnit = gpsMM; + break; + } + case MeasureUnit::CM: + { + // 0.001mm = 1 mm/100 (exactly) + fRetval = ((10.0 / 1.0) / 10000.0); + psUnit = gpsCM; + break; + } + case MeasureUnit::POINT: + { + // 0.01pt = 0.35 mm/100 (exactly) + fRetval = ((72000.0 / 2540.0) / 1000.0); + psUnit = gpsPT; + break; + } + case MeasureUnit::INCH: + default: + { + OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values"); + // 0.0001in = 0.254 mm/100 (exactly) + fRetval = ((100000.0 / 2540.0) / 100000.0); + psUnit = gpsINCH; + break; + } + } + break; + } + } + + if( psUnit ) + rUnit.appendAscii( psUnit ); + } + + return fRetval; +} + +sal_Int16 Converter::GetUnitFromString(const ::rtl::OUString& rString, sal_Int16 nDefaultUnit) +{ + sal_Int32 nPos = 0L; + sal_Int32 nLen = rString.getLength(); + sal_Int16 nRetUnit = nDefaultUnit; + + // skip white space + while( nPos < nLen && sal_Unicode(' ') == rString[nPos] ) + nPos++; + + // skip negative + if( nPos < nLen && sal_Unicode('-') == rString[nPos] ) + nPos++; + + // skip number + while( nPos < nLen && sal_Unicode('0') <= rString[nPos] && sal_Unicode('9') >= rString[nPos] ) + nPos++; + + if( nPos < nLen && sal_Unicode('.') == rString[nPos] ) + { + nPos++; + while( nPos < nLen && sal_Unicode('0') <= rString[nPos] && sal_Unicode('9') >= rString[nPos] ) + nPos++; + } + + // skip white space + while( nPos < nLen && sal_Unicode(' ') == rString[nPos] ) + nPos++; + + if( nPos < nLen ) + { + switch(rString[nPos]) + { + case sal_Unicode('%') : + { + nRetUnit = MeasureUnit::PERCENT; + break; + } + case sal_Unicode('c'): + case sal_Unicode('C'): + { + if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('m') + || rString[nPos+1] == sal_Unicode('M'))) + nRetUnit = MeasureUnit::CM; + break; + } + case sal_Unicode('e'): + case sal_Unicode('E'): + { + // CSS1_EMS or CSS1_EMX later + break; + } + case sal_Unicode('i'): + case sal_Unicode('I'): + { + if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('n') + || rString[nPos+1] == sal_Unicode('n'))) + nRetUnit = MeasureUnit::INCH; + break; + } + case sal_Unicode('m'): + case sal_Unicode('M'): + { + if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('m') + || rString[nPos+1] == sal_Unicode('M'))) + nRetUnit = MeasureUnit::MM; + break; + } + case sal_Unicode('p'): + case sal_Unicode('P'): + { + if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('t') + || rString[nPos+1] == sal_Unicode('T'))) + nRetUnit = MeasureUnit::POINT; + if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('c') + || rString[nPos+1] == sal_Unicode('C'))) + nRetUnit = MeasureUnit::TWIP; + break; + } + } + } + + return nRetUnit; +} + +} |