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