merge the formfield patch from ooo-build
[ooovba.git] / sax / source / tools / converter.cxx
blob2eadd95fbd4e8639151a0675a8699adf2c72f5c2
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: converter.cxx,v $
10 * $Revision: 1.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
32 #include <com/sun/star/i18n/UnicodeType.hpp>
33 #include <com/sun/star/util/DateTime.hpp>
34 #include <com/sun/star/util/Date.hpp>
35 #include <com/sun/star/util/Time.hpp>
36 #include <com/sun/star/uno/Sequence.hxx>
37 #include <rtl/ustrbuf.hxx>
38 #include <rtl/math.hxx>
39 #include "sax/tools/converter.hxx"
41 using namespace rtl;
42 using namespace com::sun::star;
43 using namespace com::sun::star::uno;
44 using namespace com::sun::star::util;
45 //using namespace com::sun::star::text;
46 //using namespace com::sun::star::style;
47 using namespace ::com::sun::star::i18n;
49 namespace sax {
51 static const sal_Char* gpsMM = "mm";
52 static const sal_Char* gpsCM = "cm";
53 static const sal_Char* gpsPT = "pt";
54 static const sal_Char* gpsINCH = "in";
55 static const sal_Char* gpsPC = "pc";
57 const sal_Int8 XML_MAXDIGITSCOUNT_TIME = 11;
58 const sal_Int8 XML_MAXDIGITSCOUNT_DATETIME = 6;
59 #define XML_NULLDATE "NullDate"
61 /** convert string to measure using optional min and max values*/
62 bool Converter::convertMeasure( sal_Int32& rValue,
63 const OUString& rString,
64 sal_Int16 nTargetUnit /* = MeasureUnit::MM_100TH */,
65 sal_Int32 nMin /* = SAL_MIN_INT32 */,
66 sal_Int32 nMax /* = SAL_MAX_INT32 */ )
68 bool bNeg = false;
69 double nVal = 0;
71 sal_Int32 nPos = 0L;
72 sal_Int32 nLen = rString.getLength();
74 // skip white space
75 while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) )
76 nPos++;
78 if( nPos < nLen && sal_Unicode('-') == rString[nPos] )
80 bNeg = true;
81 nPos++;
84 // get number
85 while( nPos < nLen &&
86 sal_Unicode('0') <= rString[nPos] &&
87 sal_Unicode('9') >= rString[nPos] )
89 // TODO: check overflow!
90 nVal *= 10;
91 nVal += (rString[nPos] - sal_Unicode('0'));
92 nPos++;
94 double nDiv = 1.;
95 if( nPos < nLen && sal_Unicode('.') == rString[nPos] )
97 nPos++;
99 while( nPos < nLen &&
100 sal_Unicode('0') <= rString[nPos] &&
101 sal_Unicode('9') >= rString[nPos] )
103 // TODO: check overflow!
104 nDiv *= 10;
105 nVal += ( ((double)(rString[nPos] - sal_Unicode('0'))) / nDiv );
106 nPos++;
110 // skip white space
111 while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) )
112 nPos++;
114 if( nPos < nLen )
117 if( MeasureUnit::PERCENT == nTargetUnit )
119 if( sal_Unicode('%') != rString[nPos] )
120 return false;
122 else if( MeasureUnit::PIXEL == nTargetUnit )
124 if( nPos + 1 >= nLen ||
125 (sal_Unicode('p') != rString[nPos] &&
126 sal_Unicode('P') != rString[nPos])||
127 (sal_Unicode('x') != rString[nPos+1] &&
128 sal_Unicode('X') != rString[nPos+1]) )
129 return false;
131 else
133 OSL_ENSURE( MeasureUnit::TWIP == nTargetUnit || MeasureUnit::POINT == nTargetUnit ||
134 MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit, "unit is not supported");
135 const sal_Char *aCmpsL[2] = { 0, 0 };
136 const sal_Char *aCmpsU[2] = { 0, 0 };
137 double aScales[2] = { 1., 1. };
139 if( MeasureUnit::TWIP == nTargetUnit )
141 switch( rString[nPos] )
143 case sal_Unicode('c'):
144 case sal_Unicode('C'):
145 aCmpsL[0] = "cm";
146 aCmpsU[0] = "CM";
147 aScales[0] = (72.*20.)/2.54; // twip
148 break;
149 case sal_Unicode('i'):
150 case sal_Unicode('I'):
151 aCmpsL[0] = "in";
152 aCmpsU[0] = "IN";
153 aScales[0] = 72.*20.; // twip
154 break;
155 case sal_Unicode('m'):
156 case sal_Unicode('M'):
157 aCmpsL[0] = "mm";
158 aCmpsU[0] = "MM";
159 aScales[0] = (72.*20.)/25.4; // twip
160 break;
161 case sal_Unicode('p'):
162 case sal_Unicode('P'):
163 aCmpsL[0] = "pt";
164 aCmpsU[0] = "PT";
165 aScales[0] = 20.; // twip
167 aCmpsL[1] = "pc";
168 aCmpsU[1] = "PC";
169 aScales[1] = 12.*20.; // twip
170 break;
173 else if( MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit )
175 double nScaleFactor = (MeasureUnit::MM_100TH == nTargetUnit) ? 100.0 : 10.0;
176 switch( rString[nPos] )
178 case sal_Unicode('c'):
179 case sal_Unicode('C'):
180 aCmpsL[0] = "cm";
181 aCmpsU[0] = "CM";
182 aScales[0] = 10.0 * nScaleFactor; // mm/100
183 break;
184 case sal_Unicode('i'):
185 case sal_Unicode('I'):
186 aCmpsL[0] = "in";
187 aCmpsU[0] = "IN";
188 aScales[0] = 1000.*2.54; // mm/100
189 break;
190 case sal_Unicode('m'):
191 case sal_Unicode('M'):
192 aCmpsL[0] = "mm";
193 aCmpsU[0] = "MM";
194 aScales[0] = 1.0 * nScaleFactor; // mm/100
195 break;
196 case sal_Unicode('p'):
197 case sal_Unicode('P'):
198 aCmpsL[0] = "pt";
199 aCmpsU[0] = "PT";
200 aScales[0] = (10.0 * nScaleFactor*2.54)/72.; // mm/100
202 aCmpsL[1] = "pc";
203 aCmpsU[1] = "PC";
204 aScales[1] = (10.0 * nScaleFactor*2.54)/12.; // mm/100
205 break;
208 else if( MeasureUnit::POINT == nTargetUnit )
210 if( rString[nPos] == 'p' || rString[nPos] == 'P' )
212 aCmpsL[0] = "pt";
213 aCmpsU[0] = "PT";
214 aScales[0] = 1;
218 if( aCmpsL[0] == NULL )
219 return false;
221 double nScale = 0.;
222 for( sal_uInt16 i= 0; i < 2; i++ )
224 const sal_Char *pL = aCmpsL[i];
225 if( pL )
227 const sal_Char *pU = aCmpsU[i];
228 while( nPos < nLen && *pL )
230 sal_Unicode c = rString[nPos];
231 if( c != *pL && c != *pU )
232 break;
233 pL++;
234 pU++;
235 nPos++;
237 if( !*pL && (nPos == nLen || ' ' == rString[nPos]) )
239 nScale = aScales[i];
240 break;
245 if( 0. == nScale )
246 return false;
248 // TODO: check overflow
249 if( nScale != 1. )
250 nVal *= nScale;
254 nVal += .5;
255 if( bNeg )
256 nVal = -nVal;
258 if( nVal <= (double)nMin )
259 rValue = nMin;
260 else if( nVal >= (double)nMax )
261 rValue = nMax;
262 else
263 rValue = (sal_Int32)nVal;
265 return true;
268 /** convert measure in given unit to string with given unit */
269 void Converter::convertMeasure( OUStringBuffer& rBuffer,
270 sal_Int32 nMeasure,
271 sal_Int16 nSourceUnit /* = MeasureUnit::MM_100TH */,
272 sal_Int16 nTargetUnit /* = MeasureUnit::INCH */ )
274 OSL_ENSURE( false, "Converter::convertMeasure - not implemented, tools/BigInt needs replacement" );
275 (void)rBuffer;
276 (void)nMeasure;
277 (void)nSourceUnit;
278 (void)nTargetUnit;
279 #if 0
280 if( nSourceUnit == MeasureUnit::PERCENT )
282 OSL_ENSURE( nTargetUnit == MeasureUnit::PERCENT,
283 "MeasureUnit::PERCENT only maps to MeasureUnit::PERCENT!" );
285 rBuffer.append( nMeasure );
286 rBuffer.append( sal_Unicode('%' ) );
288 else
290 // the sign is processed seperatly
291 if( nMeasure < 0 )
293 nMeasure = -nMeasure;
294 rBuffer.append( sal_Unicode('-') );
297 // The new length is (nVal * nMul)/(nDiv*nFac*10)
298 long nMul = 1000;
299 long nDiv = 1;
300 long nFac = 100;
301 const sal_Char* psUnit = 0;
302 switch( nSourceUnit )
304 case MeasureUnit::TWIP:
305 switch( nTargetUnit )
307 case MeasureUnit::MM_100TH:
308 case MeasureUnit::MM_10TH:
309 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,"output unit not supported for twip values" );
310 case MeasureUnit::MM:
311 // 0.01mm = 0.57twip (exactly)
312 nMul = 25400; // 25.4 * 1000
313 nDiv = 1440; // 72 * 20;
314 nFac = 100;
315 psUnit = gpsMM;
316 break;
318 case MeasureUnit::CM:
319 // 0.001cm = 0.57twip (exactly)
320 nMul = 25400; // 2.54 * 10000
321 nDiv = 1440; // 72 * 20;
322 nFac = 1000;
323 psUnit = gpsCM;
324 break;
326 case MeasureUnit::POINT:
327 // 0.01pt = 0.2twip (exactly)
328 nMul = 1000;
329 nDiv = 20;
330 nFac = 100;
331 psUnit = gpsPT;
332 break;
334 case MeasureUnit::INCH:
335 default:
336 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,
337 "output unit not supported for twip values" );
338 // 0.0001in = 0.144twip (exactly)
339 nMul = 100000;
340 nDiv = 1440; // 72 * 20;
341 nFac = 10000;
342 psUnit = gpsINCH;
343 break;
345 break;
347 case MeasureUnit::POINT:
348 // 1pt = 1pt (exactly)
349 OSL_ENSURE( MeasureUnit::POINT == nTargetUnit,
350 "output unit not supported for pt values" );
351 nMul = 10;
352 nDiv = 1;
353 nFac = 1;
354 psUnit = gpsPT;
355 break;
356 case MeasureUnit::MM_10TH:
357 case MeasureUnit::MM_100TH:
359 long nFac2 = (MeasureUnit::MM_100TH == nSourceUnit) ? 100 : 10;
360 switch( nTargetUnit )
362 case MeasureUnit::MM_100TH:
363 case MeasureUnit::MM_10TH:
364 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,
365 "output unit not supported for 1/100mm values" );
366 case MeasureUnit::MM:
367 // 0.01mm = 1 mm/100 (exactly)
368 nMul = 10;
369 nDiv = 1;
370 nFac = nFac2;
371 psUnit = gpsMM;
372 break;
374 case MeasureUnit::CM:
375 // 0.001mm = 1 mm/100 (exactly)
376 nMul = 10;
377 nDiv = 1; // 72 * 20;
378 nFac = 10*nFac2;
379 psUnit = gpsCM;
380 break;
382 case MeasureUnit::POINT:
383 // 0.01pt = 0.35 mm/100 (exactly)
384 nMul = 72000;
385 nDiv = 2540;
386 nFac = nFac2;
387 psUnit = gpsPT;
388 break;
390 case MeasureUnit::INCH:
391 default:
392 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,
393 "output unit not supported for 1/100mm values" );
394 // 0.0001in = 0.254 mm/100 (exactly)
395 nMul = 100000;
396 nDiv = 2540;
397 nFac = 100*nFac2;
398 psUnit = gpsINCH;
399 break;
401 break;
405 long nLongVal = 0;
406 bool bOutLongVal = true;
407 if( nMeasure > SAL_INT32_MAX / nMul )
409 // A big int is required for calculation
410 BigInt nBigVal( nMeasure );
411 BigInt nBigFac( nFac );
412 nBigVal *= nMul;
413 nBigVal /= nDiv;
414 nBigVal += 5;
415 nBigVal /= 10;
417 if( nBigVal.IsLong() )
419 // To convert the value into a string a long is sufficient
420 nLongVal = (long)nBigVal;
422 else
424 BigInt nBigFac2( nFac );
425 BigInt nBig10( 10 );
426 rBuffer.append( (sal_Int32)(nBigVal / nBigFac2) );
427 if( !(nBigVal % nBigFac2).IsZero() )
429 rBuffer.append( sal_Unicode('.') );
430 while( nFac > 1 && !(nBigVal % nBigFac2).IsZero() )
432 nFac /= 10;
433 nBigFac2 = nFac;
434 rBuffer.append( (sal_Int32)((nBigVal / nBigFac2) % nBig10 ) );
437 bOutLongVal = false;
440 else
442 nLongVal = nMeasure * nMul;
443 nLongVal /= nDiv;
444 nLongVal += 5;
445 nLongVal /= 10;
448 if( bOutLongVal )
450 rBuffer.append( (sal_Int32)(nLongVal / nFac) );
451 if( nFac > 1 && (nLongVal % nFac) != 0 )
453 rBuffer.append( sal_Unicode('.') );
454 while( nFac > 1 && (nLongVal % nFac) != 0 )
456 nFac /= 10;
457 rBuffer.append( (sal_Int32)((nLongVal / nFac) % 10) );
462 if( psUnit )
463 rBuffer.appendAscii( psUnit );
465 #endif
468 static const OUString& getTrueString()
470 static const OUString sTrue( RTL_CONSTASCII_USTRINGPARAM( "true" ) );
471 return sTrue;
474 static const OUString& getFalseString()
476 static const OUString sFalse( RTL_CONSTASCII_USTRINGPARAM( "false" ) );
477 return sFalse;
480 /** convert string to boolean */
481 bool Converter::convertBool( bool& rBool, const OUString& rString )
483 rBool = rString == getTrueString();
485 return rBool || (rString == getFalseString());
488 /** convert boolean to string */
489 void Converter::convertBool( OUStringBuffer& rBuffer, bool bValue )
491 rBuffer.append( bValue ? getTrueString() : getFalseString() );
494 /** convert string to percent */
495 bool Converter::convertPercent( sal_Int32& rPercent, const OUString& rString )
497 return convertMeasure( rPercent, rString, MeasureUnit::PERCENT );
500 /** convert percent to string */
501 void Converter::convertPercent( OUStringBuffer& rBuffer, sal_Int32 nValue )
503 rBuffer.append( nValue );
504 rBuffer.append( sal_Unicode('%' ) );
507 /** convert string to pixel measure */
508 bool Converter::convertMeasurePx( sal_Int32& rPixel, const OUString& rString )
510 return convertMeasure( rPixel, rString, MeasureUnit::PIXEL );
513 /** convert pixel measure to string */
514 void Converter::convertMeasurePx( OUStringBuffer& rBuffer, sal_Int32 nValue )
516 rBuffer.append( nValue );
517 rBuffer.append( sal_Unicode('p' ) );
518 rBuffer.append( sal_Unicode('x' ) );
521 int lcl_gethex( int nChar )
523 if( nChar >= '0' && nChar <= '9' )
524 return nChar - '0';
525 else if( nChar >= 'a' && nChar <= 'f' )
526 return nChar - 'a' + 10;
527 else if( nChar >= 'A' && nChar <= 'F' )
528 return nChar - 'A' + 10;
529 else
530 return 0;
533 /** convert string to color */
534 bool Converter::convertColor( sal_Int32& rColor, const OUString& rValue )
536 if( rValue.getLength() != 7 || rValue[0] != '#' )
537 return false;
539 rColor = lcl_gethex( rValue[1] ) * 16 + lcl_gethex( rValue[2] );
540 rColor <<= 8;
542 rColor |= ( lcl_gethex( rValue[3] ) * 16 + lcl_gethex( rValue[4] ) );
543 rColor <<= 8;
545 rColor |= ( lcl_gethex( rValue[5] ) * 16 + lcl_gethex( rValue[6] ) );
547 return true;
550 static sal_Char aHexTab[] = "0123456789abcdef";
552 /** convert color to string */
553 void Converter::convertColor( OUStringBuffer& rBuffer, sal_Int32 nColor )
555 rBuffer.append( sal_Unicode( '#' ) );
557 sal_uInt8 nCol = (sal_uInt8)(nColor >> 16);
558 rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
559 rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
561 nCol = (sal_uInt8)(nColor >> 8);
562 rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
563 rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
565 nCol = (sal_uInt8)nColor;
566 rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
567 rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
570 /** convert number to string */
571 void Converter::convertNumber( OUStringBuffer& rBuffer, sal_Int32 nNumber )
573 rBuffer.append( nNumber );
576 /** convert string to number with optional min and max values */
577 bool Converter::convertNumber( sal_Int32& rValue,
578 const OUString& rString,
579 sal_Int32 nMin, sal_Int32 nMax )
581 bool bNeg = false;
582 rValue = 0;
584 sal_Int32 nPos = 0L;
585 sal_Int32 nLen = rString.getLength();
587 // skip white space
588 while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) )
589 nPos++;
591 if( nPos < nLen && sal_Unicode('-') == rString[nPos] )
593 bNeg = true;
594 nPos++;
597 // get number
598 while( nPos < nLen &&
599 sal_Unicode('0') <= rString[nPos] &&
600 sal_Unicode('9') >= rString[nPos] )
602 // TODO: check overflow!
603 rValue *= 10;
604 rValue += (rString[nPos] - sal_Unicode('0'));
605 nPos++;
608 if( bNeg )
609 rValue *= -1;
611 if( rValue < nMin )
612 rValue = nMin;
613 else if( rValue > nMax )
614 rValue = nMax;
616 return nPos == nLen;
619 /** convert double number to string (using ::rtl::math) */
620 void Converter::convertDouble( OUStringBuffer& rBuffer,
621 double fNumber,
622 bool bWriteUnits,
623 sal_Int16 nSourceUnit,
624 sal_Int16 nTargetUnit)
626 if(MeasureUnit::PERCENT == nSourceUnit)
628 OSL_ENSURE( nTargetUnit == MeasureUnit::PERCENT, "MeasureUnit::PERCENT only maps to MeasureUnit::PERCENT!" );
629 ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
630 if(bWriteUnits)
631 rBuffer.append(sal_Unicode('%'));
633 else
635 OUStringBuffer sUnit;
636 double fFactor = GetConversionFactor(sUnit, nSourceUnit, nTargetUnit);
637 if(fFactor != 1.0)
638 fNumber *= fFactor;
639 ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
640 if(bWriteUnits)
641 rBuffer.append(sUnit);
645 /** convert double number to string (using ::rtl::math) */
646 void Converter::convertDouble( ::rtl::OUStringBuffer& rBuffer, double fNumber)
648 ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
651 /** convert string to double number (using ::rtl::math) */
652 bool Converter::convertDouble(double& rValue,
653 const ::rtl::OUString& rString, sal_Int16 nTargetUnit)
655 sal_Int16 nSourceUnit = GetUnitFromString(rString, nTargetUnit);
657 return convertDouble(rValue, rString, nSourceUnit, nTargetUnit );
660 /** convert string to double number (using ::rtl::math) */
661 bool Converter::convertDouble(double& rValue,
662 const ::rtl::OUString& rString, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
664 rtl_math_ConversionStatus eStatus;
665 rValue = ::rtl::math::stringToDouble( rString, (sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL );
667 if(eStatus == rtl_math_ConversionStatus_Ok)
669 OUStringBuffer sUnit;
670 double fFactor = GetConversionFactor(sUnit, nSourceUnit, nTargetUnit);
671 if(fFactor != 1.0 && fFactor != 0.0)
672 rValue /= fFactor;
675 return ( eStatus == rtl_math_ConversionStatus_Ok );
678 /** convert string to double number (using ::rtl::math) */
679 bool Converter::convertDouble(double& rValue, const ::rtl::OUString& rString)
681 rtl_math_ConversionStatus eStatus;
682 rValue = ::rtl::math::stringToDouble( rString, (sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL );
683 return ( eStatus == rtl_math_ConversionStatus_Ok );
686 /** convert double to ISO Time String; negative durations allowed */
687 void Converter::convertTime( ::rtl::OUStringBuffer& rBuffer,
688 const double& fTime)
691 double fValue = fTime;
693 // take care of negative durations as specified in:
694 // XML Schema, W3C Working Draft 07 April 2000, section 3.2.6.1
695 if (fValue < 0.0)
697 rBuffer.append(sal_Unicode('-'));
698 fValue = - fValue;
701 rBuffer.appendAscii(RTL_CONSTASCII_STRINGPARAM( "PT" ));
702 fValue *= 24;
703 double fHoursValue = ::rtl::math::approxFloor (fValue);
704 fValue -= fHoursValue;
705 fValue *= 60;
706 double fMinsValue = ::rtl::math::approxFloor (fValue);
707 fValue -= fMinsValue;
708 fValue *= 60;
709 double fSecsValue = ::rtl::math::approxFloor (fValue);
710 fValue -= fSecsValue;
711 double f100SecsValue;
712 if (fValue > 0.00001)
713 f100SecsValue = ::rtl::math::round( fValue, XML_MAXDIGITSCOUNT_TIME - 5);
714 else
715 f100SecsValue = 0.0;
717 if (f100SecsValue == 1.0)
719 f100SecsValue = 0.0;
720 fSecsValue += 1.0;
722 if (fSecsValue >= 60.0)
724 fSecsValue -= 60.0;
725 fMinsValue += 1.0;
727 if (fMinsValue >= 60.0)
729 fMinsValue -= 60.0;
730 fHoursValue += 1.0;
733 if (fHoursValue < 10)
734 rBuffer.append( sal_Unicode('0'));
735 rBuffer.append( sal_Int32( fHoursValue));
736 rBuffer.append( sal_Unicode('H'));
737 if (fMinsValue < 10)
738 rBuffer.append( sal_Unicode('0'));
739 rBuffer.append( sal_Int32( fMinsValue));
740 rBuffer.append( sal_Unicode('M'));
741 if (fSecsValue < 10)
742 rBuffer.append( sal_Unicode('0'));
743 rBuffer.append( sal_Int32( fSecsValue));
744 if (f100SecsValue > 0.0)
746 ::rtl::OUString a100th( ::rtl::math::doubleToUString( fValue,
747 rtl_math_StringFormat_F, XML_MAXDIGITSCOUNT_TIME - 5, '.',
748 true));
749 if ( a100th.getLength() > 2 )
751 rBuffer.append( sal_Unicode('.'));
752 rBuffer.append( a100th.copy( 2 ) ); // strip 0.
755 rBuffer.append( sal_Unicode('S'));
758 /** convert ISO Time String to double; negative durations allowed */
759 bool Converter::convertTime( double& fTime,
760 const ::rtl::OUString& rString)
762 rtl::OUString aTrimmed = rString.trim().toAsciiUpperCase();
763 const sal_Unicode* pStr = aTrimmed.getStr();
765 // negative time duration?
766 bool bIsNegativeDuration = false;
767 if ( sal_Unicode('-') == (*pStr) )
769 bIsNegativeDuration = true;
770 pStr++;
773 if ( *(pStr++) != sal_Unicode('P') ) // duration must start with "P"
774 return false;
776 rtl::OUString sDoubleStr;
777 bool bSuccess = true;
778 bool bDone = false;
779 bool bTimePart = false;
780 bool bIsFraction = false;
781 sal_Int32 nDays = 0;
782 sal_Int32 nHours = 0;
783 sal_Int32 nMins = 0;
784 sal_Int32 nSecs = 0;
785 sal_Int32 nTemp = 0;
787 while ( bSuccess && !bDone )
789 sal_Unicode c = *(pStr++);
790 if ( !c ) // end
791 bDone = true;
792 else if ( sal_Unicode('0') <= c && sal_Unicode('9') >= c )
794 if ( nTemp >= SAL_MAX_INT32 / 10 )
795 bSuccess = false;
796 else
798 if ( !bIsFraction )
800 nTemp *= 10;
801 nTemp += (c - sal_Unicode('0'));
803 else
805 sDoubleStr += OUString::valueOf(c);
809 else if ( bTimePart )
811 if ( c == sal_Unicode('H') )
813 nHours = nTemp;
814 nTemp = 0;
816 else if ( c == sal_Unicode('M') )
818 nMins = nTemp;
819 nTemp = 0;
821 else if ( (c == sal_Unicode(',')) || (c == sal_Unicode('.')) )
823 nSecs = nTemp;
824 nTemp = 0;
825 bIsFraction = true;
826 sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0."));
828 else if ( c == sal_Unicode('S') )
830 if ( !bIsFraction )
832 nSecs = nTemp;
833 nTemp = 0;
834 sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0.0"));
837 else
838 bSuccess = false; // invalid character
840 else
842 if ( c == sal_Unicode('T') ) // "T" starts time part
843 bTimePart = true;
844 else if ( c == sal_Unicode('D') )
846 nDays = nTemp;
847 nTemp = 0;
849 else if ( c == sal_Unicode('Y') || c == sal_Unicode('M') )
851 //! how many days is a year or month?
853 OSL_ENSURE( false, "years or months in duration: not implemented");
854 bSuccess = false;
856 else
857 bSuccess = false; // invalid character
861 if ( bSuccess )
863 if ( nDays )
864 nHours += nDays * 24; // add the days to the hours part
865 double fTempTime = 0.0;
866 double fHour = nHours;
867 double fMin = nMins;
868 double fSec = nSecs;
869 double fSec100 = 0.0;
870 double fFraction = sDoubleStr.toDouble();
871 fTempTime = fHour / 24;
872 fTempTime += fMin / (24 * 60);
873 fTempTime += fSec / (24 * 60 * 60);
874 fTempTime += fSec100 / (24 * 60 * 60 * 60);
875 fTempTime += fFraction / (24 * 60 * 60);
877 // negative duration?
878 if ( bIsNegativeDuration )
880 fTempTime = -fTempTime;
883 fTime = fTempTime;
885 return bSuccess;
888 /** convert util::DateTime to ISO Time String */
889 void Converter::convertTime( ::rtl::OUStringBuffer& rBuffer,
890 const ::com::sun::star::util::DateTime& rDateTime )
892 double fHour = rDateTime.Hours;
893 double fMin = rDateTime.Minutes;
894 double fSec = rDateTime.Seconds;
895 double fSec100 = rDateTime.HundredthSeconds;
896 double fTempTime = fHour / 24;
897 fTempTime += fMin / (24 * 60);
898 fTempTime += fSec / (24 * 60 * 60);
899 fTempTime += fSec100 / (24 * 60 * 60 * 100);
900 convertTime( rBuffer, fTempTime );
903 /** convert ISO Time String to util::DateTime */
904 bool Converter::convertTime( ::com::sun::star::util::DateTime& rDateTime,
905 const ::rtl::OUString& rString )
907 double fCalculatedTime = 0.0;
908 if( convertTime( fCalculatedTime, rString ) )
910 // #101357# declare as volatile to prevent optimization
911 // (gcc 3.0.1 Linux)
912 volatile double fTempTime = fCalculatedTime;
913 fTempTime *= 24;
914 double fHoursValue = ::rtl::math::approxFloor (fTempTime);
915 fTempTime -= fHoursValue;
916 fTempTime *= 60;
917 double fMinsValue = ::rtl::math::approxFloor (fTempTime);
918 fTempTime -= fMinsValue;
919 fTempTime *= 60;
920 double fSecsValue = ::rtl::math::approxFloor (fTempTime);
921 fTempTime -= fSecsValue;
922 double f100SecsValue = 0.0;
924 if( fTempTime > 0.00001 )
925 f100SecsValue = fTempTime;
927 rDateTime.Year = 0;
928 rDateTime.Month = 0;
929 rDateTime.Day = 0;
930 rDateTime.Hours = static_cast < sal_uInt16 > ( fHoursValue );
931 rDateTime.Minutes = static_cast < sal_uInt16 > ( fMinsValue );
932 rDateTime.Seconds = static_cast < sal_uInt16 > ( fSecsValue );
933 rDateTime.HundredthSeconds = static_cast < sal_uInt16 > ( f100SecsValue * 100.0 );
935 return true;
937 return false;
940 /** convert util::DateTime to ISO Date String */
941 void Converter::convertDateTime(
942 ::rtl::OUStringBuffer& i_rBuffer,
943 const com::sun::star::util::DateTime& i_rDateTime,
944 bool i_bAddTimeIf0AM )
946 const sal_Unicode dash('-');
947 const sal_Unicode col (':');
948 const sal_Unicode dot ('.');
949 const sal_Unicode zero('0');
950 const sal_Unicode tee ('T');
952 i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Year) ).append(dash);
953 if( i_rDateTime.Month < 10 ) {
954 i_rBuffer.append(zero);
956 i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Month) ).append(dash);
957 if( i_rDateTime.Day < 10 ) {
958 i_rBuffer.append(zero);
960 i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Day) );
962 if( i_rDateTime.Seconds != 0 ||
963 i_rDateTime.Minutes != 0 ||
964 i_rDateTime.Hours != 0 ||
965 i_bAddTimeIf0AM )
967 i_rBuffer.append(tee);
968 if( i_rDateTime.Hours < 10 ) {
969 i_rBuffer.append(zero);
971 i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Hours) )
972 .append(col);
973 if( i_rDateTime.Minutes < 10 ) {
974 i_rBuffer.append(zero);
976 i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Minutes) )
977 .append(col);
978 if( i_rDateTime.Seconds < 10 ) {
979 i_rBuffer.append(zero);
981 i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Seconds) );
982 if( i_rDateTime.HundredthSeconds > 0 ) {
983 i_rBuffer.append(dot);
984 if( i_rDateTime.HundredthSeconds < 10 ) {
985 i_rBuffer.append(zero);
987 i_rBuffer.append(
988 static_cast<sal_Int32>(i_rDateTime.HundredthSeconds) );
993 /** convert ISO Date String to util::DateTime */
994 bool Converter::convertDateTime( com::sun::star::util::DateTime& rDateTime,
995 const ::rtl::OUString& rString )
997 bool bSuccess = true;
999 rtl::OUString aDateStr, aTimeStr, sDoubleStr;
1000 sal_Int32 nPos = rString.indexOf( (sal_Unicode) 'T' );
1001 sal_Int32 nPos2 = rString.indexOf( (sal_Unicode) ',' );
1002 if (nPos2 < 0)
1003 nPos2 = rString.indexOf( (sal_Unicode) '.' );
1004 if ( nPos >= 0 )
1006 aDateStr = rString.copy( 0, nPos );
1007 if ( nPos2 >= 0 )
1009 aTimeStr = rString.copy( nPos + 1, nPos2 - nPos - 1 );
1010 sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0."));
1011 sDoubleStr += rString.copy( nPos2 + 1 );
1013 else
1015 aTimeStr = rString.copy(nPos + 1);
1016 sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0.0"));
1019 else
1020 aDateStr = rString; // no separator: only date part
1022 sal_Int32 nYear = 1899;
1023 sal_Int32 nMonth = 12;
1024 sal_Int32 nDay = 30;
1025 sal_Int32 nHour = 0;
1026 sal_Int32 nMin = 0;
1027 sal_Int32 nSec = 0;
1029 const sal_Unicode* pStr = aDateStr.getStr();
1030 sal_Int32 nDateTokens = 1;
1031 while ( *pStr )
1033 if ( *pStr == '-' )
1034 nDateTokens++;
1035 pStr++;
1037 if ( nDateTokens > 3 || aDateStr.getLength() == 0 )
1038 bSuccess = false;
1039 else
1041 sal_Int32 n = 0;
1042 if ( !convertNumber( nYear, aDateStr.getToken( 0, '-', n ), 0, 9999 ) )
1043 bSuccess = false;
1044 if ( nDateTokens >= 2 )
1045 if ( !convertNumber( nMonth, aDateStr.getToken( 0, '-', n ), 0, 12 ) )
1046 bSuccess = false;
1047 if ( nDateTokens >= 3 )
1048 if ( !convertNumber( nDay, aDateStr.getToken( 0, '-', n ), 0, 31 ) )
1049 bSuccess = false;
1052 if ( aTimeStr.getLength() > 0 ) // time is optional
1054 pStr = aTimeStr.getStr();
1055 sal_Int32 nTimeTokens = 1;
1056 while ( *pStr )
1058 if ( *pStr == ':' )
1059 nTimeTokens++;
1060 pStr++;
1062 if ( nTimeTokens > 3 )
1063 bSuccess = false;
1064 else
1066 sal_Int32 n = 0;
1067 if ( !convertNumber( nHour, aTimeStr.getToken( 0, ':', n ), 0, 23 ) )
1068 bSuccess = false;
1069 if ( nTimeTokens >= 2 )
1070 if ( !convertNumber( nMin, aTimeStr.getToken( 0, ':', n ), 0, 59 ) )
1071 bSuccess = false;
1072 if ( nTimeTokens >= 3 )
1073 if ( !convertNumber( nSec, aTimeStr.getToken( 0, ':', n ), 0, 59 ) )
1074 bSuccess = false;
1078 if (bSuccess)
1080 rDateTime.Year = (sal_uInt16)nYear;
1081 rDateTime.Month = (sal_uInt16)nMonth;
1082 rDateTime.Day = (sal_uInt16)nDay;
1083 rDateTime.Hours = (sal_uInt16)nHour;
1084 rDateTime.Minutes = (sal_uInt16)nMin;
1085 rDateTime.Seconds = (sal_uInt16)nSec;
1086 rDateTime.HundredthSeconds = (sal_uInt16)(sDoubleStr.toDouble() * 100);
1088 return bSuccess;
1091 /** gets the position of the first comma after npos in the string
1092 rStr. Commas inside '"' pairs are not matched */
1093 sal_Int32 Converter::indexOfComma( const OUString& rStr,
1094 sal_Int32 nPos )
1096 sal_Unicode cQuote = 0;
1097 sal_Int32 nLen = rStr.getLength();
1098 for( ; nPos < nLen; nPos++ )
1100 sal_Unicode c = rStr[nPos];
1101 switch( c )
1103 case sal_Unicode('\''):
1104 if( 0 == cQuote )
1105 cQuote = c;
1106 else if( '\'' == cQuote )
1107 cQuote = 0;
1108 break;
1110 case sal_Unicode('"'):
1111 if( 0 == cQuote )
1112 cQuote = c;
1113 else if( '\"' == cQuote )
1114 cQuote = 0;
1115 break;
1117 case sal_Unicode(','):
1118 if( 0 == cQuote )
1119 return nPos;
1120 break;
1124 return -1;
1127 const
1128 sal_Char aBase64EncodeTable[] =
1129 { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
1130 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
1131 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
1132 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
1133 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };
1135 const
1136 sal_uInt8 aBase64DecodeTable[] =
1137 { 62,255,255,255, 63, // 43-47
1138 // + /
1140 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255, // 48-63
1141 // 0 1 2 3 4 5 6 7 8 9 =
1143 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79
1144 // A B C D E F G H I J K L M N O
1146 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255, // 80-95
1147 // P Q R S T U V W X Y Z
1149 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111
1150 // a b c d e f g h i j k l m n o
1152 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 }; // 112-123
1153 // p q r s t u v w x y z
1157 void ThreeByteToFourByte (const sal_Int8* pBuffer, const sal_Int32 nStart, const sal_Int32 nFullLen, rtl::OUStringBuffer& sBuffer)
1159 sal_Int32 nLen(nFullLen - nStart);
1160 if (nLen > 3)
1161 nLen = 3;
1162 if (nLen == 0)
1164 sBuffer.setLength(0);
1165 return;
1168 sal_Int32 nBinaer;
1169 switch (nLen)
1171 case 1:
1173 nBinaer = ((sal_uInt8)pBuffer[nStart + 0]) << 16;
1175 break;
1176 case 2:
1178 nBinaer = (((sal_uInt8)pBuffer[nStart + 0]) << 16) +
1179 (((sal_uInt8)pBuffer[nStart + 1]) << 8);
1181 break;
1182 default:
1184 nBinaer = (((sal_uInt8)pBuffer[nStart + 0]) << 16) +
1185 (((sal_uInt8)pBuffer[nStart + 1]) << 8) +
1186 ((sal_uInt8)pBuffer[nStart + 2]);
1188 break;
1191 sBuffer.appendAscii("====");
1193 sal_uInt8 nIndex (static_cast<sal_uInt8>((nBinaer & 0xFC0000) >> 18));
1194 sBuffer.setCharAt(0, aBase64EncodeTable [nIndex]);
1196 nIndex = static_cast<sal_uInt8>((nBinaer & 0x3F000) >> 12);
1197 sBuffer.setCharAt(1, aBase64EncodeTable [nIndex]);
1198 if (nLen == 1)
1199 return;
1201 nIndex = static_cast<sal_uInt8>((nBinaer & 0xFC0) >> 6);
1202 sBuffer.setCharAt(2, aBase64EncodeTable [nIndex]);
1203 if (nLen == 2)
1204 return;
1206 nIndex = static_cast<sal_uInt8>((nBinaer & 0x3F));
1207 sBuffer.setCharAt(3, aBase64EncodeTable [nIndex]);
1210 void Converter::encodeBase64(rtl::OUStringBuffer& aStrBuffer, const uno::Sequence<sal_Int8>& aPass)
1212 sal_Int32 i(0);
1213 sal_Int32 nBufferLength(aPass.getLength());
1214 const sal_Int8* pBuffer = aPass.getConstArray();
1215 while (i < nBufferLength)
1217 rtl::OUStringBuffer sBuffer;
1218 ThreeByteToFourByte (pBuffer, i, nBufferLength, sBuffer);
1219 aStrBuffer.append(sBuffer);
1220 i += 3;
1224 void Converter::decodeBase64(uno::Sequence<sal_Int8>& aBuffer, const rtl::OUString& sBuffer)
1226 #if OSL_DEBUG_LEVEL > 0
1227 sal_Int32 nCharsDecoded =
1228 #endif
1229 decodeBase64SomeChars( aBuffer, sBuffer );
1230 OSL_ENSURE( nCharsDecoded == sBuffer.getLength(), "some bytes left in base64 decoding!" );
1233 sal_Int32 Converter::decodeBase64SomeChars(
1234 uno::Sequence<sal_Int8>& rOutBuffer,
1235 const rtl::OUString& rInBuffer)
1237 sal_Int32 nInBufferLen = rInBuffer.getLength();
1238 sal_Int32 nMinOutBufferLen = (nInBufferLen / 4) * 3;
1239 if( rOutBuffer.getLength() < nMinOutBufferLen )
1240 rOutBuffer.realloc( nMinOutBufferLen );
1242 const sal_Unicode *pInBuffer = rInBuffer.getStr();
1243 sal_Int8 *pOutBuffer = rOutBuffer.getArray();
1244 sal_Int8 *pOutBufferStart = pOutBuffer;
1245 sal_Int32 nCharsDecoded = 0;
1247 sal_uInt8 aDecodeBuffer[4];
1248 sal_Int32 nBytesToDecode = 0;
1249 sal_Int32 nBytesGotFromDecoding = 3;
1250 sal_Int32 nInBufferPos= 0;
1251 while( nInBufferPos < nInBufferLen )
1253 sal_Unicode cChar = *pInBuffer;
1254 if( cChar >= '+' && cChar <= 'z' )
1256 sal_uInt8 nByte = aBase64DecodeTable[cChar-'+'];
1257 if( nByte != 255 )
1259 // We have found a valid character!
1260 aDecodeBuffer[nBytesToDecode++] = nByte;
1262 // One '=' character at the end means 2 out bytes
1263 // Two '=' characters at the end mean 1 out bytes
1264 if( '=' == cChar && nBytesToDecode > 2 )
1265 nBytesGotFromDecoding--;
1266 if( 4 == nBytesToDecode )
1268 // Four characters found, so we may convert now!
1269 sal_uInt32 nOut = (aDecodeBuffer[0] << 18) +
1270 (aDecodeBuffer[1] << 12) +
1271 (aDecodeBuffer[2] << 6) +
1272 aDecodeBuffer[3];
1274 *pOutBuffer++ = (sal_Int8)((nOut & 0xff0000) >> 16);
1275 if( nBytesGotFromDecoding > 1 )
1276 *pOutBuffer++ = (sal_Int8)((nOut & 0xff00) >> 8);
1277 if( nBytesGotFromDecoding > 2 )
1278 *pOutBuffer++ = (sal_Int8)(nOut & 0xff);
1279 nCharsDecoded = nInBufferPos + 1;
1280 nBytesToDecode = 0;
1281 nBytesGotFromDecoding = 3;
1284 else
1286 nCharsDecoded++;
1289 else
1291 nCharsDecoded++;
1294 nInBufferPos++;
1295 pInBuffer++;
1297 if( (pOutBuffer - pOutBufferStart) != rOutBuffer.getLength() )
1298 rOutBuffer.realloc( pOutBuffer - pOutBufferStart );
1300 return nCharsDecoded;
1303 void Converter::clearUndefinedChars(rtl::OUString& rTarget, const rtl::OUString& rSource)
1305 sal_uInt32 nLength(rSource.getLength());
1306 rtl::OUStringBuffer sBuffer(nLength);
1307 for (sal_uInt32 i = 0; i < nLength; i++)
1309 sal_Unicode cChar = rSource[i];
1310 if (!(cChar < 0x0020) ||
1311 (cChar == 0x0009) || // TAB
1312 (cChar == 0x000A) || // LF
1313 (cChar == 0x000D)) // legal character
1314 sBuffer.append(cChar);
1316 rTarget = sBuffer.makeStringAndClear();
1319 double Converter::GetConversionFactor(::rtl::OUStringBuffer& rUnit, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
1321 double fRetval(1.0);
1322 rUnit.setLength(0L);
1324 const sal_Char* psUnit = 0;
1326 if(nSourceUnit != nTargetUnit)
1328 switch(nSourceUnit)
1330 case MeasureUnit::TWIP:
1332 switch(nTargetUnit)
1334 case MeasureUnit::MM_100TH:
1335 case MeasureUnit::MM_10TH:
1337 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for twip values");
1339 case MeasureUnit::MM:
1341 // 0.01mm = 0.57twip (exactly)
1342 fRetval = ((25400.0 / 1440.0) / 1000.0);
1343 psUnit = gpsMM;
1344 break;
1346 case MeasureUnit::CM:
1348 // 0.001cm = 0.57twip (exactly)
1349 fRetval = ((25400.0 / 1440.0) / 10000.0);
1350 psUnit = gpsCM;
1351 break;
1353 case MeasureUnit::POINT:
1355 // 0.01pt = 0.2twip (exactly)
1356 fRetval = ((1000.0 / 20.0) / 1000.0);
1357 psUnit = gpsPT;
1358 break;
1360 case MeasureUnit::INCH:
1361 default:
1363 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for twip values");
1364 // 0.0001in = 0.144twip (exactly)
1365 fRetval = ((100000.0 / 1440.0) / 100000.0);
1366 psUnit = gpsINCH;
1367 break;
1370 break;
1372 case MeasureUnit::POINT:
1374 switch(nTargetUnit)
1376 case MeasureUnit::MM:
1377 // 1mm = 72 / 25.4 pt (exactly)
1378 fRetval = ( 25.4 / 72.0 );
1379 psUnit = gpsMM;
1380 break;
1382 case MeasureUnit::CM:
1383 // 1cm = 72 / 2.54 pt (exactly)
1384 fRetval = ( 2.54 / 72.0 );
1385 psUnit = gpsCM;
1386 break;
1388 case MeasureUnit::TWIP:
1389 // 1twip = 72 / 1440 pt (exactly)
1390 fRetval = 20.0; // 1440.0 / 72.0
1391 psUnit = gpsPC;
1392 break;
1394 case MeasureUnit::INCH:
1395 default:
1396 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for pt values");
1397 // 1in = 72 pt (exactly)
1398 fRetval = ( 1.0 / 72.0 );
1399 psUnit = gpsINCH;
1400 break;
1402 break;
1404 case MeasureUnit::MM_10TH:
1406 switch(nTargetUnit)
1408 case MeasureUnit::MM_100TH:
1409 case MeasureUnit::MM_10TH:
1411 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values");
1413 case MeasureUnit::MM:
1415 // 0.01mm = 1 mm/100 (exactly)
1416 fRetval = ((10.0 / 1.0) / 100.0);
1417 psUnit = gpsMM;
1418 break;
1420 case MeasureUnit::CM:
1422 // 0.001mm = 1 mm/100 (exactly)
1423 fRetval = ((10.0 / 1.0) / 1000.0);
1424 psUnit = gpsCM;
1425 break;
1427 case MeasureUnit::POINT:
1429 // 0.01pt = 0.35 mm/100 (exactly)
1430 fRetval = ((72000.0 / 2540.0) / 100.0);
1431 psUnit = gpsPT;
1432 break;
1434 case MeasureUnit::INCH:
1435 default:
1437 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values");
1438 // 0.0001in = 0.254 mm/100 (exactly)
1439 fRetval = ((100000.0 / 2540.0) / 10000.0);
1440 psUnit = gpsINCH;
1441 break;
1444 break;
1446 case MeasureUnit::MM_100TH:
1448 switch(nTargetUnit)
1450 case MeasureUnit::MM_100TH:
1451 case MeasureUnit::MM_10TH:
1453 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values");
1455 case MeasureUnit::MM:
1457 // 0.01mm = 1 mm/100 (exactly)
1458 fRetval = ((10.0 / 1.0) / 1000.0);
1459 psUnit = gpsMM;
1460 break;
1462 case MeasureUnit::CM:
1464 // 0.001mm = 1 mm/100 (exactly)
1465 fRetval = ((10.0 / 1.0) / 10000.0);
1466 psUnit = gpsCM;
1467 break;
1469 case MeasureUnit::POINT:
1471 // 0.01pt = 0.35 mm/100 (exactly)
1472 fRetval = ((72000.0 / 2540.0) / 1000.0);
1473 psUnit = gpsPT;
1474 break;
1476 case MeasureUnit::INCH:
1477 default:
1479 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values");
1480 // 0.0001in = 0.254 mm/100 (exactly)
1481 fRetval = ((100000.0 / 2540.0) / 100000.0);
1482 psUnit = gpsINCH;
1483 break;
1486 break;
1490 if( psUnit )
1491 rUnit.appendAscii( psUnit );
1494 return fRetval;
1497 sal_Int16 Converter::GetUnitFromString(const ::rtl::OUString& rString, sal_Int16 nDefaultUnit)
1499 sal_Int32 nPos = 0L;
1500 sal_Int32 nLen = rString.getLength();
1501 sal_Int16 nRetUnit = nDefaultUnit;
1503 // skip white space
1504 while( nPos < nLen && sal_Unicode(' ') == rString[nPos] )
1505 nPos++;
1507 // skip negative
1508 if( nPos < nLen && sal_Unicode('-') == rString[nPos] )
1509 nPos++;
1511 // skip number
1512 while( nPos < nLen && sal_Unicode('0') <= rString[nPos] && sal_Unicode('9') >= rString[nPos] )
1513 nPos++;
1515 if( nPos < nLen && sal_Unicode('.') == rString[nPos] )
1517 nPos++;
1518 while( nPos < nLen && sal_Unicode('0') <= rString[nPos] && sal_Unicode('9') >= rString[nPos] )
1519 nPos++;
1522 // skip white space
1523 while( nPos < nLen && sal_Unicode(' ') == rString[nPos] )
1524 nPos++;
1526 if( nPos < nLen )
1528 switch(rString[nPos])
1530 case sal_Unicode('%') :
1532 nRetUnit = MeasureUnit::PERCENT;
1533 break;
1535 case sal_Unicode('c'):
1536 case sal_Unicode('C'):
1538 if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('m')
1539 || rString[nPos+1] == sal_Unicode('M')))
1540 nRetUnit = MeasureUnit::CM;
1541 break;
1543 case sal_Unicode('e'):
1544 case sal_Unicode('E'):
1546 // CSS1_EMS or CSS1_EMX later
1547 break;
1549 case sal_Unicode('i'):
1550 case sal_Unicode('I'):
1552 if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('n')
1553 || rString[nPos+1] == sal_Unicode('n')))
1554 nRetUnit = MeasureUnit::INCH;
1555 break;
1557 case sal_Unicode('m'):
1558 case sal_Unicode('M'):
1560 if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('m')
1561 || rString[nPos+1] == sal_Unicode('M')))
1562 nRetUnit = MeasureUnit::MM;
1563 break;
1565 case sal_Unicode('p'):
1566 case sal_Unicode('P'):
1568 if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('t')
1569 || rString[nPos+1] == sal_Unicode('T')))
1570 nRetUnit = MeasureUnit::POINT;
1571 if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('c')
1572 || rString[nPos+1] == sal_Unicode('C')))
1573 nRetUnit = MeasureUnit::TWIP;
1574 break;
1579 return nRetUnit;