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