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 31 #define _SVSTDARR_ULONGS 32 #define _ZFORLIST_DECLARE_TABLE 33 34 #include <svl/svstdarr.hxx> 35 #include <svl/zforlist.hxx> 36 #include <svl/zformat.hxx> 37 #include <svl/numuno.hxx> 38 #include <i18npool/mslangid.hxx> 39 #include <tools/debug.hxx> 40 #include <rtl/math.hxx> 41 #include <unotools/calendarwrapper.hxx> 42 #include <unotools/charclass.hxx> 43 #include <com/sun/star/lang/Locale.hpp> 44 #include <rtl/ustrbuf.hxx> 45 46 // #110680# 47 //#include <comphelper/processfactory.hxx> 48 49 #include <com/sun/star/i18n/NativeNumberXmlAttributes.hpp> 50 51 #include <xmloff/xmlnumfe.hxx> 52 #include "xmloff/xmlnmspe.hxx" 53 #include <xmloff/xmluconv.hxx> 54 #include <xmloff/attrlist.hxx> 55 #include <xmloff/nmspmap.hxx> 56 #include <xmloff/families.hxx> 57 #include <xmloff/xmlnumfi.hxx> // SvXMLNumFmtDefaults 58 59 #define _SVSTDARR_USHORTS 60 #include <svl/svstdarr.hxx> 61 #include <svl/nfsymbol.hxx> 62 #include <xmloff/xmltoken.hxx> 63 #include <xmloff/xmlexp.hxx> 64 65 #include <set> 66 67 using ::rtl::OUString; 68 using ::rtl::OUStringBuffer; 69 70 using namespace ::com::sun::star; 71 using namespace ::xmloff::token; 72 using namespace ::svt; 73 74 //------------------------------------------------------------------------- 75 76 // 4th condition for text formats doesn't work 77 //#define XMLNUM_MAX_PARTS 4 78 #define XMLNUM_MAX_PARTS 3 79 80 //------------------------------------------------------------------------- 81 82 struct LessuInt32 83 { 84 sal_Bool operator() (const sal_uInt32 rValue1, const sal_uInt32 rValue2) const 85 { 86 return rValue1 < rValue2; 87 } 88 }; 89 90 typedef std::set< sal_uInt32, LessuInt32 > SvXMLuInt32Set; 91 92 class SvXMLNumUsedList_Impl 93 { 94 SvXMLuInt32Set aUsed; 95 SvXMLuInt32Set aWasUsed; 96 SvXMLuInt32Set::iterator aCurrentUsedPos; 97 sal_uInt32 nUsedCount; 98 sal_uInt32 nWasUsedCount; 99 100 public: 101 SvXMLNumUsedList_Impl(); 102 ~SvXMLNumUsedList_Impl(); 103 104 void SetUsed( sal_uInt32 nKey ); 105 sal_Bool IsUsed( sal_uInt32 nKey ) const; 106 sal_Bool IsWasUsed( sal_uInt32 nKey ) const; 107 void Export(); 108 109 sal_Bool GetFirstUsed(sal_uInt32& nKey); 110 sal_Bool GetNextUsed(sal_uInt32& nKey); 111 112 void GetWasUsed(uno::Sequence<sal_Int32>& rWasUsed); 113 void SetWasUsed(const uno::Sequence<sal_Int32>& rWasUsed); 114 }; 115 116 //------------------------------------------------------------------------- 117 118 struct SvXMLEmbeddedTextEntry 119 { 120 sal_uInt16 nSourcePos; // position in NumberFormat (to skip later) 121 sal_Int32 nFormatPos; // resulting position in embedded-text element 122 rtl::OUString aText; 123 124 SvXMLEmbeddedTextEntry( sal_uInt16 nSP, sal_Int32 nFP, const rtl::OUString& rT ) : 125 nSourcePos(nSP), nFormatPos(nFP), aText(rT) {} 126 }; 127 128 typedef SvXMLEmbeddedTextEntry* SvXMLEmbeddedTextEntryPtr; 129 SV_DECL_PTRARR_DEL( SvXMLEmbeddedTextEntryArr, SvXMLEmbeddedTextEntryPtr, 4, 4 ) 130 131 //------------------------------------------------------------------------- 132 133 SV_IMPL_PTRARR( SvXMLEmbeddedTextEntryArr, SvXMLEmbeddedTextEntryPtr ); 134 135 //------------------------------------------------------------------------- 136 137 // 138 //! SvXMLNumUsedList_Impl should be optimized! 139 // 140 141 SvXMLNumUsedList_Impl::SvXMLNumUsedList_Impl() : 142 nUsedCount(0), 143 nWasUsedCount(0) 144 { 145 } 146 147 SvXMLNumUsedList_Impl::~SvXMLNumUsedList_Impl() 148 { 149 } 150 151 void SvXMLNumUsedList_Impl::SetUsed( sal_uInt32 nKey ) 152 { 153 if ( !IsWasUsed(nKey) ) 154 { 155 std::pair<SvXMLuInt32Set::iterator, bool> aPair = aUsed.insert( nKey ); 156 if (aPair.second) 157 nUsedCount++; 158 } 159 } 160 161 sal_Bool SvXMLNumUsedList_Impl::IsUsed( sal_uInt32 nKey ) const 162 { 163 SvXMLuInt32Set::iterator aItr = aUsed.find(nKey); 164 return (aItr != aUsed.end()); 165 } 166 167 sal_Bool SvXMLNumUsedList_Impl::IsWasUsed( sal_uInt32 nKey ) const 168 { 169 SvXMLuInt32Set::iterator aItr = aWasUsed.find(nKey); 170 return (aItr != aWasUsed.end()); 171 } 172 173 void SvXMLNumUsedList_Impl::Export() 174 { 175 SvXMLuInt32Set::iterator aItr = aUsed.begin(); 176 while (aItr != aUsed.end()) 177 { 178 std::pair<SvXMLuInt32Set::iterator, bool> aPair = aWasUsed.insert( *aItr ); 179 if (aPair.second) 180 nWasUsedCount++; 181 aItr++; 182 } 183 aUsed.clear(); 184 nUsedCount = 0; 185 } 186 187 sal_Bool SvXMLNumUsedList_Impl::GetFirstUsed(sal_uInt32& nKey) 188 { 189 sal_Bool bRet(sal_False); 190 aCurrentUsedPos = aUsed.begin(); 191 if(nUsedCount) 192 { 193 DBG_ASSERT(aCurrentUsedPos != aUsed.end(), "something went wrong"); 194 nKey = *aCurrentUsedPos; 195 bRet = sal_True; 196 } 197 return bRet; 198 } 199 200 sal_Bool SvXMLNumUsedList_Impl::GetNextUsed(sal_uInt32& nKey) 201 { 202 sal_Bool bRet(sal_False); 203 if (aCurrentUsedPos != aUsed.end()) 204 { 205 aCurrentUsedPos++; 206 if (aCurrentUsedPos != aUsed.end()) 207 { 208 nKey = *aCurrentUsedPos; 209 bRet = sal_True; 210 } 211 } 212 return bRet; 213 } 214 215 void SvXMLNumUsedList_Impl::GetWasUsed(uno::Sequence<sal_Int32>& rWasUsed) 216 { 217 rWasUsed.realloc(nWasUsedCount); 218 sal_Int32* pWasUsed = rWasUsed.getArray(); 219 if (pWasUsed) 220 { 221 SvXMLuInt32Set::iterator aItr = aWasUsed.begin(); 222 while (aItr != aWasUsed.end()) 223 { 224 *pWasUsed = *aItr; 225 aItr++; 226 pWasUsed++; 227 } 228 } 229 } 230 231 void SvXMLNumUsedList_Impl::SetWasUsed(const uno::Sequence<sal_Int32>& rWasUsed) 232 { 233 DBG_ASSERT(nWasUsedCount == 0, "WasUsed should be empty"); 234 sal_Int32 nCount(rWasUsed.getLength()); 235 const sal_Int32* pWasUsed = rWasUsed.getConstArray(); 236 for (sal_uInt16 i = 0; i < nCount; i++, pWasUsed++) 237 { 238 std::pair<SvXMLuInt32Set::iterator, bool> aPair = aWasUsed.insert( *pWasUsed ); 239 if (aPair.second) 240 nWasUsedCount++; 241 } 242 } 243 244 //------------------------------------------------------------------------- 245 246 SvXMLNumFmtExport::SvXMLNumFmtExport( 247 SvXMLExport& rExp, 248 const uno::Reference< util::XNumberFormatsSupplier >& rSupp ) : 249 rExport( rExp ), 250 sPrefix( OUString::createFromAscii( "N" ) ), 251 pFormatter( NULL ), 252 pCharClass( NULL ), 253 pLocaleData( NULL ) 254 { 255 // supplier must be SvNumberFormatsSupplierObj 256 SvNumberFormatsSupplierObj* pObj = 257 SvNumberFormatsSupplierObj::getImplementation( rSupp ); 258 if (pObj) 259 pFormatter = pObj->GetNumberFormatter(); 260 261 if ( pFormatter ) 262 { 263 pCharClass = new CharClass( pFormatter->GetServiceManager(), 264 pFormatter->GetLocale() ); 265 pLocaleData = new LocaleDataWrapper( pFormatter->GetServiceManager(), 266 pFormatter->GetLocale() ); 267 } 268 else 269 { 270 lang::Locale aLocale( MsLangId::convertLanguageToLocale( MsLangId::getSystemLanguage() ) ); 271 272 // #110680# 273 // pCharClass = new CharClass( ::comphelper::getProcessServiceFactory(), aLocale ); 274 // pLocaleData = new LocaleDataWrapper( ::comphelper::getProcessServiceFactory(), aLocale ); 275 pCharClass = new CharClass( rExport.getServiceFactory(), aLocale ); 276 pLocaleData = new LocaleDataWrapper( rExport.getServiceFactory(), aLocale ); 277 } 278 279 pUsedList = new SvXMLNumUsedList_Impl; 280 } 281 282 SvXMLNumFmtExport::SvXMLNumFmtExport( 283 SvXMLExport& rExp, 284 const ::com::sun::star::uno::Reference< 285 ::com::sun::star::util::XNumberFormatsSupplier >& rSupp, 286 const rtl::OUString& rPrefix ) : 287 rExport( rExp ), 288 sPrefix( rPrefix ), 289 pFormatter( NULL ), 290 pCharClass( NULL ), 291 pLocaleData( NULL ) 292 { 293 // supplier must be SvNumberFormatsSupplierObj 294 SvNumberFormatsSupplierObj* pObj = 295 SvNumberFormatsSupplierObj::getImplementation( rSupp ); 296 if (pObj) 297 pFormatter = pObj->GetNumberFormatter(); 298 299 if ( pFormatter ) 300 { 301 pCharClass = new CharClass( pFormatter->GetServiceManager(), 302 pFormatter->GetLocale() ); 303 pLocaleData = new LocaleDataWrapper( pFormatter->GetServiceManager(), 304 pFormatter->GetLocale() ); 305 } 306 else 307 { 308 lang::Locale aLocale( MsLangId::convertLanguageToLocale( MsLangId::getSystemLanguage() ) ); 309 310 // #110680# 311 // pCharClass = new CharClass( ::comphelper::getProcessServiceFactory(), aLocale ); 312 // pLocaleData = new LocaleDataWrapper( ::comphelper::getProcessServiceFactory(), aLocale ); 313 pCharClass = new CharClass( rExport.getServiceFactory(), aLocale ); 314 pLocaleData = new LocaleDataWrapper( rExport.getServiceFactory(), aLocale ); 315 } 316 317 pUsedList = new SvXMLNumUsedList_Impl; 318 } 319 320 SvXMLNumFmtExport::~SvXMLNumFmtExport() 321 { 322 delete pUsedList; 323 delete pLocaleData; 324 delete pCharClass; 325 } 326 327 //------------------------------------------------------------------------- 328 329 // 330 // helper methods 331 // 332 333 OUString lcl_CreateStyleName( sal_Int32 nKey, sal_Int32 nPart, sal_Bool bDefPart, const rtl::OUString& rPrefix ) 334 { 335 OUStringBuffer aFmtName( 10L ); 336 aFmtName.append( rPrefix ); 337 aFmtName.append( nKey ); 338 if (!bDefPart) 339 { 340 aFmtName.append( (sal_Unicode)'P' ); 341 aFmtName.append( nPart ); 342 } 343 return aFmtName.makeStringAndClear(); 344 } 345 346 void SvXMLNumFmtExport::AddCalendarAttr_Impl( const OUString& rCalendar ) 347 { 348 if ( rCalendar.getLength() ) 349 { 350 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_CALENDAR, rCalendar ); 351 } 352 } 353 354 void SvXMLNumFmtExport::AddTextualAttr_Impl( sal_Bool bText ) 355 { 356 if ( bText ) // non-textual 357 { 358 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TEXTUAL, XML_TRUE ); 359 } 360 } 361 362 void SvXMLNumFmtExport::AddStyleAttr_Impl( sal_Bool bLong ) 363 { 364 if ( bLong ) // short is default 365 { 366 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_STYLE, XML_LONG ); 367 } 368 } 369 370 void SvXMLNumFmtExport::AddLanguageAttr_Impl( sal_Int32 nLang ) 371 { 372 if ( nLang != LANGUAGE_SYSTEM ) 373 { 374 OUString aLangStr, aCountryStr; 375 MsLangId::convertLanguageToIsoNames( (LanguageType)nLang, aLangStr, aCountryStr ); 376 377 if (aLangStr.getLength()) 378 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_LANGUAGE, aLangStr ); 379 if (aCountryStr.getLength()) 380 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_COUNTRY, aCountryStr ); 381 } 382 } 383 384 //------------------------------------------------------------------------- 385 386 // 387 // methods to write individual elements within a format 388 // 389 390 void SvXMLNumFmtExport::AddToTextElement_Impl( const OUString& rString ) 391 { 392 // append to sTextContent, write element in FinishTextElement_Impl 393 // to avoid several text elements following each other 394 395 sTextContent.append( rString ); 396 } 397 398 void SvXMLNumFmtExport::FinishTextElement_Impl() 399 { 400 if ( sTextContent.getLength() ) 401 { 402 SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_TEXT, 403 sal_True, sal_False ); 404 rExport.Characters( sTextContent.makeStringAndClear() ); 405 } 406 } 407 408 void SvXMLNumFmtExport::WriteColorElement_Impl( const Color& rColor ) 409 { 410 FinishTextElement_Impl(); 411 412 OUStringBuffer aColStr( 7 ); 413 SvXMLUnitConverter::convertColor( aColStr, rColor ); 414 rExport.AddAttribute( XML_NAMESPACE_FO, XML_COLOR, 415 aColStr.makeStringAndClear() ); 416 417 SvXMLElementExport aElem( rExport, XML_NAMESPACE_STYLE, XML_TEXT_PROPERTIES, 418 sal_True, sal_False ); 419 } 420 421 void SvXMLNumFmtExport::WriteCurrencyElement_Impl( const OUString& rString, 422 const OUString& rExt ) 423 { 424 FinishTextElement_Impl(); 425 426 if ( rExt.getLength() ) 427 { 428 sal_Int32 nLang = rExt.toInt32(16); // hex 429 if ( nLang < 0 ) // extension string may contain "-" separator 430 nLang = -nLang; 431 AddLanguageAttr_Impl( nLang ); // adds to pAttrList 432 } 433 434 SvXMLElementExport aElem( rExport, 435 XML_NAMESPACE_NUMBER, XML_CURRENCY_SYMBOL, 436 sal_True, sal_False ); 437 rExport.Characters( rString ); 438 } 439 440 void SvXMLNumFmtExport::WriteBooleanElement_Impl() 441 { 442 FinishTextElement_Impl(); 443 444 SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_BOOLEAN, 445 sal_True, sal_False ); 446 } 447 448 void SvXMLNumFmtExport::WriteTextContentElement_Impl() 449 { 450 FinishTextElement_Impl(); 451 452 SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_TEXT_CONTENT, 453 sal_True, sal_False ); 454 } 455 456 // date elements 457 458 void SvXMLNumFmtExport::WriteDayElement_Impl( const OUString& rCalendar, sal_Bool bLong ) 459 { 460 FinishTextElement_Impl(); 461 462 AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList 463 AddStyleAttr_Impl( bLong ); // adds to pAttrList 464 465 SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_DAY, 466 sal_True, sal_False ); 467 } 468 469 void SvXMLNumFmtExport::WriteMonthElement_Impl( const OUString& rCalendar, sal_Bool bLong, sal_Bool bText ) 470 { 471 FinishTextElement_Impl(); 472 473 AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList 474 AddStyleAttr_Impl( bLong ); // adds to pAttrList 475 AddTextualAttr_Impl( bText ); // adds to pAttrList 476 477 SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_MONTH, 478 sal_True, sal_False ); 479 } 480 481 void SvXMLNumFmtExport::WriteYearElement_Impl( const OUString& rCalendar, sal_Bool bLong ) 482 { 483 FinishTextElement_Impl(); 484 485 AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList 486 AddStyleAttr_Impl( bLong ); // adds to pAttrList 487 488 SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_YEAR, 489 sal_True, sal_False ); 490 } 491 492 void SvXMLNumFmtExport::WriteEraElement_Impl( const OUString& rCalendar, sal_Bool bLong ) 493 { 494 FinishTextElement_Impl(); 495 496 AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList 497 AddStyleAttr_Impl( bLong ); // adds to pAttrList 498 499 SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_ERA, 500 sal_True, sal_False ); 501 } 502 503 void SvXMLNumFmtExport::WriteDayOfWeekElement_Impl( const OUString& rCalendar, sal_Bool bLong ) 504 { 505 FinishTextElement_Impl(); 506 507 AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList 508 AddStyleAttr_Impl( bLong ); // adds to pAttrList 509 510 SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_DAY_OF_WEEK, 511 sal_True, sal_False ); 512 } 513 514 void SvXMLNumFmtExport::WriteWeekElement_Impl( const OUString& rCalendar ) 515 { 516 FinishTextElement_Impl(); 517 518 AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList 519 520 SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_WEEK_OF_YEAR, 521 sal_True, sal_False ); 522 } 523 524 void SvXMLNumFmtExport::WriteQuarterElement_Impl( const OUString& rCalendar, sal_Bool bLong ) 525 { 526 FinishTextElement_Impl(); 527 528 AddCalendarAttr_Impl( rCalendar ); // adds to pAttrList 529 AddStyleAttr_Impl( bLong ); // adds to pAttrList 530 531 SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_QUARTER, 532 sal_True, sal_False ); 533 } 534 535 // time elements 536 537 void SvXMLNumFmtExport::WriteHoursElement_Impl( sal_Bool bLong ) 538 { 539 FinishTextElement_Impl(); 540 541 AddStyleAttr_Impl( bLong ); // adds to pAttrList 542 543 SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_HOURS, 544 sal_True, sal_False ); 545 } 546 547 void SvXMLNumFmtExport::WriteMinutesElement_Impl( sal_Bool bLong ) 548 { 549 FinishTextElement_Impl(); 550 551 AddStyleAttr_Impl( bLong ); // adds to pAttrList 552 553 SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_MINUTES, 554 sal_True, sal_False ); 555 } 556 557 void SvXMLNumFmtExport::WriteSecondsElement_Impl( sal_Bool bLong, sal_uInt16 nDecimals ) 558 { 559 FinishTextElement_Impl(); 560 561 AddStyleAttr_Impl( bLong ); // adds to pAttrList 562 if ( nDecimals > 0 ) 563 { 564 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_DECIMAL_PLACES, 565 OUString::valueOf( (sal_Int32) nDecimals ) ); 566 } 567 568 SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_SECONDS, 569 sal_True, sal_False ); 570 } 571 572 void SvXMLNumFmtExport::WriteAMPMElement_Impl() 573 { 574 FinishTextElement_Impl(); 575 576 SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_AM_PM, 577 sal_True, sal_False ); 578 } 579 580 // numbers 581 582 void SvXMLNumFmtExport::WriteNumberElement_Impl( 583 sal_Int32 nDecimals, sal_Int32 nInteger, 584 const OUString& rDashStr, sal_Bool bVarDecimals, 585 sal_Bool bGrouping, sal_Int32 nTrailingThousands, 586 const SvXMLEmbeddedTextEntryArr& rEmbeddedEntries ) 587 { 588 FinishTextElement_Impl(); 589 590 // decimals 591 if ( nDecimals >= 0 ) // negative = automatic 592 { 593 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_DECIMAL_PLACES, 594 OUString::valueOf( nDecimals ) ); 595 } 596 597 // integer digits 598 if ( nInteger >= 0 ) // negative = automatic 599 { 600 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_INTEGER_DIGITS, 601 OUString::valueOf( nInteger ) ); 602 } 603 604 // decimal replacement (dashes) or variable decimals (#) 605 if ( rDashStr.getLength() || bVarDecimals ) 606 { 607 // variable decimals means an empty replacement string 608 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_DECIMAL_REPLACEMENT, 609 rDashStr ); 610 } 611 612 // (automatic) grouping separator 613 if ( bGrouping ) 614 { 615 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_GROUPING, XML_TRUE ); 616 } 617 618 // display-factor if there are trailing thousands separators 619 if ( nTrailingThousands ) 620 { 621 // each separator character removes three digits 622 double fFactor = ::rtl::math::pow10Exp( 1.0, 3 * nTrailingThousands ); 623 624 OUStringBuffer aFactStr; 625 SvXMLUnitConverter::convertDouble( aFactStr, fFactor ); 626 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_DISPLAY_FACTOR, aFactStr.makeStringAndClear() ); 627 } 628 629 SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_NUMBER, 630 sal_True, sal_True ); 631 632 // number:embedded-text as child elements 633 634 sal_uInt16 nEntryCount = rEmbeddedEntries.Count(); 635 for (sal_uInt16 nEntry=0; nEntry<nEntryCount; nEntry++) 636 { 637 SvXMLEmbeddedTextEntry* pObj = rEmbeddedEntries[nEntry]; 638 639 // position attribute 640 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_POSITION, 641 OUString::valueOf( pObj->nFormatPos ) ); 642 SvXMLElementExport aChildElem( rExport, XML_NAMESPACE_NUMBER, XML_EMBEDDED_TEXT, 643 sal_True, sal_False ); 644 645 // text as element content 646 rtl::OUString aContent( pObj->aText ); 647 while ( nEntry+1 < nEntryCount && rEmbeddedEntries[nEntry+1]->nFormatPos == pObj->nFormatPos ) 648 { 649 // The array can contain several elements for the same position in the number 650 // (for example, literal text and space from underscores). They must be merged 651 // into a single embedded-text element. 652 aContent += rEmbeddedEntries[nEntry+1]->aText; 653 ++nEntry; 654 } 655 rExport.Characters( aContent ); 656 } 657 } 658 659 void SvXMLNumFmtExport::WriteScientificElement_Impl( 660 sal_Int32 nDecimals, sal_Int32 nInteger, 661 sal_Bool bGrouping, sal_Int32 nExp ) 662 { 663 FinishTextElement_Impl(); 664 665 // decimals 666 if ( nDecimals >= 0 ) // negative = automatic 667 { 668 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_DECIMAL_PLACES, 669 OUString::valueOf( nDecimals ) ); 670 } 671 672 // integer digits 673 if ( nInteger >= 0 ) // negative = automatic 674 { 675 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_INTEGER_DIGITS, 676 OUString::valueOf( nInteger ) ); 677 } 678 679 // (automatic) grouping separator 680 if ( bGrouping ) 681 { 682 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_GROUPING, XML_TRUE ); 683 } 684 685 // exponent digits 686 if ( nExp >= 0 ) 687 { 688 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_EXPONENT_DIGITS, 689 OUString::valueOf( nExp ) ); 690 } 691 692 SvXMLElementExport aElem( rExport, 693 XML_NAMESPACE_NUMBER, XML_SCIENTIFIC_NUMBER, 694 sal_True, sal_False ); 695 } 696 697 void SvXMLNumFmtExport::WriteFractionElement_Impl( 698 sal_Int32 nInteger, sal_Bool bGrouping, 699 sal_Int32 nNumerator, sal_Int32 nDenominator ) 700 { 701 FinishTextElement_Impl(); 702 703 // integer digits 704 if ( nInteger >= 0 ) // negative = default (no integer part) 705 { 706 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_INTEGER_DIGITS, 707 OUString::valueOf( nInteger ) ); 708 } 709 710 // (automatic) grouping separator 711 if ( bGrouping ) 712 { 713 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_GROUPING, XML_TRUE ); 714 } 715 716 // numerator digits 717 if ( nNumerator >= 0 ) 718 { 719 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_NUMERATOR_DIGITS, 720 OUString::valueOf( nNumerator ) ); 721 } 722 723 // denominator digits 724 if ( nDenominator >= 0 ) 725 { 726 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_MIN_DENOMINATOR_DIGITS, 727 OUString::valueOf( nDenominator ) ); 728 } 729 730 SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, XML_FRACTION, 731 sal_True, sal_False ); 732 } 733 734 // mapping (condition) 735 736 void SvXMLNumFmtExport::WriteMapElement_Impl( sal_Int32 nOp, double fLimit, 737 sal_Int32 nKey, sal_Int32 nPart ) 738 { 739 FinishTextElement_Impl(); 740 741 if ( nOp != NUMBERFORMAT_OP_NO ) 742 { 743 // style namespace 744 745 OUStringBuffer aCondStr( 20L ); 746 aCondStr.appendAscii( "value()" ); //! define constant 747 switch ( nOp ) 748 { 749 case NUMBERFORMAT_OP_EQ: aCondStr.append( (sal_Unicode) '=' ); break; 750 case NUMBERFORMAT_OP_NE: aCondStr.appendAscii( "<>" ); break; 751 case NUMBERFORMAT_OP_LT: aCondStr.append( (sal_Unicode) '<' ); break; 752 case NUMBERFORMAT_OP_LE: aCondStr.appendAscii( "<=" ); break; 753 case NUMBERFORMAT_OP_GT: aCondStr.append( (sal_Unicode) '>' ); break; 754 case NUMBERFORMAT_OP_GE: aCondStr.appendAscii( ">=" ); break; 755 default: 756 DBG_ERROR("unknown operator"); 757 } 758 ::rtl::math::doubleToUStringBuffer( aCondStr, fLimit, 759 rtl_math_StringFormat_Automatic, rtl_math_DecimalPlaces_Max, 760 '.', true ); 761 762 rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_CONDITION, 763 aCondStr.makeStringAndClear() ); 764 765 rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_APPLY_STYLE_NAME, 766 rExport.EncodeStyleName( lcl_CreateStyleName( nKey, nPart, sal_False, 767 sPrefix ) ) ); 768 769 SvXMLElementExport aElem( rExport, XML_NAMESPACE_STYLE, XML_MAP, 770 sal_True, sal_False ); 771 } 772 } 773 774 //------------------------------------------------------------------------- 775 // for old (automatic) currency formats: parse currency symbol from text 776 777 xub_StrLen lcl_FindSymbol( const String& sUpperStr, const String& sCurString ) 778 { 779 // search for currency symbol 780 // Quoting as in ImpSvNumberformatScan::Symbol_Division 781 782 xub_StrLen nCPos = 0; 783 while (nCPos != STRING_NOTFOUND) 784 { 785 nCPos = sUpperStr.Search( sCurString, nCPos ); 786 if (nCPos != STRING_NOTFOUND) 787 { 788 // in Quotes? 789 xub_StrLen nQ = SvNumberformat::GetQuoteEnd( sUpperStr, nCPos ); 790 if ( nQ == STRING_NOTFOUND ) 791 { 792 // dm can be escaped as "dm or \d 793 sal_Unicode c; 794 if ( nCPos == 0 || 795 ((c = sUpperStr.GetChar(xub_StrLen(nCPos-1))) != '"' 796 && c != '\\') ) 797 { 798 return nCPos; // found 799 } 800 else 801 nCPos++; // continue 802 } 803 else 804 nCPos = nQ + 1; // continue after quote end 805 } 806 } 807 return STRING_NOTFOUND; // not found 808 } 809 810 sal_Bool SvXMLNumFmtExport::WriteTextWithCurrency_Impl( const OUString& rString, 811 const ::com::sun::star::lang::Locale& rLocale ) 812 { 813 // returns sal_True if currency element was written 814 815 sal_Bool bRet = sal_False; 816 817 // pLocaleData->setLocale( rLocale ); 818 // String sCurString = pLocaleData->getCurrSymbol(); 819 820 LanguageType nLang = MsLangId::convertLocaleToLanguage( rLocale ); 821 pFormatter->ChangeIntl( nLang ); 822 String sCurString, sDummy; 823 pFormatter->GetCompatibilityCurrency( sCurString, sDummy ); 824 825 pCharClass->setLocale( rLocale ); 826 String sUpperStr = pCharClass->upper(rString); 827 xub_StrLen nPos = lcl_FindSymbol( sUpperStr, sCurString ); 828 if ( nPos != STRING_NOTFOUND ) 829 { 830 sal_Int32 nLength = rString.getLength(); 831 sal_Int32 nCurLen = sCurString.Len(); 832 sal_Int32 nCont = nPos + nCurLen; 833 834 // text before currency symbol 835 if ( nPos > 0 ) 836 AddToTextElement_Impl( rString.copy( 0, nPos ) ); 837 838 // currency symbol (empty string -> default) 839 OUString sEmpty; 840 WriteCurrencyElement_Impl( sEmpty, sEmpty ); 841 bRet = sal_True; 842 843 // text after currency symbol 844 if ( nCont < nLength ) 845 AddToTextElement_Impl( rString.copy( nCont, nLength-nCont ) ); 846 } 847 else 848 AddToTextElement_Impl( rString ); // simple text 849 850 return bRet; // sal_True: currency element written 851 } 852 853 //------------------------------------------------------------------------- 854 855 OUString lcl_GetDefaultCalendar( SvNumberFormatter* pFormatter, LanguageType nLang ) 856 { 857 // get name of first non-gregorian calendar for the language 858 859 OUString aCalendar; 860 CalendarWrapper* pCalendar = pFormatter->GetCalendar(); 861 if (pCalendar) 862 { 863 lang::Locale aLocale( MsLangId::convertLanguageToLocale( nLang ) ); 864 865 uno::Sequence<OUString> aCals = pCalendar->getAllCalendars( aLocale ); 866 sal_Int32 nCnt = aCals.getLength(); 867 sal_Bool bFound = sal_False; 868 for ( sal_Int32 j=0; j < nCnt && !bFound; j++ ) 869 { 870 if ( !aCals[j].equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("gregorian") ) ) 871 { 872 aCalendar = aCals[j]; 873 bFound = sal_True; 874 } 875 } 876 } 877 return aCalendar; 878 } 879 880 //------------------------------------------------------------------------- 881 882 sal_Bool lcl_IsInEmbedded( const SvXMLEmbeddedTextEntryArr& rEmbeddedEntries, sal_uInt16 nPos ) 883 { 884 sal_uInt16 nCount = rEmbeddedEntries.Count(); 885 for (sal_uInt16 i=0; i<nCount; i++) 886 if ( rEmbeddedEntries[i]->nSourcePos == nPos ) 887 return sal_True; 888 889 return sal_False; // not found 890 } 891 892 sal_Bool lcl_IsDefaultDateFormat( const SvNumberformat& rFormat, sal_Bool bSystemDate, NfIndexTableOffset eBuiltIn ) 893 { 894 // make an extra loop to collect date elements, to check if it is a default format 895 // before adding the automatic-order attribute 896 897 SvXMLDateElementAttributes eDateDOW = XML_DEA_NONE; 898 SvXMLDateElementAttributes eDateDay = XML_DEA_NONE; 899 SvXMLDateElementAttributes eDateMonth = XML_DEA_NONE; 900 SvXMLDateElementAttributes eDateYear = XML_DEA_NONE; 901 SvXMLDateElementAttributes eDateHours = XML_DEA_NONE; 902 SvXMLDateElementAttributes eDateMins = XML_DEA_NONE; 903 SvXMLDateElementAttributes eDateSecs = XML_DEA_NONE; 904 sal_Bool bDateNoDefault = sal_False; 905 906 sal_uInt16 nPos = 0; 907 sal_Bool bEnd = sal_False; 908 short nLastType = 0; 909 while (!bEnd) 910 { 911 short nElemType = rFormat.GetNumForType( 0, nPos, sal_False ); 912 switch ( nElemType ) 913 { 914 case 0: 915 if ( nLastType == NF_SYMBOLTYPE_STRING ) 916 bDateNoDefault = sal_True; // text at the end -> no default date format 917 bEnd = sal_True; // end of format reached 918 break; 919 case NF_SYMBOLTYPE_STRING: 920 case NF_SYMBOLTYPE_DATESEP: 921 case NF_SYMBOLTYPE_TIMESEP: 922 case NF_SYMBOLTYPE_TIME100SECSEP: 923 // text is ignored, except at the end 924 break; 925 // same mapping as in SvXMLNumFormatContext::AddNfKeyword: 926 case NF_KEY_NN: eDateDOW = XML_DEA_SHORT; break; 927 case NF_KEY_NNN: 928 case NF_KEY_NNNN: eDateDOW = XML_DEA_LONG; break; 929 case NF_KEY_D: eDateDay = XML_DEA_SHORT; break; 930 case NF_KEY_DD: eDateDay = XML_DEA_LONG; break; 931 case NF_KEY_M: eDateMonth = XML_DEA_SHORT; break; 932 case NF_KEY_MM: eDateMonth = XML_DEA_LONG; break; 933 case NF_KEY_MMM: eDateMonth = XML_DEA_TEXTSHORT; break; 934 case NF_KEY_MMMM: eDateMonth = XML_DEA_TEXTLONG; break; 935 case NF_KEY_YY: eDateYear = XML_DEA_SHORT; break; 936 case NF_KEY_YYYY: eDateYear = XML_DEA_LONG; break; 937 case NF_KEY_H: eDateHours = XML_DEA_SHORT; break; 938 case NF_KEY_HH: eDateHours = XML_DEA_LONG; break; 939 case NF_KEY_MI: eDateMins = XML_DEA_SHORT; break; 940 case NF_KEY_MMI: eDateMins = XML_DEA_LONG; break; 941 case NF_KEY_S: eDateSecs = XML_DEA_SHORT; break; 942 case NF_KEY_SS: eDateSecs = XML_DEA_LONG; break; 943 case NF_KEY_AP: 944 case NF_KEY_AMPM: break; // AM/PM may or may not be in date/time formats -> ignore by itself 945 default: 946 bDateNoDefault = sal_True; // any other element -> no default format 947 } 948 nLastType = nElemType; 949 ++nPos; 950 } 951 952 if ( bDateNoDefault ) 953 return sal_False; // additional elements 954 else 955 { 956 NfIndexTableOffset eFound = (NfIndexTableOffset) SvXMLNumFmtDefaults::GetDefaultDateFormat( 957 eDateDOW, eDateDay, eDateMonth, eDateYear, eDateHours, eDateMins, eDateSecs, bSystemDate ); 958 959 return ( eFound == eBuiltIn ); 960 } 961 } 962 963 // 964 // export one part (condition) 965 // 966 967 void SvXMLNumFmtExport::ExportPart_Impl( const SvNumberformat& rFormat, sal_uInt32 nKey, 968 sal_uInt16 nPart, sal_Bool bDefPart ) 969 { 970 //! for the default part, pass the coditions from the other parts! 971 972 // 973 // element name 974 // 975 976 NfIndexTableOffset eBuiltIn = pFormatter->GetIndexTableOffset( nKey ); 977 978 short nFmtType = 0; 979 sal_Bool bThousand = sal_False; 980 sal_uInt16 nPrecision = 0; 981 sal_uInt16 nLeading = 0; 982 rFormat.GetNumForInfo( nPart, nFmtType, bThousand, nPrecision, nLeading); 983 nFmtType &= ~NUMBERFORMAT_DEFINED; 984 985 // special treatment of builtin formats that aren't detected by normal parsing 986 // (the same formats that get the type set in SvNumberFormatter::ImpGenerateFormats) 987 if ( eBuiltIn == NF_NUMBER_STANDARD ) 988 nFmtType = NUMBERFORMAT_NUMBER; 989 else if ( eBuiltIn == NF_BOOLEAN ) 990 nFmtType = NUMBERFORMAT_LOGICAL; 991 else if ( eBuiltIn == NF_TEXT ) 992 nFmtType = NUMBERFORMAT_TEXT; 993 994 // #101606# An empty subformat is a valid number-style resulting in an 995 // empty display string for the condition of the subformat. 996 if ( nFmtType == NUMBERFORMAT_UNDEFINED && rFormat.GetNumForType( nPart, 997 0, sal_False ) == 0 ) 998 nFmtType = 0; 999 1000 XMLTokenEnum eType = XML_TOKEN_INVALID; 1001 switch ( nFmtType ) 1002 { 1003 // type is 0 if a format contains no recognized elements 1004 // (like text only) - this is handled as a number-style. 1005 case 0: 1006 case NUMBERFORMAT_NUMBER: 1007 case NUMBERFORMAT_SCIENTIFIC: 1008 case NUMBERFORMAT_FRACTION: 1009 eType = XML_NUMBER_STYLE; 1010 break; 1011 case NUMBERFORMAT_PERCENT: 1012 eType = XML_PERCENTAGE_STYLE; 1013 break; 1014 case NUMBERFORMAT_CURRENCY: 1015 eType = XML_CURRENCY_STYLE; 1016 break; 1017 case NUMBERFORMAT_DATE: 1018 case NUMBERFORMAT_DATETIME: 1019 eType = XML_DATE_STYLE; 1020 break; 1021 case NUMBERFORMAT_TIME: 1022 eType = XML_TIME_STYLE; 1023 break; 1024 case NUMBERFORMAT_TEXT: 1025 eType = XML_TEXT_STYLE; 1026 break; 1027 case NUMBERFORMAT_LOGICAL: 1028 eType = XML_BOOLEAN_STYLE; 1029 break; 1030 } 1031 DBG_ASSERT( eType != XML_TOKEN_INVALID, "unknown format type" ); 1032 1033 OUString sAttrValue; 1034 sal_Bool bUserDef = ( ( rFormat.GetType() & NUMBERFORMAT_DEFINED ) != 0 ); 1035 1036 // 1037 // common attributes for format 1038 // 1039 1040 // format name (generated from key) - style namespace 1041 rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_NAME, 1042 lcl_CreateStyleName( nKey, nPart, bDefPart, sPrefix ) ); 1043 1044 // "volatile" attribute for styles used only in maps 1045 if ( !bDefPart ) 1046 rExport.AddAttribute( XML_NAMESPACE_STYLE, XML_VOLATILE, XML_TRUE ); 1047 1048 // language / country 1049 LanguageType nLang = rFormat.GetLanguage(); 1050 AddLanguageAttr_Impl( nLang ); // adds to pAttrList 1051 1052 // title (comment) 1053 // titles for builtin formats are not written 1054 sAttrValue = rFormat.GetComment(); 1055 if ( sAttrValue.getLength() && bUserDef && bDefPart ) 1056 { 1057 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TITLE, sAttrValue ); 1058 } 1059 1060 // automatic ordering for currency and date formats 1061 // only used for some built-in formats 1062 sal_Bool bAutoOrder = ( eBuiltIn == NF_CURRENCY_1000INT || eBuiltIn == NF_CURRENCY_1000DEC2 || 1063 eBuiltIn == NF_CURRENCY_1000INT_RED || eBuiltIn == NF_CURRENCY_1000DEC2_RED || 1064 eBuiltIn == NF_CURRENCY_1000DEC2_DASHED || 1065 eBuiltIn == NF_DATE_SYSTEM_SHORT || eBuiltIn == NF_DATE_SYSTEM_LONG || 1066 eBuiltIn == NF_DATE_SYS_MMYY || eBuiltIn == NF_DATE_SYS_DDMMM || 1067 eBuiltIn == NF_DATE_SYS_DDMMYYYY || eBuiltIn == NF_DATE_SYS_DDMMYY || 1068 eBuiltIn == NF_DATE_SYS_DMMMYY || eBuiltIn == NF_DATE_SYS_DMMMYYYY || 1069 eBuiltIn == NF_DATE_SYS_DMMMMYYYY || eBuiltIn == NF_DATE_SYS_NNDMMMYY || 1070 eBuiltIn == NF_DATE_SYS_NNDMMMMYYYY || eBuiltIn == NF_DATE_SYS_NNNNDMMMMYYYY || 1071 eBuiltIn == NF_DATETIME_SYSTEM_SHORT_HHMM || eBuiltIn == NF_DATETIME_SYS_DDMMYYYY_HHMMSS ); 1072 1073 // format source (for date and time formats) 1074 // only used for some built-in formats 1075 sal_Bool bSystemDate = ( eBuiltIn == NF_DATE_SYSTEM_SHORT || 1076 eBuiltIn == NF_DATE_SYSTEM_LONG || 1077 eBuiltIn == NF_DATETIME_SYSTEM_SHORT_HHMM ); 1078 sal_Bool bLongSysDate = ( eBuiltIn == NF_DATE_SYSTEM_LONG ); 1079 1080 // check if the format definition matches the key 1081 if ( bAutoOrder && ( nFmtType == NUMBERFORMAT_DATE || nFmtType == NUMBERFORMAT_DATETIME ) && 1082 !lcl_IsDefaultDateFormat( rFormat, bSystemDate, eBuiltIn ) ) 1083 { 1084 bAutoOrder = bSystemDate = bLongSysDate = sal_False; // don't write automatic-order attribute then 1085 } 1086 1087 if ( bAutoOrder && 1088 ( nFmtType == NUMBERFORMAT_CURRENCY || nFmtType == NUMBERFORMAT_DATE || nFmtType == NUMBERFORMAT_DATETIME ) ) 1089 { 1090 // #85109# format type must be checked to avoid dtd errors if 1091 // locale data contains other format types at the built-in positions 1092 1093 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_AUTOMATIC_ORDER, 1094 XML_TRUE ); 1095 } 1096 1097 if ( bSystemDate && bAutoOrder && 1098 ( nFmtType == NUMBERFORMAT_DATE || nFmtType == NUMBERFORMAT_DATETIME ) ) 1099 { 1100 // #85109# format type must be checked to avoid dtd errors if 1101 // locale data contains other format types at the built-in positions 1102 1103 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_FORMAT_SOURCE, 1104 XML_LANGUAGE ); 1105 } 1106 1107 // overflow for time formats as in [hh]:mm 1108 // controlled by bThousand from number format info 1109 // default for truncate-on-overflow is true 1110 if ( nFmtType == NUMBERFORMAT_TIME && bThousand ) 1111 { 1112 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRUNCATE_ON_OVERFLOW, 1113 XML_FALSE ); 1114 } 1115 1116 // 1117 // Native number transliteration 1118 // 1119 ::com::sun::star::i18n::NativeNumberXmlAttributes aAttr; 1120 rFormat.GetNatNumXml( aAttr, nPart ); 1121 if ( aAttr.Format.getLength() ) 1122 { 1123 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_FORMAT, 1124 aAttr.Format ); 1125 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_LANGUAGE, 1126 aAttr.Locale.Language ); 1127 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_COUNTRY, 1128 aAttr.Locale.Country ); 1129 rExport.AddAttribute( XML_NAMESPACE_NUMBER, XML_TRANSLITERATION_STYLE, 1130 aAttr.Style ); 1131 } 1132 1133 // 1134 // The element 1135 // 1136 SvXMLElementExport aElem( rExport, XML_NAMESPACE_NUMBER, eType, 1137 sal_True, sal_True ); 1138 1139 // 1140 // color (properties element) 1141 // 1142 1143 const Color* pCol = rFormat.GetColor( nPart ); 1144 if (pCol) 1145 WriteColorElement_Impl(*pCol); 1146 1147 1148 // detect if there is "real" content, excluding color and maps 1149 //! move to implementation of Write... methods? 1150 sal_Bool bAnyContent = sal_False; 1151 1152 // 1153 // format elements 1154 // 1155 1156 SvXMLEmbeddedTextEntryArr aEmbeddedEntries(0); 1157 if ( eBuiltIn == NF_NUMBER_STANDARD ) 1158 { 1159 // default number format contains just one number element 1160 WriteNumberElement_Impl( -1, 1, OUString(), sal_False, sal_False, 0, aEmbeddedEntries ); 1161 bAnyContent = sal_True; 1162 } 1163 else if ( eBuiltIn == NF_BOOLEAN ) 1164 { 1165 // boolean format contains just one boolean element 1166 WriteBooleanElement_Impl(); 1167 bAnyContent = sal_True; 1168 } 1169 else 1170 { 1171 // first loop to collect attributes 1172 1173 sal_Bool bDecDashes = sal_False; 1174 sal_Bool bVarDecimals = sal_False; 1175 sal_Bool bExpFound = sal_False; 1176 sal_Bool bCurrFound = sal_False; 1177 sal_Bool bInInteger = sal_True; 1178 sal_Int32 nExpDigits = 0; 1179 sal_Int32 nIntegerSymbols = 0; // for embedded-text, including "#" 1180 sal_Int32 nTrailingThousands = 0; // thousands-separators after all digits 1181 OUString sCurrExt; 1182 OUString aCalendar; 1183 sal_uInt16 nPos = 0; 1184 sal_Bool bEnd = sal_False; 1185 while (!bEnd) 1186 { 1187 short nElemType = rFormat.GetNumForType( nPart, nPos, sal_False ); 1188 const XubString* pElemStr = rFormat.GetNumForString( nPart, nPos, sal_False ); 1189 1190 switch ( nElemType ) 1191 { 1192 case 0: 1193 bEnd = sal_True; // end of format reached 1194 break; 1195 case NF_SYMBOLTYPE_DIGIT: 1196 if ( bExpFound && pElemStr ) 1197 nExpDigits += pElemStr->Len(); 1198 else if ( !bDecDashes && pElemStr && pElemStr->GetChar(0) == '-' ) 1199 bDecDashes = sal_True; 1200 else if ( !bVarDecimals && !bInInteger && pElemStr && pElemStr->GetChar(0) == '#' ) 1201 { 1202 // If the decimal digits string starts with a '#', variable 1203 // decimals is assumed (for 0.###, but not 0.0##). 1204 bVarDecimals = sal_True; 1205 } 1206 if ( bInInteger && pElemStr ) 1207 nIntegerSymbols += pElemStr->Len(); 1208 nTrailingThousands = 0; 1209 break; 1210 case NF_SYMBOLTYPE_DECSEP: 1211 bInInteger = sal_False; 1212 break; 1213 case NF_SYMBOLTYPE_THSEP: 1214 if (pElemStr) 1215 nTrailingThousands += pElemStr->Len(); // is reset to 0 if digits follow 1216 break; 1217 case NF_SYMBOLTYPE_EXP: 1218 bExpFound = sal_True; // following digits are exponent digits 1219 bInInteger = sal_False; 1220 break; 1221 case NF_SYMBOLTYPE_CURRENCY: 1222 bCurrFound = sal_True; 1223 break; 1224 case NF_SYMBOLTYPE_CURREXT: 1225 if (pElemStr) 1226 sCurrExt = *pElemStr; 1227 break; 1228 1229 // E, EE, R, RR: select non-gregorian calendar 1230 // AAA, AAAA: calendar is switched at the position of the element 1231 case NF_KEY_EC: 1232 case NF_KEY_EEC: 1233 case NF_KEY_R: 1234 case NF_KEY_RR: 1235 if (!aCalendar.getLength()) 1236 aCalendar = lcl_GetDefaultCalendar( pFormatter, nLang ); 1237 break; 1238 } 1239 ++nPos; 1240 } 1241 1242 // collect strings for embedded-text (must be known before number element is written) 1243 1244 sal_Bool bAllowEmbedded = ( nFmtType == 0 || nFmtType == NUMBERFORMAT_NUMBER || 1245 nFmtType == NUMBERFORMAT_CURRENCY || 1246 nFmtType == NUMBERFORMAT_PERCENT ); 1247 if ( bAllowEmbedded ) 1248 { 1249 sal_Int32 nDigitsPassed = 0; 1250 nPos = 0; 1251 bEnd = sal_False; 1252 while (!bEnd) 1253 { 1254 short nElemType = rFormat.GetNumForType( nPart, nPos, sal_False ); 1255 const XubString* pElemStr = rFormat.GetNumForString( nPart, nPos, sal_False ); 1256 1257 switch ( nElemType ) 1258 { 1259 case 0: 1260 bEnd = sal_True; // end of format reached 1261 break; 1262 case NF_SYMBOLTYPE_DIGIT: 1263 if ( pElemStr ) 1264 nDigitsPassed += pElemStr->Len(); 1265 break; 1266 case NF_SYMBOLTYPE_STRING: 1267 case NF_SYMBOLTYPE_BLANK: 1268 case NF_SYMBOLTYPE_PERCENT: 1269 if ( nDigitsPassed > 0 && nDigitsPassed < nIntegerSymbols && pElemStr ) 1270 { 1271 // text (literal or underscore) within the integer part of a number:number element 1272 1273 String aEmbeddedStr; 1274 if ( nElemType == NF_SYMBOLTYPE_STRING || nElemType == NF_SYMBOLTYPE_PERCENT ) 1275 aEmbeddedStr = *pElemStr; 1276 else 1277 SvNumberformat::InsertBlanks( aEmbeddedStr, 0, pElemStr->GetChar(1) ); 1278 1279 sal_Int32 nEmbedPos = nIntegerSymbols - nDigitsPassed; 1280 1281 SvXMLEmbeddedTextEntry* pObj = new SvXMLEmbeddedTextEntry( nPos, nEmbedPos, aEmbeddedStr ); 1282 aEmbeddedEntries.Insert( pObj, aEmbeddedEntries.Count() ); 1283 } 1284 break; 1285 } 1286 ++nPos; 1287 } 1288 } 1289 1290 // final loop to write elements 1291 1292 sal_Bool bNumWritten = sal_False; 1293 sal_Bool bCurrencyWritten = sal_False; 1294 short nPrevType = 0; 1295 nPos = 0; 1296 bEnd = sal_False; 1297 while (!bEnd) 1298 { 1299 short nElemType = rFormat.GetNumForType( nPart, nPos, sal_False ); 1300 const XubString* pElemStr = rFormat.GetNumForString( nPart, nPos, sal_False ); 1301 1302 switch ( nElemType ) 1303 { 1304 case 0: 1305 bEnd = sal_True; // end of format reached 1306 break; 1307 case NF_SYMBOLTYPE_STRING: 1308 case NF_SYMBOLTYPE_DATESEP: 1309 case NF_SYMBOLTYPE_TIMESEP: 1310 case NF_SYMBOLTYPE_TIME100SECSEP: 1311 case NF_SYMBOLTYPE_PERCENT: 1312 if (pElemStr) 1313 { 1314 if ( ( nPrevType == NF_KEY_S || nPrevType == NF_KEY_SS ) && 1315 ( nElemType == NF_SYMBOLTYPE_TIME100SECSEP ) && 1316 nPrecision > 0 ) 1317 { 1318 // decimal separator after seconds is implied by 1319 // "decimal-places" attribute and must not be written 1320 // as text element 1321 //! difference between '.' and ',' is lost here 1322 } 1323 else if ( lcl_IsInEmbedded( aEmbeddedEntries, nPos ) ) 1324 { 1325 // text is written as embedded-text child of the number, 1326 // don't create a text element 1327 } 1328 else if ( nFmtType == NUMBERFORMAT_CURRENCY && !bCurrFound && !bCurrencyWritten ) 1329 { 1330 // automatic currency symbol is implemented as part of 1331 // normal text -> search for the symbol 1332 bCurrencyWritten = WriteTextWithCurrency_Impl( *pElemStr, 1333 MsLangId::convertLanguageToLocale( nLang ) ); 1334 bAnyContent = sal_True; 1335 } 1336 else 1337 AddToTextElement_Impl( *pElemStr ); 1338 } 1339 break; 1340 case NF_SYMBOLTYPE_BLANK: 1341 if ( pElemStr && !lcl_IsInEmbedded( aEmbeddedEntries, nPos ) ) 1342 { 1343 // turn "_x" into the number of spaces used for x in InsertBlanks in the NumberFormat 1344 // (#i20396# the spaces may also be in embedded-text elements) 1345 1346 String aBlanks; 1347 SvNumberformat::InsertBlanks( aBlanks, 0, pElemStr->GetChar(1) ); 1348 AddToTextElement_Impl( aBlanks ); 1349 } 1350 break; 1351 case NF_KEY_GENERAL : 1352 WriteNumberElement_Impl( -1, 1, OUString(), sal_False, sal_False, 0, aEmbeddedEntries ); 1353 break; 1354 case NF_KEY_CCC: 1355 if (pElemStr) 1356 { 1357 if ( bCurrencyWritten ) 1358 AddToTextElement_Impl( *pElemStr ); // never more than one currency element 1359 else 1360 { 1361 //! must be different from short automatic format 1362 //! but should still be empty (meaning automatic) 1363 // pElemStr is "CCC" 1364 1365 WriteCurrencyElement_Impl( *pElemStr, OUString() ); 1366 bAnyContent = sal_True; 1367 bCurrencyWritten = sal_True; 1368 } 1369 } 1370 break; 1371 case NF_SYMBOLTYPE_CURRENCY: 1372 if (pElemStr) 1373 { 1374 if ( bCurrencyWritten ) 1375 AddToTextElement_Impl( *pElemStr ); // never more than one currency element 1376 else 1377 { 1378 WriteCurrencyElement_Impl( *pElemStr, sCurrExt ); 1379 bAnyContent = sal_True; 1380 bCurrencyWritten = sal_True; 1381 } 1382 } 1383 break; 1384 case NF_SYMBOLTYPE_DIGIT: 1385 if (!bNumWritten) // write number part 1386 { 1387 switch ( nFmtType ) 1388 { 1389 // for type 0 (not recognized as a special type), 1390 // write a "normal" number 1391 case 0: 1392 case NUMBERFORMAT_NUMBER: 1393 case NUMBERFORMAT_CURRENCY: 1394 case NUMBERFORMAT_PERCENT: 1395 { 1396 // decimals 1397 // only some built-in formats have automatic decimals 1398 sal_Int32 nDecimals = nPrecision; // from GetFormatSpecialInfo 1399 if ( eBuiltIn == NF_NUMBER_STANDARD || 1400 eBuiltIn == NF_CURRENCY_1000DEC2 || 1401 eBuiltIn == NF_CURRENCY_1000DEC2_RED || 1402 eBuiltIn == NF_CURRENCY_1000DEC2_CCC || 1403 eBuiltIn == NF_CURRENCY_1000DEC2_DASHED ) 1404 nDecimals = -1; 1405 1406 // integer digits 1407 // only one built-in format has automatic integer digits 1408 sal_Int32 nInteger = nLeading; 1409 if ( eBuiltIn == NF_NUMBER_SYSTEM ) 1410 nInteger = -1; 1411 1412 // string for decimal replacement 1413 // has to be taken from nPrecision 1414 // (positive number even for automatic decimals) 1415 String sDashStr; 1416 if ( bDecDashes && nPrecision > 0 ) 1417 sDashStr.Fill( nPrecision, '-' ); 1418 1419 WriteNumberElement_Impl( nDecimals, nInteger, sDashStr, bVarDecimals, 1420 bThousand, nTrailingThousands, aEmbeddedEntries ); 1421 bAnyContent = sal_True; 1422 } 1423 break; 1424 case NUMBERFORMAT_SCIENTIFIC: 1425 // #i43959# for scientific numbers, count all integer symbols ("0" and "#") 1426 // as integer digits: use nIntegerSymbols instead of nLeading 1427 // (use of '#' to select multiples in exponent might be added later) 1428 WriteScientificElement_Impl( nPrecision, nIntegerSymbols, bThousand, nExpDigits ); 1429 bAnyContent = sal_True; 1430 break; 1431 case NUMBERFORMAT_FRACTION: 1432 { 1433 sal_Int32 nInteger = nLeading; 1434 if ( pElemStr && pElemStr->GetChar(0) == '?' ) 1435 { 1436 // If the first digit character is a question mark, 1437 // the fraction doesn't have an integer part, and no 1438 // min-integer-digits attribute must be written. 1439 nInteger = -1; 1440 } 1441 WriteFractionElement_Impl( nInteger, bThousand, nPrecision, nPrecision ); 1442 bAnyContent = sal_True; 1443 } 1444 break; 1445 } 1446 1447 bNumWritten = sal_True; 1448 } 1449 break; 1450 case NF_SYMBOLTYPE_DECSEP: 1451 if ( pElemStr && nPrecision == 0 ) 1452 { 1453 // A decimal separator after the number, without following decimal digits, 1454 // isn't modelled as part of the number element, so it's written as text 1455 // (the distinction between a quoted and non-quoted, locale-dependent 1456 // character is lost here). 1457 1458 AddToTextElement_Impl( *pElemStr ); 1459 } 1460 break; 1461 case NF_SYMBOLTYPE_DEL: 1462 if ( pElemStr && *pElemStr == XubString('@') ) 1463 { 1464 WriteTextContentElement_Impl(); 1465 bAnyContent = sal_True; 1466 } 1467 break; 1468 1469 case NF_SYMBOLTYPE_CALENDAR: 1470 if ( pElemStr ) 1471 aCalendar = *pElemStr; 1472 break; 1473 1474 // date elements: 1475 1476 case NF_KEY_D: 1477 case NF_KEY_DD: 1478 { 1479 sal_Bool bLong = ( nElemType == NF_KEY_DD ); 1480 WriteDayElement_Impl( aCalendar, ( bSystemDate ? bLongSysDate : bLong ) ); 1481 bAnyContent = sal_True; 1482 } 1483 break; 1484 case NF_KEY_DDD: 1485 case NF_KEY_DDDD: 1486 case NF_KEY_NN: 1487 case NF_KEY_NNN: 1488 case NF_KEY_NNNN: 1489 case NF_KEY_AAA: 1490 case NF_KEY_AAAA: 1491 { 1492 OUString aCalAttr = aCalendar; 1493 if ( nElemType == NF_KEY_AAA || nElemType == NF_KEY_AAAA ) 1494 { 1495 // calendar attribute for AAA and AAAA is switched only for this element 1496 if (!aCalAttr.getLength()) 1497 aCalAttr = lcl_GetDefaultCalendar( pFormatter, nLang ); 1498 } 1499 1500 sal_Bool bLong = ( nElemType == NF_KEY_NNN || nElemType == NF_KEY_NNNN || 1501 nElemType == NF_KEY_DDDD || nElemType == NF_KEY_AAAA ); 1502 WriteDayOfWeekElement_Impl( aCalAttr, ( bSystemDate ? bLongSysDate : bLong ) ); 1503 bAnyContent = sal_True; 1504 if ( nElemType == NF_KEY_NNNN ) 1505 { 1506 // write additional text element for separator 1507 pLocaleData->setLocale( MsLangId::convertLanguageToLocale( nLang ) ); 1508 AddToTextElement_Impl( pLocaleData->getLongDateDayOfWeekSep() ); 1509 } 1510 } 1511 break; 1512 case NF_KEY_M: 1513 case NF_KEY_MM: 1514 case NF_KEY_MMM: 1515 case NF_KEY_MMMM: 1516 case NF_KEY_MMMMM: //! first letter of month name, no attribute available 1517 { 1518 sal_Bool bLong = ( nElemType == NF_KEY_MM || nElemType == NF_KEY_MMMM ); 1519 sal_Bool bText = ( nElemType == NF_KEY_MMM || nElemType == NF_KEY_MMMM || 1520 nElemType == NF_KEY_MMMMM ); 1521 WriteMonthElement_Impl( aCalendar, ( bSystemDate ? bLongSysDate : bLong ), bText ); 1522 bAnyContent = sal_True; 1523 } 1524 break; 1525 case NF_KEY_YY: 1526 case NF_KEY_YYYY: 1527 case NF_KEY_EC: 1528 case NF_KEY_EEC: 1529 case NF_KEY_R: //! R acts as EE, no attribute available 1530 { 1531 //! distinguish EE and R 1532 // calendar attribute for E and EE and R is set in first loop 1533 sal_Bool bLong = ( nElemType == NF_KEY_YYYY || nElemType == NF_KEY_EEC || 1534 nElemType == NF_KEY_R ); 1535 WriteYearElement_Impl( aCalendar, ( bSystemDate ? bLongSysDate : bLong ) ); 1536 bAnyContent = sal_True; 1537 } 1538 break; 1539 case NF_KEY_G: 1540 case NF_KEY_GG: 1541 case NF_KEY_GGG: 1542 case NF_KEY_RR: //! RR acts as GGGEE, no attribute available 1543 { 1544 //! distinguish GG and GGG and RR 1545 sal_Bool bLong = ( nElemType == NF_KEY_GGG || nElemType == NF_KEY_RR ); 1546 WriteEraElement_Impl( aCalendar, ( bSystemDate ? bLongSysDate : bLong ) ); 1547 bAnyContent = sal_True; 1548 if ( nElemType == NF_KEY_RR ) 1549 { 1550 // calendar attribute for RR is set in first loop 1551 WriteYearElement_Impl( aCalendar, ( bSystemDate ? bLongSysDate : sal_True ) ); 1552 } 1553 } 1554 break; 1555 case NF_KEY_Q: 1556 case NF_KEY_QQ: 1557 { 1558 sal_Bool bLong = ( nElemType == NF_KEY_QQ ); 1559 WriteQuarterElement_Impl( aCalendar, ( bSystemDate ? bLongSysDate : bLong ) ); 1560 bAnyContent = sal_True; 1561 } 1562 break; 1563 case NF_KEY_WW: 1564 WriteWeekElement_Impl( aCalendar ); 1565 bAnyContent = sal_True; 1566 break; 1567 1568 // time elements (bSystemDate is not used): 1569 1570 case NF_KEY_H: 1571 case NF_KEY_HH: 1572 WriteHoursElement_Impl( nElemType == NF_KEY_HH ); 1573 bAnyContent = sal_True; 1574 break; 1575 case NF_KEY_MI: 1576 case NF_KEY_MMI: 1577 WriteMinutesElement_Impl( nElemType == NF_KEY_MMI ); 1578 bAnyContent = sal_True; 1579 break; 1580 case NF_KEY_S: 1581 case NF_KEY_SS: 1582 WriteSecondsElement_Impl( ( nElemType == NF_KEY_SS ), nPrecision ); 1583 bAnyContent = sal_True; 1584 break; 1585 case NF_KEY_AMPM: 1586 case NF_KEY_AP: 1587 WriteAMPMElement_Impl(); // short/long? 1588 bAnyContent = sal_True; 1589 break; 1590 } 1591 nPrevType = nElemType; 1592 ++nPos; 1593 } 1594 } 1595 1596 if ( sTextContent.getLength() ) 1597 bAnyContent = sal_True; // element written in FinishTextElement_Impl 1598 1599 FinishTextElement_Impl(); // final text element - before maps 1600 1601 if ( !bAnyContent ) 1602 { 1603 // for an empty format, write an empty text element 1604 SvXMLElementExport aTElem( rExport, XML_NAMESPACE_NUMBER, XML_TEXT, 1605 sal_True, sal_False ); 1606 } 1607 1608 // 1609 // mapping (conditions) must be last elements 1610 // 1611 1612 if (bDefPart) 1613 { 1614 SvNumberformatLimitOps eOp1, eOp2; 1615 double fLimit1, fLimit2; 1616 rFormat.GetConditions( eOp1, fLimit1, eOp2, fLimit2 ); 1617 1618 WriteMapElement_Impl( eOp1, fLimit1, nKey, 0 ); 1619 WriteMapElement_Impl( eOp2, fLimit2, nKey, 1 ); 1620 1621 if ( rFormat.HasTextFormat() ) 1622 { 1623 // 4th part is for text -> make an "all other numbers" condition for the 3rd part 1624 // by reversing the 2nd condition 1625 1626 SvNumberformatLimitOps eOp3 = NUMBERFORMAT_OP_NO; 1627 double fLimit3 = fLimit2; 1628 switch ( eOp2 ) 1629 { 1630 case NUMBERFORMAT_OP_EQ: eOp3 = NUMBERFORMAT_OP_NE; break; 1631 case NUMBERFORMAT_OP_NE: eOp3 = NUMBERFORMAT_OP_EQ; break; 1632 case NUMBERFORMAT_OP_LT: eOp3 = NUMBERFORMAT_OP_GE; break; 1633 case NUMBERFORMAT_OP_LE: eOp3 = NUMBERFORMAT_OP_GT; break; 1634 case NUMBERFORMAT_OP_GT: eOp3 = NUMBERFORMAT_OP_LE; break; 1635 case NUMBERFORMAT_OP_GE: eOp3 = NUMBERFORMAT_OP_LT; break; 1636 default: 1637 break; 1638 } 1639 1640 if ( fLimit1 == fLimit2 && 1641 ( ( eOp1 == NUMBERFORMAT_OP_LT && eOp2 == NUMBERFORMAT_OP_GT ) || 1642 ( eOp1 == NUMBERFORMAT_OP_GT && eOp2 == NUMBERFORMAT_OP_LT ) ) ) 1643 { 1644 // For <x and >x, add =x as last condition 1645 // (just for readability, <=x would be valid, too) 1646 1647 eOp3 = NUMBERFORMAT_OP_EQ; 1648 } 1649 1650 WriteMapElement_Impl( eOp3, fLimit3, nKey, 2 ); 1651 } 1652 } 1653 } 1654 1655 //------------------------------------------------------------------------- 1656 1657 // 1658 // export one format 1659 // 1660 1661 void SvXMLNumFmtExport::ExportFormat_Impl( const SvNumberformat& rFormat, sal_uInt32 nKey ) 1662 { 1663 sal_uInt16 nUsedParts = 0; 1664 sal_uInt16 nPart; 1665 for (nPart=0; nPart<XMLNUM_MAX_PARTS; nPart++) 1666 if (rFormat.GetNumForType( nPart, 0, sal_False ) != 0) 1667 nUsedParts = nPart+1; 1668 1669 SvNumberformatLimitOps eOp1, eOp2; 1670 double fLimit1, fLimit2; 1671 rFormat.GetConditions( eOp1, fLimit1, eOp2, fLimit2 ); 1672 1673 // if conditions are set, even empty formats must be written 1674 1675 if ( eOp1 != NUMBERFORMAT_OP_NO && nUsedParts < 2 ) 1676 nUsedParts = 2; 1677 if ( eOp2 != NUMBERFORMAT_OP_NO && nUsedParts < 3 ) 1678 nUsedParts = 3; 1679 if ( rFormat.HasTextFormat() && nUsedParts < 4 ) 1680 nUsedParts = 4; 1681 1682 for (nPart=0; nPart<nUsedParts; nPart++) 1683 { 1684 sal_Bool bDefault = ( nPart+1 == nUsedParts ); // last = default 1685 ExportPart_Impl( rFormat, nKey, nPart, bDefault ); 1686 } 1687 } 1688 1689 //------------------------------------------------------------------------- 1690 1691 // 1692 // export method called by application 1693 // 1694 1695 void SvXMLNumFmtExport::Export( sal_Bool bIsAutoStyle ) 1696 { 1697 if ( !pFormatter ) 1698 return; // no formatter -> no entries 1699 1700 sal_uInt32 nKey; 1701 const SvNumberformat* pFormat = NULL; 1702 sal_Bool bNext(pUsedList->GetFirstUsed(nKey)); 1703 while(bNext) 1704 { 1705 pFormat = pFormatter->GetEntry(nKey); 1706 if(pFormat) 1707 ExportFormat_Impl( *pFormat, nKey ); 1708 bNext = pUsedList->GetNextUsed(nKey); 1709 } 1710 if (!bIsAutoStyle) 1711 { 1712 SvUShorts aLanguages; 1713 pFormatter->GetUsedLanguages( aLanguages ); 1714 sal_uInt16 nLangCount = aLanguages.Count(); 1715 for (sal_uInt16 nLangPos=0; nLangPos<nLangCount; nLangPos++) 1716 { 1717 LanguageType nLang = aLanguages[nLangPos]; 1718 1719 sal_uInt32 nDefaultIndex = 0; 1720 SvNumberFormatTable& rTable = pFormatter->GetEntryTable( 1721 NUMBERFORMAT_DEFINED, nDefaultIndex, nLang ); 1722 pFormat = rTable.First(); 1723 while (pFormat) 1724 { 1725 nKey = rTable.GetCurKey(); 1726 if (!pUsedList->IsUsed(nKey)) 1727 { 1728 DBG_ASSERT((pFormat->GetType() & NUMBERFORMAT_DEFINED) != 0, "a not user defined numberformat found"); 1729 // user-defined and used formats are exported 1730 ExportFormat_Impl( *pFormat, nKey ); 1731 // if it is a user-defined Format it will be added else nothing will hapen 1732 pUsedList->SetUsed(nKey); 1733 } 1734 1735 pFormat = rTable.Next(); 1736 } 1737 } 1738 } 1739 pUsedList->Export(); 1740 } 1741 1742 OUString SvXMLNumFmtExport::GetStyleName( sal_uInt32 nKey ) 1743 { 1744 if(pUsedList->IsUsed(nKey) || pUsedList->IsWasUsed(nKey)) 1745 return lcl_CreateStyleName( nKey, 0, sal_True, sPrefix ); 1746 else 1747 { 1748 DBG_ERROR("There is no written Data-Style"); 1749 return rtl::OUString(); 1750 } 1751 } 1752 1753 void SvXMLNumFmtExport::SetUsed( sal_uInt32 nKey ) 1754 { 1755 DBG_ASSERT( pFormatter != NULL, "missing formatter" ); 1756 if( !pFormatter ) 1757 return; 1758 1759 if (pFormatter->GetEntry(nKey)) 1760 pUsedList->SetUsed( nKey ); 1761 else { 1762 DBG_ERROR("no existing Numberformat found with this key"); 1763 } 1764 } 1765 1766 void SvXMLNumFmtExport::GetWasUsed(uno::Sequence<sal_Int32>& rWasUsed) 1767 { 1768 if (pUsedList) 1769 pUsedList->GetWasUsed(rWasUsed); 1770 } 1771 1772 void SvXMLNumFmtExport::SetWasUsed(const uno::Sequence<sal_Int32>& rWasUsed) 1773 { 1774 if (pUsedList) 1775 pUsedList->SetWasUsed(rWasUsed); 1776 } 1777 1778 1779 1780 const SvNumberformat* lcl_GetFormat( SvNumberFormatter* pFormatter, 1781 sal_uInt32 nKey ) 1782 { 1783 return ( pFormatter != NULL ) ? pFormatter->GetEntry( nKey ) : NULL; 1784 } 1785 1786 sal_uInt32 SvXMLNumFmtExport::ForceSystemLanguage( sal_uInt32 nKey ) 1787 { 1788 sal_uInt32 nRet = nKey; 1789 1790 const SvNumberformat* pFormat = lcl_GetFormat( pFormatter, nKey ); 1791 if( pFormat != NULL ) 1792 { 1793 DBG_ASSERT( pFormatter != NULL, "format without formatter?" ); 1794 1795 xub_StrLen nErrorPos; 1796 short nType = pFormat->GetType(); 1797 1798 sal_uInt32 nNewKey = pFormatter->GetFormatForLanguageIfBuiltIn( 1799 nKey, LANGUAGE_SYSTEM ); 1800 1801 if( nNewKey != nKey ) 1802 { 1803 nRet = nNewKey; 1804 } 1805 else 1806 { 1807 String aFormatString( pFormat->GetFormatstring() ); 1808 pFormatter->PutandConvertEntry( 1809 aFormatString, 1810 nErrorPos, nType, nNewKey, 1811 pFormat->GetLanguage(), LANGUAGE_SYSTEM ); 1812 1813 // success? Then use new key. 1814 if( nErrorPos == 0 ) 1815 nRet = nNewKey; 1816 } 1817 } 1818 1819 return nRet; 1820 } 1821