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