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*/ 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 */ 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 462 static const OUString& getTrueString() 463 { 464 static const OUString sTrue( RTL_CONSTASCII_USTRINGPARAM( "true" ) ); 465 return sTrue; 466 } 467 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 */ 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 */ 483 void Converter::convertBool( OUStringBuffer& rBuffer, bool bValue ) 484 { 485 rBuffer.append( bValue ? getTrueString() : getFalseString() ); 486 } 487 488 /** convert string to percent */ 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 */ 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 */ 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 */ 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 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 */ 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 */ 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 */ 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 */ 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) */ 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) */ 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) */ 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) */ 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) */ 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 */ 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 */ 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 */ 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 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 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 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 */ 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 */ 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 */ 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 */ 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 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 1336 static bool lcl_isLeapYear(const sal_uInt32 nYear) 1337 { 1338 return ((nYear % 4) == 0) 1339 && !(((nYear % 100) == 0) || ((nYear % 400) == 0)); 1340 } 1341 1342 static sal_uInt16 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 */ 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 */ 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 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 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 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 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 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 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 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