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