1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22
23
24
25 #include <com/sun/star/i18n/UnicodeType.hpp>
26 #include <com/sun/star/util/DateTime.hpp>
27 #include <com/sun/star/util/Date.hpp>
28 #include <com/sun/star/util/Duration.hpp>
29 #include <com/sun/star/uno/Sequence.hxx>
30
31 #include <rtl/ustrbuf.hxx>
32 #include <rtl/math.hxx>
33 #include "sax/tools/converter.hxx"
34
35 using namespace rtl;
36 using namespace com::sun::star;
37 using namespace com::sun::star::uno;
38 using namespace com::sun::star::util;
39 //using namespace com::sun::star::text;
40 //using namespace com::sun::star::style;
41 using namespace ::com::sun::star::i18n;
42
43 namespace sax {
44
45 static const sal_Char* gpsMM = "mm";
46 static const sal_Char* gpsCM = "cm";
47 static const sal_Char* gpsPT = "pt";
48 static const sal_Char* gpsINCH = "in";
49 static const sal_Char* gpsPC = "pc";
50
51 const sal_Int8 XML_MAXDIGITSCOUNT_TIME = 11;
52 const sal_Int8 XML_MAXDIGITSCOUNT_DATETIME = 6;
53 #define XML_NULLDATE "NullDate"
54
55 /** convert string to measure using optional min and max values*/
convertMeasure(sal_Int32 & rValue,const OUString & rString,sal_Int16 nTargetUnit,sal_Int32 nMin,sal_Int32 nMax)56 bool Converter::convertMeasure( sal_Int32& rValue,
57 const OUString& rString,
58 sal_Int16 nTargetUnit /* = MeasureUnit::MM_100TH */,
59 sal_Int32 nMin /* = SAL_MIN_INT32 */,
60 sal_Int32 nMax /* = SAL_MAX_INT32 */ )
61 {
62 bool bNeg = false;
63 double nVal = 0;
64
65 sal_Int32 nPos = 0;
66 sal_Int32 nLen = rString.getLength();
67
68 // skip white space
69 while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) )
70 nPos++;
71
72 if( nPos < nLen && sal_Unicode('-') == rString[nPos] )
73 {
74 bNeg = true;
75 nPos++;
76 }
77
78 // get number
79 while( nPos < nLen &&
80 sal_Unicode('0') <= rString[nPos] &&
81 sal_Unicode('9') >= rString[nPos] )
82 {
83 // TODO: check overflow!
84 nVal *= 10;
85 nVal += (rString[nPos] - sal_Unicode('0'));
86 nPos++;
87 }
88 double nDiv = 1.;
89 if( nPos < nLen && sal_Unicode('.') == rString[nPos] )
90 {
91 nPos++;
92
93 while( nPos < nLen &&
94 sal_Unicode('0') <= rString[nPos] &&
95 sal_Unicode('9') >= rString[nPos] )
96 {
97 // TODO: check overflow!
98 nDiv *= 10;
99 nVal += ( ((double)(rString[nPos] - sal_Unicode('0'))) / nDiv );
100 nPos++;
101 }
102 }
103
104 // skip white space
105 while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) )
106 nPos++;
107
108 if( nPos < nLen )
109 {
110
111 if( MeasureUnit::PERCENT == nTargetUnit )
112 {
113 if( sal_Unicode('%') != rString[nPos] )
114 return false;
115 }
116 else if( MeasureUnit::PIXEL == nTargetUnit )
117 {
118 if( nPos + 1 >= nLen ||
119 (sal_Unicode('p') != rString[nPos] &&
120 sal_Unicode('P') != rString[nPos])||
121 (sal_Unicode('x') != rString[nPos+1] &&
122 sal_Unicode('X') != rString[nPos+1]) )
123 return false;
124 }
125 else
126 {
127 OSL_ENSURE( MeasureUnit::TWIP == nTargetUnit || MeasureUnit::POINT == nTargetUnit ||
128 MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit, "unit is not supported");
129 const sal_Char *aCmpsL[2] = { 0, 0 };
130 const sal_Char *aCmpsU[2] = { 0, 0 };
131 double aScales[2] = { 1., 1. };
132
133 if( MeasureUnit::TWIP == nTargetUnit )
134 {
135 switch( rString[nPos] )
136 {
137 case sal_Unicode('c'):
138 case sal_Unicode('C'):
139 aCmpsL[0] = "cm";
140 aCmpsU[0] = "CM";
141 aScales[0] = (72.*20.)/2.54; // twip
142 break;
143 case sal_Unicode('i'):
144 case sal_Unicode('I'):
145 aCmpsL[0] = "in";
146 aCmpsU[0] = "IN";
147 aScales[0] = 72.*20.; // twip
148 break;
149 case sal_Unicode('m'):
150 case sal_Unicode('M'):
151 aCmpsL[0] = "mm";
152 aCmpsU[0] = "MM";
153 aScales[0] = (72.*20.)/25.4; // twip
154 break;
155 case sal_Unicode('p'):
156 case sal_Unicode('P'):
157 aCmpsL[0] = "pt";
158 aCmpsU[0] = "PT";
159 aScales[0] = 20.; // twip
160
161 aCmpsL[1] = "pc";
162 aCmpsU[1] = "PC";
163 aScales[1] = 12.*20.; // twip
164 break;
165 }
166 }
167 else if( MeasureUnit::MM_100TH == nTargetUnit || MeasureUnit::MM_10TH == nTargetUnit )
168 {
169 double nScaleFactor = (MeasureUnit::MM_100TH == nTargetUnit) ? 100.0 : 10.0;
170 switch( rString[nPos] )
171 {
172 case sal_Unicode('c'):
173 case sal_Unicode('C'):
174 aCmpsL[0] = "cm";
175 aCmpsU[0] = "CM";
176 aScales[0] = 10.0 * nScaleFactor; // mm/100
177 break;
178 case sal_Unicode('i'):
179 case sal_Unicode('I'):
180 aCmpsL[0] = "in";
181 aCmpsU[0] = "IN";
182 aScales[0] = 1000.*2.54; // mm/100
183 break;
184 case sal_Unicode('m'):
185 case sal_Unicode('M'):
186 aCmpsL[0] = "mm";
187 aCmpsU[0] = "MM";
188 aScales[0] = 1.0 * nScaleFactor; // mm/100
189 break;
190 case sal_Unicode('p'):
191 case sal_Unicode('P'):
192 aCmpsL[0] = "pt";
193 aCmpsU[0] = "PT";
194 aScales[0] = (10.0 * nScaleFactor*2.54)/72.; // mm/100
195
196 aCmpsL[1] = "pc";
197 aCmpsU[1] = "PC";
198 aScales[1] = (10.0 * nScaleFactor*2.54)/12.; // mm/100
199 break;
200 }
201 }
202 else if( MeasureUnit::POINT == nTargetUnit )
203 {
204 if( rString[nPos] == 'p' || rString[nPos] == 'P' )
205 {
206 aCmpsL[0] = "pt";
207 aCmpsU[0] = "PT";
208 aScales[0] = 1;
209 }
210 }
211
212 if( aCmpsL[0] == NULL )
213 return false;
214
215 double nScale = 0.;
216 for( sal_uInt16 i= 0; i < 2; i++ )
217 {
218 const sal_Char *pL = aCmpsL[i];
219 if( pL )
220 {
221 const sal_Char *pU = aCmpsU[i];
222 while( nPos < nLen && *pL )
223 {
224 sal_Unicode c = rString[nPos];
225 if( c != *pL && c != *pU )
226 break;
227 pL++;
228 pU++;
229 nPos++;
230 }
231 if( !*pL && (nPos == nLen || ' ' == rString[nPos]) )
232 {
233 nScale = aScales[i];
234 break;
235 }
236 }
237 }
238
239 if( 0. == nScale )
240 return false;
241
242 // TODO: check overflow
243 if( nScale != 1. )
244 nVal *= nScale;
245 }
246 }
247
248 nVal += .5;
249 if( bNeg )
250 nVal = -nVal;
251
252 if( nVal <= (double)nMin )
253 rValue = nMin;
254 else if( nVal >= (double)nMax )
255 rValue = nMax;
256 else
257 rValue = (sal_Int32)nVal;
258
259 return true;
260 }
261
262 /** convert measure in given unit to string with given unit */
convertMeasure(OUStringBuffer & rBuffer,sal_Int32 nMeasure,sal_Int16 nSourceUnit,sal_Int16 nTargetUnit)263 void Converter::convertMeasure( OUStringBuffer& rBuffer,
264 sal_Int32 nMeasure,
265 sal_Int16 nSourceUnit /* = MeasureUnit::MM_100TH */,
266 sal_Int16 nTargetUnit /* = MeasureUnit::INCH */ )
267 {
268 OSL_ENSURE( false, "Converter::convertMeasure - not implemented, tools/BigInt needs replacement" );
269 (void)rBuffer;
270 (void)nMeasure;
271 (void)nSourceUnit;
272 (void)nTargetUnit;
273 #if 0
274 if( nSourceUnit == MeasureUnit::PERCENT )
275 {
276 OSL_ENSURE( nTargetUnit == MeasureUnit::PERCENT,
277 "MeasureUnit::PERCENT only maps to MeasureUnit::PERCENT!" );
278
279 rBuffer.append( nMeasure );
280 rBuffer.append( sal_Unicode('%' ) );
281 }
282 else
283 {
284 // the sign is processed seperatly
285 if( nMeasure < 0 )
286 {
287 nMeasure = -nMeasure;
288 rBuffer.append( sal_Unicode('-') );
289 }
290
291 // The new length is (nVal * nMul)/(nDiv*nFac*10)
292 long nMul = 1000;
293 long nDiv = 1;
294 long nFac = 100;
295 const sal_Char* psUnit = 0;
296 switch( nSourceUnit )
297 {
298 case MeasureUnit::TWIP:
299 switch( nTargetUnit )
300 {
301 case MeasureUnit::MM_100TH:
302 case MeasureUnit::MM_10TH:
303 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,"output unit not supported for twip values" );
304 case MeasureUnit::MM:
305 // 0.01mm = 0.57twip (exactly)
306 nMul = 25400; // 25.4 * 1000
307 nDiv = 1440; // 72 * 20;
308 nFac = 100;
309 psUnit = gpsMM;
310 break;
311
312 case MeasureUnit::CM:
313 // 0.001cm = 0.57twip (exactly)
314 nMul = 25400; // 2.54 * 10000
315 nDiv = 1440; // 72 * 20;
316 nFac = 1000;
317 psUnit = gpsCM;
318 break;
319
320 case MeasureUnit::POINT:
321 // 0.01pt = 0.2twip (exactly)
322 nMul = 1000;
323 nDiv = 20;
324 nFac = 100;
325 psUnit = gpsPT;
326 break;
327
328 case MeasureUnit::INCH:
329 default:
330 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,
331 "output unit not supported for twip values" );
332 // 0.0001in = 0.144twip (exactly)
333 nMul = 100000;
334 nDiv = 1440; // 72 * 20;
335 nFac = 10000;
336 psUnit = gpsINCH;
337 break;
338 }
339 break;
340
341 case MeasureUnit::POINT:
342 // 1pt = 1pt (exactly)
343 OSL_ENSURE( MeasureUnit::POINT == nTargetUnit,
344 "output unit not supported for pt values" );
345 nMul = 10;
346 nDiv = 1;
347 nFac = 1;
348 psUnit = gpsPT;
349 break;
350 case MeasureUnit::MM_10TH:
351 case MeasureUnit::MM_100TH:
352 {
353 long nFac2 = (MeasureUnit::MM_100TH == nSourceUnit) ? 100 : 10;
354 switch( nTargetUnit )
355 {
356 case MeasureUnit::MM_100TH:
357 case MeasureUnit::MM_10TH:
358 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,
359 "output unit not supported for 1/100mm values" );
360 case MeasureUnit::MM:
361 // 0.01mm = 1 mm/100 (exactly)
362 nMul = 10;
363 nDiv = 1;
364 nFac = nFac2;
365 psUnit = gpsMM;
366 break;
367
368 case MeasureUnit::CM:
369 // 0.001mm = 1 mm/100 (exactly)
370 nMul = 10;
371 nDiv = 1; // 72 * 20;
372 nFac = 10*nFac2;
373 psUnit = gpsCM;
374 break;
375
376 case MeasureUnit::POINT:
377 // 0.01pt = 0.35 mm/100 (exactly)
378 nMul = 72000;
379 nDiv = 2540;
380 nFac = nFac2;
381 psUnit = gpsPT;
382 break;
383
384 case MeasureUnit::INCH:
385 default:
386 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit,
387 "output unit not supported for 1/100mm values" );
388 // 0.0001in = 0.254 mm/100 (exactly)
389 nMul = 100000;
390 nDiv = 2540;
391 nFac = 100*nFac2;
392 psUnit = gpsINCH;
393 break;
394 }
395 break;
396 }
397 }
398
399 long nLongVal = 0;
400 bool bOutLongVal = true;
401 if( nMeasure > SAL_INT32_MAX / nMul )
402 {
403 // A big int is required for calculation
404 BigInt nBigVal( nMeasure );
405 BigInt nBigFac( nFac );
406 nBigVal *= nMul;
407 nBigVal /= nDiv;
408 nBigVal += 5;
409 nBigVal /= 10;
410
411 if( nBigVal.IsLong() )
412 {
413 // To convert the value into a string a long is sufficient
414 nLongVal = (long)nBigVal;
415 }
416 else
417 {
418 BigInt nBigFac2( nFac );
419 BigInt nBig10( 10 );
420 rBuffer.append( (sal_Int32)(nBigVal / nBigFac2) );
421 if( !(nBigVal % nBigFac2).IsZero() )
422 {
423 rBuffer.append( sal_Unicode('.') );
424 while( nFac > 1 && !(nBigVal % nBigFac2).IsZero() )
425 {
426 nFac /= 10;
427 nBigFac2 = nFac;
428 rBuffer.append( (sal_Int32)((nBigVal / nBigFac2) % nBig10 ) );
429 }
430 }
431 bOutLongVal = false;
432 }
433 }
434 else
435 {
436 nLongVal = nMeasure * nMul;
437 nLongVal /= nDiv;
438 nLongVal += 5;
439 nLongVal /= 10;
440 }
441
442 if( bOutLongVal )
443 {
444 rBuffer.append( (sal_Int32)(nLongVal / nFac) );
445 if( nFac > 1 && (nLongVal % nFac) != 0 )
446 {
447 rBuffer.append( sal_Unicode('.') );
448 while( nFac > 1 && (nLongVal % nFac) != 0 )
449 {
450 nFac /= 10;
451 rBuffer.append( (sal_Int32)((nLongVal / nFac) % 10) );
452 }
453 }
454 }
455
456 if( psUnit )
457 rBuffer.appendAscii( psUnit );
458 }
459 #endif
460 }
461
getTrueString()462 static const OUString& getTrueString()
463 {
464 static const OUString sTrue( RTL_CONSTASCII_USTRINGPARAM( "true" ) );
465 return sTrue;
466 }
467
getFalseString()468 static const OUString& getFalseString()
469 {
470 static const OUString sFalse( RTL_CONSTASCII_USTRINGPARAM( "false" ) );
471 return sFalse;
472 }
473
474 /** convert string to boolean */
convertBool(bool & rBool,const OUString & rString)475 bool Converter::convertBool( bool& rBool, const OUString& rString )
476 {
477 rBool = rString == getTrueString();
478
479 return rBool || (rString == getFalseString());
480 }
481
482 /** convert boolean to string */
convertBool(OUStringBuffer & rBuffer,bool bValue)483 void Converter::convertBool( OUStringBuffer& rBuffer, bool bValue )
484 {
485 rBuffer.append( bValue ? getTrueString() : getFalseString() );
486 }
487
488 /** convert string to percent */
convertPercent(sal_Int32 & rPercent,const OUString & rString)489 bool Converter::convertPercent( sal_Int32& rPercent, const OUString& rString )
490 {
491 return convertMeasure( rPercent, rString, MeasureUnit::PERCENT );
492 }
493
494 /** convert percent to string */
convertPercent(OUStringBuffer & rBuffer,sal_Int32 nValue)495 void Converter::convertPercent( OUStringBuffer& rBuffer, sal_Int32 nValue )
496 {
497 rBuffer.append( nValue );
498 rBuffer.append( sal_Unicode('%' ) );
499 }
500
501 /** convert string to pixel measure */
convertMeasurePx(sal_Int32 & rPixel,const OUString & rString)502 bool Converter::convertMeasurePx( sal_Int32& rPixel, const OUString& rString )
503 {
504 return convertMeasure( rPixel, rString, MeasureUnit::PIXEL );
505 }
506
507 /** convert pixel measure to string */
convertMeasurePx(OUStringBuffer & rBuffer,sal_Int32 nValue)508 void Converter::convertMeasurePx( OUStringBuffer& rBuffer, sal_Int32 nValue )
509 {
510 rBuffer.append( nValue );
511 rBuffer.append( sal_Unicode('p' ) );
512 rBuffer.append( sal_Unicode('x' ) );
513 }
514
lcl_gethex(int nChar)515 int lcl_gethex( int nChar )
516 {
517 if( nChar >= '0' && nChar <= '9' )
518 return nChar - '0';
519 else if( nChar >= 'a' && nChar <= 'f' )
520 return nChar - 'a' + 10;
521 else if( nChar >= 'A' && nChar <= 'F' )
522 return nChar - 'A' + 10;
523 else
524 return 0;
525 }
526
527 /** convert string to color */
convertColor(sal_Int32 & rColor,const OUString & rValue)528 bool Converter::convertColor( sal_Int32& rColor, const OUString& rValue )
529 {
530 if( rValue.getLength() != 7 || rValue[0] != '#' )
531 return false;
532
533 rColor = lcl_gethex( rValue[1] ) * 16 + lcl_gethex( rValue[2] );
534 rColor <<= 8;
535
536 rColor |= ( lcl_gethex( rValue[3] ) * 16 + lcl_gethex( rValue[4] ) );
537 rColor <<= 8;
538
539 rColor |= ( lcl_gethex( rValue[5] ) * 16 + lcl_gethex( rValue[6] ) );
540
541 return true;
542 }
543
544 static sal_Char aHexTab[] = "0123456789abcdef";
545
546 /** convert color to string */
convertColor(OUStringBuffer & rBuffer,sal_Int32 nColor)547 void Converter::convertColor( OUStringBuffer& rBuffer, sal_Int32 nColor )
548 {
549 rBuffer.append( sal_Unicode( '#' ) );
550
551 sal_uInt8 nCol = (sal_uInt8)(nColor >> 16);
552 rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
553 rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
554
555 nCol = (sal_uInt8)(nColor >> 8);
556 rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
557 rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
558
559 nCol = (sal_uInt8)nColor;
560 rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) );
561 rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) );
562 }
563
564 /** convert number to string */
convertNumber(OUStringBuffer & rBuffer,sal_Int32 nNumber)565 void Converter::convertNumber( OUStringBuffer& rBuffer, sal_Int32 nNumber )
566 {
567 rBuffer.append( nNumber );
568 }
569
570 /** convert string to number with optional min and max values */
convertNumber(sal_Int32 & rValue,const OUString & rString,sal_Int32 nMin,sal_Int32 nMax)571 bool Converter::convertNumber( sal_Int32& rValue,
572 const OUString& rString,
573 sal_Int32 nMin, sal_Int32 nMax )
574 {
575 bool bNeg = false;
576 rValue = 0;
577
578 sal_Int32 nPos = 0;
579 sal_Int32 nLen = rString.getLength();
580
581 // skip white space
582 while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) )
583 nPos++;
584
585 if( nPos < nLen && sal_Unicode('-') == rString[nPos] )
586 {
587 bNeg = true;
588 nPos++;
589 }
590
591 // get number
592 while( nPos < nLen &&
593 sal_Unicode('0') <= rString[nPos] &&
594 sal_Unicode('9') >= rString[nPos] )
595 {
596 // TODO: check overflow!
597 rValue *= 10;
598 rValue += (rString[nPos] - sal_Unicode('0'));
599 nPos++;
600 }
601
602 if( bNeg )
603 rValue *= -1;
604
605 if( rValue < nMin )
606 rValue = nMin;
607 else if( rValue > nMax )
608 rValue = nMax;
609
610 return nPos == nLen;
611 }
612
613 /** convert double number to string (using ::rtl::math) */
convertDouble(OUStringBuffer & rBuffer,double fNumber,bool bWriteUnits,sal_Int16 nSourceUnit,sal_Int16 nTargetUnit)614 void Converter::convertDouble( OUStringBuffer& rBuffer,
615 double fNumber,
616 bool bWriteUnits,
617 sal_Int16 nSourceUnit,
618 sal_Int16 nTargetUnit)
619 {
620 if(MeasureUnit::PERCENT == nSourceUnit)
621 {
622 OSL_ENSURE( nTargetUnit == MeasureUnit::PERCENT, "MeasureUnit::PERCENT only maps to MeasureUnit::PERCENT!" );
623 ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
624 if(bWriteUnits)
625 rBuffer.append(sal_Unicode('%'));
626 }
627 else
628 {
629 OUStringBuffer sUnit;
630 double fFactor = GetConversionFactor(sUnit, nSourceUnit, nTargetUnit);
631 if(fFactor != 1.0)
632 fNumber *= fFactor;
633 ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
634 if(bWriteUnits)
635 rBuffer.append(sUnit);
636 }
637 }
638
639 /** convert double number to string (using ::rtl::math) */
convertDouble(::rtl::OUStringBuffer & rBuffer,double fNumber)640 void Converter::convertDouble( ::rtl::OUStringBuffer& rBuffer, double fNumber)
641 {
642 ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', true);
643 }
644
645 /** convert string to double number (using ::rtl::math) */
convertDouble(double & rValue,const::rtl::OUString & rString,sal_Int16 nTargetUnit)646 bool Converter::convertDouble(double& rValue,
647 const ::rtl::OUString& rString, sal_Int16 nTargetUnit)
648 {
649 sal_Int16 nSourceUnit = GetUnitFromString(rString, nTargetUnit);
650
651 return convertDouble(rValue, rString, nSourceUnit, nTargetUnit );
652 }
653
654 /** convert string to double number (using ::rtl::math) */
convertDouble(double & rValue,const::rtl::OUString & rString,sal_Int16 nSourceUnit,sal_Int16 nTargetUnit)655 bool Converter::convertDouble(double& rValue,
656 const ::rtl::OUString& rString, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
657 {
658 rtl_math_ConversionStatus eStatus;
659 rValue = ::rtl::math::stringToDouble( rString, (sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL );
660
661 if(eStatus == rtl_math_ConversionStatus_Ok)
662 {
663 OUStringBuffer sUnit;
664 double fFactor = GetConversionFactor(sUnit, nSourceUnit, nTargetUnit);
665 if(fFactor != 1.0 && fFactor != 0.0)
666 rValue /= fFactor;
667 }
668
669 return ( eStatus == rtl_math_ConversionStatus_Ok );
670 }
671
672 /** convert string to double number (using ::rtl::math) */
convertDouble(double & rValue,const::rtl::OUString & rString)673 bool Converter::convertDouble(double& rValue, const ::rtl::OUString& rString)
674 {
675 rtl_math_ConversionStatus eStatus;
676 rValue = ::rtl::math::stringToDouble( rString, (sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL );
677 return ( eStatus == rtl_math_ConversionStatus_Ok );
678 }
679
680 /** convert double to ISO "duration" string; negative durations allowed */
convertDuration(::rtl::OUStringBuffer & rBuffer,const double fTime)681 void Converter::convertDuration(::rtl::OUStringBuffer& rBuffer,
682 const double fTime)
683 {
684 double fValue = fTime;
685
686 // take care of negative durations as specified in:
687 // XML Schema, W3C Working Draft 07 April 2000, section 3.2.6.1
688 if (fValue < 0.0)
689 {
690 rBuffer.append(sal_Unicode('-'));
691 fValue = - fValue;
692 }
693
694 rBuffer.appendAscii(RTL_CONSTASCII_STRINGPARAM( "PT" ));
695 fValue *= 24;
696 double fHoursValue = ::rtl::math::approxFloor (fValue);
697 fValue -= fHoursValue;
698 fValue *= 60;
699 double fMinsValue = ::rtl::math::approxFloor (fValue);
700 fValue -= fMinsValue;
701 fValue *= 60;
702 double fSecsValue = ::rtl::math::approxFloor (fValue);
703 fValue -= fSecsValue;
704 double f100SecsValue;
705 if (fValue > 0.00001)
706 f100SecsValue = ::rtl::math::round( fValue, XML_MAXDIGITSCOUNT_TIME - 5);
707 else
708 f100SecsValue = 0.0;
709
710 if (f100SecsValue == 1.0)
711 {
712 f100SecsValue = 0.0;
713 fSecsValue += 1.0;
714 }
715 if (fSecsValue >= 60.0)
716 {
717 fSecsValue -= 60.0;
718 fMinsValue += 1.0;
719 }
720 if (fMinsValue >= 60.0)
721 {
722 fMinsValue -= 60.0;
723 fHoursValue += 1.0;
724 }
725
726 if (fHoursValue < 10)
727 rBuffer.append( sal_Unicode('0'));
728 rBuffer.append( sal_Int32( fHoursValue));
729 rBuffer.append( sal_Unicode('H'));
730 if (fMinsValue < 10)
731 rBuffer.append( sal_Unicode('0'));
732 rBuffer.append( sal_Int32( fMinsValue));
733 rBuffer.append( sal_Unicode('M'));
734 if (fSecsValue < 10)
735 rBuffer.append( sal_Unicode('0'));
736 rBuffer.append( sal_Int32( fSecsValue));
737 if (f100SecsValue > 0.0)
738 {
739 ::rtl::OUString a100th( ::rtl::math::doubleToUString( fValue,
740 rtl_math_StringFormat_F, XML_MAXDIGITSCOUNT_TIME - 5, '.',
741 true));
742 if ( a100th.getLength() > 2 )
743 {
744 rBuffer.append( sal_Unicode('.'));
745 rBuffer.append( a100th.copy( 2 ) ); // strip 0.
746 }
747 }
748 rBuffer.append( sal_Unicode('S'));
749 }
750
751 /** convert ISO "duration" string to double; negative durations allowed */
convertDuration(double & rfTime,const::rtl::OUString & rString)752 bool Converter::convertDuration(double& rfTime,
753 const ::rtl::OUString& rString)
754 {
755 rtl::OUString aTrimmed = rString.trim().toAsciiUpperCase();
756 const sal_Unicode* pStr = aTrimmed.getStr();
757
758 // negative time duration?
759 bool bIsNegativeDuration = false;
760 if ( sal_Unicode('-') == (*pStr) )
761 {
762 bIsNegativeDuration = true;
763 pStr++;
764 }
765
766 if ( *(pStr++) != sal_Unicode('P') ) // duration must start with "P"
767 return false;
768
769 rtl::OUString sDoubleStr;
770 bool bSuccess = true;
771 bool bDone = false;
772 bool bTimePart = false;
773 bool bIsFraction = false;
774 sal_Int32 nDays = 0;
775 sal_Int32 nHours = 0;
776 sal_Int32 nMins = 0;
777 sal_Int32 nSecs = 0;
778 sal_Int32 nTemp = 0;
779
780 while ( bSuccess && !bDone )
781 {
782 sal_Unicode c = *(pStr++);
783 if ( !c ) // end
784 bDone = true;
785 else if ( sal_Unicode('0') <= c && sal_Unicode('9') >= c )
786 {
787 if ( nTemp >= SAL_MAX_INT32 / 10 )
788 bSuccess = false;
789 else
790 {
791 if ( !bIsFraction )
792 {
793 nTemp *= 10;
794 nTemp += (c - sal_Unicode('0'));
795 }
796 else
797 {
798 sDoubleStr += OUString::valueOf(c);
799 }
800 }
801 }
802 else if ( bTimePart )
803 {
804 if ( c == sal_Unicode('H') )
805 {
806 nHours = nTemp;
807 nTemp = 0;
808 }
809 else if ( c == sal_Unicode('M') )
810 {
811 nMins = nTemp;
812 nTemp = 0;
813 }
814 else if ( (c == sal_Unicode(',')) || (c == sal_Unicode('.')) )
815 {
816 nSecs = nTemp;
817 nTemp = 0;
818 bIsFraction = true;
819 sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0."));
820 }
821 else if ( c == sal_Unicode('S') )
822 {
823 if ( !bIsFraction )
824 {
825 nSecs = nTemp;
826 nTemp = 0;
827 sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0.0"));
828 }
829 }
830 else
831 bSuccess = false; // invalid character
832 }
833 else
834 {
835 if ( c == sal_Unicode('T') ) // "T" starts time part
836 bTimePart = true;
837 else if ( c == sal_Unicode('D') )
838 {
839 nDays = nTemp;
840 nTemp = 0;
841 }
842 else if ( c == sal_Unicode('Y') || c == sal_Unicode('M') )
843 {
844 //! how many days is a year or month?
845
846 OSL_ENSURE( false, "years or months in duration: not implemented");
847 bSuccess = false;
848 }
849 else
850 bSuccess = false; // invalid character
851 }
852 }
853
854 if ( bSuccess )
855 {
856 if ( nDays )
857 nHours += nDays * 24; // add the days to the hours part
858 double fTempTime = 0.0;
859 double fHour = nHours;
860 double fMin = nMins;
861 double fSec = nSecs;
862 double fSec100 = 0.0;
863 double fFraction = sDoubleStr.toDouble();
864 fTempTime = fHour / 24;
865 fTempTime += fMin / (24 * 60);
866 fTempTime += fSec / (24 * 60 * 60);
867 fTempTime += fSec100 / (24 * 60 * 60 * 60);
868 fTempTime += fFraction / (24 * 60 * 60);
869
870 // negative duration?
871 if ( bIsNegativeDuration )
872 {
873 fTempTime = -fTempTime;
874 }
875
876 rfTime = fTempTime;
877 }
878 return bSuccess;
879 }
880
881 /** convert util::Duration to ISO "duration" string */
convertDuration(::rtl::OUStringBuffer & rBuffer,const::util::Duration & rDuration)882 void Converter::convertDuration(::rtl::OUStringBuffer& rBuffer,
883 const ::util::Duration& rDuration)
884 {
885 if (rDuration.Negative)
886 {
887 rBuffer.append(sal_Unicode('-'));
888 }
889 rBuffer.append(sal_Unicode('P'));
890 const bool bHaveDate(static_cast<sal_Int32>(rDuration.Years)
891 +static_cast<sal_Int32>(rDuration.Months)
892 +static_cast<sal_Int32>(rDuration.Days));
893 if (rDuration.Years)
894 {
895 rBuffer.append(static_cast<sal_Int32>(rDuration.Years));
896 rBuffer.append(sal_Unicode('Y'));
897 }
898 if (rDuration.Months)
899 {
900 rBuffer.append(static_cast<sal_Int32>(rDuration.Months));
901 rBuffer.append(sal_Unicode('M'));
902 }
903 if (rDuration.Days)
904 {
905 rBuffer.append(static_cast<sal_Int32>(rDuration.Days));
906 rBuffer.append(sal_Unicode('D'));
907 }
908 const sal_Int32 nMSecs(static_cast<sal_Int32>(rDuration.Seconds)
909 + static_cast<sal_Int32>(rDuration.MilliSeconds));
910 if (static_cast<sal_Int32>(rDuration.Hours) +
911 static_cast<sal_Int32>(rDuration.Minutes) + nMSecs)
912 {
913 rBuffer.append(sal_Unicode('T')); // time separator
914 if (rDuration.Hours)
915 {
916 rBuffer.append(static_cast<sal_Int32>(rDuration.Hours));
917 rBuffer.append(sal_Unicode('H'));
918 }
919 if (rDuration.Minutes)
920 {
921 rBuffer.append(static_cast<sal_Int32>(rDuration.Minutes));
922 rBuffer.append(sal_Unicode('M'));
923 }
924 if (nMSecs)
925 {
926 // seconds must not be omitted (i.e. ".42S" is not valid)
927 rBuffer.append(static_cast<sal_Int32>(rDuration.Seconds));
928 if (rDuration.MilliSeconds)
929 {
930 rBuffer.append(sal_Unicode('.'));
931 const sal_Int32 nMilliSeconds(rDuration.MilliSeconds % 1000);
932 if (nMilliSeconds < 100)
933 {
934 rBuffer.append(sal_Unicode('0'));
935 }
936 if (nMilliSeconds < 10)
937 {
938 rBuffer.append(sal_Unicode('0'));
939 }
940 if (0 == (nMilliSeconds % 10))
941 {
942 if (0 == (nMilliSeconds % 100))
943 {
944 rBuffer.append(nMilliSeconds / 100);
945 }
946 else
947 {
948 rBuffer.append(nMilliSeconds / 10);
949 }
950 }
951 else
952 {
953 rBuffer.append(nMilliSeconds);
954 }
955 }
956 rBuffer.append(sal_Unicode('S'));
957 }
958 }
959 else if (!bHaveDate)
960 {
961 // zero duration: XMLSchema-2 says there must be at least one component
962 rBuffer.append(sal_Unicode('0'));
963 rBuffer.append(sal_Unicode('D'));
964 }
965 }
966
967 enum Result { R_NOTHING, R_OVERFLOW, R_SUCCESS };
968
969 static Result
readUnsignedNumber(const::rtl::OUString & rString,sal_Int32 & io_rnPos,sal_Int32 & o_rNumber)970 readUnsignedNumber(const ::rtl::OUString & rString,
971 sal_Int32 & io_rnPos, sal_Int32 & o_rNumber)
972 {
973 bool bOverflow(false);
974 sal_Int32 nTemp(0);
975 sal_Int32 nPos(io_rnPos);
976
977 while (nPos < rString.getLength())
978 {
979 const sal_Unicode c = rString[nPos];
980 if ((sal_Unicode('0') <= c) && (c <= sal_Unicode('9')))
981 {
982 nTemp *= 10;
983 nTemp += (c - sal_Unicode('0'));
984 if (nTemp >= SAL_MAX_INT16)
985 {
986 bOverflow = true;
987 }
988 }
989 else
990 {
991 break;
992 }
993 ++nPos;
994 }
995
996 if (io_rnPos == nPos) // read something?
997 {
998 o_rNumber = -1;
999 return R_NOTHING;
1000 }
1001
1002 io_rnPos = nPos;
1003 o_rNumber = nTemp;
1004 return (bOverflow) ? R_OVERFLOW : R_SUCCESS;
1005 }
1006
1007 static bool
readDurationT(const::rtl::OUString & rString,sal_Int32 & io_rnPos)1008 readDurationT(const ::rtl::OUString & rString, sal_Int32 & io_rnPos)
1009 {
1010 if ((io_rnPos < rString.getLength()) &&
1011 (rString[io_rnPos] == sal_Unicode('T')))
1012 {
1013 ++io_rnPos;
1014 return true;
1015 }
1016 return false;
1017 }
1018
1019 static bool
readDurationComponent(const::rtl::OUString & rString,sal_Int32 & io_rnPos,sal_Int32 & io_rnTemp,bool & io_rbTimePart,sal_Int32 & o_rnTarget,const sal_Unicode c)1020 readDurationComponent(const ::rtl::OUString & rString,
1021 sal_Int32 & io_rnPos, sal_Int32 & io_rnTemp, bool & io_rbTimePart,
1022 sal_Int32 & o_rnTarget, const sal_Unicode c)
1023 {
1024 if ((io_rnPos < rString.getLength()))
1025 {
1026 if (c == rString[io_rnPos])
1027 {
1028 ++io_rnPos;
1029 if (-1 != io_rnTemp)
1030 {
1031 o_rnTarget = io_rnTemp;
1032 io_rnTemp = -1;
1033 if (!io_rbTimePart)
1034 {
1035 io_rbTimePart = readDurationT(rString, io_rnPos);
1036 }
1037 return (R_OVERFLOW !=
1038 readUnsignedNumber(rString, io_rnPos, io_rnTemp));
1039 }
1040 else
1041 {
1042 return false;
1043 }
1044 }
1045 }
1046 return true;
1047 }
1048
1049 /** convert ISO "duration" string to util::Duration */
convertDuration(util::Duration & rDuration,const::rtl::OUString & rString)1050 bool Converter::convertDuration(util::Duration& rDuration,
1051 const ::rtl::OUString& rString)
1052 {
1053 const ::rtl::OUString string = rString.trim().toAsciiUpperCase();
1054 sal_Int32 nPos(0);
1055
1056 bool bIsNegativeDuration(false);
1057 if (string.getLength() && (sal_Unicode('-') == string[0]))
1058 {
1059 bIsNegativeDuration = true;
1060 ++nPos;
1061 }
1062
1063 if ((nPos < string.getLength())
1064 && (string[nPos] != sal_Unicode('P'))) // duration must start with "P"
1065 {
1066 return false;
1067 }
1068
1069 ++nPos;
1070
1071 /// last read number; -1 == no valid number! always reset after using!
1072 sal_Int32 nTemp(-1);
1073 bool bTimePart(false); // have we read 'T'?
1074 bool bSuccess(false);
1075 sal_Int32 nYears(0);
1076 sal_Int32 nMonths(0);
1077 sal_Int32 nDays(0);
1078 sal_Int32 nHours(0);
1079 sal_Int32 nMinutes(0);
1080 sal_Int32 nSeconds(0);
1081 sal_Int32 nMilliSeconds(0);
1082
1083 bTimePart = readDurationT(string, nPos);
1084 bSuccess = (R_SUCCESS == readUnsignedNumber(string, nPos, nTemp));
1085
1086 if (!bTimePart && bSuccess)
1087 {
1088 bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1089 nYears, sal_Unicode('Y'));
1090 }
1091
1092 if (!bTimePart && bSuccess)
1093 {
1094 bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1095 nMonths, sal_Unicode('M'));
1096 }
1097
1098 if (!bTimePart && bSuccess)
1099 {
1100 bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1101 nDays, sal_Unicode('D'));
1102 }
1103
1104 if (bTimePart)
1105 {
1106 if (-1 == nTemp) // a 'T' must be followed by a component
1107 {
1108 bSuccess = false;
1109 }
1110
1111 if (bSuccess)
1112 {
1113 bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1114 nHours, sal_Unicode('H'));
1115 }
1116
1117 if (bSuccess)
1118 {
1119 bSuccess = readDurationComponent(string, nPos, nTemp, bTimePart,
1120 nMinutes, sal_Unicode('M'));
1121 }
1122
1123 // eeek! seconds are icky.
1124 if ((nPos < string.getLength()) && bSuccess)
1125 {
1126 if (sal_Unicode('.') == string[nPos])
1127 {
1128 ++nPos;
1129 if (-1 != nTemp)
1130 {
1131 nSeconds = nTemp;
1132 nTemp = -1;
1133 const sal_Int32 nStart(nPos);
1134 bSuccess =
1135 (R_NOTHING != readUnsignedNumber(string, nPos, nTemp));
1136 if ((nPos < string.getLength()) && bSuccess)
1137 {
1138 if (-1 != nTemp)
1139 {
1140 nTemp = -1;
1141 const sal_Int32 nDigits = nPos - nStart;
1142 OSL_ENSURE(nDigits > 0, "bad code monkey");
1143 const sal_Unicode cZero('0');
1144 nMilliSeconds = 100 * (string[nStart] - cZero);
1145 if (nDigits >= 2)
1146 {
1147 nMilliSeconds += 10 *
1148 (string[nStart+1] - cZero);
1149 if (nDigits >= 3)
1150 {
1151 nMilliSeconds += (string[nStart+2] - cZero);
1152 }
1153 }
1154
1155 if (sal_Unicode('S') == string[nPos])
1156 {
1157 ++nPos;
1158 }
1159 else
1160 {
1161 bSuccess = false;
1162 }
1163 }
1164 else
1165 {
1166 bSuccess = false;
1167 }
1168 }
1169 }
1170 else
1171 {
1172 bSuccess = false;
1173 }
1174 }
1175 else if (sal_Unicode('S') == string[nPos])
1176 {
1177 ++nPos;
1178 if (-1 != nTemp)
1179 {
1180 nSeconds = nTemp;
1181 nTemp = -1;
1182 }
1183 else
1184 {
1185 bSuccess = false;
1186 }
1187 }
1188 }
1189 }
1190
1191 if (nPos != string.getLength()) // string not processed completely?
1192 {
1193 bSuccess = false;
1194 }
1195
1196 if (nTemp != -1) // unprocessed number?
1197 {
1198 bSuccess = false;
1199 }
1200
1201 if (bSuccess)
1202 {
1203 rDuration.Negative = bIsNegativeDuration;
1204 rDuration.Years = static_cast<sal_Int16>(nYears);
1205 rDuration.Months = static_cast<sal_Int16>(nMonths);
1206 rDuration.Days = static_cast<sal_Int16>(nDays);
1207 rDuration.Hours = static_cast<sal_Int16>(nHours);
1208 rDuration.Minutes = static_cast<sal_Int16>(nMinutes);
1209 rDuration.Seconds = static_cast<sal_Int16>(nSeconds);
1210 rDuration.MilliSeconds = static_cast<sal_Int16>(nMilliSeconds);
1211 }
1212
1213 return bSuccess;
1214 }
1215
1216
1217 /** convert util::Date to ISO "date" string */
convertDate(::rtl::OUStringBuffer & i_rBuffer,const util::Date & i_rDate)1218 void Converter::convertDate(
1219 ::rtl::OUStringBuffer& i_rBuffer,
1220 const util::Date& i_rDate)
1221 {
1222 const util::DateTime dt(
1223 0, 0, 0, 0, i_rDate.Day, i_rDate.Month, i_rDate.Year);
1224 convertDateTime(i_rBuffer, dt, false);
1225 }
1226
1227 /** convert util::DateTime to ISO "date" or "dateTime" string */
convertDateTime(::rtl::OUStringBuffer & i_rBuffer,const com::sun::star::util::DateTime & i_rDateTime,bool i_bAddTimeIf0AM)1228 void Converter::convertDateTime(
1229 ::rtl::OUStringBuffer& i_rBuffer,
1230 const com::sun::star::util::DateTime& i_rDateTime,
1231 bool i_bAddTimeIf0AM )
1232 {
1233 const sal_Unicode dash('-');
1234 const sal_Unicode col (':');
1235 const sal_Unicode dot ('.');
1236 const sal_Unicode zero('0');
1237 const sal_Unicode tee ('T');
1238
1239 if (i_rDateTime.Year < 1000) {
1240 i_rBuffer.append(zero);
1241 }
1242 if (i_rDateTime.Year < 100) {
1243 i_rBuffer.append(zero);
1244 }
1245 if (i_rDateTime.Year < 10) {
1246 i_rBuffer.append(zero);
1247 }
1248 i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Year) ).append(dash);
1249 if( i_rDateTime.Month < 10 ) {
1250 i_rBuffer.append(zero);
1251 }
1252 i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Month) ).append(dash);
1253 if( i_rDateTime.Day < 10 ) {
1254 i_rBuffer.append(zero);
1255 }
1256 i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Day) );
1257
1258 if( i_rDateTime.Seconds != 0 ||
1259 i_rDateTime.Minutes != 0 ||
1260 i_rDateTime.Hours != 0 ||
1261 i_bAddTimeIf0AM )
1262 {
1263 i_rBuffer.append(tee);
1264 if( i_rDateTime.Hours < 10 ) {
1265 i_rBuffer.append(zero);
1266 }
1267 i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Hours) )
1268 .append(col);
1269 if( i_rDateTime.Minutes < 10 ) {
1270 i_rBuffer.append(zero);
1271 }
1272 i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Minutes) )
1273 .append(col);
1274 if( i_rDateTime.Seconds < 10 ) {
1275 i_rBuffer.append(zero);
1276 }
1277 i_rBuffer.append( static_cast<sal_Int32>(i_rDateTime.Seconds) );
1278 if( i_rDateTime.HundredthSeconds > 0 ) {
1279 i_rBuffer.append(dot);
1280 if( i_rDateTime.HundredthSeconds < 10 ) {
1281 i_rBuffer.append(zero);
1282 }
1283 i_rBuffer.append(
1284 static_cast<sal_Int32>(i_rDateTime.HundredthSeconds) );
1285 }
1286 }
1287 }
1288
1289 /** convert ISO "date" or "dateTime" string to util::DateTime */
convertDateTime(util::DateTime & rDateTime,const::rtl::OUString & rString)1290 bool Converter::convertDateTime( util::DateTime& rDateTime,
1291 const ::rtl::OUString& rString )
1292 {
1293 bool isDateTime;
1294 util::Date date;
1295 if (convertDateOrDateTime(date, rDateTime, isDateTime, rString))
1296 {
1297 if (!isDateTime)
1298 {
1299 rDateTime.Year = date.Year;
1300 rDateTime.Month = date.Month;
1301 rDateTime.Day = date.Day;
1302 rDateTime.Hours = 0;
1303 rDateTime.Minutes = 0;
1304 rDateTime.Seconds = 0;
1305 rDateTime.HundredthSeconds = 0;
1306 }
1307 return true;
1308 }
1309 else
1310 {
1311 return false;
1312 }
1313 }
1314
1315 static bool
readDateTimeComponent(const::rtl::OUString & rString,sal_Int32 & io_rnPos,sal_Int32 & o_rnTarget,const sal_Int32 nMinLength,const bool bExactLength)1316 readDateTimeComponent(const ::rtl::OUString & rString,
1317 sal_Int32 & io_rnPos, sal_Int32 & o_rnTarget,
1318 const sal_Int32 nMinLength, const bool bExactLength)
1319 {
1320 const sal_Int32 nOldPos(io_rnPos);
1321 sal_Int32 nTemp(0);
1322 if (R_SUCCESS != readUnsignedNumber(rString, io_rnPos, nTemp))
1323 {
1324 return false;
1325 }
1326 const sal_Int32 nTokenLength(io_rnPos - nOldPos);
1327 if ((nTokenLength < nMinLength) ||
1328 (bExactLength && (nTokenLength > nMinLength)))
1329 {
1330 return false; // bad length
1331 }
1332 o_rnTarget = nTemp;
1333 return true;
1334 }
1335
lcl_isLeapYear(const sal_uInt32 nYear)1336 static bool lcl_isLeapYear(const sal_uInt32 nYear)
1337 {
1338 return (((nYear % 4 == 0) && (nYear % 100 != 0)) ||
1339 (nYear % 400 == 0));
1340 }
1341
1342 static sal_uInt16
lcl_MaxDaysPerMonth(const sal_Int32 nMonth,const sal_Int32 nYear)1343 lcl_MaxDaysPerMonth(const sal_Int32 nMonth, const sal_Int32 nYear)
1344 {
1345 static sal_uInt16 s_MaxDaysPerMonth[12] =
1346 { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
1347 OSL_ASSERT(0 < nMonth && nMonth <= 12);
1348 if ((2 == nMonth) && lcl_isLeapYear(nYear))
1349 {
1350 return 29;
1351 }
1352 return s_MaxDaysPerMonth[nMonth - 1];
1353 }
1354
1355 /** convert ISO "date" or "dateTime" string to util::DateTime or util::Date */
convertDateOrDateTime(util::Date & rDate,util::DateTime & rDateTime,bool & rbDateTime,const::rtl::OUString & rString)1356 bool Converter::convertDateOrDateTime(
1357 util::Date & rDate, util::DateTime & rDateTime,
1358 bool & rbDateTime, const ::rtl::OUString & rString )
1359 {
1360 bool bSuccess = true;
1361
1362 const ::rtl::OUString string = rString.trim().toAsciiUpperCase();
1363 sal_Int32 nPos(0);
1364 bool bNegative(false);
1365 if ((string.getLength() > nPos) && (sal_Unicode('-') == string[nPos]))
1366 {
1367 ++nPos;
1368 bNegative = true;
1369 }
1370
1371 sal_Int32 nYear(0);
1372 {
1373 bSuccess = readDateTimeComponent(string, nPos, nYear, 4, false);
1374 bSuccess &= (0 < nYear);
1375 bSuccess &= (nPos < string.getLength()); // not last token
1376 }
1377 if (bSuccess && (sal_Unicode('-') != string[nPos])) // separator
1378 {
1379 bSuccess = false;
1380 }
1381 if (bSuccess)
1382 {
1383 ++nPos;
1384 }
1385
1386 sal_Int32 nMonth(0);
1387 if (bSuccess)
1388 {
1389 bSuccess = readDateTimeComponent(string, nPos, nMonth, 2, true);
1390 bSuccess &= (0 < nMonth) && (nMonth <= 12);
1391 bSuccess &= (nPos < string.getLength()); // not last token
1392 }
1393 if (bSuccess && (sal_Unicode('-') != string[nPos])) // separator
1394 {
1395 bSuccess = false;
1396 }
1397 if (bSuccess)
1398 {
1399 ++nPos;
1400 }
1401
1402 sal_Int32 nDay(0);
1403 if (bSuccess)
1404 {
1405 bSuccess = readDateTimeComponent(string, nPos, nDay, 2, true);
1406 bSuccess &= (0 < nDay) && (nDay <= lcl_MaxDaysPerMonth(nMonth, nYear));
1407 }
1408
1409 bool bHaveTime(false);
1410 if (bSuccess && (nPos < string.getLength()))
1411 {
1412 if (sal_Unicode('T') == string[nPos]) // time separator
1413 {
1414 bHaveTime = true;
1415 ++nPos;
1416 }
1417 }
1418
1419 sal_Int32 nHours(0);
1420 sal_Int32 nMinutes(0);
1421 sal_Int32 nSeconds(0);
1422 sal_Int32 nMilliSeconds(0);
1423 if (bSuccess && bHaveTime)
1424 {
1425 {
1426 bSuccess = readDateTimeComponent(string, nPos, nHours, 2, true);
1427 bSuccess &= (0 <= nHours) && (nHours <= 24);
1428 bSuccess &= (nPos < string.getLength()); // not last token
1429 }
1430 if (bSuccess && (sal_Unicode(':') != string[nPos])) // separator
1431 {
1432 bSuccess = false;
1433 }
1434 if (bSuccess)
1435 {
1436 ++nPos;
1437 }
1438
1439 if (bSuccess)
1440 {
1441 bSuccess = readDateTimeComponent(string, nPos, nMinutes, 2, true);
1442 bSuccess &= (0 <= nMinutes) && (nMinutes < 60);
1443 bSuccess &= (nPos < string.getLength()); // not last token
1444 }
1445 if (bSuccess && (sal_Unicode(':') != string[nPos])) // separator
1446 {
1447 bSuccess = false;
1448 }
1449 if (bSuccess)
1450 {
1451 ++nPos;
1452 }
1453
1454 if (bSuccess)
1455 {
1456 bSuccess = readDateTimeComponent(string, nPos, nSeconds, 2, true);
1457 bSuccess &= (0 <= nSeconds) && (nSeconds < 60);
1458 }
1459 if (bSuccess && (nPos < string.getLength()) &&
1460 (sal_Unicode('.') == string[nPos])) // fraction separator
1461 {
1462 ++nPos;
1463 const sal_Int32 nStart(nPos);
1464 sal_Int32 nTemp(0);
1465 if (R_NOTHING == readUnsignedNumber(string, nPos, nTemp))
1466 {
1467 bSuccess = false;
1468 }
1469 if (bSuccess)
1470 {
1471 // cannot use nTemp because of possible leading zeros
1472 // and possible overflow => read digits directly
1473 const sal_Int32 nDigits(nPos - nStart);
1474 OSL_ENSURE(nDigits > 0, "bad code monkey");
1475 const sal_Unicode cZero('0');
1476 nMilliSeconds = 100 * (string[nStart] - cZero);
1477 if (nDigits >= 2)
1478 {
1479 nMilliSeconds += 10 * (string[nStart+1] - cZero);
1480 if (nDigits >= 3)
1481 {
1482 nMilliSeconds += (string[nStart+2] - cZero);
1483 }
1484 }
1485 }
1486 }
1487
1488 if (bSuccess && (nHours == 24))
1489 {
1490 if (!((0 == nMinutes) && (0 == nSeconds) && (0 == nMilliSeconds)))
1491 {
1492 bSuccess = false; // only 24:00:00 is valid
1493 }
1494 #if 0
1495 else
1496 {
1497 nHours = 0; // normalize 24:00:00 to 00:00:00 of next day
1498 lcl_addDay(bNegative, nYear, nMonth, nDay, 1);
1499 }
1500 #endif
1501 }
1502 }
1503
1504 bool bHaveTimezone(false);
1505 bool bHaveTimezonePlus(false);
1506 bool bHaveTimezoneMinus(false);
1507 if (bSuccess && (nPos < string.getLength()))
1508 {
1509 const sal_Unicode c(string[nPos]);
1510 if (sal_Unicode('+') == c)
1511 {
1512 bHaveTimezone = true;
1513 bHaveTimezonePlus = true;
1514 ++nPos;
1515 }
1516 else if (sal_Unicode('-') == c)
1517 {
1518 bHaveTimezone = true;
1519 bHaveTimezoneMinus = true;
1520 ++nPos;
1521 }
1522 else if (sal_Unicode('Z') == c)
1523 {
1524 bHaveTimezone = true;
1525 ++nPos;
1526 }
1527 else
1528 {
1529 bSuccess = false;
1530 }
1531 }
1532 sal_Int32 nTimezoneHours(0);
1533 sal_Int32 nTimezoneMinutes(0);
1534 if (bSuccess && (bHaveTimezonePlus || bHaveTimezoneMinus))
1535 {
1536 bSuccess = readDateTimeComponent(
1537 string, nPos, nTimezoneHours, 2, true);
1538 bSuccess &= (0 <= nTimezoneHours) && (nTimezoneHours <= 14);
1539 bSuccess &= (nPos < string.getLength()); // not last token
1540 if (bSuccess && (sal_Unicode(':') != string[nPos])) // separator
1541 {
1542 bSuccess = false;
1543 }
1544 if (bSuccess)
1545 {
1546 ++nPos;
1547 }
1548 if (bSuccess)
1549 {
1550 bSuccess = readDateTimeComponent(
1551 string, nPos, nTimezoneMinutes, 2, true);
1552 bSuccess &= (0 <= nTimezoneMinutes) && (nTimezoneMinutes < 60);
1553 }
1554 if (bSuccess && (nTimezoneHours == 14))
1555 {
1556 if (0 != nTimezoneMinutes)
1557 {
1558 bSuccess = false; // only +-14:00 is valid
1559 }
1560 }
1561 }
1562
1563 bSuccess &= (nPos == string.getLength()); // trailing junk?
1564
1565 if (bSuccess && bHaveTimezone)
1566 {
1567 // util::DateTime does not support timezones!
1568 #if 0
1569 // do not add timezone, just strip it (as suggested by er)
1570 lcl_addTimezone(bNegative, nYear, nMonth, nDay, nHours, nMinutes,
1571 !bHaveTimezoneMinus, nTimezoneHours, nTimezoneMinutes);
1572 #endif
1573 }
1574
1575 if (bSuccess)
1576 {
1577 if (bHaveTime) // time is optional
1578 {
1579 // util::DateTime does not support negative years!
1580 rDateTime.Year = static_cast<sal_uInt16>(nYear);
1581 rDateTime.Month = static_cast<sal_uInt16>(nMonth);
1582 rDateTime.Day = static_cast<sal_uInt16>(nDay);
1583 rDateTime.Hours = static_cast<sal_uInt16>(nHours);
1584 rDateTime.Minutes = static_cast<sal_uInt16>(nMinutes);
1585 rDateTime.Seconds = static_cast<sal_uInt16>(nSeconds);
1586 // util::DateTime does not support 3 decimal digits of precision!
1587 rDateTime.HundredthSeconds =
1588 static_cast<sal_uInt16>(nMilliSeconds / 10);
1589 rbDateTime = true;
1590 }
1591 else
1592 {
1593 rDate.Year = static_cast<sal_uInt16>(nYear);
1594 rDate.Month = static_cast<sal_uInt16>(nMonth);
1595 rDate.Day = static_cast<sal_uInt16>(nDay);
1596 rbDateTime = false;
1597 }
1598 }
1599 return bSuccess;
1600 }
1601
1602
1603 /** gets the position of the first comma after npos in the string
1604 rStr. Commas inside '"' pairs are not matched */
indexOfComma(const OUString & rStr,sal_Int32 nPos)1605 sal_Int32 Converter::indexOfComma( const OUString& rStr,
1606 sal_Int32 nPos )
1607 {
1608 sal_Unicode cQuote = 0;
1609 sal_Int32 nLen = rStr.getLength();
1610 for( ; nPos < nLen; nPos++ )
1611 {
1612 sal_Unicode c = rStr[nPos];
1613 switch( c )
1614 {
1615 case sal_Unicode('\''):
1616 if( 0 == cQuote )
1617 cQuote = c;
1618 else if( '\'' == cQuote )
1619 cQuote = 0;
1620 break;
1621
1622 case sal_Unicode('"'):
1623 if( 0 == cQuote )
1624 cQuote = c;
1625 else if( '\"' == cQuote )
1626 cQuote = 0;
1627 break;
1628
1629 case sal_Unicode(','):
1630 if( 0 == cQuote )
1631 return nPos;
1632 break;
1633 }
1634 }
1635
1636 return -1;
1637 }
1638
1639 const
1640 sal_Char aBase64EncodeTable[] =
1641 { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
1642 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
1643 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm',
1644 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
1645 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };
1646
1647 const
1648 sal_uInt8 aBase64DecodeTable[] =
1649 { 62,255,255,255, 63, // 43-47
1650 // + /
1651
1652 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255, // 48-63
1653 // 0 1 2 3 4 5 6 7 8 9 =
1654
1655 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79
1656 // A B C D E F G H I J K L M N O
1657
1658 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255, // 80-95
1659 // P Q R S T U V W X Y Z
1660
1661 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111
1662 // a b c d e f g h i j k l m n o
1663
1664 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 }; // 112-123
1665 // p q r s t u v w x y z
1666
1667
1668
ThreeByteToFourByte(const sal_Int8 * pBuffer,const sal_Int32 nStart,const sal_Int32 nFullLen,rtl::OUStringBuffer & sBuffer)1669 void ThreeByteToFourByte (const sal_Int8* pBuffer, const sal_Int32 nStart, const sal_Int32 nFullLen, rtl::OUStringBuffer& sBuffer)
1670 {
1671 sal_Int32 nLen(nFullLen - nStart);
1672 if (nLen > 3)
1673 nLen = 3;
1674 if (nLen == 0)
1675 {
1676 sBuffer.setLength(0);
1677 return;
1678 }
1679
1680 sal_Int32 nBinaer;
1681 switch (nLen)
1682 {
1683 case 1:
1684 {
1685 nBinaer = ((sal_uInt8)pBuffer[nStart + 0]) << 16;
1686 }
1687 break;
1688 case 2:
1689 {
1690 nBinaer = (((sal_uInt8)pBuffer[nStart + 0]) << 16) +
1691 (((sal_uInt8)pBuffer[nStart + 1]) << 8);
1692 }
1693 break;
1694 default:
1695 {
1696 nBinaer = (((sal_uInt8)pBuffer[nStart + 0]) << 16) +
1697 (((sal_uInt8)pBuffer[nStart + 1]) << 8) +
1698 ((sal_uInt8)pBuffer[nStart + 2]);
1699 }
1700 break;
1701 }
1702
1703 sBuffer.appendAscii("====");
1704
1705 sal_uInt8 nIndex (static_cast<sal_uInt8>((nBinaer & 0xFC0000) >> 18));
1706 sBuffer.setCharAt(0, aBase64EncodeTable [nIndex]);
1707
1708 nIndex = static_cast<sal_uInt8>((nBinaer & 0x3F000) >> 12);
1709 sBuffer.setCharAt(1, aBase64EncodeTable [nIndex]);
1710 if (nLen == 1)
1711 return;
1712
1713 nIndex = static_cast<sal_uInt8>((nBinaer & 0xFC0) >> 6);
1714 sBuffer.setCharAt(2, aBase64EncodeTable [nIndex]);
1715 if (nLen == 2)
1716 return;
1717
1718 nIndex = static_cast<sal_uInt8>((nBinaer & 0x3F));
1719 sBuffer.setCharAt(3, aBase64EncodeTable [nIndex]);
1720 }
1721
encodeBase64(rtl::OUStringBuffer & aStrBuffer,const uno::Sequence<sal_Int8> & aPass)1722 void Converter::encodeBase64(rtl::OUStringBuffer& aStrBuffer, const uno::Sequence<sal_Int8>& aPass)
1723 {
1724 sal_Int32 i(0);
1725 sal_Int32 nBufferLength(aPass.getLength());
1726 const sal_Int8* pBuffer = aPass.getConstArray();
1727 while (i < nBufferLength)
1728 {
1729 rtl::OUStringBuffer sBuffer;
1730 ThreeByteToFourByte (pBuffer, i, nBufferLength, sBuffer);
1731 aStrBuffer.append(sBuffer);
1732 i += 3;
1733 }
1734 }
1735
decodeBase64(uno::Sequence<sal_Int8> & aBuffer,const rtl::OUString & sBuffer)1736 void Converter::decodeBase64(uno::Sequence<sal_Int8>& aBuffer, const rtl::OUString& sBuffer)
1737 {
1738 #if OSL_DEBUG_LEVEL > 0
1739 sal_Int32 nCharsDecoded =
1740 #endif
1741 decodeBase64SomeChars( aBuffer, sBuffer );
1742 OSL_ENSURE( nCharsDecoded == sBuffer.getLength(), "some bytes left in base64 decoding!" );
1743 }
1744
decodeBase64SomeChars(uno::Sequence<sal_Int8> & rOutBuffer,const rtl::OUString & rInBuffer)1745 sal_Int32 Converter::decodeBase64SomeChars(
1746 uno::Sequence<sal_Int8>& rOutBuffer,
1747 const rtl::OUString& rInBuffer)
1748 {
1749 sal_Int32 nInBufferLen = rInBuffer.getLength();
1750 sal_Int32 nMinOutBufferLen = (nInBufferLen / 4) * 3;
1751 if( rOutBuffer.getLength() < nMinOutBufferLen )
1752 rOutBuffer.realloc( nMinOutBufferLen );
1753
1754 const sal_Unicode *pInBuffer = rInBuffer.getStr();
1755 sal_Int8 *pOutBuffer = rOutBuffer.getArray();
1756 sal_Int8 *pOutBufferStart = pOutBuffer;
1757 sal_Int32 nCharsDecoded = 0;
1758
1759 sal_uInt8 aDecodeBuffer[4];
1760 sal_Int32 nBytesToDecode = 0;
1761 sal_Int32 nBytesGotFromDecoding = 3;
1762 sal_Int32 nInBufferPos= 0;
1763 while( nInBufferPos < nInBufferLen )
1764 {
1765 sal_Unicode cChar = *pInBuffer;
1766 if( cChar >= '+' && cChar <= 'z' )
1767 {
1768 sal_uInt8 nByte = aBase64DecodeTable[cChar-'+'];
1769 if( nByte != 255 )
1770 {
1771 // We have found a valid character!
1772 aDecodeBuffer[nBytesToDecode++] = nByte;
1773
1774 // One '=' character at the end means 2 out bytes
1775 // Two '=' characters at the end mean 1 out bytes
1776 if( '=' == cChar && nBytesToDecode > 2 )
1777 nBytesGotFromDecoding--;
1778 if( 4 == nBytesToDecode )
1779 {
1780 // Four characters found, so we may convert now!
1781 sal_uInt32 nOut = (aDecodeBuffer[0] << 18) +
1782 (aDecodeBuffer[1] << 12) +
1783 (aDecodeBuffer[2] << 6) +
1784 aDecodeBuffer[3];
1785
1786 *pOutBuffer++ = (sal_Int8)((nOut & 0xff0000) >> 16);
1787 if( nBytesGotFromDecoding > 1 )
1788 *pOutBuffer++ = (sal_Int8)((nOut & 0xff00) >> 8);
1789 if( nBytesGotFromDecoding > 2 )
1790 *pOutBuffer++ = (sal_Int8)(nOut & 0xff);
1791 nCharsDecoded = nInBufferPos + 1;
1792 nBytesToDecode = 0;
1793 nBytesGotFromDecoding = 3;
1794 }
1795 }
1796 else
1797 {
1798 nCharsDecoded++;
1799 }
1800 }
1801 else
1802 {
1803 nCharsDecoded++;
1804 }
1805
1806 nInBufferPos++;
1807 pInBuffer++;
1808 }
1809 if( (pOutBuffer - pOutBufferStart) != rOutBuffer.getLength() )
1810 rOutBuffer.realloc( pOutBuffer - pOutBufferStart );
1811
1812 return nCharsDecoded;
1813 }
1814
clearUndefinedChars(rtl::OUString & rTarget,const rtl::OUString & rSource)1815 void Converter::clearUndefinedChars(rtl::OUString& rTarget, const rtl::OUString& rSource)
1816 {
1817 sal_uInt32 nLength(rSource.getLength());
1818 rtl::OUStringBuffer sBuffer(nLength);
1819 for (sal_uInt32 i = 0; i < nLength; i++)
1820 {
1821 sal_Unicode cChar = rSource[i];
1822 if (!(cChar < 0x0020) ||
1823 (cChar == 0x0009) || // TAB
1824 (cChar == 0x000A) || // LF
1825 (cChar == 0x000D)) // legal character
1826 sBuffer.append(cChar);
1827 }
1828 rTarget = sBuffer.makeStringAndClear();
1829 }
1830
GetConversionFactor(::rtl::OUStringBuffer & rUnit,sal_Int16 nSourceUnit,sal_Int16 nTargetUnit)1831 double Converter::GetConversionFactor(::rtl::OUStringBuffer& rUnit, sal_Int16 nSourceUnit, sal_Int16 nTargetUnit)
1832 {
1833 double fRetval(1.0);
1834 rUnit.setLength(0L);
1835
1836 const sal_Char* psUnit = 0;
1837
1838 if(nSourceUnit != nTargetUnit)
1839 {
1840 switch(nSourceUnit)
1841 {
1842 case MeasureUnit::TWIP:
1843 {
1844 switch(nTargetUnit)
1845 {
1846 case MeasureUnit::MM_100TH:
1847 case MeasureUnit::MM_10TH:
1848 {
1849 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for twip values");
1850 }
1851 case MeasureUnit::MM:
1852 {
1853 // 0.01mm = 0.57twip (exactly)
1854 fRetval = ((25400.0 / 1440.0) / 1000.0);
1855 psUnit = gpsMM;
1856 break;
1857 }
1858 case MeasureUnit::CM:
1859 {
1860 // 0.001cm = 0.57twip (exactly)
1861 fRetval = ((25400.0 / 1440.0) / 10000.0);
1862 psUnit = gpsCM;
1863 break;
1864 }
1865 case MeasureUnit::POINT:
1866 {
1867 // 0.01pt = 0.2twip (exactly)
1868 fRetval = ((1000.0 / 20.0) / 1000.0);
1869 psUnit = gpsPT;
1870 break;
1871 }
1872 case MeasureUnit::INCH:
1873 default:
1874 {
1875 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for twip values");
1876 // 0.0001in = 0.144twip (exactly)
1877 fRetval = ((100000.0 / 1440.0) / 100000.0);
1878 psUnit = gpsINCH;
1879 break;
1880 }
1881 }
1882 break;
1883 }
1884 case MeasureUnit::POINT:
1885 {
1886 switch(nTargetUnit)
1887 {
1888 case MeasureUnit::MM:
1889 // 1mm = 72 / 25.4 pt (exactly)
1890 fRetval = ( 25.4 / 72.0 );
1891 psUnit = gpsMM;
1892 break;
1893
1894 case MeasureUnit::CM:
1895 // 1cm = 72 / 2.54 pt (exactly)
1896 fRetval = ( 2.54 / 72.0 );
1897 psUnit = gpsCM;
1898 break;
1899
1900 case MeasureUnit::TWIP:
1901 // 1twip = 72 / 1440 pt (exactly)
1902 fRetval = 20.0; // 1440.0 / 72.0
1903 psUnit = gpsPC;
1904 break;
1905
1906 case MeasureUnit::INCH:
1907 default:
1908 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for pt values");
1909 // 1in = 72 pt (exactly)
1910 fRetval = ( 1.0 / 72.0 );
1911 psUnit = gpsINCH;
1912 break;
1913 }
1914 break;
1915 }
1916 case MeasureUnit::MM_10TH:
1917 {
1918 switch(nTargetUnit)
1919 {
1920 case MeasureUnit::MM_100TH:
1921 case MeasureUnit::MM_10TH:
1922 {
1923 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values");
1924 }
1925 case MeasureUnit::MM:
1926 {
1927 // 0.01mm = 1 mm/100 (exactly)
1928 fRetval = ((10.0 / 1.0) / 100.0);
1929 psUnit = gpsMM;
1930 break;
1931 }
1932 case MeasureUnit::CM:
1933 {
1934 // 0.001mm = 1 mm/100 (exactly)
1935 fRetval = ((10.0 / 1.0) / 1000.0);
1936 psUnit = gpsCM;
1937 break;
1938 }
1939 case MeasureUnit::POINT:
1940 {
1941 // 0.01pt = 0.35 mm/100 (exactly)
1942 fRetval = ((72000.0 / 2540.0) / 100.0);
1943 psUnit = gpsPT;
1944 break;
1945 }
1946 case MeasureUnit::INCH:
1947 default:
1948 {
1949 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values");
1950 // 0.0001in = 0.254 mm/100 (exactly)
1951 fRetval = ((100000.0 / 2540.0) / 10000.0);
1952 psUnit = gpsINCH;
1953 break;
1954 }
1955 }
1956 break;
1957 }
1958 case MeasureUnit::MM_100TH:
1959 {
1960 switch(nTargetUnit)
1961 {
1962 case MeasureUnit::MM_100TH:
1963 case MeasureUnit::MM_10TH:
1964 {
1965 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values");
1966 }
1967 case MeasureUnit::MM:
1968 {
1969 // 0.01mm = 1 mm/100 (exactly)
1970 fRetval = ((10.0 / 1.0) / 1000.0);
1971 psUnit = gpsMM;
1972 break;
1973 }
1974 case MeasureUnit::CM:
1975 {
1976 // 0.001mm = 1 mm/100 (exactly)
1977 fRetval = ((10.0 / 1.0) / 10000.0);
1978 psUnit = gpsCM;
1979 break;
1980 }
1981 case MeasureUnit::POINT:
1982 {
1983 // 0.01pt = 0.35 mm/100 (exactly)
1984 fRetval = ((72000.0 / 2540.0) / 1000.0);
1985 psUnit = gpsPT;
1986 break;
1987 }
1988 case MeasureUnit::INCH:
1989 default:
1990 {
1991 OSL_ENSURE( MeasureUnit::INCH == nTargetUnit, "output unit not supported for 1/100mm values");
1992 // 0.0001in = 0.254 mm/100 (exactly)
1993 fRetval = ((100000.0 / 2540.0) / 100000.0);
1994 psUnit = gpsINCH;
1995 break;
1996 }
1997 }
1998 break;
1999 }
2000 }
2001
2002 if( psUnit )
2003 rUnit.appendAscii( psUnit );
2004 }
2005
2006 return fRetval;
2007 }
2008
GetUnitFromString(const::rtl::OUString & rString,sal_Int16 nDefaultUnit)2009 sal_Int16 Converter::GetUnitFromString(const ::rtl::OUString& rString, sal_Int16 nDefaultUnit)
2010 {
2011 sal_Int32 nPos = 0L;
2012 sal_Int32 nLen = rString.getLength();
2013 sal_Int16 nRetUnit = nDefaultUnit;
2014
2015 // skip white space
2016 while( nPos < nLen && sal_Unicode(' ') == rString[nPos] )
2017 nPos++;
2018
2019 // skip negative
2020 if( nPos < nLen && sal_Unicode('-') == rString[nPos] )
2021 nPos++;
2022
2023 // skip number
2024 while( nPos < nLen && sal_Unicode('0') <= rString[nPos] && sal_Unicode('9') >= rString[nPos] )
2025 nPos++;
2026
2027 if( nPos < nLen && sal_Unicode('.') == rString[nPos] )
2028 {
2029 nPos++;
2030 while( nPos < nLen && sal_Unicode('0') <= rString[nPos] && sal_Unicode('9') >= rString[nPos] )
2031 nPos++;
2032 }
2033
2034 // skip white space
2035 while( nPos < nLen && sal_Unicode(' ') == rString[nPos] )
2036 nPos++;
2037
2038 if( nPos < nLen )
2039 {
2040 switch(rString[nPos])
2041 {
2042 case sal_Unicode('%') :
2043 {
2044 nRetUnit = MeasureUnit::PERCENT;
2045 break;
2046 }
2047 case sal_Unicode('c'):
2048 case sal_Unicode('C'):
2049 {
2050 if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('m')
2051 || rString[nPos+1] == sal_Unicode('M')))
2052 nRetUnit = MeasureUnit::CM;
2053 break;
2054 }
2055 case sal_Unicode('e'):
2056 case sal_Unicode('E'):
2057 {
2058 // CSS1_EMS or CSS1_EMX later
2059 break;
2060 }
2061 case sal_Unicode('i'):
2062 case sal_Unicode('I'):
2063 {
2064 if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('n')
2065 || rString[nPos+1] == sal_Unicode('n')))
2066 nRetUnit = MeasureUnit::INCH;
2067 break;
2068 }
2069 case sal_Unicode('m'):
2070 case sal_Unicode('M'):
2071 {
2072 if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('m')
2073 || rString[nPos+1] == sal_Unicode('M')))
2074 nRetUnit = MeasureUnit::MM;
2075 break;
2076 }
2077 case sal_Unicode('p'):
2078 case sal_Unicode('P'):
2079 {
2080 if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('t')
2081 || rString[nPos+1] == sal_Unicode('T')))
2082 nRetUnit = MeasureUnit::POINT;
2083 if(nPos+1 < nLen && (rString[nPos+1] == sal_Unicode('c')
2084 || rString[nPos+1] == sal_Unicode('C')))
2085 nRetUnit = MeasureUnit::TWIP;
2086 break;
2087 }
2088 }
2089 }
2090
2091 return nRetUnit;
2092 }
2093
2094 }
2095