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 != NULL ) 317 nStt = SwGetExpField::GetReferenceTextPos( pTxtAttr->GetFmtFld(), *pDoc ); 318 else if( nStt + 1 < nEnd ) 319 ++nStt; 320 } 321 break; 322 323 case REF_ONLYSEQNO: 324 if( nStt + 1 < nEnd ) 325 nEnd = nStt + 1; 326 break; 327 328 default: 329 nStt = 0; 330 break; 331 } 332 break; 333 334 case REF_BOOKMARK: 335 if( USHRT_MAX == nEnd ) 336 { 337 // Text steht ueber verschiedene Nodes verteilt. 338 // Gesamten Text oder nur bis zum Ende vom Node? 339 nEnd = pTxtNd->GetTxt().Len(); 340 } 341 break; 342 343 case REF_OUTLINE: 344 break; 345 346 case REF_FOOTNOTE: 347 case REF_ENDNOTE: 348 { 349 // die Nummer oder den NumString besorgen 350 sal_uInt16 n, nFtnCnt = pDoc->GetFtnIdxs().Count(); 351 SwTxtFtn* pFtnIdx; 352 for( n = 0; n < nFtnCnt; ++n ) 353 if( nSeqNo == (pFtnIdx = pDoc->GetFtnIdxs()[ n ])->GetSeqRefNo() ) 354 { 355 sTxt = pFtnIdx->GetFtn().GetViewNumStr( *pDoc ); 356 break; 357 } 358 nStt = nEnd; // kein Bereich, der String ist fertig 359 } 360 break; 361 } 362 363 if( nStt != nEnd ) // ein Bereich? 364 { 365 sTxt = pTxtNd->GetExpandTxt( nStt, nEnd - nStt ); 366 367 // alle Sonderzeichen entfernen (durch Blanks ersetzen): 368 if( sTxt.Len() ) 369 { 370 sTxt.EraseAllChars( 0xad ); 371 for( sal_Unicode* p = sTxt.GetBufferAccess(); *p; ++p ) 372 { 373 if( *p < 0x20 ) 374 *p = 0x20; 375 else if(*p == 0x2011) 376 *p = '-'; 377 } 378 } 379 } 380 } 381 break; 382 383 case REF_PAGE: 384 case REF_PAGE_PGDESC: 385 { 386 const SwTxtFrm* pFrm = (SwTxtFrm*)pTxtNd->getLayoutFrm( pDoc->GetCurrentLayout(), 0,0,sal_False), 387 *pSave = pFrm; 388 while( pFrm && !pFrm->IsInside( nStt ) ) 389 pFrm = (SwTxtFrm*)pFrm->GetFollow(); 390 391 if( pFrm || 0 != ( pFrm = pSave )) 392 { 393 sal_uInt16 nPageNo = pFrm->GetVirtPageNum(); 394 const SwPageFrm *pPage; 395 if( REF_PAGE_PGDESC == GetFormat() && 396 0 != ( pPage = pFrm->FindPageFrm() ) && 397 pPage->GetPageDesc() ) 398 sTxt = pPage->GetPageDesc()->GetNumType().GetNumStr( nPageNo ); 399 else 400 sTxt = String::CreateFromInt32(nPageNo); 401 } 402 } 403 break; 404 405 case REF_CHAPTER: 406 { 407 // ein bischen trickreich: suche irgend einen Frame 408 const SwFrm* pFrm = pTxtNd->getLayoutFrm( pDoc->GetCurrentLayout() ); 409 if( pFrm ) 410 { 411 SwChapterFieldType aFldTyp; 412 SwChapterField aFld( &aFldTyp, 0 ); 413 aFld.SetLevel( MAXLEVEL - 1 ); 414 aFld.ChangeExpansion( pFrm, pTxtNd, sal_True ); 415 sTxt = aFld.GetNumber(); 416 } 417 } 418 break; 419 420 case REF_UPDOWN: 421 { 422 // simplified: use parameter <pFldTxtAttr> 423 if( !pFldTxtAttr || !pFldTxtAttr->GetpTxtNode() ) 424 break; 425 426 LocaleDataWrapper aLocaleData( ::comphelper::getProcessServiceFactory(), SvxCreateLocale( GetLanguage() ) ); 427 428 // erstmal ein "Kurz" - Test - falls beide im selben 429 // Node stehen! 430 if( pFldTxtAttr->GetpTxtNode() == pTxtNd ) 431 { 432 sTxt = nStt < *pFldTxtAttr->GetStart() 433 ? aLocaleData.getAboveWord() 434 : aLocaleData.getBelowWord(); 435 break; 436 } 437 438 sTxt = 439 ::IsFrameBehind( *pFldTxtAttr->GetpTxtNode(), *pFldTxtAttr->GetStart(), *pTxtNd, nStt ) 440 ? aLocaleData.getAboveWord() 441 : aLocaleData.getBelowWord(); 442 } 443 break; 444 445 case REF_NUMBER: 446 case REF_NUMBER_NO_CONTEXT: 447 case REF_NUMBER_FULL_CONTEXT: 448 { 449 if ( pFldTxtAttr && pFldTxtAttr->GetpTxtNode() ) 450 { 451 sTxt = MakeRefNumStr( pFldTxtAttr->GetTxtNode(), *pTxtNd, GetFormat() ); 452 } 453 } 454 break; 455 456 default: 457 DBG_ERROR("<SwGetRefField::UpdateField(..)> - unknown format type"); 458 } 459 } 460 461 // --> OD 2007-09-06 #i81002# 462 String SwGetRefField::MakeRefNumStr( const SwTxtNode& rTxtNodeOfField, 463 const SwTxtNode& rTxtNodeOfReferencedItem, 464 const sal_uInt32 nRefNumFormat ) const 465 { 466 if ( rTxtNodeOfReferencedItem.HasNumber() && 467 rTxtNodeOfReferencedItem.IsCountedInList() ) 468 { 469 ASSERT( rTxtNodeOfReferencedItem.GetNum(), 470 "<SwGetRefField::MakeRefNumStr(..)> - referenced paragraph has number, but no <SwNodeNum> instance --> please inform OD!" ); 471 472 // Determine, up to which level the superior list labels have to be 473 // included - default is to include all superior list labels. 474 sal_uInt8 nRestrictInclToThisLevel( 0 ); 475 // Determine for format REF_NUMBER the level, up to which the superior 476 // list labels have to be restricted, if the text node of the reference 477 // field and the text node of the referenced item are in the same 478 // document context. 479 if ( nRefNumFormat == REF_NUMBER && 480 rTxtNodeOfField.FindFlyStartNode() 481 == rTxtNodeOfReferencedItem.FindFlyStartNode() && 482 rTxtNodeOfField.FindFootnoteStartNode() 483 == rTxtNodeOfReferencedItem.FindFootnoteStartNode() && 484 rTxtNodeOfField.FindHeaderStartNode() 485 == rTxtNodeOfReferencedItem.FindHeaderStartNode() && 486 rTxtNodeOfField.FindFooterStartNode() 487 == rTxtNodeOfReferencedItem.FindFooterStartNode() ) 488 { 489 const SwNodeNum* pNodeNumForTxtNodeOfField( 0 ); 490 if ( rTxtNodeOfField.HasNumber() && 491 rTxtNodeOfField.GetNumRule() == rTxtNodeOfReferencedItem.GetNumRule() ) 492 { 493 pNodeNumForTxtNodeOfField = rTxtNodeOfField.GetNum(); 494 } 495 else 496 { 497 pNodeNumForTxtNodeOfField = 498 rTxtNodeOfReferencedItem.GetNum()->GetPrecedingNodeNumOf( rTxtNodeOfField ); 499 } 500 if ( pNodeNumForTxtNodeOfField ) 501 { 502 const SwNumberTree::tNumberVector rFieldNumVec = pNodeNumForTxtNodeOfField->GetNumberVector(); 503 const SwNumberTree::tNumberVector rRefItemNumVec = rTxtNodeOfReferencedItem.GetNum()->GetNumberVector(); 504 sal_uInt8 nLevel( 0 ); 505 while ( nLevel < rFieldNumVec.size() && nLevel < rRefItemNumVec.size() ) 506 { 507 if ( rRefItemNumVec[nLevel] == rFieldNumVec[nLevel] ) 508 { 509 nRestrictInclToThisLevel = nLevel + 1; 510 } 511 else 512 { 513 break; 514 } 515 ++nLevel; 516 } 517 } 518 } 519 520 // Determine, if superior list labels have to be included 521 const bool bInclSuperiorNumLabels( 522 ( nRestrictInclToThisLevel < rTxtNodeOfReferencedItem.GetActualListLevel() && 523 ( nRefNumFormat == REF_NUMBER || nRefNumFormat == REF_NUMBER_FULL_CONTEXT ) ) ); 524 525 ASSERT( rTxtNodeOfReferencedItem.GetNumRule(), 526 "<SwGetRefField::MakeRefNumStr(..)> - referenced numbered paragraph has no numbering rule set --> please inform OD!" ); 527 return rTxtNodeOfReferencedItem.GetNumRule()->MakeRefNumString( 528 *(rTxtNodeOfReferencedItem.GetNum()), 529 bInclSuperiorNumLabels, 530 nRestrictInclToThisLevel ); 531 } 532 533 return String(); 534 } 535 // <-- 536 537 SwField* SwGetRefField::Copy() const 538 { 539 SwGetRefField* pFld = new SwGetRefField( (SwGetRefFieldType*)GetTyp(), 540 sSetRefName, nSubType, 541 nSeqNo, GetFormat() ); 542 pFld->sTxt = sTxt; 543 return pFld; 544 } 545 546 /*-------------------------------------------------------------------- 547 Beschreibung: ReferenzName holen 548 --------------------------------------------------------------------*/ 549 550 551 const String& SwGetRefField::GetPar1() const 552 { 553 return sSetRefName; 554 } 555 556 557 void SwGetRefField::SetPar1( const String& rName ) 558 { 559 sSetRefName = rName; 560 } 561 562 563 String SwGetRefField::GetPar2() const 564 { 565 return Expand(); 566 } 567 568 sal_Bool SwGetRefField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const 569 { 570 switch( nWhichId ) 571 { 572 case FIELD_PROP_USHORT1: 573 { 574 sal_Int16 nPart = 0; 575 switch(GetFormat()) 576 { 577 case REF_PAGE : nPart = ReferenceFieldPart::PAGE ; break; 578 case REF_CHAPTER : nPart = ReferenceFieldPart::CHAPTER ; break; 579 case REF_CONTENT : nPart = ReferenceFieldPart::TEXT ; break; 580 case REF_UPDOWN : nPart = ReferenceFieldPart::UP_DOWN ; break; 581 case REF_PAGE_PGDESC: nPart = ReferenceFieldPart::PAGE_DESC ; break; 582 case REF_ONLYNUMBER : nPart = ReferenceFieldPart::CATEGORY_AND_NUMBER ; break; 583 case REF_ONLYCAPTION: nPart = ReferenceFieldPart::ONLY_CAPTION ; break; 584 case REF_ONLYSEQNO : nPart = ReferenceFieldPart::ONLY_SEQUENCE_NUMBER; break; 585 // --> OD 2007-09-06 #i81002# 586 case REF_NUMBER: nPart = ReferenceFieldPart::NUMBER; break; 587 case REF_NUMBER_NO_CONTEXT: nPart = ReferenceFieldPart::NUMBER_NO_CONTEXT; break; 588 case REF_NUMBER_FULL_CONTEXT: nPart = ReferenceFieldPart::NUMBER_FULL_CONTEXT; break; 589 // <-- 590 } 591 rAny <<= nPart; 592 } 593 break; 594 case FIELD_PROP_USHORT2: 595 { 596 sal_Int16 nSource = 0; 597 switch(nSubType) 598 { 599 case REF_SETREFATTR : nSource = ReferenceFieldSource::REFERENCE_MARK; break; 600 case REF_SEQUENCEFLD: nSource = ReferenceFieldSource::SEQUENCE_FIELD; break; 601 case REF_BOOKMARK : nSource = ReferenceFieldSource::BOOKMARK; break; 602 case REF_OUTLINE : DBG_ERROR("not implemented"); break; 603 case REF_FOOTNOTE : nSource = ReferenceFieldSource::FOOTNOTE; break; 604 case REF_ENDNOTE : nSource = ReferenceFieldSource::ENDNOTE; break; 605 } 606 rAny <<= nSource; 607 } 608 break; 609 case FIELD_PROP_PAR1: 610 { 611 String sTmp(GetPar1()); 612 if(REF_SEQUENCEFLD == nSubType) 613 { 614 sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( sTmp, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL ); 615 switch( nPoolId ) 616 { 617 case RES_POOLCOLL_LABEL_ABB: 618 case RES_POOLCOLL_LABEL_TABLE: 619 case RES_POOLCOLL_LABEL_FRAME: 620 case RES_POOLCOLL_LABEL_DRAWING: 621 SwStyleNameMapper::FillProgName(nPoolId, sTmp) ; 622 break; 623 } 624 } 625 rAny <<= rtl::OUString(sTmp); 626 } 627 break; 628 case FIELD_PROP_PAR3: 629 rAny <<= rtl::OUString(Expand()); 630 break; 631 case FIELD_PROP_SHORT1: 632 rAny <<= (sal_Int16)nSeqNo; 633 break; 634 default: 635 DBG_ERROR("illegal property"); 636 } 637 return sal_True; 638 } 639 640 sal_Bool SwGetRefField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId ) 641 { 642 String sTmp; 643 switch( nWhichId ) 644 { 645 case FIELD_PROP_USHORT1: 646 { 647 sal_Int16 nPart = 0; 648 rAny >>= nPart; 649 switch(nPart) 650 { 651 case ReferenceFieldPart::PAGE: nPart = REF_PAGE; break; 652 case ReferenceFieldPart::CHAPTER: nPart = REF_CHAPTER; break; 653 case ReferenceFieldPart::TEXT: nPart = REF_CONTENT; break; 654 case ReferenceFieldPart::UP_DOWN: nPart = REF_UPDOWN; break; 655 case ReferenceFieldPart::PAGE_DESC: nPart = REF_PAGE_PGDESC; break; 656 case ReferenceFieldPart::CATEGORY_AND_NUMBER: nPart = REF_ONLYNUMBER; break; 657 case ReferenceFieldPart::ONLY_CAPTION: nPart = REF_ONLYCAPTION; break; 658 case ReferenceFieldPart::ONLY_SEQUENCE_NUMBER : nPart = REF_ONLYSEQNO; break; 659 // --> OD 2007-09-06 #i81002# 660 case ReferenceFieldPart::NUMBER: nPart = REF_NUMBER; break; 661 case ReferenceFieldPart::NUMBER_NO_CONTEXT: nPart = REF_NUMBER_NO_CONTEXT; break; 662 case ReferenceFieldPart::NUMBER_FULL_CONTEXT: nPart = REF_NUMBER_FULL_CONTEXT; break; 663 // <-- 664 default: return sal_False; 665 } 666 SetFormat(nPart); 667 } 668 break; 669 case FIELD_PROP_USHORT2: 670 { 671 sal_Int16 nSource = 0; 672 rAny >>= nSource; 673 switch(nSource) 674 { 675 case ReferenceFieldSource::REFERENCE_MARK : nSubType = REF_SETREFATTR ; break; 676 case ReferenceFieldSource::SEQUENCE_FIELD : 677 { 678 if(REF_SEQUENCEFLD == nSubType) 679 break; 680 nSubType = REF_SEQUENCEFLD; 681 ConvertProgrammaticToUIName(); 682 } 683 break; 684 case ReferenceFieldSource::BOOKMARK : nSubType = REF_BOOKMARK ; break; 685 case ReferenceFieldSource::FOOTNOTE : nSubType = REF_FOOTNOTE ; break; 686 case ReferenceFieldSource::ENDNOTE : nSubType = REF_ENDNOTE ; break; 687 } 688 } 689 break; 690 case FIELD_PROP_PAR1: 691 { 692 OUString sTmpStr; 693 rAny >>= sTmpStr; 694 SetPar1(sTmpStr); 695 ConvertProgrammaticToUIName(); 696 } 697 break; 698 case FIELD_PROP_PAR3: 699 SetExpand( ::GetString( rAny, sTmp )); 700 break; 701 case FIELD_PROP_SHORT1: 702 { 703 sal_Int16 nSetSeq = 0; 704 rAny >>= nSetSeq; 705 if(nSetSeq >= 0) 706 nSeqNo = nSetSeq; 707 } 708 break; 709 default: 710 DBG_ERROR("illegal property"); 711 } 712 return sal_True; 713 } 714 715 void SwGetRefField::ConvertProgrammaticToUIName() 716 { 717 if(GetTyp() && REF_SEQUENCEFLD == nSubType) 718 { 719 SwDoc* pDoc = ((SwGetRefFieldType*)GetTyp())->GetDoc(); 720 const String& rPar1 = GetPar1(); 721 //don't convert when the name points to an existing field type 722 if(!pDoc->GetFldType(RES_SETEXPFLD, rPar1, false)) 723 { 724 sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromProgName( rPar1, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL ); 725 sal_uInt16 nResId = USHRT_MAX; 726 switch( nPoolId ) 727 { 728 case RES_POOLCOLL_LABEL_ABB: 729 nResId = STR_POOLCOLL_LABEL_ABB; 730 break; 731 case RES_POOLCOLL_LABEL_TABLE: 732 nResId = STR_POOLCOLL_LABEL_TABLE; 733 break; 734 case RES_POOLCOLL_LABEL_FRAME: 735 nResId = STR_POOLCOLL_LABEL_FRAME; 736 break; 737 case RES_POOLCOLL_LABEL_DRAWING: 738 nResId = STR_POOLCOLL_LABEL_DRAWING; 739 break; 740 } 741 if( nResId != USHRT_MAX ) 742 SetPar1(SW_RESSTR( nResId )); 743 } 744 } 745 } 746 747 SwGetRefFieldType::SwGetRefFieldType( SwDoc* pDc ) 748 : SwFieldType( RES_GETREFFLD ), pDoc( pDc ) 749 {} 750 751 752 SwFieldType* SwGetRefFieldType::Copy() const 753 { 754 return new SwGetRefFieldType( pDoc ); 755 } 756 757 758 void SwGetRefFieldType::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew ) 759 { 760 // Update auf alle GetReferenz-Felder 761 if( !pNew && !pOld ) 762 { 763 SwIterator<SwFmtFld,SwFieldType> aIter( *this ); 764 for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() ) 765 { 766 // nur die GetRef-Felder Updaten 767 //JP 3.4.2001: Task 71231 - we need the correct language 768 SwGetRefField* pGRef = (SwGetRefField*)pFmtFld->GetField(); 769 const SwTxtFld* pTFld; 770 if( !pGRef->GetLanguage() && 771 0 != ( pTFld = pFmtFld->GetTxtFld()) && 772 pTFld->GetpTxtNode() ) 773 { 774 pGRef->SetLanguage( pTFld->GetpTxtNode()->GetLang( 775 *pTFld->GetStart() ) ); 776 } 777 778 pGRef->UpdateField( pFmtFld->GetTxtFld() ); 779 } 780 } 781 // weiter an die Text-Felder, diese "Expandieren" den Text 782 NotifyClients( pOld, pNew ); 783 } 784 785 SwTxtNode* SwGetRefFieldType::FindAnchor( SwDoc* pDoc, const String& rRefMark, 786 sal_uInt16 nSubType, sal_uInt16 nSeqNo, 787 sal_uInt16* pStt, sal_uInt16* pEnd ) 788 { 789 ASSERT( pStt, "warum wird keine StartPos abgefragt?" ); 790 791 SwTxtNode* pTxtNd = 0; 792 switch( nSubType ) 793 { 794 case REF_SETREFATTR: 795 { 796 const SwFmtRefMark *pRef = pDoc->GetRefMark( rRefMark ); 797 if( pRef && pRef->GetTxtRefMark() ) 798 { 799 pTxtNd = (SwTxtNode*)&pRef->GetTxtRefMark()->GetTxtNode(); 800 *pStt = *pRef->GetTxtRefMark()->GetStart(); 801 if( pEnd ) 802 *pEnd = *pRef->GetTxtRefMark()->GetAnyEnd(); 803 } 804 } 805 break; 806 807 case REF_SEQUENCEFLD: 808 { 809 SwFieldType* pFldType = pDoc->GetFldType( RES_SETEXPFLD, rRefMark, false ); 810 if( pFldType && pFldType->GetDepends() && 811 nsSwGetSetExpType::GSE_SEQ & ((SwSetExpFieldType*)pFldType)->GetType() ) 812 { 813 SwIterator<SwFmtFld,SwFieldType> aIter( *pFldType ); 814 for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() ) 815 { 816 if( pFmtFld->GetTxtFld() && nSeqNo == 817 ((SwSetExpField*)pFmtFld->GetField())->GetSeqNumber() ) 818 { 819 SwTxtFld* pTxtFld = pFmtFld->GetTxtFld(); 820 pTxtNd = (SwTxtNode*)pTxtFld->GetpTxtNode(); 821 *pStt = *pTxtFld->GetStart(); 822 if( pEnd ) 823 *pEnd = (*pStt) + 1; 824 break; 825 } 826 } 827 } 828 } 829 break; 830 831 case REF_BOOKMARK: 832 { 833 IDocumentMarkAccess::const_iterator_t ppMark = pDoc->getIDocumentMarkAccess()->findMark(rRefMark); 834 if(ppMark != pDoc->getIDocumentMarkAccess()->getAllMarksEnd()) 835 { 836 const ::sw::mark::IMark* pBkmk = ppMark->get(); 837 const SwPosition* pPos = &pBkmk->GetMarkStart(); 838 839 pTxtNd = pPos->nNode.GetNode().GetTxtNode(); 840 *pStt = pPos->nContent.GetIndex(); 841 if(pEnd) 842 { 843 if(!pBkmk->IsExpanded()) 844 { 845 *pEnd = *pStt; 846 // --> OD 2007-10-18 #i81002# 847 if(dynamic_cast< ::sw::mark::CrossRefBookmark const *>(pBkmk)) 848 { 849 ASSERT( pTxtNd, 850 "<SwGetRefFieldType::FindAnchor(..)> - node marked by cross-reference bookmark isn't a text node --> crash" ); 851 *pEnd = pTxtNd->Len(); 852 } 853 // <-- 854 } 855 else if(pBkmk->GetOtherMarkPos().nNode == pBkmk->GetMarkPos().nNode) 856 *pEnd = pBkmk->GetMarkEnd().nContent.GetIndex(); 857 else 858 *pEnd = USHRT_MAX; 859 } 860 } 861 } 862 break; 863 864 case REF_OUTLINE: 865 break; 866 867 case REF_FOOTNOTE: 868 case REF_ENDNOTE: 869 { 870 sal_uInt16 n, nFtnCnt = pDoc->GetFtnIdxs().Count(); 871 SwTxtFtn* pFtnIdx; 872 for( n = 0; n < nFtnCnt; ++n ) 873 if( nSeqNo == (pFtnIdx = pDoc->GetFtnIdxs()[ n ])->GetSeqRefNo() ) 874 { 875 SwNodeIndex* pIdx = pFtnIdx->GetStartNode(); 876 if( pIdx ) 877 { 878 SwNodeIndex aIdx( *pIdx, 1 ); 879 if( 0 == ( pTxtNd = aIdx.GetNode().GetTxtNode())) 880 pTxtNd = (SwTxtNode*)pDoc->GetNodes().GoNext( &aIdx ); 881 } 882 *pStt = 0; 883 if( pEnd ) 884 *pEnd = 0; 885 break; 886 } 887 } 888 break; 889 } 890 891 return pTxtNd; 892 } 893 894 895 struct _RefIdsMap 896 { 897 String aName; 898 SvUShortsSort aIds, aDstIds, aIdsMap; 899 SvUShorts aMap; 900 sal_Bool bInit; 901 902 _RefIdsMap( const String& rName ) 903 : aName( rName ), aIds( 16, 16 ), aIdsMap( 16, 16 ), aMap( 16, 16 ), 904 bInit( sal_False ) 905 {} 906 907 void Check( SwDoc& rDoc, SwDoc& rDestDoc, SwGetRefField& rFld, 908 sal_Bool bField = sal_True ); 909 910 sal_Bool IsInit() const { return bInit; } 911 }; 912 913 SV_DECL_PTRARR_DEL( _RefIdsMaps, _RefIdsMap*, 5, 5 ) 914 SV_IMPL_PTRARR( _RefIdsMaps, _RefIdsMap* ) 915 916 void _RefIdsMap::Check( SwDoc& rDoc, SwDoc& rDestDoc, SwGetRefField& rFld, 917 sal_Bool bField ) 918 { 919 920 if( !bInit ) 921 { 922 if( bField ) 923 { 924 const SwTxtNode* pNd; 925 SwFieldType* pType; 926 if( 0 != ( pType = rDestDoc.GetFldType( RES_SETEXPFLD, aName, false ) )) 927 { 928 SwIterator<SwFmtFld,SwFieldType> aIter( *pType ); 929 for( SwFmtFld* pF = aIter.First(); pF; pF = aIter.Next() ) 930 if( pF->GetTxtFld() && 931 0 != ( pNd = pF->GetTxtFld()->GetpTxtNode() ) && 932 pNd->GetNodes().IsDocNodes() ) 933 aIds.Insert( ((SwSetExpField*)pF->GetField())->GetSeqNumber() ); 934 } 935 if( 0 != ( pType = rDoc.GetFldType( RES_SETEXPFLD, aName, false ) )) 936 { 937 SwIterator<SwFmtFld,SwFieldType> aIter( *pType ); 938 for( SwFmtFld* pF = aIter.First(); pF; pF = aIter.Next() ) 939 if( pF->GetTxtFld() && 940 0 != ( pNd = pF->GetTxtFld()->GetpTxtNode() ) && 941 pNd->GetNodes().IsDocNodes() ) 942 aDstIds.Insert( ((SwSetExpField*)pF->GetField())->GetSeqNumber() ); 943 } 944 } 945 else 946 { 947 sal_uInt16 n; 948 949 for( n = rDestDoc.GetFtnIdxs().Count(); n; ) 950 aIds.Insert( rDestDoc.GetFtnIdxs()[ --n ]->GetSeqRefNo() ); 951 for( n = rDoc.GetFtnIdxs().Count(); n; ) 952 aDstIds.Insert( rDoc.GetFtnIdxs()[ --n ]->GetSeqRefNo() ); 953 } 954 bInit = sal_True; 955 } 956 957 // dann teste mal, ob die Nummer schon vergeben ist 958 // oder ob eine neue bestimmt werden muss. 959 sal_uInt16 nPos, nSeqNo = rFld.GetSeqNo(); 960 if( aIds.Seek_Entry( nSeqNo ) && aDstIds.Seek_Entry( nSeqNo )) 961 { 962 // ist schon vergeben, also muss eine neue 963 // erzeugt werden. 964 if( aIdsMap.Seek_Entry( nSeqNo, &nPos )) 965 rFld.SetSeqNo( aMap[ nPos ] ); 966 else 967 { 968 sal_uInt16 n; 969 970 for( n = 0; n < aIds.Count(); ++n ) 971 if( n != aIds[ n ] ) 972 break; 973 974 // die neue SeqNo eintragen, damit die "belegt" ist 975 aIds.Insert( n ); 976 aIdsMap.Insert( nSeqNo, nPos ); 977 aMap.Insert( n, nPos ); 978 rFld.SetSeqNo( n ); 979 980 // und noch die Felder oder Fuss-/EndNote auf die neue 981 // Id umsetzen 982 if( bField ) 983 { 984 SwFieldType* pType = rDoc.GetFldType( RES_SETEXPFLD, aName, false ); 985 if( pType ) 986 { 987 SwIterator<SwFmtFld,SwFieldType> aIter( *pType ); 988 for( SwFmtFld* pF = aIter.First(); pF; pF = aIter.Next() ) 989 if( pF->GetTxtFld() && nSeqNo == 990 ((SwSetExpField*)pF->GetField())->GetSeqNumber() ) 991 ((SwSetExpField*)pF->GetField())->SetSeqNumber( n ); 992 } 993 } 994 else 995 { 996 SwTxtFtn* pFtnIdx; 997 for( sal_uInt16 i = 0, nCnt = rDoc.GetFtnIdxs().Count(); i < nCnt; ++i ) 998 if( nSeqNo == (pFtnIdx = rDoc.GetFtnIdxs()[ i ])->GetSeqRefNo() ) 999 { 1000 pFtnIdx->SetSeqNo( n ); 1001 break; 1002 } 1003 } 1004 } 1005 } 1006 else 1007 { 1008 aIds.Insert( nSeqNo ); 1009 aIdsMap.Insert( nSeqNo, nPos ); 1010 aMap.Insert( nSeqNo, nPos ); 1011 } 1012 } 1013 1014 1015 void SwGetRefFieldType::MergeWithOtherDoc( SwDoc& rDestDoc ) 1016 { 1017 if( &rDestDoc != pDoc && 1018 rDestDoc.GetSysFldType( RES_GETREFFLD )->GetDepends() ) 1019 { 1020 // dann gibt es im DestDoc RefFelder, also muessen im SourceDoc 1021 // alle RefFelder auf einduetige Ids in beiden Docs umgestellt 1022 // werden. 1023 _RefIdsMap aFntMap( aEmptyStr ); 1024 _RefIdsMaps aFldMap; 1025 1026 SwIterator<SwFmtFld,SwFieldType> aIter( *this ); 1027 for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() ) 1028 { 1029 SwGetRefField& rRefFld = *(SwGetRefField*)pFld->GetField(); 1030 switch( rRefFld.GetSubType() ) 1031 { 1032 case REF_SEQUENCEFLD: 1033 { 1034 _RefIdsMap* pMap = 0; 1035 for( sal_uInt16 n = aFldMap.Count(); n; ) 1036 if( aFldMap[ --n ]->aName == rRefFld.GetSetRefName() ) 1037 { 1038 pMap = aFldMap[ n ]; 1039 break; 1040 } 1041 if( !pMap ) 1042 { 1043 pMap = new _RefIdsMap( rRefFld.GetSetRefName() ); 1044 aFldMap.C40_INSERT( _RefIdsMap, pMap, aFldMap.Count() ); 1045 } 1046 1047 pMap->Check( *pDoc, rDestDoc, rRefFld, sal_True ); 1048 } 1049 break; 1050 1051 case REF_FOOTNOTE: 1052 case REF_ENDNOTE: 1053 aFntMap.Check( *pDoc, rDestDoc, rRefFld, sal_False ); 1054 break; 1055 } 1056 } 1057 } 1058 } 1059 1060