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 28 #define _SVSTDARR_USHORTSSORT 29 #define _SVSTDARR_USHORTS 30 #include <svl/svstdarr.hxx> 31 #include <com/sun/star/text/ReferenceFieldPart.hpp> 32 #include <com/sun/star/text/ReferenceFieldSource.hpp> 33 #include <unotools/localedatawrapper.hxx> 34 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 35 #include <comphelper/processfactory.hxx> 36 #include <editeng/unolingu.hxx> 37 #include <doc.hxx> 38 #include <pam.hxx> 39 #include <cntfrm.hxx> 40 #include <pagefrm.hxx> 41 #include <docary.hxx> 42 #include <fmtfld.hxx> 43 #include <txtfld.hxx> 44 #include <txtftn.hxx> 45 #include <fmtrfmrk.hxx> 46 #include <txtrfmrk.hxx> 47 #include <fmtftn.hxx> 48 #include <ndtxt.hxx> 49 #include <chpfld.hxx> 50 #include <reffld.hxx> 51 #include <expfld.hxx> 52 #include <txtfrm.hxx> 53 #include <flyfrm.hxx> 54 #include <pagedesc.hxx> 55 #include <IMark.hxx> 56 #include <crossrefbookmark.hxx> 57 #include <ftnidx.hxx> 58 #include <viewsh.hxx> 59 #include <unofldmid.h> 60 #include <SwStyleNameMapper.hxx> 61 #include <shellres.hxx> 62 #include <poolfmt.hxx> 63 #include <poolfmt.hrc> 64 #include <comcore.hrc> 65 #include <numrule.hxx> 66 #include <SwNodeNum.hxx> 67 #include <switerator.hxx> 68 69 using namespace ::com::sun::star; 70 using namespace ::com::sun::star::text; 71 using namespace ::com::sun::star::lang; 72 using ::rtl::OUString; 73 74 extern void InsertSort( SvUShorts& rArr, sal_uInt16 nIdx, sal_uInt16* pInsPos = 0 ); 75 76 void lcl_GetLayTree( const SwFrm* pFrm, SvPtrarr& rArr ) 77 { 78 while( pFrm ) 79 { 80 if( pFrm->IsBodyFrm() ) // soll uns nicht weiter interessieren 81 pFrm = pFrm->GetUpper(); 82 else 83 { 84 void* p = (void*)pFrm; 85 rArr.Insert( p, rArr.Count() ); 86 87 // bei der Seite ist schluss 88 if( pFrm->IsPageFrm() ) 89 break; 90 91 if( pFrm->IsFlyFrm() ) 92 pFrm = ((SwFlyFrm*)pFrm)->GetAnchorFrm(); 93 else 94 pFrm = pFrm->GetUpper(); 95 } 96 } 97 } 98 99 100 sal_Bool IsFrameBehind( const SwTxtNode& rMyNd, sal_uInt16 nMySttPos, 101 const SwTxtNode& rBehindNd, sal_uInt16 nSttPos ) 102 { 103 const SwTxtFrm *pMyFrm = (SwTxtFrm*)rMyNd.getLayoutFrm( rMyNd.GetDoc()->GetCurrentLayout(), 0,0,sal_False), 104 *pFrm = (SwTxtFrm*)rBehindNd.getLayoutFrm( rBehindNd.GetDoc()->GetCurrentLayout(), 0,0,sal_False); 105 106 while( pFrm && !pFrm->IsInside( nSttPos ) ) 107 pFrm = (SwTxtFrm*)pFrm->GetFollow(); 108 while( pMyFrm && !pMyFrm->IsInside( nMySttPos ) ) 109 pMyFrm = (SwTxtFrm*)pMyFrm->GetFollow(); 110 111 if( !pFrm || !pMyFrm || pFrm == pMyFrm ) 112 return sal_False; 113 114 SvPtrarr aRefArr( 10, 10 ), aArr( 10, 10 ); 115 ::lcl_GetLayTree( pFrm, aRefArr ); 116 ::lcl_GetLayTree( pMyFrm, aArr ); 117 118 sal_uInt16 nRefCnt = aRefArr.Count() - 1, nCnt = aArr.Count() - 1; 119 sal_Bool bVert = sal_False; 120 sal_Bool bR2L = sal_False; 121 122 // solange bis ein Frame ungleich ist ? 123 while( nRefCnt && nCnt && aRefArr[ nRefCnt ] == aArr[ nCnt ] ) 124 { 125 const SwFrm* pTmpFrm = (const SwFrm*)aArr[ nCnt ]; 126 bVert = pTmpFrm->IsVertical(); 127 bR2L = pTmpFrm->IsRightToLeft(); 128 --nCnt, --nRefCnt; 129 } 130 131 // sollte einer der Counter ueberlaeufen? 132 if( aRefArr[ nRefCnt ] == aArr[ nCnt ] ) 133 { 134 if( nCnt ) 135 --nCnt; 136 else 137 --nRefCnt; 138 } 139 140 const SwFrm* pRefFrm = (const SwFrm*)aRefArr[ nRefCnt ]; 141 const SwFrm* pFldFrm = (const SwFrm*)aArr[ nCnt ]; 142 143 // unterschiedliche Frames, dann ueberpruefe deren Y-/X-Position 144 sal_Bool bRefIsLower = sal_False; 145 if( ( FRM_COLUMN | FRM_CELL ) & pFldFrm->GetType() || 146 ( FRM_COLUMN | FRM_CELL ) & pRefFrm->GetType() ) 147 { 148 if( pFldFrm->GetType() == pRefFrm->GetType() ) 149 { 150 // hier ist die X-Pos wichtiger! 151 if( bVert ) 152 { 153 if( bR2L ) 154 bRefIsLower = pRefFrm->Frm().Top() < pFldFrm->Frm().Top() || 155 ( pRefFrm->Frm().Top() == pFldFrm->Frm().Top() && 156 pRefFrm->Frm().Left() < pFldFrm->Frm().Left() ); 157 else 158 bRefIsLower = pRefFrm->Frm().Top() < pFldFrm->Frm().Top() || 159 ( pRefFrm->Frm().Top() == pFldFrm->Frm().Top() && 160 pRefFrm->Frm().Left() > pFldFrm->Frm().Left() ); 161 } 162 else if( bR2L ) 163 bRefIsLower = pRefFrm->Frm().Left() > pFldFrm->Frm().Left() || 164 ( pRefFrm->Frm().Left() == pFldFrm->Frm().Left() && 165 pRefFrm->Frm().Top() < pFldFrm->Frm().Top() ); 166 else 167 bRefIsLower = pRefFrm->Frm().Left() < pFldFrm->Frm().Left() || 168 ( pRefFrm->Frm().Left() == pFldFrm->Frm().Left() && 169 pRefFrm->Frm().Top() < pFldFrm->Frm().Top() ); 170 pRefFrm = 0; 171 } 172 else if( ( FRM_COLUMN | FRM_CELL ) & pFldFrm->GetType() ) 173 pFldFrm = (const SwFrm*)aArr[ nCnt - 1 ]; 174 else 175 pRefFrm = (const SwFrm*)aRefArr[ nRefCnt - 1 ]; 176 } 177 178 if( pRefFrm ) // als Flag missbrauchen 179 { 180 if( bVert ) 181 { 182 if( bR2L ) 183 bRefIsLower = pRefFrm->Frm().Left() < pFldFrm->Frm().Left() || 184 ( pRefFrm->Frm().Left() == pFldFrm->Frm().Left() && 185 pRefFrm->Frm().Top() < pFldFrm->Frm().Top() ); 186 else 187 bRefIsLower = pRefFrm->Frm().Left() > pFldFrm->Frm().Left() || 188 ( pRefFrm->Frm().Left() == pFldFrm->Frm().Left() && 189 pRefFrm->Frm().Top() < pFldFrm->Frm().Top() ); 190 } 191 else if( bR2L ) 192 bRefIsLower = pRefFrm->Frm().Top() < pFldFrm->Frm().Top() || 193 ( pRefFrm->Frm().Top() == pFldFrm->Frm().Top() && 194 pRefFrm->Frm().Left() > pFldFrm->Frm().Left() ); 195 else 196 bRefIsLower = pRefFrm->Frm().Top() < pFldFrm->Frm().Top() || 197 ( pRefFrm->Frm().Top() == pFldFrm->Frm().Top() && 198 pRefFrm->Frm().Left() < pFldFrm->Frm().Left() ); 199 } 200 return bRefIsLower; 201 } 202 203 /*-------------------------------------------------------------------- 204 Beschreibung: Referenzen holen 205 --------------------------------------------------------------------*/ 206 207 208 SwGetRefField::SwGetRefField( SwGetRefFieldType* pFldType, 209 const String& rSetRef, sal_uInt16 nSubTyp, 210 sal_uInt16 nSeqenceNo, sal_uLong nFmt ) 211 : SwField( pFldType, nFmt ), 212 sSetRefName( rSetRef ), 213 nSubType( nSubTyp ), 214 nSeqNo( nSeqenceNo ) 215 { 216 } 217 218 SwGetRefField::~SwGetRefField() 219 { 220 } 221 222 String SwGetRefField::GetDescription() const 223 { 224 return SW_RES(STR_REFERENCE); 225 } 226 227 sal_uInt16 SwGetRefField::GetSubType() const 228 { 229 return nSubType; 230 } 231 232 void SwGetRefField::SetSubType( sal_uInt16 n ) 233 { 234 nSubType = n; 235 } 236 237 // --> OD 2007-11-09 #i81002# 238 bool SwGetRefField::IsRefToHeadingCrossRefBookmark() const 239 { 240 return GetSubType() == REF_BOOKMARK && 241 ::sw::mark::CrossRefHeadingBookmark::IsLegalName(sSetRefName); 242 } 243 244 bool SwGetRefField::IsRefToNumItemCrossRefBookmark() const 245 { 246 return GetSubType() == REF_BOOKMARK && 247 ::sw::mark::CrossRefNumItemBookmark::IsLegalName(sSetRefName); 248 } 249 250 const SwTxtNode* SwGetRefField::GetReferencedTxtNode() const 251 { 252 SwDoc* pDoc = dynamic_cast<SwGetRefFieldType*>(GetTyp())->GetDoc(); 253 sal_uInt16 nDummy = USHRT_MAX; 254 return SwGetRefFieldType::FindAnchor( pDoc, sSetRefName, nSubType, nSeqNo, &nDummy ); 255 } 256 // <-- 257 // --> OD 2008-01-09 #i85090# 258 String SwGetRefField::GetExpandedTxtOfReferencedTxtNode() const 259 { 260 const SwTxtNode* pReferencedTxtNode( GetReferencedTxtNode() ); 261 return pReferencedTxtNode 262 ? pReferencedTxtNode->GetExpandTxt( 0, STRING_LEN, true, true ) 263 : aEmptyStr; 264 } 265 266 String SwGetRefField::Expand() const 267 { 268 return sTxt; 269 } 270 271 272 String SwGetRefField::GetFieldName() const 273 { 274 String aStr(GetTyp()->GetName()); 275 aStr += ' '; 276 aStr += sSetRefName; 277 return aStr; 278 } 279 280 void SwGetRefField::UpdateField( const SwTxtFld* pFldTxtAttr ) 281 { 282 sTxt.Erase(); 283 284 SwDoc* pDoc = ((SwGetRefFieldType*)GetTyp())->GetDoc(); 285 sal_uInt16 nStt = USHRT_MAX; 286 sal_uInt16 nEnd = USHRT_MAX; 287 SwTxtNode* pTxtNd = SwGetRefFieldType::FindAnchor( pDoc, sSetRefName, nSubType, nSeqNo, &nStt, &nEnd ); 288 if ( !pTxtNd ) 289 { 290 sTxt = ViewShell::GetShellRes()->aGetRefFld_RefItemNotFound; 291 return ; 292 } 293 294 switch( GetFormat() ) 295 { 296 case REF_CONTENT: 297 case REF_ONLYNUMBER: 298 case REF_ONLYCAPTION: 299 case REF_ONLYSEQNO: 300 { 301 switch( nSubType ) 302 { 303 case REF_SEQUENCEFLD: 304 nEnd = pTxtNd->GetTxt().Len(); 305 switch( GetFormat() ) 306 { 307 case REF_ONLYNUMBER: 308 if( nStt + 1 < nEnd ) 309 nEnd = nStt + 1; 310 nStt = 0; 311 break; 312 313 case REF_ONLYCAPTION: 314 { 315 const SwTxtAttr* const pTxtAttr = pTxtNd->GetTxtAttrForCharAt(nStt, RES_TXTATR_FIELD); 316 if( pTxtAttr ) 317 nStt = SwGetExpField::GetReferenceTextPos( 318 pTxtAttr->GetFmtFld(), *pDoc ); 319 else if( nStt + 1 < nEnd ) 320 ++nStt; 321 } 322 break; 323 324 case REF_ONLYSEQNO: 325 if( nStt + 1 < nEnd ) 326 nEnd = nStt + 1; 327 break; 328 329 default: 330 nStt = 0; 331 break; 332 } 333 break; 334 335 case REF_BOOKMARK: 336 if( USHRT_MAX == nEnd ) 337 { 338 // Text steht ueber verschiedene Nodes verteilt. 339 // Gesamten Text oder nur bis zum Ende vom Node? 340 nEnd = pTxtNd->GetTxt().Len(); 341 } 342 break; 343 344 case REF_OUTLINE: 345 break; 346 347 case REF_FOOTNOTE: 348 case REF_ENDNOTE: 349 { 350 // die Nummer oder den NumString besorgen 351 sal_uInt16 n, nFtnCnt = pDoc->GetFtnIdxs().Count(); 352 SwTxtFtn* pFtnIdx; 353 for( n = 0; n < nFtnCnt; ++n ) 354 if( nSeqNo == (pFtnIdx = pDoc->GetFtnIdxs()[ n ])->GetSeqRefNo() ) 355 { 356 sTxt = pFtnIdx->GetFtn().GetViewNumStr( *pDoc ); 357 break; 358 } 359 nStt = nEnd; // kein Bereich, der String ist fertig 360 } 361 break; 362 } 363 364 if( nStt != nEnd ) // ein Bereich? 365 { 366 sTxt = pTxtNd->GetExpandTxt( nStt, nEnd - nStt ); 367 368 // alle Sonderzeichen entfernen (durch Blanks ersetzen): 369 if( sTxt.Len() ) 370 { 371 sTxt.EraseAllChars( 0xad ); 372 for( sal_Unicode* p = sTxt.GetBufferAccess(); *p; ++p ) 373 { 374 if( *p < 0x20 ) 375 *p = 0x20; 376 else if(*p == 0x2011) 377 *p = '-'; 378 } 379 } 380 } 381 } 382 break; 383 384 case REF_PAGE: 385 case REF_PAGE_PGDESC: 386 { 387 const SwTxtFrm* pFrm = (SwTxtFrm*)pTxtNd->getLayoutFrm( pDoc->GetCurrentLayout(), 0,0,sal_False), 388 *pSave = pFrm; 389 while( pFrm && !pFrm->IsInside( nStt ) ) 390 pFrm = (SwTxtFrm*)pFrm->GetFollow(); 391 392 if( pFrm || 0 != ( pFrm = pSave )) 393 { 394 sal_uInt16 nPageNo = pFrm->GetVirtPageNum(); 395 const SwPageFrm *pPage; 396 if( REF_PAGE_PGDESC == GetFormat() && 397 0 != ( pPage = pFrm->FindPageFrm() ) && 398 pPage->GetPageDesc() ) 399 sTxt = pPage->GetPageDesc()->GetNumType().GetNumStr( nPageNo ); 400 else 401 sTxt = String::CreateFromInt32(nPageNo); 402 } 403 } 404 break; 405 406 case REF_CHAPTER: 407 { 408 // ein bischen trickreich: suche irgend einen Frame 409 const SwFrm* pFrm = pTxtNd->getLayoutFrm( pDoc->GetCurrentLayout() ); 410 if( pFrm ) 411 { 412 SwChapterFieldType aFldTyp; 413 SwChapterField aFld( &aFldTyp, 0 ); 414 aFld.SetLevel( MAXLEVEL - 1 ); 415 aFld.ChangeExpansion( pFrm, pTxtNd, sal_True ); 416 sTxt = aFld.GetNumber(); 417 } 418 } 419 break; 420 421 case REF_UPDOWN: 422 { 423 // simplified: use parameter <pFldTxtAttr> 424 if( !pFldTxtAttr || !pFldTxtAttr->GetpTxtNode() ) 425 break; 426 427 LocaleDataWrapper aLocaleData( ::comphelper::getProcessServiceFactory(), SvxCreateLocale( GetLanguage() ) ); 428 429 // erstmal ein "Kurz" - Test - falls beide im selben 430 // Node stehen! 431 if( pFldTxtAttr->GetpTxtNode() == pTxtNd ) 432 { 433 sTxt = nStt < *pFldTxtAttr->GetStart() 434 ? aLocaleData.getAboveWord() 435 : aLocaleData.getBelowWord(); 436 break; 437 } 438 439 sTxt = 440 ::IsFrameBehind( *pFldTxtAttr->GetpTxtNode(), *pFldTxtAttr->GetStart(), *pTxtNd, nStt ) 441 ? aLocaleData.getAboveWord() 442 : aLocaleData.getBelowWord(); 443 } 444 break; 445 446 case REF_NUMBER: 447 case REF_NUMBER_NO_CONTEXT: 448 case REF_NUMBER_FULL_CONTEXT: 449 { 450 if ( pFldTxtAttr && pFldTxtAttr->GetpTxtNode() ) 451 { 452 sTxt = MakeRefNumStr( pFldTxtAttr->GetTxtNode(), *pTxtNd, GetFormat() ); 453 } 454 } 455 break; 456 457 default: 458 DBG_ERROR("<SwGetRefField::UpdateField(..)> - unknown format type"); 459 } 460 } 461 462 // --> OD 2007-09-06 #i81002# 463 String SwGetRefField::MakeRefNumStr( const SwTxtNode& rTxtNodeOfField, 464 const SwTxtNode& rTxtNodeOfReferencedItem, 465 const sal_uInt32 nRefNumFormat ) const 466 { 467 if ( rTxtNodeOfReferencedItem.HasNumber() && 468 rTxtNodeOfReferencedItem.IsCountedInList() ) 469 { 470 ASSERT( rTxtNodeOfReferencedItem.GetNum(), 471 "<SwGetRefField::MakeRefNumStr(..)> - referenced paragraph has number, but no <SwNodeNum> instance --> please inform OD!" ); 472 473 // Determine, up to which level the superior list labels have to be 474 // included - default is to include all superior list labels. 475 sal_uInt8 nRestrictInclToThisLevel( 0 ); 476 // Determine for format REF_NUMBER the level, up to which the superior 477 // list labels have to be restricted, if the text node of the reference 478 // field and the text node of the referenced item are in the same 479 // document context. 480 if ( nRefNumFormat == REF_NUMBER && 481 rTxtNodeOfField.FindFlyStartNode() 482 == rTxtNodeOfReferencedItem.FindFlyStartNode() && 483 rTxtNodeOfField.FindFootnoteStartNode() 484 == rTxtNodeOfReferencedItem.FindFootnoteStartNode() && 485 rTxtNodeOfField.FindHeaderStartNode() 486 == rTxtNodeOfReferencedItem.FindHeaderStartNode() && 487 rTxtNodeOfField.FindFooterStartNode() 488 == rTxtNodeOfReferencedItem.FindFooterStartNode() ) 489 { 490 const SwNodeNum* pNodeNumForTxtNodeOfField( 0 ); 491 if ( rTxtNodeOfField.HasNumber() && 492 rTxtNodeOfField.GetNumRule() == rTxtNodeOfReferencedItem.GetNumRule() ) 493 { 494 pNodeNumForTxtNodeOfField = rTxtNodeOfField.GetNum(); 495 } 496 else 497 { 498 pNodeNumForTxtNodeOfField = 499 rTxtNodeOfReferencedItem.GetNum()->GetPrecedingNodeNumOf( rTxtNodeOfField ); 500 } 501 if ( pNodeNumForTxtNodeOfField ) 502 { 503 const SwNumberTree::tNumberVector rFieldNumVec = pNodeNumForTxtNodeOfField->GetNumberVector(); 504 const SwNumberTree::tNumberVector rRefItemNumVec = rTxtNodeOfReferencedItem.GetNum()->GetNumberVector(); 505 sal_uInt8 nLevel( 0 ); 506 while ( nLevel < rFieldNumVec.size() && nLevel < rRefItemNumVec.size() ) 507 { 508 if ( rRefItemNumVec[nLevel] == rFieldNumVec[nLevel] ) 509 { 510 nRestrictInclToThisLevel = nLevel + 1; 511 } 512 else 513 { 514 break; 515 } 516 ++nLevel; 517 } 518 } 519 } 520 521 // Determine, if superior list labels have to be included 522 const bool bInclSuperiorNumLabels( 523 ( nRestrictInclToThisLevel < rTxtNodeOfReferencedItem.GetActualListLevel() && 524 ( nRefNumFormat == REF_NUMBER || nRefNumFormat == REF_NUMBER_FULL_CONTEXT ) ) ); 525 526 ASSERT( rTxtNodeOfReferencedItem.GetNumRule(), 527 "<SwGetRefField::MakeRefNumStr(..)> - referenced numbered paragraph has no numbering rule set --> please inform OD!" ); 528 return rTxtNodeOfReferencedItem.GetNumRule()->MakeRefNumString( 529 *(rTxtNodeOfReferencedItem.GetNum()), 530 bInclSuperiorNumLabels, 531 nRestrictInclToThisLevel ); 532 } 533 534 return String(); 535 } 536 // <-- 537 538 SwField* SwGetRefField::Copy() const 539 { 540 SwGetRefField* pFld = new SwGetRefField( (SwGetRefFieldType*)GetTyp(), 541 sSetRefName, nSubType, 542 nSeqNo, GetFormat() ); 543 pFld->sTxt = sTxt; 544 return pFld; 545 } 546 547 /*-------------------------------------------------------------------- 548 Beschreibung: ReferenzName holen 549 --------------------------------------------------------------------*/ 550 551 552 const String& SwGetRefField::GetPar1() const 553 { 554 return sSetRefName; 555 } 556 557 558 void SwGetRefField::SetPar1( const String& rName ) 559 { 560 sSetRefName = rName; 561 } 562 563 564 String SwGetRefField::GetPar2() const 565 { 566 return Expand(); 567 } 568 569 sal_Bool SwGetRefField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const 570 { 571 switch( nWhichId ) 572 { 573 case FIELD_PROP_USHORT1: 574 { 575 sal_Int16 nPart = 0; 576 switch(GetFormat()) 577 { 578 case REF_PAGE : nPart = ReferenceFieldPart::PAGE ; break; 579 case REF_CHAPTER : nPart = ReferenceFieldPart::CHAPTER ; break; 580 case REF_CONTENT : nPart = ReferenceFieldPart::TEXT ; break; 581 case REF_UPDOWN : nPart = ReferenceFieldPart::UP_DOWN ; break; 582 case REF_PAGE_PGDESC: nPart = ReferenceFieldPart::PAGE_DESC ; break; 583 case REF_ONLYNUMBER : nPart = ReferenceFieldPart::CATEGORY_AND_NUMBER ; break; 584 case REF_ONLYCAPTION: nPart = ReferenceFieldPart::ONLY_CAPTION ; break; 585 case REF_ONLYSEQNO : nPart = ReferenceFieldPart::ONLY_SEQUENCE_NUMBER; break; 586 // --> OD 2007-09-06 #i81002# 587 case REF_NUMBER: nPart = ReferenceFieldPart::NUMBER; break; 588 case REF_NUMBER_NO_CONTEXT: nPart = ReferenceFieldPart::NUMBER_NO_CONTEXT; break; 589 case REF_NUMBER_FULL_CONTEXT: nPart = ReferenceFieldPart::NUMBER_FULL_CONTEXT; break; 590 // <-- 591 } 592 rAny <<= nPart; 593 } 594 break; 595 case FIELD_PROP_USHORT2: 596 { 597 sal_Int16 nSource = 0; 598 switch(nSubType) 599 { 600 case REF_SETREFATTR : nSource = ReferenceFieldSource::REFERENCE_MARK; break; 601 case REF_SEQUENCEFLD: nSource = ReferenceFieldSource::SEQUENCE_FIELD; break; 602 case REF_BOOKMARK : nSource = ReferenceFieldSource::BOOKMARK; break; 603 case REF_OUTLINE : DBG_ERROR("not implemented"); break; 604 case REF_FOOTNOTE : nSource = ReferenceFieldSource::FOOTNOTE; break; 605 case REF_ENDNOTE : nSource = ReferenceFieldSource::ENDNOTE; break; 606 } 607 rAny <<= nSource; 608 } 609 break; 610 case FIELD_PROP_PAR1: 611 { 612 String sTmp(GetPar1()); 613 if(REF_SEQUENCEFLD == nSubType) 614 { 615 sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( sTmp, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL ); 616 switch( nPoolId ) 617 { 618 case RES_POOLCOLL_LABEL_ABB: 619 case RES_POOLCOLL_LABEL_TABLE: 620 case RES_POOLCOLL_LABEL_FRAME: 621 case RES_POOLCOLL_LABEL_DRAWING: 622 SwStyleNameMapper::FillProgName(nPoolId, sTmp) ; 623 break; 624 } 625 } 626 rAny <<= rtl::OUString(sTmp); 627 } 628 break; 629 case FIELD_PROP_PAR3: 630 rAny <<= rtl::OUString(Expand()); 631 break; 632 case FIELD_PROP_SHORT1: 633 rAny <<= (sal_Int16)nSeqNo; 634 break; 635 default: 636 DBG_ERROR("illegal property"); 637 } 638 return sal_True; 639 } 640 641 sal_Bool SwGetRefField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId ) 642 { 643 String sTmp; 644 switch( nWhichId ) 645 { 646 case FIELD_PROP_USHORT1: 647 { 648 sal_Int16 nPart = 0; 649 rAny >>= nPart; 650 switch(nPart) 651 { 652 case ReferenceFieldPart::PAGE: nPart = REF_PAGE; break; 653 case ReferenceFieldPart::CHAPTER: nPart = REF_CHAPTER; break; 654 case ReferenceFieldPart::TEXT: nPart = REF_CONTENT; break; 655 case ReferenceFieldPart::UP_DOWN: nPart = REF_UPDOWN; break; 656 case ReferenceFieldPart::PAGE_DESC: nPart = REF_PAGE_PGDESC; break; 657 case ReferenceFieldPart::CATEGORY_AND_NUMBER: nPart = REF_ONLYNUMBER; break; 658 case ReferenceFieldPart::ONLY_CAPTION: nPart = REF_ONLYCAPTION; break; 659 case ReferenceFieldPart::ONLY_SEQUENCE_NUMBER : nPart = REF_ONLYSEQNO; break; 660 // --> OD 2007-09-06 #i81002# 661 case ReferenceFieldPart::NUMBER: nPart = REF_NUMBER; break; 662 case ReferenceFieldPart::NUMBER_NO_CONTEXT: nPart = REF_NUMBER_NO_CONTEXT; break; 663 case ReferenceFieldPart::NUMBER_FULL_CONTEXT: nPart = REF_NUMBER_FULL_CONTEXT; break; 664 // <-- 665 default: return sal_False; 666 } 667 SetFormat(nPart); 668 } 669 break; 670 case FIELD_PROP_USHORT2: 671 { 672 sal_Int16 nSource = 0; 673 rAny >>= nSource; 674 switch(nSource) 675 { 676 case ReferenceFieldSource::REFERENCE_MARK : nSubType = REF_SETREFATTR ; break; 677 case ReferenceFieldSource::SEQUENCE_FIELD : 678 { 679 if(REF_SEQUENCEFLD == nSubType) 680 break; 681 nSubType = REF_SEQUENCEFLD; 682 ConvertProgrammaticToUIName(); 683 } 684 break; 685 case ReferenceFieldSource::BOOKMARK : nSubType = REF_BOOKMARK ; break; 686 case ReferenceFieldSource::FOOTNOTE : nSubType = REF_FOOTNOTE ; break; 687 case ReferenceFieldSource::ENDNOTE : nSubType = REF_ENDNOTE ; break; 688 } 689 } 690 break; 691 case FIELD_PROP_PAR1: 692 { 693 OUString sTmpStr; 694 rAny >>= sTmpStr; 695 SetPar1(sTmpStr); 696 ConvertProgrammaticToUIName(); 697 } 698 break; 699 case FIELD_PROP_PAR3: 700 SetExpand( ::GetString( rAny, sTmp )); 701 break; 702 case FIELD_PROP_SHORT1: 703 { 704 sal_Int16 nSetSeq = 0; 705 rAny >>= nSetSeq; 706 if(nSetSeq >= 0) 707 nSeqNo = nSetSeq; 708 } 709 break; 710 default: 711 DBG_ERROR("illegal property"); 712 } 713 return sal_True; 714 } 715 716 void SwGetRefField::ConvertProgrammaticToUIName() 717 { 718 if(GetTyp() && REF_SEQUENCEFLD == nSubType) 719 { 720 SwDoc* pDoc = ((SwGetRefFieldType*)GetTyp())->GetDoc(); 721 const String& rPar1 = GetPar1(); 722 //don't convert when the name points to an existing field type 723 if(!pDoc->GetFldType(RES_SETEXPFLD, rPar1, false)) 724 { 725 sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromProgName( rPar1, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL ); 726 sal_uInt16 nResId = USHRT_MAX; 727 switch( nPoolId ) 728 { 729 case RES_POOLCOLL_LABEL_ABB: 730 nResId = STR_POOLCOLL_LABEL_ABB; 731 break; 732 case RES_POOLCOLL_LABEL_TABLE: 733 nResId = STR_POOLCOLL_LABEL_TABLE; 734 break; 735 case RES_POOLCOLL_LABEL_FRAME: 736 nResId = STR_POOLCOLL_LABEL_FRAME; 737 break; 738 case RES_POOLCOLL_LABEL_DRAWING: 739 nResId = STR_POOLCOLL_LABEL_DRAWING; 740 break; 741 } 742 if( nResId != USHRT_MAX ) 743 SetPar1(SW_RESSTR( nResId )); 744 } 745 } 746 } 747 748 SwGetRefFieldType::SwGetRefFieldType( SwDoc* pDc ) 749 : SwFieldType( RES_GETREFFLD ), pDoc( pDc ) 750 {} 751 752 753 SwFieldType* SwGetRefFieldType::Copy() const 754 { 755 return new SwGetRefFieldType( pDoc ); 756 } 757 758 759 void SwGetRefFieldType::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew ) 760 { 761 // Update auf alle GetReferenz-Felder 762 if( !pNew && !pOld ) 763 { 764 SwIterator<SwFmtFld,SwFieldType> aIter( *this ); 765 for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() ) 766 { 767 // nur die GetRef-Felder Updaten 768 //JP 3.4.2001: Task 71231 - we need the correct language 769 SwGetRefField* pGRef = (SwGetRefField*)pFmtFld->GetField(); 770 const SwTxtFld* pTFld; 771 if( !pGRef->GetLanguage() && 772 0 != ( pTFld = pFmtFld->GetTxtFld()) && 773 pTFld->GetpTxtNode() ) 774 { 775 pGRef->SetLanguage( pTFld->GetpTxtNode()->GetLang( 776 *pTFld->GetStart() ) ); 777 } 778 779 pGRef->UpdateField( pFmtFld->GetTxtFld() ); 780 } 781 } 782 // weiter an die Text-Felder, diese "Expandieren" den Text 783 NotifyClients( pOld, pNew ); 784 } 785 786 SwTxtNode* SwGetRefFieldType::FindAnchor( SwDoc* pDoc, const String& rRefMark, 787 sal_uInt16 nSubType, sal_uInt16 nSeqNo, 788 sal_uInt16* pStt, sal_uInt16* pEnd ) 789 { 790 ASSERT( pStt, "warum wird keine StartPos abgefragt?" ); 791 792 SwTxtNode* pTxtNd = 0; 793 switch( nSubType ) 794 { 795 case REF_SETREFATTR: 796 { 797 const SwFmtRefMark *pRef = pDoc->GetRefMark( rRefMark ); 798 if( pRef && pRef->GetTxtRefMark() ) 799 { 800 pTxtNd = (SwTxtNode*)&pRef->GetTxtRefMark()->GetTxtNode(); 801 *pStt = *pRef->GetTxtRefMark()->GetStart(); 802 if( pEnd ) 803 *pEnd = *pRef->GetTxtRefMark()->GetAnyEnd(); 804 } 805 } 806 break; 807 808 case REF_SEQUENCEFLD: 809 { 810 SwFieldType* pFldType = pDoc->GetFldType( RES_SETEXPFLD, rRefMark, false ); 811 if( pFldType && pFldType->GetDepends() && 812 nsSwGetSetExpType::GSE_SEQ & ((SwSetExpFieldType*)pFldType)->GetType() ) 813 { 814 SwIterator<SwFmtFld,SwFieldType> aIter( *pFldType ); 815 for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() ) 816 { 817 if( pFmtFld->GetTxtFld() && nSeqNo == 818 ((SwSetExpField*)pFmtFld->GetField())->GetSeqNumber() ) 819 { 820 SwTxtFld* pTxtFld = pFmtFld->GetTxtFld(); 821 pTxtNd = (SwTxtNode*)pTxtFld->GetpTxtNode(); 822 *pStt = *pTxtFld->GetStart(); 823 if( pEnd ) 824 *pEnd = (*pStt) + 1; 825 break; 826 } 827 } 828 } 829 } 830 break; 831 832 case REF_BOOKMARK: 833 { 834 IDocumentMarkAccess::const_iterator_t ppMark = pDoc->getIDocumentMarkAccess()->findMark(rRefMark); 835 if(ppMark != pDoc->getIDocumentMarkAccess()->getMarksEnd()) 836 { 837 const ::sw::mark::IMark* pBkmk = ppMark->get(); 838 const SwPosition* pPos = &pBkmk->GetMarkStart(); 839 840 pTxtNd = pPos->nNode.GetNode().GetTxtNode(); 841 *pStt = pPos->nContent.GetIndex(); 842 if(pEnd) 843 { 844 if(!pBkmk->IsExpanded()) 845 { 846 *pEnd = *pStt; 847 // --> OD 2007-10-18 #i81002# 848 if(dynamic_cast< ::sw::mark::CrossRefBookmark const *>(pBkmk)) 849 { 850 ASSERT( pTxtNd, 851 "<SwGetRefFieldType::FindAnchor(..)> - node marked by cross-reference bookmark isn't a text node --> crash" ); 852 *pEnd = pTxtNd->Len(); 853 } 854 // <-- 855 } 856 else if(pBkmk->GetOtherMarkPos().nNode == pBkmk->GetMarkPos().nNode) 857 *pEnd = pBkmk->GetMarkEnd().nContent.GetIndex(); 858 else 859 *pEnd = USHRT_MAX; 860 } 861 } 862 } 863 break; 864 865 case REF_OUTLINE: 866 break; 867 868 case REF_FOOTNOTE: 869 case REF_ENDNOTE: 870 { 871 sal_uInt16 n, nFtnCnt = pDoc->GetFtnIdxs().Count(); 872 SwTxtFtn* pFtnIdx; 873 for( n = 0; n < nFtnCnt; ++n ) 874 if( nSeqNo == (pFtnIdx = pDoc->GetFtnIdxs()[ n ])->GetSeqRefNo() ) 875 { 876 SwNodeIndex* pIdx = pFtnIdx->GetStartNode(); 877 if( pIdx ) 878 { 879 SwNodeIndex aIdx( *pIdx, 1 ); 880 if( 0 == ( pTxtNd = aIdx.GetNode().GetTxtNode())) 881 pTxtNd = (SwTxtNode*)pDoc->GetNodes().GoNext( &aIdx ); 882 } 883 *pStt = 0; 884 if( pEnd ) 885 *pEnd = 0; 886 break; 887 } 888 } 889 break; 890 } 891 892 return pTxtNd; 893 } 894 895 896 struct _RefIdsMap 897 { 898 String aName; 899 SvUShortsSort aIds, aDstIds, aIdsMap; 900 SvUShorts aMap; 901 sal_Bool bInit; 902 903 _RefIdsMap( const String& rName ) 904 : aName( rName ), aIds( 16, 16 ), aIdsMap( 16, 16 ), aMap( 16, 16 ), 905 bInit( sal_False ) 906 {} 907 908 void Check( SwDoc& rDoc, SwDoc& rDestDoc, SwGetRefField& rFld, 909 sal_Bool bField = sal_True ); 910 911 sal_Bool IsInit() const { return bInit; } 912 }; 913 914 SV_DECL_PTRARR_DEL( _RefIdsMaps, _RefIdsMap*, 5, 5 ) 915 SV_IMPL_PTRARR( _RefIdsMaps, _RefIdsMap* ) 916 917 void _RefIdsMap::Check( SwDoc& rDoc, SwDoc& rDestDoc, SwGetRefField& rFld, 918 sal_Bool bField ) 919 { 920 921 if( !bInit ) 922 { 923 if( bField ) 924 { 925 const SwTxtNode* pNd; 926 SwFieldType* pType; 927 if( 0 != ( pType = rDestDoc.GetFldType( RES_SETEXPFLD, aName, false ) )) 928 { 929 SwIterator<SwFmtFld,SwFieldType> aIter( *pType ); 930 for( SwFmtFld* pF = aIter.First(); pF; pF = aIter.Next() ) 931 if( pF->GetTxtFld() && 932 0 != ( pNd = pF->GetTxtFld()->GetpTxtNode() ) && 933 pNd->GetNodes().IsDocNodes() ) 934 aIds.Insert( ((SwSetExpField*)pF->GetField())->GetSeqNumber() ); 935 } 936 if( 0 != ( pType = rDoc.GetFldType( RES_SETEXPFLD, aName, false ) )) 937 { 938 SwIterator<SwFmtFld,SwFieldType> aIter( *pType ); 939 for( SwFmtFld* pF = aIter.First(); pF; pF = aIter.Next() ) 940 if( pF->GetTxtFld() && 941 0 != ( pNd = pF->GetTxtFld()->GetpTxtNode() ) && 942 pNd->GetNodes().IsDocNodes() ) 943 aDstIds.Insert( ((SwSetExpField*)pF->GetField())->GetSeqNumber() ); 944 } 945 } 946 else 947 { 948 sal_uInt16 n; 949 950 for( n = rDestDoc.GetFtnIdxs().Count(); n; ) 951 aIds.Insert( rDestDoc.GetFtnIdxs()[ --n ]->GetSeqRefNo() ); 952 for( n = rDoc.GetFtnIdxs().Count(); n; ) 953 aDstIds.Insert( rDoc.GetFtnIdxs()[ --n ]->GetSeqRefNo() ); 954 } 955 bInit = sal_True; 956 } 957 958 // dann teste mal, ob die Nummer schon vergeben ist 959 // oder ob eine neue bestimmt werden muss. 960 sal_uInt16 nPos, nSeqNo = rFld.GetSeqNo(); 961 if( aIds.Seek_Entry( nSeqNo ) && aDstIds.Seek_Entry( nSeqNo )) 962 { 963 // ist schon vergeben, also muss eine neue 964 // erzeugt werden. 965 if( aIdsMap.Seek_Entry( nSeqNo, &nPos )) 966 rFld.SetSeqNo( aMap[ nPos ] ); 967 else 968 { 969 sal_uInt16 n; 970 971 for( n = 0; n < aIds.Count(); ++n ) 972 if( n != aIds[ n ] ) 973 break; 974 975 // die neue SeqNo eintragen, damit die "belegt" ist 976 aIds.Insert( n ); 977 aIdsMap.Insert( nSeqNo, nPos ); 978 aMap.Insert( n, nPos ); 979 rFld.SetSeqNo( n ); 980 981 // und noch die Felder oder Fuss-/EndNote auf die neue 982 // Id umsetzen 983 if( bField ) 984 { 985 SwFieldType* pType = rDoc.GetFldType( RES_SETEXPFLD, aName, false ); 986 if( pType ) 987 { 988 SwIterator<SwFmtFld,SwFieldType> aIter( *pType ); 989 for( SwFmtFld* pF = aIter.First(); pF; pF = aIter.Next() ) 990 if( pF->GetTxtFld() && nSeqNo == 991 ((SwSetExpField*)pF->GetField())->GetSeqNumber() ) 992 ((SwSetExpField*)pF->GetField())->SetSeqNumber( n ); 993 } 994 } 995 else 996 { 997 SwTxtFtn* pFtnIdx; 998 for( sal_uInt16 i = 0, nCnt = rDoc.GetFtnIdxs().Count(); i < nCnt; ++i ) 999 if( nSeqNo == (pFtnIdx = rDoc.GetFtnIdxs()[ i ])->GetSeqRefNo() ) 1000 { 1001 pFtnIdx->SetSeqNo( n ); 1002 break; 1003 } 1004 } 1005 } 1006 } 1007 else 1008 { 1009 aIds.Insert( nSeqNo ); 1010 aIdsMap.Insert( nSeqNo, nPos ); 1011 aMap.Insert( nSeqNo, nPos ); 1012 } 1013 } 1014 1015 1016 void SwGetRefFieldType::MergeWithOtherDoc( SwDoc& rDestDoc ) 1017 { 1018 if( &rDestDoc != pDoc && 1019 rDestDoc.GetSysFldType( RES_GETREFFLD )->GetDepends() ) 1020 { 1021 // dann gibt es im DestDoc RefFelder, also muessen im SourceDoc 1022 // alle RefFelder auf einduetige Ids in beiden Docs umgestellt 1023 // werden. 1024 _RefIdsMap aFntMap( aEmptyStr ); 1025 _RefIdsMaps aFldMap; 1026 1027 SwIterator<SwFmtFld,SwFieldType> aIter( *this ); 1028 for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() ) 1029 { 1030 SwGetRefField& rRefFld = *(SwGetRefField*)pFld->GetField(); 1031 switch( rRefFld.GetSubType() ) 1032 { 1033 case REF_SEQUENCEFLD: 1034 { 1035 _RefIdsMap* pMap = 0; 1036 for( sal_uInt16 n = aFldMap.Count(); n; ) 1037 if( aFldMap[ --n ]->aName == rRefFld.GetSetRefName() ) 1038 { 1039 pMap = aFldMap[ n ]; 1040 break; 1041 } 1042 if( !pMap ) 1043 { 1044 pMap = new _RefIdsMap( rRefFld.GetSetRefName() ); 1045 aFldMap.C40_INSERT( _RefIdsMap, pMap, aFldMap.Count() ); 1046 } 1047 1048 pMap->Check( *pDoc, rDestDoc, rRefFld, sal_True ); 1049 } 1050 break; 1051 1052 case REF_FOOTNOTE: 1053 case REF_ENDNOTE: 1054 aFntMap.Check( *pDoc, rDestDoc, rRefFld, sal_False ); 1055 break; 1056 } 1057 } 1058 } 1059 } 1060 1061