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