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