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 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_xmloff.hxx" 30 #include <com/sun/star/util/DateTime.hpp> 31 #include <com/sun/star/util/Date.hpp> 32 #include <com/sun/star/util/Time.hpp> 33 #include <tools/debug.hxx> 34 #include <rtl/ustrbuf.hxx> 35 #include "xmlehelp.hxx" 36 #include <xmloff/xmlement.hxx> 37 #include <xmloff/xmluconv.hxx> 38 #include <xmloff/xmltoken.hxx> 39 #include <rtl/math.hxx> 40 #include <rtl/logfile.hxx> 41 42 #ifndef _TOOLS_DATE_HXX 43 #include <tools/date.hxx> 44 45 #include <tools/string.hxx> 46 47 #endif 48 49 #include <tools/time.hxx> 50 #include <tools/fldunit.hxx> 51 52 // #110680# 53 //#ifndef _COMPHELPER_PROCESSFACTORY_HXX_ 54 //#include <comphelper/processfactory.hxx> 55 //#endif 56 #include <com/sun/star/util/XNumberFormatsSupplier.hpp> 57 #include <com/sun/star/style/NumberingType.hpp> 58 #include <com/sun/star/text/XNumberingTypeInfo.hpp> 59 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 60 #include <com/sun/star/i18n/XCharacterClassification.hpp> 61 #include <com/sun/star/i18n/UnicodeType.hpp> 62 #include <basegfx/vector/b3dvector.hxx> 63 64 using namespace rtl; 65 using namespace com::sun::star; 66 using namespace com::sun::star::uno; 67 using namespace com::sun::star::lang; 68 using namespace com::sun::star::text; 69 using namespace com::sun::star::style; 70 using namespace ::com::sun::star::i18n; 71 using namespace ::xmloff::token; 72 73 const sal_Int8 XML_MAXDIGITSCOUNT_TIME = 11; 74 const sal_Int8 XML_MAXDIGITSCOUNT_DATETIME = 6; 75 #define XML_NULLDATE "NullDate" 76 77 OUString SvXMLUnitConverter::msXML_true; 78 OUString SvXMLUnitConverter::msXML_false; 79 80 void SvXMLUnitConverter::initXMLStrings() 81 { 82 if( msXML_true.getLength() == 0 ) 83 { 84 msXML_true = GetXMLToken(XML_TRUE); 85 msXML_false = GetXMLToken(XML_FALSE); 86 } 87 } 88 89 void SvXMLUnitConverter::createNumTypeInfo() const 90 { 91 // #110680# 92 //Reference< lang::XMultiServiceFactory > xServiceFactory = 93 // comphelper::getProcessServiceFactory(); 94 //OSL_ENSURE( xServiceFactory.is(), 95 // "XMLUnitConverter: got no service factory" ); 96 97 if( mxServiceFactory.is() ) 98 { 99 ((SvXMLUnitConverter *)this)->xNumTypeInfo = 100 Reference < XNumberingTypeInfo > ( 101 mxServiceFactory->createInstance( 102 OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.DefaultNumberingProvider") ) ), UNO_QUERY ); 103 } 104 } 105 106 /** constructs a SvXMLUnitConverter. The core measure unit is the 107 default unit for numerical measures, the XML measure unit is 108 the default unit for textual measures 109 */ 110 111 // #110680# 112 //SvXMLUnitConverter::SvXMLUnitConverter( MapUnit eCoreMeasureUnit, 113 // MapUnit eXMLMeasureUnit ) : 114 SvXMLUnitConverter::SvXMLUnitConverter( 115 MapUnit eCoreMeasureUnit, 116 MapUnit eXMLMeasureUnit, 117 const uno::Reference<lang::XMultiServiceFactory>& xServiceFactory ) : 118 aNullDate(30, 12, 1899), 119 mxServiceFactory( xServiceFactory ) 120 { 121 DBG_ASSERT( mxServiceFactory.is(), "got no service manager" ); 122 123 meCoreMeasureUnit = eCoreMeasureUnit; 124 meXMLMeasureUnit = eXMLMeasureUnit; 125 } 126 127 SvXMLUnitConverter::~SvXMLUnitConverter() 128 { 129 } 130 131 MapUnit SvXMLUnitConverter::GetMapUnit(sal_Int16 nFieldUnit) 132 { 133 MapUnit eUnit = MAP_INCH; 134 switch( nFieldUnit ) 135 { 136 case FUNIT_MM: 137 eUnit = MAP_MM; 138 break; 139 case FUNIT_CM: 140 case FUNIT_M: 141 case FUNIT_KM: 142 eUnit = MAP_CM; 143 break; 144 case FUNIT_TWIP: 145 eUnit = MAP_TWIP; 146 break; 147 case FUNIT_POINT: 148 case FUNIT_PICA: 149 eUnit = MAP_POINT; 150 break; 151 // case FUNIT_INCH: 152 // case FUNIT_FOOT: 153 // case FUNIT_MILE: 154 // eUnit = MAP_INCH; 155 // break; 156 case FUNIT_100TH_MM: 157 eUnit = MAP_100TH_MM; 158 break; 159 } 160 return eUnit; 161 } 162 163 /** convert string to measure using optional min and max values*/ 164 sal_Bool SvXMLUnitConverter::convertMeasure( sal_Int32& nValue, 165 const OUString& rString, 166 sal_Int32 nMin, sal_Int32 nMax ) const 167 { 168 return SvXMLUnitConverter::convertMeasure( nValue, rString, 169 meCoreMeasureUnit, 170 nMin, nMax ); 171 } 172 173 /** convert measure to string */ 174 void SvXMLUnitConverter::convertMeasure( OUStringBuffer& rString, 175 sal_Int32 nMeasure ) const 176 { 177 SvXMLUnitConverter::convertMeasure( rString, nMeasure, 178 meCoreMeasureUnit, 179 meXMLMeasureUnit ); 180 } 181 182 /** convert measure with given unit to string */ 183 void SvXMLUnitConverter::convertMeasure( OUStringBuffer& rString, 184 sal_Int32 nMeasure, 185 MapUnit eSrcUnit ) const 186 { 187 SvXMLUnitConverter::convertMeasure( rString, nMeasure, 188 eSrcUnit, 189 meXMLMeasureUnit ); 190 } 191 192 /** convert the value from the given string to an int value 193 with the given map unit using optional min and max values 194 */ 195 sal_Bool SvXMLUnitConverter::convertMeasure( sal_Int32& rValue, 196 const OUString& rString, 197 MapUnit eDstUnit, 198 sal_Int32 nMin, sal_Int32 nMax ) 199 { 200 sal_Bool bNeg = sal_False; 201 double nVal = 0; 202 203 sal_Int32 nPos = 0; 204 const sal_Int32 nLen = rString.getLength(); 205 206 // skip white space 207 while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) ) 208 nPos++; 209 210 if( nPos < nLen && sal_Unicode('-') == rString[nPos] ) 211 { 212 bNeg = sal_True; 213 ++nPos; 214 } 215 216 // get number 217 while( nPos < nLen && 218 sal_Unicode('0') <= rString[nPos] && 219 sal_Unicode('9') >= rString[nPos] ) 220 { 221 // TODO: check overflow! 222 nVal *= 10; 223 nVal += (rString[nPos] - sal_Unicode('0')); 224 ++nPos; 225 } 226 double nDiv = 1.; 227 if( nPos < nLen && sal_Unicode('.') == rString[nPos] ) 228 { 229 ++nPos; 230 231 while( nPos < nLen && 232 sal_Unicode('0') <= rString[nPos] && 233 sal_Unicode('9') >= rString[nPos] ) 234 { 235 // TODO: check overflow! 236 nDiv *= 10; 237 nVal += ( ((double)(rString[nPos] - sal_Unicode('0'))) / nDiv ); 238 ++nPos; 239 } 240 } 241 242 // skip white space 243 while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) ) 244 ++nPos; 245 246 if( nPos < nLen ) 247 { 248 249 if( MAP_RELATIVE == eDstUnit ) 250 { 251 if( sal_Unicode('%') != rString[nPos] ) 252 return sal_False; 253 } 254 else if( MAP_PIXEL == eDstUnit ) 255 { 256 if( nPos + 1 >= nLen || 257 (sal_Unicode('p') != rString[nPos] && 258 sal_Unicode('P') != rString[nPos])|| 259 (sal_Unicode('x') != rString[nPos+1] && 260 sal_Unicode('X') != rString[nPos+1]) ) 261 return sal_False; 262 } 263 else 264 { 265 DBG_ASSERT( MAP_TWIP == eDstUnit || MAP_POINT == eDstUnit || 266 MAP_100TH_MM == eDstUnit || MAP_10TH_MM == eDstUnit, "unit is not supported"); 267 const sal_Char *aCmpsL[2] = { 0, 0 }; 268 const sal_Char *aCmpsU[2] = { 0, 0 }; 269 double aScales[2] = { 1., 1. }; 270 271 if( MAP_TWIP == eDstUnit ) 272 { 273 switch( rString[nPos] ) 274 { 275 case sal_Unicode('c'): 276 case sal_Unicode('C'): 277 aCmpsL[0] = "cm"; 278 aCmpsU[0] = "CM"; 279 aScales[0] = (72.*20.)/2.54; // twip 280 break; 281 case sal_Unicode('e'): 282 case sal_Unicode('E'): 283 // pCmp1 = sXML_unit_em; 284 // nToken1 = CSS1_EMS; 285 286 // pCmp2 = sXML_unit_ex; 287 // nToken2 = CSS1_EMX; 288 break; 289 case sal_Unicode('i'): 290 case sal_Unicode('I'): 291 aCmpsL[0] = "in"; 292 aCmpsU[0] = "IN"; 293 aScales[0] = 72.*20.; // twip 294 break; 295 case sal_Unicode('m'): 296 case sal_Unicode('M'): 297 aCmpsL[0] = "mm"; 298 aCmpsU[0] = "MM"; 299 aScales[0] = (72.*20.)/25.4; // twip 300 break; 301 case sal_Unicode('p'): 302 case sal_Unicode('P'): 303 aCmpsL[0] = "pt"; 304 aCmpsU[0] = "PT"; 305 aScales[0] = 20.; // twip 306 307 aCmpsL[1] = "pc"; 308 aCmpsU[1] = "PC"; 309 aScales[1] = 12.*20.; // twip 310 311 // pCmp3 = sXML_unit_px; 312 // nToken3 = CSS1_PIXLENGTH; 313 break; 314 } 315 } 316 else if( MAP_100TH_MM == eDstUnit || MAP_10TH_MM == eDstUnit ) 317 { 318 double nScaleFactor = (MAP_100TH_MM == eDstUnit) ? 100.0 : 10.0; 319 switch( rString[nPos] ) 320 { 321 case sal_Unicode('c'): 322 case sal_Unicode('C'): 323 aCmpsL[0] = "cm"; 324 aCmpsU[0] = "CM"; 325 aScales[0] = 10.0 * nScaleFactor; // mm/100 326 break; 327 case sal_Unicode('e'): 328 case sal_Unicode('E'): 329 // pCmp1 = sXML_unit_em; 330 // nToken1 = CSS1_EMS; 331 332 // pCmp2 = sXML_unit_ex; 333 // nToken2 = CSS1_EMX; 334 break; 335 case sal_Unicode('i'): 336 case sal_Unicode('I'): 337 aCmpsL[0] = "in"; 338 aCmpsU[0] = "IN"; 339 aScales[0] = 1000.*2.54; // mm/100 340 break; 341 case sal_Unicode('m'): 342 case sal_Unicode('M'): 343 aCmpsL[0] = "mm"; 344 aCmpsU[0] = "MM"; 345 aScales[0] = 1.0 * nScaleFactor; // mm/100 346 break; 347 case sal_Unicode('p'): 348 case sal_Unicode('P'): 349 aCmpsL[0] = "pt"; 350 aCmpsU[0] = "PT"; 351 aScales[0] = (10.0 * nScaleFactor*2.54)/72.; // mm/100 352 353 aCmpsL[1] = "pc"; 354 aCmpsU[1] = "PC"; 355 aScales[1] = (10.0 * nScaleFactor*2.54)/12.; // mm/100 356 357 // pCmp3 = sXML_unit_px; 358 // nToken3 = CSS1_PIXLENGTH; 359 break; 360 } 361 } 362 else if( MAP_POINT == eDstUnit ) 363 { 364 if( rString[nPos] == 'p' || rString[nPos] == 'P' ) 365 { 366 aCmpsL[0] = "pt"; 367 aCmpsU[0] = "PT"; 368 aScales[0] = 1; 369 } 370 } 371 372 if( aCmpsL[0] == NULL ) 373 return sal_False; 374 375 double nScale = 0.; 376 for( sal_uInt16 i= 0; i < 2; ++i ) 377 { 378 const sal_Char *pL = aCmpsL[i]; 379 if( pL ) 380 { 381 const sal_Char *pU = aCmpsU[i]; 382 while( nPos < nLen && *pL ) 383 { 384 sal_Unicode c = rString[nPos]; 385 if( c != *pL && c != *pU ) 386 break; 387 ++pL; 388 ++pU; 389 ++nPos; 390 } 391 if( !*pL && (nPos == nLen || ' ' == rString[nPos]) ) 392 { 393 nScale = aScales[i]; 394 break; 395 } 396 } 397 } 398 399 if( 0. == nScale ) 400 return sal_False; 401 402 // TODO: check overflow 403 if( nScale != 1. ) 404 nVal *= nScale; 405 } 406 } 407 408 nVal += .5; 409 if( bNeg ) 410 nVal = -nVal; 411 412 if( nVal <= (double)nMin ) 413 rValue = nMin; 414 else if( nVal >= (double)nMax ) 415 rValue = nMax; 416 else 417 rValue = (sal_Int32)nVal; 418 419 return sal_True; 420 } 421 422 /** convert measure in given unit to string with given unit */ 423 void SvXMLUnitConverter::convertMeasure( OUStringBuffer& rBuffer, 424 sal_Int32 nMeasure, 425 MapUnit eSrcUnit, 426 MapUnit eDstUnit ) 427 { 428 if( eSrcUnit == MAP_RELATIVE ) 429 { 430 DBG_ASSERT( eDstUnit == MAP_RELATIVE, 431 "MAP_RELATIVE only maps to MAP_RELATIVE!" ); 432 433 rBuffer.append( nMeasure ); 434 rBuffer.append( sal_Unicode('%' ) ); 435 } 436 else 437 { 438 SvXMLExportHelper::AddLength( nMeasure, eSrcUnit, 439 rBuffer, eDstUnit ); 440 } 441 } 442 443 /** convert string to boolean */ 444 sal_Bool SvXMLUnitConverter::convertBool( sal_Bool& rBool, 445 const OUString& rString ) 446 { 447 rBool = IsXMLToken(rString, XML_TRUE); 448 449 return rBool || IsXMLToken(rString, XML_FALSE); 450 } 451 452 /** convert boolean to string */ 453 void SvXMLUnitConverter::convertBool( OUStringBuffer& rBuffer, 454 sal_Bool bValue ) 455 { 456 rBuffer.append( GetXMLToken( bValue ? XML_TRUE : XML_FALSE ) ); 457 } 458 459 /** convert string to percent */ 460 sal_Bool SvXMLUnitConverter::convertPercent( sal_Int32& rPercent, 461 const OUString& rString ) 462 { 463 return convertMeasure( rPercent, rString, MAP_RELATIVE ); 464 } 465 466 /** convert percent to string */ 467 void SvXMLUnitConverter::convertPercent( OUStringBuffer& rBuffer, 468 sal_Int32 nValue ) 469 { 470 rBuffer.append( nValue ); 471 rBuffer.append( sal_Unicode('%' ) ); 472 } 473 474 /** convert string to pixel measure */ 475 sal_Bool SvXMLUnitConverter::convertMeasurePx( sal_Int32& rPixel, 476 const OUString& rString ) 477 { 478 return convertMeasure( rPixel, rString, MAP_PIXEL ); 479 } 480 481 /** convert pixel measure to string */ 482 void SvXMLUnitConverter::convertMeasurePx( OUStringBuffer& rBuffer, 483 sal_Int32 nValue ) 484 { 485 rBuffer.append( nValue ); 486 rBuffer.append( sal_Unicode('p' ) ); 487 rBuffer.append( sal_Unicode('x' ) ); 488 } 489 490 /** convert string to enum using given enum map, if the enum is 491 not found in the map, this method will return false 492 */ 493 sal_Bool SvXMLUnitConverter::convertEnum( sal_uInt16& rEnum, 494 const OUString& rValue, 495 const SvXMLEnumStringMapEntry *pMap ) 496 { 497 while( pMap->pName ) 498 { 499 if( rValue.equalsAsciiL( pMap->pName, pMap->nNameLength ) ) 500 { 501 rEnum = pMap->nValue; 502 return sal_True; 503 } 504 ++pMap; 505 } 506 507 return sal_False; 508 } 509 510 /** convert string to enum using given token map, if the enum is 511 not found in the map, this method will return false */ 512 sal_Bool SvXMLUnitConverter::convertEnum( 513 sal_uInt16& rEnum, 514 const OUString& rValue, 515 const SvXMLEnumMapEntry *pMap ) 516 { 517 while( pMap->eToken != XML_TOKEN_INVALID ) 518 { 519 if( IsXMLToken( rValue, pMap->eToken ) ) 520 { 521 rEnum = pMap->nValue; 522 return sal_True; 523 } 524 ++pMap; 525 } 526 return sal_False; 527 } 528 529 /** convert enum to string using given enum map with optional 530 default string. If the enum is not found in the map, 531 this method will either use the given default or return 532 false if not default is set 533 */ 534 sal_Bool SvXMLUnitConverter::convertEnum( OUStringBuffer& rBuffer, 535 sal_uInt16 nValue, 536 const SvXMLEnumStringMapEntry *pMap, 537 sal_Char * pDefault /* = NULL */ ) 538 { 539 const sal_Char *pStr = pDefault; 540 541 while( pMap->pName ) 542 { 543 if( pMap->nValue == nValue ) 544 { 545 pStr = pMap->pName; 546 break; 547 } 548 ++pMap; 549 } 550 551 if( NULL == pStr ) 552 pStr = pDefault; 553 554 if( NULL != pStr ) 555 rBuffer.appendAscii( pStr ); 556 557 return NULL != pStr; 558 } 559 560 /** convert enum to string using given token map with an optional 561 default token. If the enum is not found in the map, 562 this method will either use the given default or return 563 false if no default is set */ 564 sal_Bool SvXMLUnitConverter::convertEnum( 565 OUStringBuffer& rBuffer, 566 unsigned int nValue, 567 const SvXMLEnumMapEntry *pMap, 568 enum XMLTokenEnum eDefault) 569 { 570 enum XMLTokenEnum eTok = eDefault; 571 572 while( pMap->eToken != XML_TOKEN_INVALID ) 573 { 574 if( pMap->nValue == nValue ) 575 { 576 eTok = pMap->eToken; 577 break; 578 } 579 ++pMap; 580 } 581 582 // the map may have contained XML_TOKEN_INVALID 583 if( eTok == XML_TOKEN_INVALID ) 584 eTok = eDefault; 585 586 if( eTok != XML_TOKEN_INVALID ) 587 rBuffer.append( GetXMLToken(eTok) ); 588 589 return (eTok != XML_TOKEN_INVALID); 590 } 591 592 int lcl_gethex( int nChar ) 593 { 594 if( nChar >= '0' && nChar <= '9' ) 595 return nChar - '0'; 596 else if( nChar >= 'a' && nChar <= 'f' ) 597 return nChar - 'a' + 10; 598 else if( nChar >= 'A' && nChar <= 'F' ) 599 return nChar - 'A' + 10; 600 else 601 return 0; 602 } 603 604 /** convert string to color */ 605 sal_Bool SvXMLUnitConverter::convertColor( Color& rColor, 606 const OUString& rValue ) 607 { 608 if( rValue.getLength() != 7 || rValue[0] != '#' ) 609 return sal_False; 610 611 rColor.SetRed( 612 sal::static_int_cast< sal_uInt8 >( 613 lcl_gethex( rValue[1] ) * 16 + lcl_gethex( rValue[2] ) ) ); 614 615 rColor.SetGreen( 616 sal::static_int_cast< sal_uInt8 >( 617 lcl_gethex( rValue[3] ) * 16 + lcl_gethex( rValue[4] ) ) ); 618 619 rColor.SetBlue( 620 sal::static_int_cast< sal_uInt8 >( 621 lcl_gethex( rValue[5] ) * 16 + lcl_gethex( rValue[6] ) ) ); 622 623 return sal_True; 624 } 625 626 static sal_Char aHexTab[] = "0123456789abcdef"; 627 628 /** convert color to string */ 629 void SvXMLUnitConverter::convertColor( OUStringBuffer& rBuffer, 630 const Color& rCol ) 631 { 632 rBuffer.append( sal_Unicode( '#' ) ); 633 634 sal_uInt8 nCol = rCol.GetRed(); 635 rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) ); 636 rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) ); 637 638 nCol = rCol.GetGreen(); 639 rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) ); 640 rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) ); 641 642 nCol = rCol.GetBlue(); 643 rBuffer.append( sal_Unicode( aHexTab[ nCol >> 4 ] ) ); 644 rBuffer.append( sal_Unicode( aHexTab[ nCol & 0xf ] ) ); 645 } 646 647 /** convert number to string */ 648 void SvXMLUnitConverter::convertNumber( OUStringBuffer& rBuffer, 649 sal_Int32 nNumber ) 650 { 651 rBuffer.append( sal_Int32( nNumber ) ); 652 } 653 654 /** convert string to number with optional min and max values */ 655 sal_Bool SvXMLUnitConverter::convertNumber( sal_Int32& rValue, 656 const OUString& rString, 657 sal_Int32 nMin, sal_Int32 nMax ) 658 { 659 rValue = 0; 660 sal_Int64 nNumber = 0; 661 sal_Bool bRet = convertNumber64(nNumber,rString,nMin,nMax); 662 if ( bRet ) 663 rValue = static_cast<sal_Int32>(nNumber); 664 return bRet; 665 } 666 667 /** convert 64-bit number to string */ 668 void SvXMLUnitConverter::convertNumber64( OUStringBuffer& rBuffer, 669 sal_Int64 nNumber ) 670 { 671 rBuffer.append( nNumber ); 672 } 673 674 /** convert string to 64-bit number with optional min and max values */ 675 sal_Bool SvXMLUnitConverter::convertNumber64( sal_Int64& rValue, 676 const OUString& rString, 677 sal_Int64 nMin, sal_Int64 nMax ) 678 { 679 sal_Bool bNeg = sal_False; 680 rValue = 0; 681 682 sal_Int32 nPos = 0; 683 const sal_Int32 nLen = rString.getLength(); 684 685 // skip white space 686 while( (nPos < nLen) && (rString[nPos] <= sal_Unicode(' ')) ) 687 ++nPos; 688 689 if( nPos < nLen && sal_Unicode('-') == rString[nPos] ) 690 { 691 bNeg = sal_True; 692 ++nPos; 693 } 694 695 // get number 696 while( nPos < nLen && 697 sal_Unicode('0') <= rString[nPos] && 698 sal_Unicode('9') >= rString[nPos] ) 699 { 700 // TODO: check overflow! 701 rValue *= 10; 702 rValue += (rString[nPos] - sal_Unicode('0')); 703 ++nPos; 704 } 705 706 if( bNeg ) 707 rValue *= -1; 708 709 return ( nPos == nLen && rValue >= nMin && rValue <= nMax ); 710 } 711 712 /** convert double number to string (using ::rtl::math) */ 713 void SvXMLUnitConverter::convertDouble(::rtl::OUStringBuffer& rBuffer, 714 double fNumber, sal_Bool bWriteUnits) const 715 { 716 SvXMLUnitConverter::convertDouble(rBuffer, fNumber, 717 bWriteUnits, meCoreMeasureUnit, meXMLMeasureUnit); 718 } 719 720 /** convert double number to string (using ::rtl::math) */ 721 void SvXMLUnitConverter::convertDouble( ::rtl::OUStringBuffer& rBuffer, 722 double fNumber, sal_Bool bWriteUnits, MapUnit eCoreUnit, MapUnit eDstUnit) 723 { 724 if(MAP_RELATIVE == eCoreUnit) 725 { 726 DBG_ASSERT(eDstUnit == MAP_RELATIVE, "MAP_RELATIVE only maps to MAP_RELATIVE!" ); 727 ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', sal_True); 728 if(bWriteUnits) 729 rBuffer.append(sal_Unicode('%')); 730 } 731 else 732 { 733 OUStringBuffer sUnit; 734 double fFactor = SvXMLExportHelper::GetConversionFactor(sUnit, eCoreUnit, eDstUnit); 735 if(fFactor != 1.0) 736 fNumber *= fFactor; 737 ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', sal_True); 738 if(bWriteUnits) 739 rBuffer.append(sUnit); 740 } 741 } 742 743 /** convert double number to string (using ::rtl::math) */ 744 void SvXMLUnitConverter::convertDouble( ::rtl::OUStringBuffer& rBuffer, double fNumber) 745 { 746 ::rtl::math::doubleToUStringBuffer( rBuffer, fNumber, rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, '.', sal_True); 747 } 748 749 /** convert string to double number (using ::rtl::math) */ 750 sal_Bool SvXMLUnitConverter::convertDouble(double& rValue, 751 const ::rtl::OUString& rString, sal_Bool bLookForUnits) const 752 { 753 if(bLookForUnits) 754 { 755 MapUnit eSrcUnit = SvXMLExportHelper::GetUnitFromString(rString, meCoreMeasureUnit); 756 757 return SvXMLUnitConverter::convertDouble(rValue, rString, 758 eSrcUnit, meCoreMeasureUnit); 759 } 760 else 761 { 762 return SvXMLUnitConverter::convertDouble(rValue, rString); 763 } 764 } 765 766 /** convert string to double number (using ::rtl::math) */ 767 sal_Bool SvXMLUnitConverter::convertDouble(double& rValue, 768 const ::rtl::OUString& rString, MapUnit eSrcUnit, MapUnit eCoreUnit) 769 { 770 rtl_math_ConversionStatus eStatus; 771 rValue = ::rtl::math::stringToDouble( rString, (sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL ); 772 773 if(eStatus == rtl_math_ConversionStatus_Ok) 774 { 775 OUStringBuffer sUnit; 776 const double fFactor = SvXMLExportHelper::GetConversionFactor(sUnit, eCoreUnit, eSrcUnit); 777 if(fFactor != 1.0 && fFactor != 0.0) 778 rValue /= fFactor; 779 } 780 781 return ( eStatus == rtl_math_ConversionStatus_Ok ); 782 } 783 784 /** convert string to double number (using ::rtl::math) */ 785 sal_Bool SvXMLUnitConverter::convertDouble(double& rValue, const ::rtl::OUString& rString) 786 { 787 rtl_math_ConversionStatus eStatus; 788 rValue = ::rtl::math::stringToDouble( rString, (sal_Unicode)('.'), (sal_Unicode)(','), &eStatus, NULL ); 789 return ( eStatus == rtl_math_ConversionStatus_Ok ); 790 } 791 792 /** get the Null Date of the XModel and set it to the UnitConverter */ 793 sal_Bool SvXMLUnitConverter::setNullDate(const com::sun::star::uno::Reference <com::sun::star::frame::XModel>& xModel) 794 { 795 com::sun::star::uno::Reference <com::sun::star::util::XNumberFormatsSupplier> xNumberFormatsSupplier (xModel, com::sun::star::uno::UNO_QUERY); 796 if (xNumberFormatsSupplier.is()) 797 { 798 const com::sun::star::uno::Reference <com::sun::star::beans::XPropertySet> xPropertySet = xNumberFormatsSupplier->getNumberFormatSettings(); 799 return xPropertySet.is() && (xPropertySet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(XML_NULLDATE))) >>= aNullDate); 800 } 801 return sal_False; 802 } 803 804 /** convert double to ISO Time String; negative durations allowed */ 805 void SvXMLUnitConverter::convertTime( ::rtl::OUStringBuffer& rBuffer, 806 const double& fTime) 807 { 808 809 double fValue = fTime; 810 811 // take care of negative durations as specified in: 812 // XML Schema, W3C Working Draft 07 April 2000, section 3.2.6.1 813 if (fValue < 0.0) 814 { 815 rBuffer.append(sal_Unicode('-')); 816 fValue = - fValue; 817 } 818 819 rBuffer.appendAscii(RTL_CONSTASCII_STRINGPARAM( "PT" )); 820 fValue *= 24; 821 double fHoursValue = ::rtl::math::approxFloor (fValue); 822 fValue -= fHoursValue; 823 fValue *= 60; 824 double fMinsValue = ::rtl::math::approxFloor (fValue); 825 fValue -= fMinsValue; 826 fValue *= 60; 827 double fSecsValue = ::rtl::math::approxFloor (fValue); 828 fValue -= fSecsValue; 829 double f100SecsValue; 830 if (fValue > 0.00001) 831 f100SecsValue = ::rtl::math::round( fValue, XML_MAXDIGITSCOUNT_TIME - 5); 832 else 833 f100SecsValue = 0.0; 834 835 if (f100SecsValue == 1.0) 836 { 837 f100SecsValue = 0.0; 838 fSecsValue += 1.0; 839 } 840 if (fSecsValue >= 60.0) 841 { 842 fSecsValue -= 60.0; 843 fMinsValue += 1.0; 844 } 845 if (fMinsValue >= 60.0) 846 { 847 fMinsValue -= 60.0; 848 fHoursValue += 1.0; 849 } 850 851 if (fHoursValue < 10) 852 rBuffer.append( sal_Unicode('0')); 853 rBuffer.append( sal_Int32( fHoursValue)); 854 rBuffer.append( sal_Unicode('H')); 855 if (fMinsValue < 10) 856 rBuffer.append( sal_Unicode('0')); 857 rBuffer.append( sal_Int32( fMinsValue)); 858 rBuffer.append( sal_Unicode('M')); 859 if (fSecsValue < 10) 860 rBuffer.append( sal_Unicode('0')); 861 rBuffer.append( sal_Int32( fSecsValue)); 862 if (f100SecsValue > 0.0) 863 { 864 ::rtl::OUString a100th( ::rtl::math::doubleToUString( fValue, 865 rtl_math_StringFormat_F, XML_MAXDIGITSCOUNT_TIME - 5, '.', 866 sal_True)); 867 if ( a100th.getLength() > 2 ) 868 { 869 rBuffer.append( sal_Unicode('.')); 870 rBuffer.append( a100th.copy( 2 ) ); // strip 0. 871 } 872 } 873 rBuffer.append( sal_Unicode('S')); 874 } 875 876 /** convert ISO Time String to double; negative durations allowed */ 877 static bool lcl_convertTime( const ::rtl::OUString& rString, sal_Int32& o_rDays, sal_Int32& o_rHours, sal_Int32& o_rMins, 878 sal_Int32& o_rSecs, sal_Bool& o_rIsNegativeTime, double& o_rFractionalSecs ) 879 { 880 rtl::OUString aTrimmed = rString.trim().toAsciiUpperCase(); 881 const sal_Unicode* pStr = aTrimmed.getStr(); 882 883 // negative time duration? 884 if ( sal_Unicode('-') == (*pStr) ) 885 { 886 o_rIsNegativeTime = sal_True; 887 pStr++; 888 } 889 890 if ( *(pStr++) != sal_Unicode('P') ) // duration must start with "P" 891 return false; 892 893 ::rtl::OUString sDoubleStr; 894 sal_Bool bSuccess = true; 895 sal_Bool bDone = sal_False; 896 sal_Bool bTimePart = sal_False; 897 sal_Bool bIsFraction = sal_False; 898 sal_Int32 nTemp = 0; 899 900 while ( bSuccess && !bDone ) 901 { 902 sal_Unicode c = *(pStr++); 903 if ( !c ) // end 904 bDone = sal_True; 905 else if ( sal_Unicode('0') <= c && sal_Unicode('9') >= c ) 906 { 907 if ( nTemp >= SAL_MAX_INT32 / 10 ) 908 bSuccess = false; 909 else 910 { 911 if ( !bIsFraction ) 912 { 913 nTemp *= 10; 914 nTemp += (c - sal_Unicode('0')); 915 } 916 else 917 { 918 sDoubleStr += OUString::valueOf(c); 919 } 920 } 921 } 922 else if ( bTimePart ) 923 { 924 if ( c == sal_Unicode('H') ) 925 { 926 o_rHours = nTemp; 927 nTemp = 0; 928 } 929 else if ( c == sal_Unicode('M') ) 930 { 931 o_rMins = nTemp; 932 nTemp = 0; 933 } 934 else if ( (c == sal_Unicode(',')) || (c == sal_Unicode('.')) ) 935 { 936 o_rSecs = nTemp; 937 nTemp = 0; 938 bIsFraction = sal_True; 939 sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0.")); 940 } 941 else if ( c == sal_Unicode('S') ) 942 { 943 if ( !bIsFraction ) 944 { 945 o_rSecs = nTemp; 946 nTemp = 0; 947 sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0.0")); 948 } 949 } 950 else 951 bSuccess = false; // invalid character 952 } 953 else 954 { 955 if ( c == sal_Unicode('T') ) // "T" starts time part 956 bTimePart = sal_True; 957 else if ( c == sal_Unicode('D') ) 958 { 959 o_rDays = nTemp; 960 nTemp = 0; 961 } 962 else if ( c == sal_Unicode('Y') || c == sal_Unicode('M') ) 963 { 964 //! how many days is a year or month? 965 966 DBG_ERROR("years or months in duration: not implemented"); 967 bSuccess = false; 968 } 969 else 970 bSuccess = false; // invalid character 971 } 972 } 973 974 if ( bSuccess ) 975 o_rFractionalSecs = sDoubleStr.toDouble(); 976 return bSuccess; 977 } 978 979 sal_Bool SvXMLUnitConverter::convertTime( double& fTime, 980 const ::rtl::OUString& rString) 981 { 982 sal_Int32 nDays = 0; 983 sal_Int32 nHours = 0; 984 sal_Int32 nMins = 0; 985 sal_Int32 nSecs = 0; 986 sal_Bool bIsNegativeDuration = sal_False; 987 double fFractionalSecs = 0.0; 988 if ( lcl_convertTime( rString, nDays, nHours, nMins, nSecs, bIsNegativeDuration, fFractionalSecs ) ) 989 { 990 if ( nDays ) 991 nHours += nDays * 24; // add the days to the hours part 992 double fTempTime = 0.0; 993 double fHour = nHours; 994 double fMin = nMins; 995 double fSec = nSecs; 996 double fSec100 = 0.0; 997 fTempTime = fHour / 24; 998 fTempTime += fMin / (24 * 60); 999 fTempTime += fSec / (24 * 60 * 60); 1000 fTempTime += fSec100 / (24 * 60 * 60 * 60); 1001 fTempTime += fFractionalSecs / (24 * 60 * 60); 1002 1003 // negative duration? 1004 if ( bIsNegativeDuration ) 1005 { 1006 fTempTime = -fTempTime; 1007 } 1008 1009 fTime = fTempTime; 1010 return sal_True; 1011 } 1012 return sal_False; 1013 } 1014 1015 /** convert util::DateTime to ISO Time String */ 1016 void SvXMLUnitConverter::convertTime( ::rtl::OUStringBuffer& rBuffer, 1017 const ::com::sun::star::util::DateTime& rDateTime ) 1018 { 1019 double fHour = rDateTime.Hours; 1020 double fMin = rDateTime.Minutes; 1021 double fSec = rDateTime.Seconds; 1022 double fSec100 = rDateTime.HundredthSeconds; 1023 double fTempTime = fHour / 24; 1024 fTempTime += fMin / (24 * 60); 1025 fTempTime += fSec / (24 * 60 * 60); 1026 fTempTime += fSec100 / (24 * 60 * 60 * 100); 1027 convertTime( rBuffer, fTempTime ); 1028 } 1029 1030 /** convert ISO Time String to util::DateTime */ 1031 sal_Bool SvXMLUnitConverter::convertTime( ::com::sun::star::util::DateTime& rDateTime, 1032 const ::rtl::OUString& rString ) 1033 { 1034 sal_Int32 nDays = 0, nHours = 0, nMins = 0, nSecs = 0; 1035 sal_Bool bIsNegativeDuration = sal_False; 1036 double fFractionalSecs = 0.0; 1037 if ( lcl_convertTime( rString, nDays, nHours, nMins, nSecs, bIsNegativeDuration, fFractionalSecs ) ) 1038 { 1039 rDateTime.Year = 0; 1040 rDateTime.Month = 0; 1041 rDateTime.Day = 0; 1042 rDateTime.Hours = static_cast < sal_uInt16 > ( nHours ); 1043 rDateTime.Minutes = static_cast < sal_uInt16 > ( nMins ); 1044 rDateTime.Seconds = static_cast < sal_uInt16 > ( nSecs ); 1045 rDateTime.HundredthSeconds = static_cast < sal_uInt16 > ( fFractionalSecs * 100.0 ); 1046 1047 return sal_True; 1048 } 1049 return sal_False; 1050 } 1051 1052 /** convert double to ISO Date Time String */ 1053 void SvXMLUnitConverter::convertDateTime( ::rtl::OUStringBuffer& rBuffer, 1054 const double& fDateTime, 1055 const com::sun::star::util::Date& aTempNullDate, 1056 sal_Bool bAddTimeIf0AM ) 1057 { 1058 double fValue = fDateTime; 1059 sal_Int32 nValue = static_cast <sal_Int32> (::rtl::math::approxFloor (fValue)); 1060 Date aDate (aTempNullDate.Day, aTempNullDate.Month, aTempNullDate.Year); 1061 aDate += nValue; 1062 fValue -= nValue; 1063 double fCount; 1064 if (nValue > 0) 1065 fCount = ::rtl::math::approxFloor (log10((double)nValue)) + 1; 1066 else if (nValue < 0) 1067 fCount = ::rtl::math::approxFloor (log10((double)(nValue * -1))) + 1; 1068 else 1069 fCount = 0.0; 1070 sal_Int16 nCount = sal_Int16(fCount); 1071 sal_Bool bHasTime(sal_False); 1072 double fHoursValue = 0; 1073 double fMinsValue = 0; 1074 double fSecsValue = 0; 1075 double f100SecsValue = 0; 1076 if (fValue > 0.0) 1077 { 1078 bHasTime = sal_True; 1079 fValue *= 24; 1080 fHoursValue = ::rtl::math::approxFloor (fValue); 1081 fValue -= fHoursValue; 1082 fValue *= 60; 1083 fMinsValue = ::rtl::math::approxFloor (fValue); 1084 fValue -= fMinsValue; 1085 fValue *= 60; 1086 fSecsValue = ::rtl::math::approxFloor (fValue); 1087 fValue -= fSecsValue; 1088 if (fValue > 0.0) 1089 f100SecsValue = ::rtl::math::round( fValue, XML_MAXDIGITSCOUNT_TIME - nCount); 1090 else 1091 f100SecsValue = 0.0; 1092 1093 if (f100SecsValue == 1.0) 1094 { 1095 f100SecsValue = 0.0; 1096 fSecsValue += 1.0; 1097 } 1098 if (fSecsValue >= 60.0) 1099 { 1100 fSecsValue -= 60.0; 1101 fMinsValue += 1.0; 1102 } 1103 if (fMinsValue >= 60.0) 1104 { 1105 fMinsValue -= 60.0; 1106 fHoursValue += 1.0; 1107 } 1108 if (fHoursValue >= 24.0) 1109 { 1110 fHoursValue -= 24.0; 1111 aDate += 1; 1112 } 1113 } 1114 rBuffer.append( sal_Int32( aDate.GetYear())); 1115 rBuffer.append( sal_Unicode('-')); 1116 sal_uInt16 nTemp = aDate.GetMonth(); 1117 if (nTemp < 10) 1118 rBuffer.append( sal_Unicode('0')); 1119 rBuffer.append( sal_Int32( nTemp)); 1120 rBuffer.append( sal_Unicode('-')); 1121 nTemp = aDate.GetDay(); 1122 if (nTemp < 10) 1123 rBuffer.append( sal_Unicode('0')); 1124 rBuffer.append( sal_Int32( nTemp)); 1125 if(bHasTime || bAddTimeIf0AM) 1126 { 1127 rBuffer.append( sal_Unicode('T')); 1128 if (fHoursValue < 10) 1129 rBuffer.append( sal_Unicode('0')); 1130 rBuffer.append( sal_Int32( fHoursValue)); 1131 rBuffer.append( sal_Unicode(':')); 1132 if (fMinsValue < 10) 1133 rBuffer.append( sal_Unicode('0')); 1134 rBuffer.append( sal_Int32( fMinsValue)); 1135 rBuffer.append( sal_Unicode(':')); 1136 if (fSecsValue < 10) 1137 rBuffer.append( sal_Unicode('0')); 1138 rBuffer.append( sal_Int32( fSecsValue)); 1139 if (f100SecsValue > 0.0) 1140 { 1141 ::rtl::OUString a100th( ::rtl::math::doubleToUString( fValue, 1142 rtl_math_StringFormat_F, 1143 XML_MAXDIGITSCOUNT_TIME - nCount, '.', sal_True)); 1144 if ( a100th.getLength() > 2 ) 1145 { 1146 rBuffer.append( sal_Unicode('.')); 1147 rBuffer.append( a100th.copy( 2 ) ); // strip 0. 1148 } 1149 } 1150 } 1151 } 1152 1153 /** convert ISO Date Time String to double */ 1154 sal_Bool SvXMLUnitConverter::convertDateTime( double& fDateTime, 1155 const ::rtl::OUString& rString, const com::sun::star::util::Date& aTempNullDate) 1156 { 1157 com::sun::star::util::DateTime aDateTime; 1158 sal_Bool bSuccess = convertDateTime(aDateTime,rString); 1159 1160 if (bSuccess) 1161 { 1162 double fTempDateTime = 0.0; 1163 const Date aTmpNullDate(aTempNullDate.Day, aTempNullDate.Month, aTempNullDate.Year); 1164 const Date aTempDate((sal_uInt16)aDateTime.Day, (sal_uInt16)aDateTime.Month, (sal_uInt16)aDateTime.Year); 1165 const sal_Int32 nTage = aTempDate - aTmpNullDate; 1166 fTempDateTime = nTage; 1167 double Hour = aDateTime.Hours; 1168 double Min = aDateTime.Minutes; 1169 double Sec = aDateTime.Seconds; 1170 double Sec100 = aDateTime.HundredthSeconds; 1171 fTempDateTime += Hour / 24; 1172 fTempDateTime += Min / (24 * 60); 1173 fTempDateTime += Sec / (24 * 60 * 60); 1174 fTempDateTime += Sec100 / (24 * 60 * 60 * 100); 1175 fDateTime = fTempDateTime; 1176 } 1177 return bSuccess; 1178 } 1179 1180 /** convert util::DateTime to ISO Date String */ 1181 void SvXMLUnitConverter::convertDateTime( 1182 ::rtl::OUStringBuffer& rBuffer, 1183 const com::sun::star::util::DateTime& rDateTime, 1184 sal_Bool bAddTimeIf0AM ) 1185 { 1186 String aString( String::CreateFromInt32( rDateTime.Year ) ); 1187 aString += '-'; 1188 if( rDateTime.Month < 10 ) 1189 aString += '0'; 1190 aString += String::CreateFromInt32( rDateTime.Month ); 1191 aString += '-'; 1192 if( rDateTime.Day < 10 ) 1193 aString += '0'; 1194 aString += String::CreateFromInt32( rDateTime.Day ); 1195 1196 if( rDateTime.Seconds != 0 || 1197 rDateTime.Minutes != 0 || 1198 rDateTime.Hours != 0 || 1199 bAddTimeIf0AM ) 1200 { 1201 aString += 'T'; 1202 if( rDateTime.Hours < 10 ) 1203 aString += '0'; 1204 aString += String::CreateFromInt32( rDateTime.Hours ); 1205 aString += ':'; 1206 if( rDateTime.Minutes < 10 ) 1207 aString += '0'; 1208 aString += String::CreateFromInt32( rDateTime.Minutes ); 1209 aString += ':'; 1210 if( rDateTime.Seconds < 10 ) 1211 aString += '0'; 1212 aString += String::CreateFromInt32( rDateTime.Seconds ); 1213 if ( rDateTime.HundredthSeconds > 0) 1214 { 1215 aString += '.'; 1216 if (rDateTime.HundredthSeconds < 10) 1217 aString += '0'; 1218 aString += String::CreateFromInt32( rDateTime.HundredthSeconds ); 1219 } 1220 } 1221 1222 rBuffer.append( aString ); 1223 } 1224 1225 /** convert ISO Date String to util::DateTime */ 1226 sal_Bool SvXMLUnitConverter::convertDateTime( com::sun::star::util::DateTime& rDateTime, 1227 const ::rtl::OUString& rString ) 1228 { 1229 sal_Bool bSuccess = sal_True; 1230 1231 rtl::OUString aDateStr, aTimeStr, sDoubleStr; 1232 sal_Int32 nPos = rString.indexOf( (sal_Unicode) 'T' ); 1233 sal_Int32 nPos2 = rString.indexOf( (sal_Unicode) ',' ); 1234 if (nPos2 < 0) 1235 nPos2 = rString.indexOf( (sal_Unicode) '.' ); 1236 if ( nPos >= 0 ) 1237 { 1238 aDateStr = rString.copy( 0, nPos ); 1239 if ( nPos2 >= 0 ) 1240 { 1241 aTimeStr = rString.copy( nPos + 1, nPos2 - nPos - 1 ); 1242 sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0.")); 1243 sDoubleStr += rString.copy( nPos2 + 1 ); 1244 } 1245 else 1246 { 1247 aTimeStr = rString.copy(nPos + 1); 1248 sDoubleStr = OUString(RTL_CONSTASCII_USTRINGPARAM("0.0")); 1249 } 1250 } 1251 else 1252 aDateStr = rString; // no separator: only date part 1253 1254 sal_Int32 nYear = 1899; 1255 sal_Int32 nMonth = 12; 1256 sal_Int32 nDay = 30; 1257 sal_Int32 nHour = 0; 1258 sal_Int32 nMin = 0; 1259 sal_Int32 nSec = 0; 1260 1261 const sal_Unicode* pStr = aDateStr.getStr(); 1262 sal_Int32 nDateTokens = 1; 1263 while ( *pStr ) 1264 { 1265 if ( *pStr == '-' ) 1266 nDateTokens++; 1267 pStr++; 1268 } 1269 if ( nDateTokens > 3 || aDateStr.getLength() == 0 ) 1270 bSuccess = sal_False; 1271 else 1272 { 1273 sal_Int32 n = 0; 1274 if ( !convertNumber( nYear, aDateStr.getToken( 0, '-', n ), 0, 9999 ) ) 1275 bSuccess = sal_False; 1276 if ( nDateTokens >= 2 ) 1277 if ( !convertNumber( nMonth, aDateStr.getToken( 0, '-', n ), 0, 12 ) ) 1278 bSuccess = sal_False; 1279 if ( nDateTokens >= 3 ) 1280 if ( !convertNumber( nDay, aDateStr.getToken( 0, '-', n ), 0, 31 ) ) 1281 bSuccess = sal_False; 1282 } 1283 1284 if ( aTimeStr.getLength() > 0 ) // time is optional 1285 { 1286 pStr = aTimeStr.getStr(); 1287 sal_Int32 nTimeTokens = 1; 1288 while ( *pStr ) 1289 { 1290 if ( *pStr == ':' ) 1291 nTimeTokens++; 1292 pStr++; 1293 } 1294 if ( nTimeTokens > 3 ) 1295 bSuccess = sal_False; 1296 else 1297 { 1298 sal_Int32 n = 0; 1299 if ( !convertNumber( nHour, aTimeStr.getToken( 0, ':', n ), 0, 23 ) ) 1300 bSuccess = sal_False; 1301 if ( nTimeTokens >= 2 ) 1302 if ( !convertNumber( nMin, aTimeStr.getToken( 0, ':', n ), 0, 59 ) ) 1303 bSuccess = sal_False; 1304 if ( nTimeTokens >= 3 ) 1305 if ( !convertNumber( nSec, aTimeStr.getToken( 0, ':', n ), 0, 59 ) ) 1306 bSuccess = sal_False; 1307 } 1308 } 1309 1310 if (bSuccess) 1311 { 1312 rDateTime.Year = (sal_uInt16)nYear; 1313 rDateTime.Month = (sal_uInt16)nMonth; 1314 rDateTime.Day = (sal_uInt16)nDay; 1315 rDateTime.Hours = (sal_uInt16)nHour; 1316 rDateTime.Minutes = (sal_uInt16)nMin; 1317 rDateTime.Seconds = (sal_uInt16)nSec; 1318 rDateTime.HundredthSeconds = (sal_uInt16)(sDoubleStr.toDouble() * 100); 1319 } 1320 return bSuccess; 1321 } 1322 1323 /** gets the position of the first comma after npos in the string 1324 rStr. Commas inside '"' pairs are not matched */ 1325 sal_Int32 SvXMLUnitConverter::indexOfComma( const OUString& rStr, 1326 sal_Int32 nPos ) 1327 { 1328 sal_Unicode cQuote = 0; 1329 sal_Int32 nLen = rStr.getLength(); 1330 for( ; nPos < nLen; nPos++ ) 1331 { 1332 sal_Unicode c = rStr[nPos]; 1333 switch( c ) 1334 { 1335 case sal_Unicode('\''): 1336 if( 0 == cQuote ) 1337 cQuote = c; 1338 else if( '\'' == cQuote ) 1339 cQuote = 0; 1340 break; 1341 1342 case sal_Unicode('"'): 1343 if( 0 == cQuote ) 1344 cQuote = c; 1345 else if( '\"' == cQuote ) 1346 cQuote = 0; 1347 break; 1348 1349 case sal_Unicode(','): 1350 if( 0 == cQuote ) 1351 return nPos; 1352 break; 1353 } 1354 } 1355 1356 return -1; 1357 } 1358 1359 // --- 1360 1361 SvXMLTokenEnumerator::SvXMLTokenEnumerator( const OUString& rString, sal_Unicode cSeperator /* = sal_Unicode(' ') */ ) 1362 : maTokenString( rString ), mnNextTokenPos(0), mcSeperator( cSeperator ) 1363 { 1364 } 1365 1366 sal_Bool SvXMLTokenEnumerator::getNextToken( OUString& rToken ) 1367 { 1368 if( -1 == mnNextTokenPos ) 1369 return sal_False; 1370 1371 int nTokenEndPos = maTokenString.indexOf( mcSeperator, mnNextTokenPos ); 1372 if( nTokenEndPos != -1 ) 1373 { 1374 rToken = maTokenString.copy( mnNextTokenPos, 1375 nTokenEndPos - mnNextTokenPos ); 1376 mnNextTokenPos = nTokenEndPos + 1; 1377 1378 // if the mnNextTokenPos is at the end of the string, we have 1379 // to deliver an empty token 1380 if( mnNextTokenPos > maTokenString.getLength() ) 1381 mnNextTokenPos = -1; 1382 } 1383 else 1384 { 1385 rToken = maTokenString.copy( mnNextTokenPos ); 1386 mnNextTokenPos = -1; 1387 } 1388 1389 return sal_True; 1390 } 1391 1392 // --- 1393 bool lcl_getPositions(const OUString& _sValue,OUString& _rContentX,OUString& _rContentY,OUString& _rContentZ) 1394 { 1395 if(!_sValue.getLength() || _sValue[0] != '(') 1396 return false; 1397 1398 sal_Int32 nPos(1L); 1399 sal_Int32 nFound = _sValue.indexOf(sal_Unicode(' '), nPos); 1400 1401 if(nFound == -1 || nFound <= nPos) 1402 return false; 1403 1404 _rContentX = _sValue.copy(nPos, nFound - nPos); 1405 1406 nPos = nFound + 1; 1407 nFound = _sValue.indexOf(sal_Unicode(' '), nPos); 1408 1409 if(nFound == -1 || nFound <= nPos) 1410 return false; 1411 1412 _rContentY = _sValue.copy(nPos, nFound - nPos); 1413 1414 nPos = nFound + 1; 1415 nFound = _sValue.indexOf(sal_Unicode(')'), nPos); 1416 1417 if(nFound == -1 || nFound <= nPos) 1418 return false; 1419 1420 _rContentZ = _sValue.copy(nPos, nFound - nPos); 1421 return true; 1422 1423 } 1424 /** convert string to ::basegfx::B3DVector */ 1425 sal_Bool SvXMLUnitConverter::convertB3DVector( ::basegfx::B3DVector& rVector, const OUString& rValue ) 1426 { 1427 OUString aContentX,aContentY,aContentZ; 1428 if ( !lcl_getPositions(rValue,aContentX,aContentY,aContentZ) ) 1429 return sal_False; 1430 1431 rtl_math_ConversionStatus eStatus; 1432 1433 rVector.setX(::rtl::math::stringToDouble(aContentX, sal_Unicode('.'), 1434 sal_Unicode(','), &eStatus, NULL)); 1435 1436 if( eStatus != rtl_math_ConversionStatus_Ok ) 1437 return sal_False; 1438 1439 rVector.setY(::rtl::math::stringToDouble(aContentY, sal_Unicode('.'), 1440 sal_Unicode(','), &eStatus, NULL)); 1441 1442 if( eStatus != rtl_math_ConversionStatus_Ok ) 1443 return sal_False; 1444 1445 rVector.setZ(::rtl::math::stringToDouble(aContentZ, sal_Unicode('.'), 1446 sal_Unicode(','), &eStatus, NULL)); 1447 1448 1449 return ( eStatus == rtl_math_ConversionStatus_Ok ); 1450 } 1451 1452 /** convert ::basegfx::B3DVector to string */ 1453 void SvXMLUnitConverter::convertB3DVector( OUStringBuffer &rBuffer, const ::basegfx::B3DVector& rVector ) 1454 { 1455 rBuffer.append(sal_Unicode('(')); 1456 convertDouble(rBuffer, rVector.getX()); 1457 rBuffer.append(sal_Unicode(' ')); 1458 convertDouble(rBuffer, rVector.getY()); 1459 rBuffer.append(sal_Unicode(' ')); 1460 convertDouble(rBuffer, rVector.getZ()); 1461 rBuffer.append(sal_Unicode(')')); 1462 } 1463 1464 /** convert string to Position3D */ 1465 sal_Bool SvXMLUnitConverter::convertPosition3D( drawing::Position3D& rPosition, 1466 const OUString& rValue ) 1467 { 1468 OUString aContentX,aContentY,aContentZ; 1469 if ( !lcl_getPositions(rValue,aContentX,aContentY,aContentZ) ) 1470 return sal_False; 1471 1472 if ( !convertDouble( rPosition.PositionX, aContentX, sal_True ) ) 1473 return sal_False; 1474 if ( !convertDouble( rPosition.PositionY, aContentY, sal_True ) ) 1475 return sal_False; 1476 return convertDouble( rPosition.PositionZ, aContentZ, sal_True ); 1477 } 1478 1479 /** convert Position3D to string */ 1480 void SvXMLUnitConverter::convertPosition3D( OUStringBuffer &rBuffer, 1481 const drawing::Position3D& rPosition ) 1482 { 1483 rBuffer.append( sal_Unicode('(') ); 1484 convertDouble( rBuffer, rPosition.PositionX, sal_True ); 1485 rBuffer.append( sal_Unicode(' ') ); 1486 convertDouble( rBuffer, rPosition.PositionY, sal_True ); 1487 rBuffer.append( sal_Unicode(' ') ); 1488 convertDouble( rBuffer, rPosition.PositionZ, sal_True ); 1489 rBuffer.append( sal_Unicode(')') ); 1490 } 1491 1492 const 1493 sal_Char aBase64EncodeTable[] = 1494 { 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 1495 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 1496 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 1497 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 1498 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' }; 1499 1500 const 1501 sal_uInt8 aBase64DecodeTable[] = 1502 { 62,255,255,255, 63, // 43-47 1503 // + / 1504 1505 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255, 0,255,255, // 48-63 1506 // 0 1 2 3 4 5 6 7 8 9 = 1507 1508 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, // 64-79 1509 // A B C D E F G H I J K L M N O 1510 1511 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255, // 80-95 1512 // P Q R S T U V W X Y Z 1513 1514 0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, // 96-111 1515 // a b c d e f g h i j k l m n o 1516 1517 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51 }; // 112-123 1518 // p q r s t u v w x y z 1519 1520 1521 1522 void ThreeByteToFourByte (const sal_Int8* pBuffer, const sal_Int32 nStart, const sal_Int32 nFullLen, rtl::OUStringBuffer& sBuffer) 1523 { 1524 sal_Int32 nLen(nFullLen - nStart); 1525 if (nLen > 3) 1526 nLen = 3; 1527 if (nLen == 0) 1528 { 1529 sBuffer.setLength(0); 1530 return; 1531 } 1532 1533 sal_Int32 nBinaer; 1534 switch (nLen) 1535 { 1536 case 1: 1537 { 1538 nBinaer = ((sal_uInt8)pBuffer[nStart + 0]) << 16; 1539 } 1540 break; 1541 case 2: 1542 { 1543 nBinaer = (((sal_uInt8)pBuffer[nStart + 0]) << 16) + 1544 (((sal_uInt8)pBuffer[nStart + 1]) << 8); 1545 } 1546 break; 1547 default: 1548 { 1549 nBinaer = (((sal_uInt8)pBuffer[nStart + 0]) << 16) + 1550 (((sal_uInt8)pBuffer[nStart + 1]) << 8) + 1551 ((sal_uInt8)pBuffer[nStart + 2]); 1552 } 1553 break; 1554 } 1555 1556 sBuffer.appendAscii("===="); 1557 1558 sal_uInt8 nIndex (static_cast<sal_uInt8>((nBinaer & 0xFC0000) >> 18)); 1559 sBuffer.setCharAt(0, aBase64EncodeTable [nIndex]); 1560 1561 nIndex = static_cast<sal_uInt8>((nBinaer & 0x3F000) >> 12); 1562 sBuffer.setCharAt(1, aBase64EncodeTable [nIndex]); 1563 if (nLen == 1) 1564 return; 1565 1566 nIndex = static_cast<sal_uInt8>((nBinaer & 0xFC0) >> 6); 1567 sBuffer.setCharAt(2, aBase64EncodeTable [nIndex]); 1568 if (nLen == 2) 1569 return; 1570 1571 nIndex = static_cast<sal_uInt8>((nBinaer & 0x3F)); 1572 sBuffer.setCharAt(3, aBase64EncodeTable [nIndex]); 1573 } 1574 1575 void SvXMLUnitConverter::encodeBase64(rtl::OUStringBuffer& aStrBuffer, const uno::Sequence<sal_Int8>& aPass) 1576 { 1577 sal_Int32 i(0); 1578 sal_Int32 nBufferLength(aPass.getLength()); 1579 const sal_Int8* pBuffer = aPass.getConstArray(); 1580 while (i < nBufferLength) 1581 { 1582 rtl::OUStringBuffer sBuffer; 1583 ThreeByteToFourByte (pBuffer, i, nBufferLength, sBuffer); 1584 aStrBuffer.append(sBuffer); 1585 i += 3; 1586 } 1587 } 1588 1589 void SvXMLUnitConverter::decodeBase64(uno::Sequence<sal_Int8>& aBuffer, const rtl::OUString& sBuffer) 1590 { 1591 sal_Int32 nCharsDecoded = decodeBase64SomeChars( aBuffer, sBuffer ); 1592 OSL_ENSURE( nCharsDecoded == sBuffer.getLength(), 1593 "some bytes left in base64 decoding!" ); 1594 (void)nCharsDecoded; 1595 } 1596 1597 sal_Int32 SvXMLUnitConverter::decodeBase64SomeChars( 1598 uno::Sequence<sal_Int8>& rOutBuffer, 1599 const rtl::OUString& rInBuffer) 1600 { 1601 sal_Int32 nInBufferLen = rInBuffer.getLength(); 1602 sal_Int32 nMinOutBufferLen = (nInBufferLen / 4) * 3; 1603 if( rOutBuffer.getLength() < nMinOutBufferLen ) 1604 rOutBuffer.realloc( nMinOutBufferLen ); 1605 1606 const sal_Unicode *pInBuffer = rInBuffer.getStr(); 1607 sal_Int8 *pOutBuffer = rOutBuffer.getArray(); 1608 sal_Int8 *pOutBufferStart = pOutBuffer; 1609 sal_Int32 nCharsDecoded = 0; 1610 1611 sal_uInt8 aDecodeBuffer[4]; 1612 sal_Int32 nBytesToDecode = 0; 1613 sal_Int32 nBytesGotFromDecoding = 3; 1614 sal_Int32 nInBufferPos= 0; 1615 while( nInBufferPos < nInBufferLen ) 1616 { 1617 sal_Unicode cChar = *pInBuffer; 1618 if( cChar >= '+' && cChar <= 'z' ) 1619 { 1620 sal_uInt8 nByte = aBase64DecodeTable[cChar-'+']; 1621 if( nByte != 255 ) 1622 { 1623 // We have found a valid character! 1624 aDecodeBuffer[nBytesToDecode++] = nByte; 1625 1626 // One '=' character at the end means 2 out bytes 1627 // Two '=' characters at the end mean 1 out bytes 1628 if( '=' == cChar && nBytesToDecode > 2 ) 1629 nBytesGotFromDecoding--; 1630 if( 4 == nBytesToDecode ) 1631 { 1632 // Four characters found, so we may convert now! 1633 sal_uInt32 nOut = (aDecodeBuffer[0] << 18) + 1634 (aDecodeBuffer[1] << 12) + 1635 (aDecodeBuffer[2] << 6) + 1636 aDecodeBuffer[3]; 1637 1638 *pOutBuffer++ = (sal_Int8)((nOut & 0xff0000) >> 16); 1639 if( nBytesGotFromDecoding > 1 ) 1640 *pOutBuffer++ = (sal_Int8)((nOut & 0xff00) >> 8); 1641 if( nBytesGotFromDecoding > 2 ) 1642 *pOutBuffer++ = (sal_Int8)(nOut & 0xff); 1643 nCharsDecoded = nInBufferPos + 1; 1644 nBytesToDecode = 0; 1645 nBytesGotFromDecoding = 3; 1646 } 1647 } 1648 else 1649 { 1650 nCharsDecoded++; 1651 } 1652 } 1653 else 1654 { 1655 nCharsDecoded++; 1656 } 1657 1658 nInBufferPos++; 1659 pInBuffer++; 1660 } 1661 if( (pOutBuffer - pOutBufferStart) != rOutBuffer.getLength() ) 1662 rOutBuffer.realloc( pOutBuffer - pOutBufferStart ); 1663 1664 return nCharsDecoded; 1665 } 1666 1667 sal_Bool SvXMLUnitConverter::convertNumFormat( 1668 sal_Int16& rType, 1669 const OUString& rNumFmt, 1670 const OUString& rNumLetterSync, 1671 sal_Bool bNumberNone ) const 1672 { 1673 sal_Bool bRet = sal_True; 1674 sal_Bool bExt = sal_False; 1675 1676 sal_Int32 nLen = rNumFmt.getLength(); 1677 if( 0 == nLen ) 1678 { 1679 if( bNumberNone ) 1680 rType = NumberingType::NUMBER_NONE; 1681 else 1682 bRet = sal_False; 1683 } 1684 else if( 1 == nLen ) 1685 { 1686 switch( rNumFmt[0] ) 1687 { 1688 case sal_Unicode('1'): rType = NumberingType::ARABIC; break; 1689 case sal_Unicode('a'): rType = NumberingType::CHARS_LOWER_LETTER; break; 1690 case sal_Unicode('A'): rType = NumberingType::CHARS_UPPER_LETTER; break; 1691 case sal_Unicode('i'): rType = NumberingType::ROMAN_LOWER; break; 1692 case sal_Unicode('I'): rType = NumberingType::ROMAN_UPPER; break; 1693 default: bExt = sal_True; break; 1694 } 1695 if( !bExt && IsXMLToken( rNumLetterSync, XML_TRUE ) ) 1696 { 1697 switch( rType ) 1698 { 1699 case NumberingType::CHARS_LOWER_LETTER: 1700 rType = NumberingType::CHARS_LOWER_LETTER_N; 1701 break; 1702 case NumberingType::CHARS_UPPER_LETTER: 1703 rType = NumberingType::CHARS_UPPER_LETTER_N; 1704 break; 1705 } 1706 } 1707 } 1708 else 1709 { 1710 bExt = sal_True; 1711 } 1712 if( bExt ) 1713 { 1714 Reference < XNumberingTypeInfo > xInfo = getNumTypeInfo(); 1715 if( xInfo.is() && xInfo->hasNumberingType( rNumFmt ) ) 1716 { 1717 rType = xInfo->getNumberingType( rNumFmt ); 1718 } 1719 else 1720 { 1721 rType = NumberingType::ARABIC; 1722 } 1723 } 1724 1725 return bRet; 1726 } 1727 1728 void SvXMLUnitConverter::convertNumFormat( OUStringBuffer& rBuffer, 1729 sal_Int16 nType ) const 1730 { 1731 enum XMLTokenEnum eFormat = XML_TOKEN_INVALID; 1732 sal_Bool bExt = sal_False; 1733 switch( nType ) 1734 { 1735 case NumberingType::CHARS_UPPER_LETTER: eFormat = XML_A_UPCASE; break; 1736 case NumberingType::CHARS_LOWER_LETTER: eFormat = XML_A; break; 1737 case NumberingType::ROMAN_UPPER: eFormat = XML_I_UPCASE; break; 1738 case NumberingType::ROMAN_LOWER: eFormat = XML_I; break; 1739 case NumberingType::ARABIC: eFormat = XML_1; break; 1740 case NumberingType::CHARS_UPPER_LETTER_N: eFormat = XML_A_UPCASE; break; 1741 case NumberingType::CHARS_LOWER_LETTER_N: eFormat = XML_A; break; 1742 case NumberingType::NUMBER_NONE: eFormat = XML__EMPTY; break; 1743 1744 case NumberingType::CHAR_SPECIAL: 1745 case NumberingType::PAGE_DESCRIPTOR: 1746 case NumberingType::BITMAP: 1747 DBG_ASSERT( eFormat != XML_TOKEN_INVALID, "invalid number format" ); 1748 break; 1749 default: 1750 bExt = sal_True; 1751 break; 1752 } 1753 1754 if( eFormat != XML_TOKEN_INVALID ) 1755 { 1756 rBuffer.append( GetXMLToken(eFormat) ); 1757 } 1758 else 1759 { 1760 Reference < XNumberingTypeInfo > xInfo = getNumTypeInfo(); 1761 if( xInfo.is() ) 1762 rBuffer.append( xInfo->getNumberingIdentifier( nType ) ); 1763 } 1764 } 1765 1766 void SvXMLUnitConverter::convertNumLetterSync( OUStringBuffer& rBuffer, 1767 sal_Int16 nType ) const 1768 { 1769 enum XMLTokenEnum eSync = XML_TOKEN_INVALID; 1770 switch( nType ) 1771 { 1772 case NumberingType::CHARS_UPPER_LETTER: 1773 case NumberingType::CHARS_LOWER_LETTER: 1774 case NumberingType::ROMAN_UPPER: 1775 case NumberingType::ROMAN_LOWER: 1776 case NumberingType::ARABIC: 1777 case NumberingType::NUMBER_NONE: 1778 // default 1779 // eSync = XML_FALSE; 1780 break; 1781 1782 case NumberingType::CHARS_UPPER_LETTER_N: 1783 case NumberingType::CHARS_LOWER_LETTER_N: 1784 eSync = XML_TRUE; 1785 break; 1786 1787 case NumberingType::CHAR_SPECIAL: 1788 case NumberingType::PAGE_DESCRIPTOR: 1789 case NumberingType::BITMAP: 1790 DBG_ASSERT( eSync != XML_TOKEN_INVALID, "invalid number format" ); 1791 break; 1792 } 1793 if( eSync != XML_TOKEN_INVALID ) 1794 rBuffer.append( GetXMLToken(eSync) ); 1795 } 1796 1797 void SvXMLUnitConverter::convertPropertySet(uno::Sequence<beans::PropertyValue>& rProps, 1798 const uno::Reference<beans::XPropertySet>& aProperties) 1799 { 1800 uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = aProperties->getPropertySetInfo(); 1801 if (xPropertySetInfo.is()) 1802 { 1803 uno::Sequence< beans::Property > aProps = xPropertySetInfo->getProperties(); 1804 const sal_Int32 nCount(aProps.getLength()); 1805 if (nCount) 1806 { 1807 rProps.realloc(nCount); 1808 beans::PropertyValue* pProps = rProps.getArray(); 1809 for (sal_Int32 i = 0; i < nCount; i++, ++pProps) 1810 { 1811 pProps->Name = aProps[i].Name; 1812 pProps->Value = aProperties->getPropertyValue(aProps[i].Name); 1813 } 1814 } 1815 } 1816 } 1817 1818 void SvXMLUnitConverter::convertPropertySet(uno::Reference<beans::XPropertySet>& rProperties, 1819 const uno::Sequence<beans::PropertyValue>& aProps) 1820 { 1821 sal_Int32 nCount(aProps.getLength()); 1822 if (nCount) 1823 { 1824 uno::Reference< beans::XPropertySetInfo > xPropertySetInfo = rProperties->getPropertySetInfo(); 1825 if (xPropertySetInfo.is()) 1826 { 1827 for (sal_Int32 i = 0; i < nCount; i++) 1828 { 1829 if (xPropertySetInfo->hasPropertyByName(aProps[i].Name)) 1830 rProperties->setPropertyValue(aProps[i].Name, aProps[i].Value); 1831 } 1832 } 1833 } 1834 } 1835 1836 void SvXMLUnitConverter::clearUndefinedChars(rtl::OUString& rTarget, const rtl::OUString& rSource) 1837 { 1838 sal_uInt32 nLength(rSource.getLength()); 1839 rtl::OUStringBuffer sBuffer(nLength); 1840 for (sal_uInt32 i = 0; i < nLength; i++) 1841 { 1842 sal_Unicode cChar = rSource[i]; 1843 if (!(cChar < 0x0020) || 1844 (cChar == 0x0009) || // TAB 1845 (cChar == 0x000A) || // LF 1846 (cChar == 0x000D)) // legal character 1847 sBuffer.append(cChar); 1848 } 1849 rTarget = sBuffer.makeStringAndClear(); 1850 } 1851 1852 OUString SvXMLUnitConverter::encodeStyleName( 1853 const OUString& rName, 1854 sal_Bool *pEncoded ) const 1855 { 1856 if( pEncoded ) 1857 *pEncoded = sal_False; 1858 1859 sal_Int32 nLen = rName.getLength(); 1860 OUStringBuffer aBuffer( nLen ); 1861 1862 for( sal_Int32 i = 0; i < nLen; i++ ) 1863 { 1864 sal_Unicode c = rName[i]; 1865 sal_Bool bValidChar = sal_False; 1866 if( c < 0x00ffU ) 1867 { 1868 bValidChar = 1869 (c >= 0x0041 && c <= 0x005a) || 1870 (c >= 0x0061 && c <= 0x007a) || 1871 (c >= 0x00c0 && c <= 0x00d6) || 1872 (c >= 0x00d8 && c <= 0x00f6) || 1873 (c >= 0x00f8 && c <= 0x00ff) || 1874 ( i > 0 && ( (c >= 0x0030 && c <= 0x0039) || 1875 c == 0x00b7 || c == '-' || c == '.') ); 1876 } 1877 else 1878 { 1879 if( (c >= 0xf900U && c <= 0xfffeU) || 1880 (c >= 0x20ddU && c <= 0x20e0U)) 1881 { 1882 bValidChar = sal_False; 1883 } 1884 else if( (c >= 0x02bbU && c <= 0x02c1U) || c == 0x0559 || 1885 c == 0x06e5 || c == 0x06e6 ) 1886 { 1887 bValidChar = sal_True; 1888 } 1889 else if( c == 0x0387 ) 1890 { 1891 bValidChar = i > 0; 1892 } 1893 else 1894 { 1895 if( !xCharClass.is() ) 1896 { 1897 if( mxServiceFactory.is() ) 1898 { 1899 try 1900 { 1901 const_cast < SvXMLUnitConverter * >(this) 1902 ->xCharClass = 1903 Reference < XCharacterClassification >( 1904 mxServiceFactory->createInstance( 1905 OUString::createFromAscii( 1906 "com.sun.star.i18n.CharacterClassification_Unicode") ), 1907 UNO_QUERY ); 1908 1909 OSL_ENSURE( xCharClass.is(), 1910 "can't instantiate character clossification component" ); 1911 } 1912 catch( com::sun::star::uno::Exception& ) 1913 { 1914 } 1915 } 1916 } 1917 if( xCharClass.is() ) 1918 { 1919 sal_Int16 nType = xCharClass->getType( rName, i ); 1920 1921 switch( nType ) 1922 { 1923 case UnicodeType::UPPERCASE_LETTER: // Lu 1924 case UnicodeType::LOWERCASE_LETTER: // Ll 1925 case UnicodeType::TITLECASE_LETTER: // Lt 1926 case UnicodeType::OTHER_LETTER: // Lo 1927 case UnicodeType::LETTER_NUMBER: // Nl 1928 bValidChar = sal_True; 1929 break; 1930 case UnicodeType::NON_SPACING_MARK: // Ms 1931 case UnicodeType::ENCLOSING_MARK: // Me 1932 case UnicodeType::COMBINING_SPACING_MARK: //Mc 1933 case UnicodeType::MODIFIER_LETTER: // Lm 1934 case UnicodeType::DECIMAL_DIGIT_NUMBER: // Nd 1935 bValidChar = i > 0; 1936 break; 1937 } 1938 } 1939 } 1940 } 1941 if( bValidChar ) 1942 { 1943 aBuffer.append( c ); 1944 } 1945 else 1946 { 1947 aBuffer.append( static_cast< sal_Unicode >( '_' ) ); 1948 if( c > 0x0fff ) 1949 aBuffer.append( static_cast< sal_Unicode >( 1950 aHexTab[ (c >> 12) & 0x0f ] ) ); 1951 if( c > 0x00ff ) 1952 aBuffer.append( static_cast< sal_Unicode >( 1953 aHexTab[ (c >> 8) & 0x0f ] ) ); 1954 if( c > 0x000f ) 1955 aBuffer.append( static_cast< sal_Unicode >( 1956 aHexTab[ (c >> 4) & 0x0f ] ) ); 1957 aBuffer.append( static_cast< sal_Unicode >( 1958 aHexTab[ c & 0x0f ] ) ); 1959 aBuffer.append( static_cast< sal_Unicode >( '_' ) ); 1960 if( pEncoded ) 1961 *pEncoded = sal_True; 1962 } 1963 } 1964 1965 // check for length 1966 if( aBuffer.getLength() > ((1<<15)-1) ) 1967 { 1968 aBuffer = rName; 1969 if( pEncoded ) 1970 *pEncoded = sal_False; 1971 } 1972 1973 1974 return aBuffer.makeStringAndClear(); 1975 } 1976 1977 // static 1978 rtl::OUString SvXMLUnitConverter::convertTimeDuration( const Time& rTime, sal_Int32 nSecondsFraction ) 1979 { 1980 // return ISO time period string 1981 rtl::OUStringBuffer sTmp; 1982 sTmp.append( sal_Unicode('P') ); // "period" 1983 1984 sal_uInt16 nHours = rTime.GetHour(); 1985 sal_Bool bHasHours = ( nHours > 0 ); 1986 if ( nHours >= 24 ) 1987 { 1988 // add days 1989 1990 sal_uInt16 nDays = nHours / 24; 1991 sTmp.append( (sal_Int32) nDays ); 1992 sTmp.append( sal_Unicode('D') ); // "days" 1993 1994 nHours -= nDays * 24; 1995 } 1996 sTmp.append( sal_Unicode('T') ); // "time" 1997 1998 if ( bHasHours ) 1999 { 2000 sTmp.append( (sal_Int32) nHours ); 2001 sTmp.append( sal_Unicode('H') ); // "hours" 2002 } 2003 sal_uInt16 nMinutes = rTime.GetMin(); 2004 if ( bHasHours || nMinutes > 0 ) 2005 { 2006 sTmp.append( (sal_Int32) nMinutes ); 2007 sTmp.append( sal_Unicode('M') ); // "minutes" 2008 } 2009 sal_uInt16 nSeconds = rTime.GetSec(); 2010 sTmp.append( (sal_Int32) nSeconds ); 2011 if ( nSecondsFraction ) 2012 { 2013 sTmp.append( sal_Unicode( '.' ) ); 2014 ::rtl::OUStringBuffer aFractional; 2015 convertNumber( aFractional, nSecondsFraction ); 2016 sTmp.append( aFractional.getStr() ); 2017 } 2018 sTmp.append( sal_Unicode('S') ); // "seconds" 2019 2020 return sTmp.makeStringAndClear(); 2021 } 2022 2023 // static 2024 bool SvXMLUnitConverter::convertTimeDuration( const rtl::OUString& rString, Time& rTime, sal_Int32* pSecondsFraction ) 2025 { 2026 rtl::OUString aTrimmed = rString.trim().toAsciiUpperCase(); 2027 const sal_Unicode* pStr = aTrimmed.getStr(); 2028 2029 if ( *(pStr++) != sal_Unicode('P') ) // duration must start with "P" 2030 return false; 2031 2032 bool bSuccess = true; 2033 sal_Bool bDone = sal_False; 2034 sal_Bool bTimePart = sal_False; 2035 sal_Bool bFractional = sal_False; 2036 sal_Int32 nDays = 0; 2037 sal_Int32 nHours = 0; 2038 sal_Int32 nMins = 0; 2039 sal_Int32 nSecs = 0; 2040 sal_Int32 nTemp = 0; 2041 sal_Int32 nSecondsFraction = 0; 2042 2043 while ( bSuccess && !bDone ) 2044 { 2045 sal_Unicode c = *(pStr++); 2046 if ( !c ) // end 2047 bDone = sal_True; 2048 else if ( sal_Unicode('0') <= c && sal_Unicode('9') >= c ) 2049 { 2050 if ( bFractional ) 2051 { 2052 if ( nSecondsFraction >= SAL_MAX_INT32 / 10 ) 2053 bSuccess = false; 2054 else 2055 { 2056 nSecondsFraction *= 10; 2057 nSecondsFraction += (c - sal_Unicode('0')); 2058 } 2059 } 2060 else 2061 { 2062 if ( nTemp >= SAL_MAX_INT32 / 10 ) 2063 bSuccess = false; 2064 else 2065 { 2066 nTemp *= 10; 2067 nTemp += (c - sal_Unicode('0')); 2068 } 2069 } 2070 } 2071 else if ( bTimePart ) 2072 { 2073 if ( c == sal_Unicode('H') ) 2074 { 2075 nHours = nTemp; 2076 nTemp = 0; 2077 } 2078 else if ( c == sal_Unicode('M') ) 2079 { 2080 nMins = nTemp; 2081 nTemp = 0; 2082 } 2083 else if ( c == sal_Unicode('S') ) 2084 { 2085 nSecs = nTemp; 2086 nTemp = 0; 2087 } 2088 else if ( c == '.' ) 2089 { 2090 bFractional = sal_True; 2091 } 2092 else 2093 bSuccess = false; // invalid characted 2094 } 2095 else 2096 { 2097 if ( c == sal_Unicode('T') ) // "T" starts time part 2098 bTimePart = sal_True; 2099 else if ( c == sal_Unicode('D') ) 2100 { 2101 nDays = nTemp; 2102 nTemp = 0; 2103 } 2104 else if ( c == sal_Unicode('Y') || c == sal_Unicode('M') ) 2105 { 2106 //! how many days is a year or month? 2107 2108 DBG_ERROR("years or months in duration: not implemented"); 2109 bSuccess = false; 2110 } 2111 else 2112 bSuccess = false; // invalid characted 2113 } 2114 } 2115 2116 if ( bSuccess ) 2117 { 2118 if ( nDays ) 2119 nHours += nDays * 24; // add the days to the hours part 2120 rTime = Time( nHours, nMins, nSecs ); 2121 if ( pSecondsFraction ) 2122 *pSecondsFraction = nSecondsFraction % 1000; 2123 } 2124 return bSuccess; 2125 } 2126 2127 sal_Bool SvXMLUnitConverter::convertAny( ::rtl::OUStringBuffer& sValue, 2128 ::rtl::OUStringBuffer& sType , 2129 const com::sun::star::uno::Any& aValue) 2130 { 2131 sal_Bool bConverted = sal_False; 2132 2133 sValue.setLength(0); 2134 sType.setLength (0); 2135 2136 switch(aValue.getValueTypeClass()) 2137 { 2138 case com::sun::star::uno::TypeClass_BYTE : 2139 case com::sun::star::uno::TypeClass_SHORT : 2140 case com::sun::star::uno::TypeClass_UNSIGNED_SHORT : 2141 case com::sun::star::uno::TypeClass_LONG : 2142 case com::sun::star::uno::TypeClass_UNSIGNED_LONG : 2143 { 2144 sal_Int32 nTempValue = 0; 2145 if (aValue >>= nTempValue) 2146 { 2147 sType.appendAscii("integer"); 2148 bConverted = sal_True; 2149 SvXMLUnitConverter::convertNumber(sValue, nTempValue); 2150 } 2151 } 2152 break; 2153 2154 case com::sun::star::uno::TypeClass_BOOLEAN : 2155 { 2156 sal_Bool bTempValue = sal_False; 2157 if (aValue >>= bTempValue) 2158 { 2159 sType.appendAscii("boolean"); 2160 bConverted = sal_True; 2161 SvXMLUnitConverter::convertBool(sValue, bTempValue); 2162 } 2163 } 2164 break; 2165 2166 case com::sun::star::uno::TypeClass_FLOAT : 2167 case com::sun::star::uno::TypeClass_DOUBLE : 2168 { 2169 double fTempValue = 0.0; 2170 if (aValue >>= fTempValue) 2171 { 2172 sType.appendAscii("float"); 2173 bConverted = sal_True; 2174 SvXMLUnitConverter::convertDouble(sValue, fTempValue); 2175 } 2176 } 2177 break; 2178 2179 case com::sun::star::uno::TypeClass_STRING : 2180 { 2181 ::rtl::OUString sTempValue; 2182 if (aValue >>= sTempValue) 2183 { 2184 sType.appendAscii("string"); 2185 bConverted = sal_True; 2186 sValue.append(sTempValue); 2187 } 2188 } 2189 break; 2190 2191 case com::sun::star::uno::TypeClass_STRUCT : 2192 { 2193 com::sun::star::util::Date aDate ; 2194 com::sun::star::util::Time aTime ; 2195 com::sun::star::util::DateTime aDateTime; 2196 2197 if (aValue >>= aDate) 2198 { 2199 sType.appendAscii("date"); 2200 bConverted = sal_True; 2201 com::sun::star::util::DateTime aTempValue; 2202 aTempValue.Day = aDate.Day; 2203 aTempValue.Month = aDate.Month; 2204 aTempValue.Year = aDate.Year; 2205 aTempValue.HundredthSeconds = 0; 2206 aTempValue.Seconds = 0; 2207 aTempValue.Minutes = 0; 2208 aTempValue.Hours = 0; 2209 SvXMLUnitConverter::convertDateTime(sValue, aTempValue); 2210 } 2211 else 2212 if (aValue >>= aTime) 2213 { 2214 sType.appendAscii("time"); 2215 bConverted = sal_True; 2216 com::sun::star::util::DateTime aTempValue; 2217 aTempValue.Day = 0; 2218 aTempValue.Month = 0; 2219 aTempValue.Year = 0; 2220 aTempValue.HundredthSeconds = aTime.HundredthSeconds; 2221 aTempValue.Seconds = aTime.Seconds; 2222 aTempValue.Minutes = aTime.Minutes; 2223 aTempValue.Hours = aTime.Hours; 2224 SvXMLUnitConverter::convertTime(sValue, aTempValue); 2225 } 2226 else 2227 if (aValue >>= aDateTime) 2228 { 2229 sType.appendAscii("date"); 2230 bConverted = sal_True; 2231 SvXMLUnitConverter::convertDateTime(sValue, aDateTime); 2232 } 2233 } 2234 break; 2235 default: 2236 break; 2237 } 2238 2239 return bConverted; 2240 } 2241 2242 sal_Bool SvXMLUnitConverter::convertAny( com::sun::star::uno::Any& aValue, 2243 const ::rtl::OUString& sType , 2244 const ::rtl::OUString& sValue) 2245 { 2246 sal_Bool bConverted = sal_False; 2247 2248 if (sType.equalsAscii("boolean")) 2249 { 2250 sal_Bool bTempValue = sal_False; 2251 SvXMLUnitConverter::convertBool(bTempValue, sValue); 2252 aValue <<= bTempValue; 2253 bConverted = sal_True; 2254 } 2255 else 2256 if (sType.equalsAscii("integer")) 2257 { 2258 sal_Int32 nTempValue = 0; 2259 SvXMLUnitConverter::convertNumber(nTempValue, sValue); 2260 aValue <<= nTempValue; 2261 bConverted = sal_True; 2262 } 2263 else 2264 if (sType.equalsAscii("float")) 2265 { 2266 double fTempValue = 0.0; 2267 SvXMLUnitConverter::convertDouble(fTempValue, sValue); 2268 aValue <<= fTempValue; 2269 bConverted = sal_True; 2270 } 2271 else 2272 if (sType.equalsAscii("string")) 2273 { 2274 aValue <<= sValue; 2275 bConverted = sal_True; 2276 } 2277 else 2278 if (sType.equalsAscii("date")) 2279 { 2280 com::sun::star::util::DateTime aTempValue; 2281 SvXMLUnitConverter::convertDateTime(aTempValue, sValue); 2282 aValue <<= aTempValue; 2283 bConverted = sal_True; 2284 } 2285 else 2286 if (sType.equalsAscii("time")) 2287 { 2288 com::sun::star::util::DateTime aTempValue; 2289 com::sun::star::util::Time aConvValue; 2290 SvXMLUnitConverter::convertTime(aTempValue, sValue); 2291 aConvValue.HundredthSeconds = aTempValue.HundredthSeconds; 2292 aConvValue.Seconds = aTempValue.Seconds; 2293 aConvValue.Minutes = aTempValue.Minutes; 2294 aConvValue.Hours = aTempValue.Hours; 2295 aValue <<= aConvValue; 2296 bConverted = sal_True; 2297 } 2298 2299 return bConverted; 2300 } 2301