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_sw.hxx" 30 31 #include "hintids.hxx" 32 #include "unomid.h" 33 34 #include <basic/sbxvar.hxx> 35 #include <svl/macitem.hxx> 36 #include <svl/stritem.hxx> 37 #include <svl/stylepool.hxx> 38 #include <fmtautofmt.hxx> 39 #include <fchrfmt.hxx> 40 #include <fmtinfmt.hxx> 41 #include <txtatr.hxx> 42 #include <fmtruby.hxx> 43 #include <charfmt.hxx> 44 #include <hints.hxx> // SwUpdateAttr 45 #include <unostyle.hxx> 46 #include <unoevent.hxx> // SwHyperlinkEventDescriptor 47 #include <com/sun/star/text/RubyAdjust.hdl> 48 49 #include <cmdid.h> 50 #include <com/sun/star/uno/Any.h> 51 #include <SwStyleNameMapper.hxx> 52 53 #include <fmtmeta.hxx> 54 #include <ndtxt.hxx> // for meta 55 #include <doc.hxx> // for meta 56 #include <unometa.hxx> 57 #include <docsh.hxx> 58 #include <svl/zforlist.hxx> // GetNumberFormat 59 60 #include <boost/bind.hpp> 61 #include <algorithm> 62 63 64 using namespace ::com::sun::star; 65 using ::rtl::OUString; 66 67 TYPEINIT1_AUTOFACTORY(SwFmtINetFmt, SfxPoolItem); 68 TYPEINIT1_AUTOFACTORY(SwFmtAutoFmt, SfxPoolItem); 69 70 /************************************************************************* 71 |* 72 |* class SwFmtCharFmt 73 |* Beschreibung 74 |* Ersterstellung JP 23.11.90 75 |* Letzte Aenderung JP 09.08.94 76 |* 77 *************************************************************************/ 78 79 SwFmtCharFmt::SwFmtCharFmt( SwCharFmt *pFmt ) 80 : SfxPoolItem( RES_TXTATR_CHARFMT ), 81 SwClient(pFmt), 82 pTxtAttr( 0 ) 83 { 84 } 85 86 87 88 SwFmtCharFmt::SwFmtCharFmt( const SwFmtCharFmt& rAttr ) 89 : SfxPoolItem( RES_TXTATR_CHARFMT ), 90 SwClient( rAttr.GetCharFmt() ), 91 pTxtAttr( 0 ) 92 { 93 } 94 95 96 97 SwFmtCharFmt::~SwFmtCharFmt() {} 98 99 100 101 int SwFmtCharFmt::operator==( const SfxPoolItem& rAttr ) const 102 { 103 ASSERT( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" ); 104 return GetCharFmt() == ((SwFmtCharFmt&)rAttr).GetCharFmt(); 105 } 106 107 108 109 SfxPoolItem* SwFmtCharFmt::Clone( SfxItemPool* ) const 110 { 111 return new SwFmtCharFmt( *this ); 112 } 113 114 115 116 // weiterleiten an das TextAttribut 117 void SwFmtCharFmt::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew ) 118 { 119 if( pTxtAttr ) 120 pTxtAttr->ModifyNotification( pOld, pNew ); 121 } 122 123 124 125 // weiterleiten an das TextAttribut 126 sal_Bool SwFmtCharFmt::GetInfo( SfxPoolItem& rInfo ) const 127 { 128 return pTxtAttr ? pTxtAttr->GetInfo( rInfo ) : sal_False; 129 } 130 sal_Bool SwFmtCharFmt::QueryValue( uno::Any& rVal, sal_uInt8 ) const 131 { 132 String sCharFmtName; 133 if(GetCharFmt()) 134 SwStyleNameMapper::FillProgName(GetCharFmt()->GetName(), sCharFmtName, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True ); 135 rVal <<= OUString( sCharFmtName ); 136 return sal_True; 137 } 138 sal_Bool SwFmtCharFmt::PutValue( const uno::Any& , sal_uInt8 ) 139 { 140 DBG_ERROR("Zeichenvorlage kann mit PutValue nicht gesetzt werden!"); 141 return sal_False; 142 } 143 144 /************************************************************************* 145 |* 146 |* class SwFmtAutoFmt 147 |* Beschreibung 148 |* Ersterstellung AMA 12.05.06 149 |* Letzte Aenderung AMA 12.05.06 150 |* 151 *************************************************************************/ 152 153 SwFmtAutoFmt::SwFmtAutoFmt( sal_uInt16 nInitWhich ) 154 : SfxPoolItem( nInitWhich ) 155 { 156 } 157 158 SwFmtAutoFmt::SwFmtAutoFmt( const SwFmtAutoFmt& rAttr ) 159 : SfxPoolItem( rAttr.Which() ), mpHandle( rAttr.mpHandle ) 160 { 161 } 162 163 SwFmtAutoFmt::~SwFmtAutoFmt() 164 { 165 } 166 167 int SwFmtAutoFmt::operator==( const SfxPoolItem& rAttr ) const 168 { 169 ASSERT( SfxPoolItem::operator==( rAttr ), "different attributes" ); 170 return mpHandle == ((SwFmtAutoFmt&)rAttr).mpHandle; 171 } 172 173 SfxPoolItem* SwFmtAutoFmt::Clone( SfxItemPool* ) const 174 { 175 return new SwFmtAutoFmt( *this ); 176 } 177 178 sal_Bool SwFmtAutoFmt::QueryValue( uno::Any& rVal, sal_uInt8 ) const 179 { 180 String sCharFmtName = StylePool::nameOf( mpHandle ); 181 rVal <<= OUString( sCharFmtName ); 182 return sal_True; 183 } 184 185 sal_Bool SwFmtAutoFmt::PutValue( const uno::Any& , sal_uInt8 ) 186 { 187 //the format is not renameable via API 188 return sal_False; 189 } 190 191 /************************************************************************* 192 |* 193 |* class SwFmtINetFmt 194 |* Beschreibung 195 |* Ersterstellung AMA 02.08.96 196 |* Letzte Aenderung AMA 02.08.96 197 |* 198 *************************************************************************/ 199 200 SwFmtINetFmt::SwFmtINetFmt() 201 : SfxPoolItem( RES_TXTATR_INETFMT ), 202 pMacroTbl( 0 ), 203 pTxtAttr( 0 ), 204 nINetId( 0 ), 205 nVisitedId( 0 ) 206 {} 207 208 SwFmtINetFmt::SwFmtINetFmt( const XubString& rURL, const XubString& rTarget ) 209 : SfxPoolItem( RES_TXTATR_INETFMT ), 210 aURL( rURL ), 211 aTargetFrame( rTarget ), 212 pMacroTbl( 0 ), 213 pTxtAttr( 0 ), 214 nINetId( 0 ), 215 nVisitedId( 0 ) 216 { 217 } 218 219 SwFmtINetFmt::SwFmtINetFmt( const SwFmtINetFmt& rAttr ) 220 : SfxPoolItem( RES_TXTATR_INETFMT ), 221 aURL( rAttr.GetValue() ), 222 aTargetFrame( rAttr.aTargetFrame ), 223 aINetFmt( rAttr.aINetFmt ), 224 aVisitedFmt( rAttr.aVisitedFmt ), 225 aName( rAttr.aName ), 226 pMacroTbl( 0 ), 227 pTxtAttr( 0 ), 228 nINetId( rAttr.nINetId ), 229 nVisitedId( rAttr.nVisitedId ) 230 { 231 if( rAttr.GetMacroTbl() ) 232 pMacroTbl = new SvxMacroTableDtor( *rAttr.GetMacroTbl() ); 233 } 234 235 SwFmtINetFmt::~SwFmtINetFmt() 236 { 237 delete pMacroTbl; 238 } 239 240 241 242 int SwFmtINetFmt::operator==( const SfxPoolItem& rAttr ) const 243 { 244 ASSERT( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" ); 245 sal_Bool bRet = SfxPoolItem::operator==( (SfxPoolItem&) rAttr ) 246 && aURL == ((SwFmtINetFmt&)rAttr).aURL 247 && aName == ((SwFmtINetFmt&)rAttr).aName 248 && aTargetFrame == ((SwFmtINetFmt&)rAttr).aTargetFrame 249 && aINetFmt == ((SwFmtINetFmt&)rAttr).aINetFmt 250 && aVisitedFmt == ((SwFmtINetFmt&)rAttr).aVisitedFmt 251 && nINetId == ((SwFmtINetFmt&)rAttr).nINetId 252 && nVisitedId == ((SwFmtINetFmt&)rAttr).nVisitedId; 253 254 if( !bRet ) 255 return sal_False; 256 257 const SvxMacroTableDtor* pOther = ((SwFmtINetFmt&)rAttr).pMacroTbl; 258 if( !pMacroTbl ) 259 return ( !pOther || !pOther->Count() ); 260 if( !pOther ) 261 return 0 == pMacroTbl->Count(); 262 263 const SvxMacroTableDtor& rOwn = *pMacroTbl; 264 const SvxMacroTableDtor& rOther = *pOther; 265 266 // Anzahl unterschiedlich => auf jeden Fall ungleich 267 if( rOwn.Count() != rOther.Count() ) 268 return sal_False; 269 270 // einzeln vergleichen; wegen Performance ist die Reihenfolge wichtig 271 for( sal_uInt16 nNo = 0; nNo < rOwn.Count(); ++nNo ) 272 { 273 const SvxMacro *pOwnMac = rOwn.GetObject(nNo); 274 const SvxMacro *pOtherMac = rOther.GetObject(nNo); 275 if ( rOwn.GetKey(pOwnMac) != rOther.GetKey(pOtherMac) || 276 pOwnMac->GetLibName() != pOtherMac->GetLibName() || 277 pOwnMac->GetMacName() != pOtherMac->GetMacName() ) 278 return sal_False; 279 } 280 return sal_True; 281 } 282 283 284 285 SfxPoolItem* SwFmtINetFmt::Clone( SfxItemPool* ) const 286 { 287 return new SwFmtINetFmt( *this ); 288 } 289 290 291 292 void SwFmtINetFmt::SetMacroTbl( const SvxMacroTableDtor* pNewTbl ) 293 { 294 if( pNewTbl ) 295 { 296 if( pMacroTbl ) 297 *pMacroTbl = *pNewTbl; 298 else 299 pMacroTbl = new SvxMacroTableDtor( *pNewTbl ); 300 } 301 else if( pMacroTbl ) 302 delete pMacroTbl, pMacroTbl = 0; 303 } 304 305 306 307 void SwFmtINetFmt::SetMacro( sal_uInt16 nEvent, const SvxMacro& rMacro ) 308 { 309 if( !pMacroTbl ) 310 pMacroTbl = new SvxMacroTableDtor; 311 312 SvxMacro *pOldMacro; 313 if( 0 != ( pOldMacro = pMacroTbl->Get( nEvent )) ) 314 { 315 delete pOldMacro; 316 pMacroTbl->Replace( nEvent, new SvxMacro( rMacro ) ); 317 } 318 else 319 pMacroTbl->Insert( nEvent, new SvxMacro( rMacro ) ); 320 } 321 322 323 324 const SvxMacro* SwFmtINetFmt::GetMacro( sal_uInt16 nEvent ) const 325 { 326 const SvxMacro* pRet = 0; 327 if( pMacroTbl && pMacroTbl->IsKeyValid( nEvent ) ) 328 pRet = pMacroTbl->Get( nEvent ); 329 return pRet; 330 } 331 332 333 334 sal_Bool SwFmtINetFmt::QueryValue( uno::Any& rVal, sal_uInt8 nMemberId ) const 335 { 336 sal_Bool bRet = sal_True; 337 XubString sVal; 338 nMemberId &= ~CONVERT_TWIPS; 339 switch(nMemberId) 340 { 341 case MID_URL_URL: 342 sVal = aURL; 343 break; 344 case MID_URL_TARGET: 345 sVal = aTargetFrame; 346 break; 347 case MID_URL_HYPERLINKNAME: 348 sVal = aName; 349 break; 350 case MID_URL_VISITED_FMT: 351 sVal = aVisitedFmt; 352 if( !sVal.Len() && nVisitedId != 0 ) 353 SwStyleNameMapper::FillUIName( nVisitedId, sVal ); 354 if( sVal.Len() ) 355 SwStyleNameMapper::FillProgName( sVal, sVal, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True ); 356 break; 357 case MID_URL_UNVISITED_FMT: 358 sVal = aINetFmt; 359 if( !sVal.Len() && nINetId != 0 ) 360 SwStyleNameMapper::FillUIName( nINetId, sVal ); 361 if( sVal.Len() ) 362 SwStyleNameMapper::FillProgName( sVal, sVal, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True ); 363 break; 364 case MID_URL_HYPERLINKEVENTS: 365 { 366 // create (and return) event descriptor 367 SwHyperlinkEventDescriptor* pEvents = 368 new SwHyperlinkEventDescriptor(); 369 pEvents->copyMacrosFromINetFmt(*this); 370 uno::Reference<container::XNameReplace> xNameReplace(pEvents); 371 372 // all others return a string; so we just set rVal here and exit 373 rVal <<= xNameReplace; 374 return bRet; 375 } 376 default: 377 break; 378 } 379 rVal <<= OUString(sVal); 380 return bRet; 381 } 382 sal_Bool SwFmtINetFmt::PutValue( const uno::Any& rVal, sal_uInt8 nMemberId ) 383 { 384 sal_Bool bRet = sal_True; 385 nMemberId &= ~CONVERT_TWIPS; 386 387 // all properties except HyperlinkEvents are of type string, hence 388 // we treat HyperlinkEvents specially 389 if (MID_URL_HYPERLINKEVENTS == nMemberId) 390 { 391 uno::Reference<container::XNameReplace> xReplace; 392 rVal >>= xReplace; 393 if (xReplace.is()) 394 { 395 // Create hyperlink event descriptor. Then copy events 396 // from argument into descriptor. Then copy events from 397 // the descriptor into the format. 398 SwHyperlinkEventDescriptor* pEvents = new SwHyperlinkEventDescriptor(); 399 uno::Reference< lang::XServiceInfo> xHold = pEvents; 400 pEvents->copyMacrosFromNameReplace(xReplace); 401 pEvents->copyMacrosIntoINetFmt(*this); 402 } 403 else 404 { 405 // wrong type! 406 bRet = sal_False; 407 } 408 } 409 else 410 { 411 // all string properties: 412 if(rVal.getValueType() != ::getCppuType((rtl::OUString*)0)) 413 return sal_False; 414 XubString sVal = *(rtl::OUString*)rVal.getValue(); 415 switch(nMemberId) 416 { 417 case MID_URL_URL: 418 aURL = sVal; 419 break; 420 case MID_URL_TARGET: 421 aTargetFrame = sVal; 422 break; 423 case MID_URL_HYPERLINKNAME: 424 aName = sVal; 425 break; 426 case MID_URL_VISITED_FMT: 427 { 428 String aString; 429 SwStyleNameMapper::FillUIName( sVal, aString, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True ); 430 aVisitedFmt = OUString ( aString ); 431 nVisitedId = SwStyleNameMapper::GetPoolIdFromUIName( aVisitedFmt, 432 nsSwGetPoolIdFromName::GET_POOLID_CHRFMT ); 433 } 434 break; 435 case MID_URL_UNVISITED_FMT: 436 { 437 String aString; 438 SwStyleNameMapper::FillUIName( sVal, aString, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True ); 439 aINetFmt = OUString ( aString ); 440 nINetId = SwStyleNameMapper::GetPoolIdFromUIName( aINetFmt, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT ); 441 } 442 break; 443 default: 444 bRet = sal_False; 445 } 446 } 447 return bRet; 448 } 449 450 451 /************************************************************************* 452 |* class SwFmtRuby 453 *************************************************************************/ 454 455 SwFmtRuby::SwFmtRuby( const String& rRubyTxt ) 456 : SfxPoolItem( RES_TXTATR_CJK_RUBY ), 457 sRubyTxt( rRubyTxt ), 458 pTxtAttr( 0 ), 459 nCharFmtId( 0 ), 460 nPosition( 0 ), 461 nAdjustment( 0 ) 462 { 463 } 464 465 SwFmtRuby::SwFmtRuby( const SwFmtRuby& rAttr ) 466 : SfxPoolItem( RES_TXTATR_CJK_RUBY ), 467 sRubyTxt( rAttr.sRubyTxt ), 468 sCharFmtName( rAttr.sCharFmtName ), 469 pTxtAttr( 0 ), 470 nCharFmtId( rAttr.nCharFmtId), 471 nPosition( rAttr.nPosition ), 472 nAdjustment( rAttr.nAdjustment ) 473 { 474 } 475 476 SwFmtRuby::~SwFmtRuby() 477 { 478 } 479 480 SwFmtRuby& SwFmtRuby::operator=( const SwFmtRuby& rAttr ) 481 { 482 sRubyTxt = rAttr.sRubyTxt; 483 sCharFmtName = rAttr.sCharFmtName; 484 nCharFmtId = rAttr.nCharFmtId; 485 nPosition = rAttr.nPosition; 486 nAdjustment = rAttr.nAdjustment; 487 pTxtAttr = 0; 488 return *this; 489 } 490 491 int SwFmtRuby::operator==( const SfxPoolItem& rAttr ) const 492 { 493 ASSERT( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" ); 494 return sRubyTxt == ((SwFmtRuby&)rAttr).sRubyTxt && 495 sCharFmtName == ((SwFmtRuby&)rAttr).sCharFmtName && 496 nCharFmtId == ((SwFmtRuby&)rAttr).nCharFmtId && 497 nPosition == ((SwFmtRuby&)rAttr).nPosition && 498 nAdjustment == ((SwFmtRuby&)rAttr).nAdjustment; 499 } 500 501 SfxPoolItem* SwFmtRuby::Clone( SfxItemPool* ) const 502 { 503 return new SwFmtRuby( *this ); 504 } 505 506 sal_Bool SwFmtRuby::QueryValue( uno::Any& rVal, 507 sal_uInt8 nMemberId ) const 508 { 509 sal_Bool bRet = sal_True; 510 nMemberId &= ~CONVERT_TWIPS; 511 switch( nMemberId ) 512 { 513 case MID_RUBY_TEXT: rVal <<= (OUString)sRubyTxt; break; 514 case MID_RUBY_ADJUST: rVal <<= (sal_Int16)nAdjustment; break; 515 case MID_RUBY_CHARSTYLE: 516 { 517 String aString; 518 SwStyleNameMapper::FillProgName(sCharFmtName, aString, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT, sal_True ); 519 rVal <<= OUString ( aString ); 520 } 521 break; 522 case MID_RUBY_ABOVE: 523 { 524 sal_Bool bAbove = !nPosition; 525 rVal.setValue(&bAbove, ::getBooleanCppuType()); 526 } 527 break; 528 default: 529 bRet = sal_False; 530 } 531 return bRet; 532 } 533 sal_Bool SwFmtRuby::PutValue( const uno::Any& rVal, 534 sal_uInt8 nMemberId ) 535 { 536 sal_Bool bRet = sal_True; 537 nMemberId &= ~CONVERT_TWIPS; 538 switch( nMemberId ) 539 { 540 case MID_RUBY_TEXT: 541 { 542 OUString sTmp; 543 bRet = rVal >>= sTmp; 544 sRubyTxt = sTmp; 545 } 546 break; 547 case MID_RUBY_ADJUST: 548 { 549 sal_Int16 nSet = 0; 550 rVal >>= nSet; 551 if(nSet >= 0 && nSet <= text::RubyAdjust_INDENT_BLOCK) 552 nAdjustment = nSet; 553 else 554 bRet = sal_False; 555 } 556 break; 557 case MID_RUBY_ABOVE: 558 { 559 const uno::Type& rType = ::getBooleanCppuType(); 560 if(rVal.hasValue() && rVal.getValueType() == rType) 561 { 562 sal_Bool bAbove = *(sal_Bool*)rVal.getValue(); 563 nPosition = bAbove ? 0 : 1; 564 } 565 } 566 break; 567 case MID_RUBY_CHARSTYLE: 568 { 569 OUString sTmp; 570 bRet = rVal >>= sTmp; 571 if(bRet) 572 sCharFmtName = SwStyleNameMapper::GetUIName(sTmp, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT ); 573 } 574 break; 575 default: 576 bRet = sal_False; 577 } 578 return bRet; 579 } 580 581 582 /************************************************************************* 583 class SwFmtMeta 584 ************************************************************************/ 585 586 SwFmtMeta * SwFmtMeta::CreatePoolDefault(const sal_uInt16 i_nWhich) 587 { 588 return new SwFmtMeta(i_nWhich); 589 } 590 591 SwFmtMeta::SwFmtMeta(const sal_uInt16 i_nWhich) 592 : SfxPoolItem( i_nWhich ) 593 , m_pMeta() 594 , m_pTxtAttr( 0 ) 595 { 596 ASSERT((RES_TXTATR_META == i_nWhich) || (RES_TXTATR_METAFIELD == i_nWhich), 597 "ERROR: SwFmtMeta: invalid which id!"); 598 } 599 600 SwFmtMeta::SwFmtMeta( ::boost::shared_ptr< ::sw::Meta > const & i_pMeta, 601 const sal_uInt16 i_nWhich ) 602 : SfxPoolItem( i_nWhich ) 603 , m_pMeta( i_pMeta ) 604 , m_pTxtAttr( 0 ) 605 { 606 ASSERT((RES_TXTATR_META == i_nWhich) || (RES_TXTATR_METAFIELD == i_nWhich), 607 "ERROR: SwFmtMeta: invalid which id!"); 608 ASSERT(m_pMeta, "SwFmtMeta: no Meta ?"); 609 // DO NOT call m_pMeta->SetFmtMeta(this) here; only from SetTxtAttr! 610 } 611 612 SwFmtMeta::~SwFmtMeta() 613 { 614 if (m_pMeta && (m_pMeta->GetFmtMeta() == this)) 615 { 616 NotifyChangeTxtNode(0); 617 m_pMeta->SetFmtMeta(0); 618 } 619 } 620 621 int SwFmtMeta::operator==( const SfxPoolItem & i_rOther ) const 622 { 623 ASSERT( SfxPoolItem::operator==( i_rOther ), "i just copied this assert" ); 624 return SfxPoolItem::operator==( i_rOther ) 625 && (m_pMeta == static_cast<SwFmtMeta const &>( i_rOther ).m_pMeta); 626 } 627 628 SfxPoolItem * SwFmtMeta::Clone( SfxItemPool * /*pPool*/ ) const 629 { 630 // if this is indeed a copy, then DoCopy must be called later! 631 return (m_pMeta) // #i105148# pool default may be cloned also! 632 ? new SwFmtMeta( m_pMeta, Which() ) : new SwFmtMeta( Which() ); 633 } 634 635 void SwFmtMeta::SetTxtAttr(SwTxtMeta * const i_pTxtAttr) 636 { 637 OSL_ENSURE(!(m_pTxtAttr && i_pTxtAttr), 638 "SwFmtMeta::SetTxtAttr: already has text attribute?"); 639 OSL_ENSURE( m_pTxtAttr || i_pTxtAttr , 640 "SwFmtMeta::SetTxtAttr: no attribute to remove?"); 641 m_pTxtAttr = i_pTxtAttr; 642 OSL_ENSURE(m_pMeta, "inserted SwFmtMeta has no sw::Meta?"); 643 // the sw::Meta must be able to find the current text attribute! 644 if (m_pMeta) 645 { 646 if (i_pTxtAttr) 647 { 648 m_pMeta->SetFmtMeta(this); 649 } 650 else if (m_pMeta->GetFmtMeta() == this) 651 { // text attribute gone => de-register from text node! 652 NotifyChangeTxtNode(0); 653 m_pMeta->SetFmtMeta(0); 654 } 655 } 656 } 657 658 void SwFmtMeta::NotifyChangeTxtNode(SwTxtNode *const pTxtNode) 659 { 660 // N.B.: do not reset m_pTxtAttr here: see call in nodes.cxx, 661 // where the hint is not deleted! 662 OSL_ENSURE(m_pMeta, "SwFmtMeta::NotifyChangeTxtNode: no Meta?"); 663 if (m_pMeta && (m_pMeta->GetFmtMeta() == this)) 664 { // do not call Modify, that would call SwXMeta::Modify! 665 m_pMeta->NotifyChangeTxtNode(pTxtNode); 666 } 667 } 668 669 // this SwFmtMeta has been cloned and points at the same sw::Meta as the source 670 // this method copies the sw::Meta 671 void SwFmtMeta::DoCopy(::sw::MetaFieldManager & i_rTargetDocManager, 672 SwTxtNode & i_rTargetTxtNode) 673 { 674 OSL_ENSURE(m_pMeta, "DoCopy called for SwFmtMeta with no sw::Meta?"); 675 if (m_pMeta) 676 { 677 const ::boost::shared_ptr< ::sw::Meta> pOriginal( m_pMeta ); 678 if (RES_TXTATR_META == Which()) 679 { 680 m_pMeta.reset( new ::sw::Meta(this) ); 681 } 682 else 683 { 684 ::sw::MetaField *const pMetaField( 685 static_cast< ::sw::MetaField* >(pOriginal.get())); 686 m_pMeta = i_rTargetDocManager.makeMetaField( this, 687 pMetaField->m_nNumberFormat, pMetaField->IsFixedLanguage() ); 688 } 689 // Meta must have a text node before calling RegisterAsCopyOf 690 m_pMeta->NotifyChangeTxtNode(& i_rTargetTxtNode); 691 // this cannot be done in Clone: a Clone is not necessarily a copy! 692 m_pMeta->RegisterAsCopyOf(*pOriginal); 693 } 694 } 695 696 697 namespace sw { 698 699 /************************************************************************* 700 class sw::Meta 701 ************************************************************************/ 702 703 Meta::Meta(SwFmtMeta * const i_pFmt) 704 : ::sfx2::Metadatable() 705 , SwModify() 706 , m_pFmt( i_pFmt ) 707 { 708 } 709 710 Meta::~Meta() 711 { 712 } 713 714 SwTxtMeta * Meta::GetTxtAttr() const 715 { 716 return (m_pFmt) ? m_pFmt->GetTxtAttr() : 0; 717 } 718 719 SwTxtNode * Meta::GetTxtNode() const 720 { 721 return m_pTxtNode; 722 } 723 724 void Meta::NotifyChangeTxtNodeImpl() 725 { 726 if (m_pTxtNode && (GetRegisteredIn() != m_pTxtNode)) 727 { 728 m_pTxtNode->Add(this); 729 } 730 else if (!m_pTxtNode && GetRegisteredIn()) 731 { 732 GetRegisteredInNonConst()->Remove(this); 733 } 734 } 735 736 void Meta::NotifyChangeTxtNode(SwTxtNode *const pTxtNode) 737 { 738 m_pTxtNode = pTxtNode; 739 NotifyChangeTxtNodeImpl(); 740 if (!pTxtNode) // text node gone? invalidate UNO object! 741 { 742 SwPtrMsgPoolItem aMsgHint( RES_REMOVE_UNO_OBJECT, 743 &static_cast<SwModify&>(*this) ); // cast to base class! 744 this->Modify(&aMsgHint, &aMsgHint); 745 } 746 } 747 748 // SwClient 749 void Meta::Modify( const SfxPoolItem *pOld, const SfxPoolItem *pNew ) 750 { 751 NotifyClients(pOld, pNew); 752 if (pOld && (RES_REMOVE_UNO_OBJECT == pOld->Which())) 753 { // invalidate cached uno object 754 SetXMeta(uno::Reference<rdf::XMetadatable>(0)); 755 } 756 } 757 758 // sfx2::Metadatable 759 ::sfx2::IXmlIdRegistry& Meta::GetRegistry() 760 { 761 SwTxtNode * const pTxtNode( GetTxtNode() ); 762 // GetRegistry may only be called on a meta that is actually in the 763 // document, which means it has a pointer to its text node 764 OSL_ENSURE(pTxtNode, "ERROR: GetRegistry: no text node?"); 765 if (!pTxtNode) 766 throw uno::RuntimeException(); 767 return pTxtNode->GetRegistry(); 768 } 769 770 bool Meta::IsInClipboard() const 771 { 772 const SwTxtNode * const pTxtNode( GetTxtNode() ); 773 // no text node: in UNDO OSL_ENSURE(pTxtNode, "IsInClipboard: no text node?"); 774 return (pTxtNode) ? pTxtNode->IsInClipboard() : false; 775 } 776 777 bool Meta::IsInUndo() const 778 { 779 const SwTxtNode * const pTxtNode( GetTxtNode() ); 780 // no text node: in UNDO OSL_ENSURE(pTxtNode, "IsInUndo: no text node?"); 781 return (pTxtNode) ? pTxtNode->IsInUndo() : true; 782 } 783 784 bool Meta::IsInContent() const 785 { 786 const SwTxtNode * const pTxtNode( GetTxtNode() ); 787 OSL_ENSURE(pTxtNode, "IsInContent: no text node?"); 788 return (pTxtNode) ? pTxtNode->IsInContent() : true; 789 } 790 791 ::com::sun::star::uno::Reference< ::com::sun::star::rdf::XMetadatable > 792 Meta::MakeUnoObject() 793 { 794 return SwXMeta::CreateXMeta(*this); 795 } 796 797 /************************************************************************* 798 class sw::MetaField 799 ************************************************************************/ 800 801 MetaField::MetaField(SwFmtMeta * const i_pFmt, 802 const sal_uInt32 nNumberFormat, const bool bIsFixedLanguage) 803 : Meta(i_pFmt) 804 , m_nNumberFormat( nNumberFormat ) 805 , m_bIsFixedLanguage( bIsFixedLanguage ) 806 { 807 } 808 809 void MetaField::GetPrefixAndSuffix( 810 ::rtl::OUString *const o_pPrefix, ::rtl::OUString *const o_pSuffix) 811 { 812 try 813 { 814 const uno::Reference<rdf::XMetadatable> xMetaField( MakeUnoObject() ); 815 OSL_ENSURE(dynamic_cast<SwXMetaField*>(xMetaField.get()), 816 "GetPrefixAndSuffix: no SwXMetaField?"); 817 if (xMetaField.is()) 818 { 819 SwTxtNode * const pTxtNode( GetTxtNode() ); 820 SwDocShell const * const pShell(pTxtNode->GetDoc()->GetDocShell()); 821 const uno::Reference<frame::XModel> xModel( 822 (pShell) ? pShell->GetModel() : 0, uno::UNO_SET_THROW); 823 getPrefixAndSuffix(xModel, xMetaField, o_pPrefix, o_pSuffix); 824 } 825 } catch (uno::Exception) { 826 OSL_ENSURE(false, "exception?"); 827 } 828 } 829 830 sal_uInt32 MetaField::GetNumberFormat(::rtl::OUString const & rContent) const 831 { 832 //TODO: this probably lacks treatment for some special cases 833 sal_uInt32 nNumberFormat( m_nNumberFormat ); 834 SwTxtNode * const pTxtNode( GetTxtNode() ); 835 if (pTxtNode) 836 { 837 SvNumberFormatter *const pNumberFormatter( 838 pTxtNode->GetDoc()->GetNumberFormatter() ); 839 double number; 840 (void) pNumberFormatter->IsNumberFormat( 841 rContent, nNumberFormat, number ); 842 } 843 return nNumberFormat; 844 } 845 846 void MetaField::SetNumberFormat(sal_uInt32 nNumberFormat) 847 { 848 // effectively, the member is only a default: 849 // GetNumberFormat checks if the text actually conforms 850 m_nNumberFormat = nNumberFormat; 851 } 852 853 854 /************************************************************************* 855 class sw::MetaFieldManager 856 ************************************************************************/ 857 858 859 MetaFieldManager::MetaFieldManager() 860 { 861 } 862 863 ::boost::shared_ptr<MetaField> 864 MetaFieldManager::makeMetaField(SwFmtMeta * const i_pFmt, 865 const sal_uInt32 nNumberFormat, const bool bIsFixedLanguage) 866 { 867 const ::boost::shared_ptr<MetaField> pMetaField( 868 new MetaField(i_pFmt, nNumberFormat, bIsFixedLanguage) ); 869 m_MetaFields.push_back(pMetaField); 870 return pMetaField; 871 } 872 873 struct IsInUndo 874 { 875 bool operator()(::boost::weak_ptr<MetaField> const & pMetaField) { 876 return pMetaField.lock()->IsInUndo(); 877 } 878 }; 879 880 struct MakeUnoObject 881 { 882 uno::Reference<text::XTextField> 883 operator()(::boost::weak_ptr<MetaField> const & pMetaField) { 884 return uno::Reference<text::XTextField>( 885 pMetaField.lock()->MakeUnoObject(), uno::UNO_QUERY); 886 } 887 }; 888 889 ::std::vector< uno::Reference<text::XTextField> > 890 MetaFieldManager::getMetaFields() 891 { 892 // erase deleted fields 893 const MetaFieldList_t::iterator iter( 894 ::std::remove_if(m_MetaFields.begin(), m_MetaFields.end(), 895 ::boost::bind(&::boost::weak_ptr<MetaField>::expired, _1))); 896 m_MetaFields.erase(iter, m_MetaFields.end()); 897 // filter out fields in UNDO 898 MetaFieldList_t filtered(m_MetaFields.size()); 899 const MetaFieldList_t::iterator iter2( 900 ::std::remove_copy_if(m_MetaFields.begin(), m_MetaFields.end(), 901 filtered.begin(), IsInUndo())); 902 filtered.erase(iter2, filtered.end()); 903 // create uno objects 904 ::std::vector< uno::Reference<text::XTextField> > ret(filtered.size()); 905 ::std::transform(filtered.begin(), filtered.end(), ret.begin(), 906 MakeUnoObject()); 907 return ret; 908 } 909 910 } // namespace sw 911 912 913