LCOV - code coverage report
Current view: top level - sw/source/core/fields - reffld.cxx (source / functions) Hit Total Coverage
Test: commit 0e63ca4fde4e446f346e35849c756a30ca294aab Lines: 157 525 29.9 %
Date: 2014-04-11 Functions: 16 37 43.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <com/sun/star/text/ReferenceFieldPart.hpp>
      21             : #include <com/sun/star/text/ReferenceFieldSource.hpp>
      22             : #include <unotools/localedatawrapper.hxx>
      23             : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      24             : #include <comphelper/processfactory.hxx>
      25             : #include <comphelper/string.hxx>
      26             : #include <editeng/unolingu.hxx>
      27             : #include <doc.hxx>
      28             : #include <pam.hxx>
      29             : #include <cntfrm.hxx>
      30             : #include <pagefrm.hxx>
      31             : #include <docary.hxx>
      32             : #include <fmtfld.hxx>
      33             : #include <txtfld.hxx>
      34             : #include <txtftn.hxx>
      35             : #include <fmtrfmrk.hxx>
      36             : #include <txtrfmrk.hxx>
      37             : #include <fmtftn.hxx>
      38             : #include <ndtxt.hxx>
      39             : #include <chpfld.hxx>
      40             : #include <reffld.hxx>
      41             : #include <expfld.hxx>
      42             : #include <txtfrm.hxx>
      43             : #include <flyfrm.hxx>
      44             : #include <pagedesc.hxx>
      45             : #include <IMark.hxx>
      46             : #include <crossrefbookmark.hxx>
      47             : #include <ftnidx.hxx>
      48             : #include <viewsh.hxx>
      49             : #include <unofldmid.h>
      50             : #include <SwStyleNameMapper.hxx>
      51             : #include <shellres.hxx>
      52             : #include <poolfmt.hxx>
      53             : #include <poolfmt.hrc>
      54             : #include <comcore.hrc>
      55             : #include <numrule.hxx>
      56             : #include <SwNodeNum.hxx>
      57             : #include <switerator.hxx>
      58             : 
      59             : #include <set>
      60             : #include <map>
      61             : #include <algorithm>
      62             : 
      63             : #include <sfx2/childwin.hxx>
      64             : 
      65             : using namespace ::com::sun::star;
      66             : using namespace ::com::sun::star::text;
      67             : using namespace ::com::sun::star::lang;
      68             : 
      69             : extern void InsertSort( std::vector<sal_uInt16>& rArr, sal_uInt16 nIdx, sal_uInt16* pInsPos = 0 );
      70             : 
      71           0 : static void lcl_GetLayTree( const SwFrm* pFrm, std::vector<const SwFrm*>& rArr )
      72             : {
      73           0 :     while( pFrm )
      74             :     {
      75           0 :         if( pFrm->IsBodyFrm() ) // unspectacular
      76           0 :             pFrm = pFrm->GetUpper();
      77             :         else
      78             :         {
      79           0 :             rArr.push_back( pFrm );
      80             : 
      81             :             // this is the last page
      82           0 :             if( pFrm->IsPageFrm() )
      83           0 :                 break;
      84             : 
      85           0 :             if( pFrm->IsFlyFrm() )
      86           0 :                 pFrm = ((SwFlyFrm*)pFrm)->GetAnchorFrm();
      87             :             else
      88           0 :                 pFrm = pFrm->GetUpper();
      89             :         }
      90             :     }
      91           0 : }
      92             : 
      93           0 : bool IsFrameBehind( const SwTxtNode& rMyNd, sal_Int32 nMySttPos,
      94             :                     const SwTxtNode& rBehindNd, sal_Int32 nSttPos )
      95             : {
      96           0 :     const SwTxtFrm *pMyFrm = (SwTxtFrm*)rMyNd.getLayoutFrm( rMyNd.GetDoc()->GetCurrentLayout(), 0, 0, false),
      97           0 :                    *pFrm = (SwTxtFrm*)rBehindNd.getLayoutFrm( rBehindNd.GetDoc()->GetCurrentLayout(), 0, 0, false);
      98             : 
      99           0 :     while( pFrm && !pFrm->IsInside( nSttPos ) )
     100           0 :         pFrm = (SwTxtFrm*)pFrm->GetFollow();
     101           0 :     while( pMyFrm && !pMyFrm->IsInside( nMySttPos ) )
     102           0 :         pMyFrm = (SwTxtFrm*)pMyFrm->GetFollow();
     103             : 
     104           0 :     if( !pFrm || !pMyFrm || pFrm == pMyFrm )
     105           0 :         return false;
     106             : 
     107           0 :     std::vector<const SwFrm*> aRefArr, aArr;
     108           0 :     ::lcl_GetLayTree( pFrm, aRefArr );
     109           0 :     ::lcl_GetLayTree( pMyFrm, aArr );
     110             : 
     111           0 :     size_t nRefCnt = aRefArr.size() - 1, nCnt = aArr.size() - 1;
     112           0 :     sal_Bool bVert = sal_False;
     113           0 :     sal_Bool bR2L = sal_False;
     114             : 
     115             :     // Loop as long as a frame does not equal?
     116           0 :     while( nRefCnt && nCnt && aRefArr[ nRefCnt ] == aArr[ nCnt ] )
     117             :     {
     118           0 :         const SwFrm* pTmpFrm = aArr[ nCnt ];
     119           0 :         bVert = pTmpFrm->IsVertical();
     120           0 :         bR2L = pTmpFrm->IsRightToLeft();
     121           0 :         --nCnt, --nRefCnt;
     122             :     }
     123             : 
     124             :     // If a counter overflows?
     125           0 :     if( aRefArr[ nRefCnt ] == aArr[ nCnt ] )
     126             :     {
     127           0 :         if( nCnt )
     128           0 :             --nCnt;
     129             :         else
     130           0 :             --nRefCnt;
     131             :     }
     132             : 
     133           0 :     const SwFrm* pRefFrm = aRefArr[ nRefCnt ];
     134           0 :     const SwFrm* pFldFrm = aArr[ nCnt ];
     135             : 
     136             :     // different frames, check their Y-/X-position
     137           0 :     bool bRefIsLower = false;
     138           0 :     if( ( FRM_COLUMN | FRM_CELL ) & pFldFrm->GetType() ||
     139           0 :         ( FRM_COLUMN | FRM_CELL ) & pRefFrm->GetType() )
     140             :     {
     141           0 :         if( pFldFrm->GetType() == pRefFrm->GetType() )
     142             :         {
     143             :             // here, the X-pos is more important
     144           0 :             if( bVert )
     145             :             {
     146           0 :                 if( bR2L )
     147           0 :                     bRefIsLower = pRefFrm->Frm().Top() < pFldFrm->Frm().Top() ||
     148           0 :                             ( pRefFrm->Frm().Top() == pFldFrm->Frm().Top() &&
     149           0 :                               pRefFrm->Frm().Left() < pFldFrm->Frm().Left() );
     150             :                 else
     151           0 :                     bRefIsLower = pRefFrm->Frm().Top() < pFldFrm->Frm().Top() ||
     152           0 :                             ( pRefFrm->Frm().Top() == pFldFrm->Frm().Top() &&
     153           0 :                               pRefFrm->Frm().Left() > pFldFrm->Frm().Left() );
     154             :             }
     155           0 :             else if( bR2L )
     156           0 :                 bRefIsLower = pRefFrm->Frm().Left() > pFldFrm->Frm().Left() ||
     157           0 :                             ( pRefFrm->Frm().Left() == pFldFrm->Frm().Left() &&
     158           0 :                               pRefFrm->Frm().Top() < pFldFrm->Frm().Top() );
     159             :             else
     160           0 :                 bRefIsLower = pRefFrm->Frm().Left() < pFldFrm->Frm().Left() ||
     161           0 :                             ( pRefFrm->Frm().Left() == pFldFrm->Frm().Left() &&
     162           0 :                               pRefFrm->Frm().Top() < pFldFrm->Frm().Top() );
     163           0 :             pRefFrm = 0;
     164             :         }
     165           0 :         else if( ( FRM_COLUMN | FRM_CELL ) & pFldFrm->GetType() )
     166           0 :             pFldFrm = aArr[ nCnt - 1 ];
     167             :         else
     168           0 :             pRefFrm = aRefArr[ nRefCnt - 1 ];
     169             :     }
     170             : 
     171           0 :     if( pRefFrm ) // misuse as flag
     172             :     {
     173           0 :         if( bVert )
     174             :         {
     175           0 :             if( bR2L )
     176           0 :                 bRefIsLower = pRefFrm->Frm().Left() < pFldFrm->Frm().Left() ||
     177           0 :                             ( pRefFrm->Frm().Left() == pFldFrm->Frm().Left() &&
     178           0 :                                 pRefFrm->Frm().Top() < pFldFrm->Frm().Top() );
     179             :             else
     180           0 :                 bRefIsLower = pRefFrm->Frm().Left() > pFldFrm->Frm().Left() ||
     181           0 :                             ( pRefFrm->Frm().Left() == pFldFrm->Frm().Left() &&
     182           0 :                                 pRefFrm->Frm().Top() < pFldFrm->Frm().Top() );
     183             :         }
     184           0 :         else if( bR2L )
     185           0 :             bRefIsLower = pRefFrm->Frm().Top() < pFldFrm->Frm().Top() ||
     186           0 :                         ( pRefFrm->Frm().Top() == pFldFrm->Frm().Top() &&
     187           0 :                             pRefFrm->Frm().Left() > pFldFrm->Frm().Left() );
     188             :         else
     189           0 :             bRefIsLower = pRefFrm->Frm().Top() < pFldFrm->Frm().Top() ||
     190           0 :                         ( pRefFrm->Frm().Top() == pFldFrm->Frm().Top() &&
     191           0 :                             pRefFrm->Frm().Left() < pFldFrm->Frm().Left() );
     192             :     }
     193           0 :     return bRefIsLower;
     194             : }
     195             : 
     196             : /// get references
     197         169 : SwGetRefField::SwGetRefField( SwGetRefFieldType* pFldType,
     198             :                               const OUString& rSetRef, sal_uInt16 nSubTyp,
     199             :                               sal_uInt16 nSeqenceNo, sal_uLong nFmt )
     200             :     : SwField( pFldType, nFmt ),
     201             :       sSetRefName( rSetRef ),
     202             :       nSubType( nSubTyp ),
     203         169 :       nSeqNo( nSeqenceNo )
     204             : {
     205         169 : }
     206             : 
     207         337 : SwGetRefField::~SwGetRefField()
     208             : {
     209         337 : }
     210             : 
     211           0 : OUString SwGetRefField::GetDescription() const
     212             : {
     213           0 :     return SW_RES(STR_REFERENCE);
     214             : }
     215             : 
     216          80 : sal_uInt16 SwGetRefField::GetSubType() const
     217             : {
     218          80 :     return nSubType;
     219             : }
     220             : 
     221           0 : void SwGetRefField::SetSubType( sal_uInt16 n )
     222             : {
     223           0 :     nSubType = n;
     224           0 : }
     225             : 
     226             : // #i81002#
     227           0 : bool SwGetRefField::IsRefToHeadingCrossRefBookmark() const
     228             : {
     229           0 :     return GetSubType() == REF_BOOKMARK &&
     230           0 :         ::sw::mark::CrossRefHeadingBookmark::IsLegalName(sSetRefName);
     231             : }
     232             : 
     233           0 : bool SwGetRefField::IsRefToNumItemCrossRefBookmark() const
     234             : {
     235           0 :     return GetSubType() == REF_BOOKMARK &&
     236           0 :         ::sw::mark::CrossRefNumItemBookmark::IsLegalName(sSetRefName);
     237             : }
     238             : 
     239           0 : const SwTxtNode* SwGetRefField::GetReferencedTxtNode() const
     240             : {
     241           0 :     SwDoc* pDoc = dynamic_cast<SwGetRefFieldType*>(GetTyp())->GetDoc();
     242           0 :     sal_Int32 nDummy = -1;
     243           0 :     return SwGetRefFieldType::FindAnchor( pDoc, sSetRefName, nSubType, nSeqNo, &nDummy );
     244             : }
     245             : 
     246             : // #i85090#
     247           0 : OUString SwGetRefField::GetExpandedTxtOfReferencedTxtNode() const
     248             : {
     249           0 :     const SwTxtNode* pReferencedTxtNode( GetReferencedTxtNode() );
     250             :     return pReferencedTxtNode
     251             :            ? OUString(pReferencedTxtNode->GetExpandTxt( 0, -1, true, true, false, false ))
     252           0 :            : OUString();
     253             : }
     254             : 
     255         607 : OUString SwGetRefField::Expand() const
     256             : {
     257         607 :     return sTxt;
     258             : }
     259             : 
     260           0 : OUString SwGetRefField::GetFieldName() const
     261             : {
     262           0 :     const OUString aName = GetTyp()->GetName();
     263           0 :     if ( !aName.isEmpty() || !sSetRefName.isEmpty() )
     264             :     {
     265           0 :         return aName + " " + sSetRefName;
     266             :     }
     267           0 :     return Expand();
     268             : }
     269             : 
     270             : // #i81002# - parameter <pFldTxtAttr> added
     271         461 : void SwGetRefField::UpdateField( const SwTxtFld* pFldTxtAttr )
     272             : {
     273         461 :     sTxt = OUString();
     274             : 
     275         461 :     SwDoc* pDoc = ((SwGetRefFieldType*)GetTyp())->GetDoc();
     276             :     // finding the reference target (the number)
     277         461 :     sal_Int32 nNumStart = -1;
     278         461 :     sal_Int32 nNumEnd = -1;
     279             :     SwTxtNode* pTxtNd = SwGetRefFieldType::FindAnchor(
     280             :         pDoc, sSetRefName, nSubType, nSeqNo, &nNumStart, &nNumEnd
     281         461 :     );
     282             :     // not found?
     283         461 :     if ( !pTxtNd )
     284             :     {
     285           0 :         sTxt = SwViewShell::GetShellRes()->aGetRefFld_RefItemNotFound;
     286           0 :         return ;
     287             :     }
     288             :     // where is the category name (e.g. "Illustration")?
     289         461 :     OUString const sText = pTxtNd->GetTxt();
     290         461 :     const sal_Int32 nCatStart = sText.indexOf(sSetRefName);
     291         461 :     const bool bHasCat = nCatStart>=0;
     292         461 :     const sal_Int32 nCatEnd = bHasCat ? nCatStart + sSetRefName.getLength() : -1;
     293             : 
     294             :     // length of the referenced text
     295         461 :     const sal_Int32 nLen = sText.getLength();
     296             : 
     297             :     // which format?
     298         461 :     switch( GetFormat() )
     299             :     {
     300             :     case REF_CONTENT:
     301             :     case REF_ONLYNUMBER:
     302             :     case REF_ONLYCAPTION:
     303             :     case REF_ONLYSEQNO:
     304             :         {
     305             :             // needed part of Text
     306             :             sal_Int32 nStart;
     307             :             sal_Int32 nEnd;
     308             : 
     309           4 :             switch( nSubType )
     310             :             {
     311             :             case REF_SEQUENCEFLD:
     312             : 
     313           0 :                 switch( GetFormat() )
     314             :                 {
     315             :                 // "Category and Number"
     316             :                 case REF_ONLYNUMBER:
     317           0 :                     if (bHasCat) {
     318           0 :                         nStart = std::min(nNumStart, nCatStart);
     319           0 :                         nEnd = std::max(nNumEnd, nCatEnd);
     320             :                     } else {
     321           0 :                         nStart = nNumStart;
     322           0 :                         nEnd = nNumEnd;
     323             :                     }
     324           0 :                     break;
     325             : 
     326             :                 // "Caption Text"
     327             :                 case REF_ONLYCAPTION: {
     328             :                     // next alphanumeric character after category+number
     329           0 :                     if (const SwTxtAttr* const pTxtAttr =
     330           0 :                         pTxtNd->GetTxtAttrForCharAt(nNumStart, RES_TXTATR_FIELD)
     331             :                     ) {
     332             :                         // start searching from nFrom
     333             :                         const sal_Int32 nFrom = bHasCat
     334           0 :                             ? std::max(nNumStart + 1, nCatEnd)
     335           0 :                             : nNumStart + 1;
     336           0 :                         nStart = SwGetExpField::GetReferenceTextPos( pTxtAttr->GetFmtFld(), *pDoc, nFrom );
     337             :                     } else {
     338           0 :                         nStart = bHasCat ? std::max(nNumEnd, nCatEnd) : nNumEnd;
     339             :                     }
     340           0 :                     nEnd = nLen;
     341           0 :                     break;
     342             :                 }
     343             : 
     344             :                 // "Numbering"
     345             :                 case REF_ONLYSEQNO:
     346           0 :                     nStart = nNumStart;
     347           0 :                     nEnd = std::min(nStart + 1, nLen);
     348           0 :                     break;
     349             : 
     350             :                 // "Reference" (whole Text)
     351             :                 default:
     352           0 :                     nStart = 0;
     353           0 :                     nEnd = nLen;
     354           0 :                     break;
     355             :                 }
     356           0 :                 break;
     357             : 
     358             :             case REF_BOOKMARK:
     359           4 :                 nStart = nNumStart;
     360             :                 // Text steht ueber verschiedene Nodes verteilt.
     361             :                 // Gesamten Text oder nur bis zum Ende vom Node?
     362           4 :                 nEnd = nNumEnd<0 ? nLen : nNumEnd;
     363           4 :                 break;
     364             : 
     365             :             case REF_OUTLINE:
     366           0 :                 nStart = nNumStart;
     367           0 :                 nEnd = nNumEnd;
     368           0 :                 break;
     369             : 
     370             :             case REF_FOOTNOTE:
     371             :             case REF_ENDNOTE:
     372             :                 // die Nummer oder den NumString besorgen
     373           0 :                 for( unsigned i = 0; i < pDoc->GetFtnIdxs().size(); ++i )
     374             :                 {
     375           0 :                     SwTxtFtn* const pFtnIdx = pDoc->GetFtnIdxs()[i];
     376           0 :                     if( nSeqNo == pFtnIdx->GetSeqRefNo() )
     377             :                     {
     378           0 :                         sTxt = pFtnIdx->GetFtn().GetViewNumStr( *pDoc );
     379           0 :                         break;
     380             :                     }
     381             :                 }
     382           0 :                 return;
     383             : 
     384             :             default:
     385           0 :                 nStart = nNumStart;
     386           0 :                 nEnd = nNumEnd;
     387           0 :                 break;
     388             :             }
     389             : 
     390           4 :             if( nStart != nEnd ) // a section?
     391             :             {
     392           4 :                 sTxt = pTxtNd->GetExpandTxt( nStart, nEnd - nStart );
     393             : 
     394             :                 // remove all special characters (replace them with blanks)
     395           4 :                 if( !sTxt.isEmpty() )
     396             :                 {
     397           4 :                     sTxt = comphelper::string::remove(sTxt, 0xad);
     398           4 :                     OUStringBuffer aBuf(sTxt);
     399           4 :                     const sal_Int32 l = aBuf.getLength();
     400          48 :                     for (sal_Int32 i=0; i<l; ++i)
     401             :                     {
     402          44 :                         if (aBuf[i]<' ')
     403             :                         {
     404           0 :                             aBuf[i]=' ';
     405             :                         }
     406          44 :                         else if (aBuf[i]==0x2011)
     407             :                         {
     408           0 :                             aBuf[i]='-';
     409             :                         }
     410             :                     }
     411           4 :                     sTxt = aBuf.makeStringAndClear();
     412             :                 }
     413             :             }
     414             :         }
     415           4 :         break;
     416             : 
     417             :     case REF_PAGE:
     418             :     case REF_PAGE_PGDESC:
     419             :         {
     420           0 :             const SwTxtFrm* pFrm = (SwTxtFrm*)pTxtNd->getLayoutFrm( pDoc->GetCurrentLayout(), 0, 0, false),
     421           0 :                         *pSave = pFrm;
     422           0 :             while( pFrm && !pFrm->IsInside( nNumStart ) )
     423           0 :                 pFrm = (SwTxtFrm*)pFrm->GetFollow();
     424             : 
     425           0 :             if( pFrm || 0 != ( pFrm = pSave ))
     426             :             {
     427           0 :                 sal_uInt16 nPageNo = pFrm->GetVirtPageNum();
     428             :                 const SwPageFrm *pPage;
     429           0 :                 if( REF_PAGE_PGDESC == GetFormat() &&
     430           0 :                     0 != ( pPage = pFrm->FindPageFrm() ) &&
     431           0 :                     pPage->GetPageDesc() )
     432           0 :                     sTxt = pPage->GetPageDesc()->GetNumType().GetNumStr( nPageNo );
     433             :                 else
     434           0 :                     sTxt = OUString::number(nPageNo);
     435             :             }
     436             :         }
     437           0 :         break;
     438             : 
     439             :     case REF_CHAPTER:
     440             :         {
     441             :             // a bit tricky: search any frame
     442           0 :             const SwFrm* pFrm = pTxtNd->getLayoutFrm( pDoc->GetCurrentLayout() );
     443           0 :             if( pFrm )
     444             :             {
     445           0 :                 SwChapterFieldType aFldTyp;
     446           0 :                 SwChapterField aFld( &aFldTyp, 0 );
     447           0 :                 aFld.SetLevel( MAXLEVEL - 1 );
     448           0 :                 aFld.ChangeExpansion( pFrm, pTxtNd, sal_True );
     449           0 :                 sTxt = aFld.GetNumber();
     450             :             }
     451             :         }
     452           0 :         break;
     453             : 
     454             :     case REF_UPDOWN:
     455             :         {
     456             :             // #i81002#
     457             :             // simplified: use parameter <pFldTxtAttr>
     458           0 :             if( !pFldTxtAttr || !pFldTxtAttr->GetpTxtNode() )
     459           0 :                 break;
     460             : 
     461           0 :             LanguageTag aLanguageTag( GetLanguage());
     462           0 :             LocaleDataWrapper aLocaleData( aLanguageTag );
     463             : 
     464             :             // first a "short" test - in case both are in the same node
     465           0 :             if( pFldTxtAttr->GetpTxtNode() == pTxtNd )
     466             :             {
     467           0 :                 sTxt = nNumStart < *pFldTxtAttr->GetStart()
     468             :                             ? aLocaleData.getAboveWord()
     469           0 :                             : aLocaleData.getBelowWord();
     470           0 :                 break;
     471             :             }
     472             : 
     473           0 :             sTxt = ::IsFrameBehind( *pFldTxtAttr->GetpTxtNode(), *pFldTxtAttr->GetStart(),
     474           0 :                                     *pTxtNd, nNumStart )
     475             :                         ? aLocaleData.getAboveWord()
     476           0 :                         : aLocaleData.getBelowWord();
     477             :         }
     478           0 :         break;
     479             :     // #i81002#
     480             :     case REF_NUMBER:
     481             :     case REF_NUMBER_NO_CONTEXT:
     482             :     case REF_NUMBER_FULL_CONTEXT:
     483             :         {
     484         457 :             if ( pFldTxtAttr && pFldTxtAttr->GetpTxtNode() )
     485             :             {
     486         457 :                 sTxt = MakeRefNumStr( pFldTxtAttr->GetTxtNode(), *pTxtNd, GetFormat() );
     487             :             }
     488             :         }
     489         457 :         break;
     490             : 
     491             :     default:
     492             :         OSL_FAIL("<SwGetRefField::UpdateField(..)> - unknown format type");
     493         461 :     }
     494             : }
     495             : 
     496             : // #i81002#
     497         457 : OUString SwGetRefField::MakeRefNumStr( const SwTxtNode& rTxtNodeOfField,
     498             :                                      const SwTxtNode& rTxtNodeOfReferencedItem,
     499             :                                      const sal_uInt32 nRefNumFormat ) const
     500             : {
     501         914 :     if ( rTxtNodeOfReferencedItem.HasNumber() &&
     502         457 :          rTxtNodeOfReferencedItem.IsCountedInList() )
     503             :     {
     504             :         OSL_ENSURE( rTxtNodeOfReferencedItem.GetNum(),
     505             :                 "<SwGetRefField::MakeRefNumStr(..)> - referenced paragraph has number, but no <SwNodeNum> instance --> please inform OD!" );
     506             : 
     507             :         // Determine, up to which level the superior list labels have to be
     508             :         // included - default is to include all superior list labels.
     509         457 :         sal_uInt8 nRestrictInclToThisLevel( 0 );
     510             :         // Determine for format REF_NUMBER the level, up to which the superior
     511             :         // list labels have to be restricted, if the text node of the reference
     512             :         // field and the text node of the referenced item are in the same
     513             :         // document context.
     514         668 :         if ( nRefNumFormat == REF_NUMBER &&
     515         211 :              rTxtNodeOfField.FindFlyStartNode()
     516         422 :                             == rTxtNodeOfReferencedItem.FindFlyStartNode() &&
     517         211 :              rTxtNodeOfField.FindFootnoteStartNode()
     518         422 :                             == rTxtNodeOfReferencedItem.FindFootnoteStartNode() &&
     519         211 :              rTxtNodeOfField.FindHeaderStartNode()
     520         879 :                             == rTxtNodeOfReferencedItem.FindHeaderStartNode() &&
     521         211 :              rTxtNodeOfField.FindFooterStartNode()
     522         211 :                             == rTxtNodeOfReferencedItem.FindFooterStartNode() )
     523             :         {
     524         211 :             const SwNodeNum* pNodeNumForTxtNodeOfField( 0 );
     525         395 :             if ( rTxtNodeOfField.HasNumber() &&
     526         184 :                  rTxtNodeOfField.GetNumRule() == rTxtNodeOfReferencedItem.GetNumRule() )
     527             :             {
     528         184 :                 pNodeNumForTxtNodeOfField = rTxtNodeOfField.GetNum();
     529             :             }
     530             :             else
     531             :             {
     532             :                 pNodeNumForTxtNodeOfField =
     533          27 :                     rTxtNodeOfReferencedItem.GetNum()->GetPrecedingNodeNumOf( rTxtNodeOfField );
     534             :             }
     535         211 :             if ( pNodeNumForTxtNodeOfField )
     536             :             {
     537         211 :                 const SwNumberTree::tNumberVector rFieldNumVec = pNodeNumForTxtNodeOfField->GetNumberVector();
     538         422 :                 const SwNumberTree::tNumberVector rRefItemNumVec = rTxtNodeOfReferencedItem.GetNum()->GetNumberVector();
     539         211 :                 sal_uInt8 nLevel( 0 );
     540         502 :                 while ( nLevel < rFieldNumVec.size() && nLevel < rRefItemNumVec.size() )
     541             :                 {
     542         280 :                     if ( rRefItemNumVec[nLevel] == rFieldNumVec[nLevel] )
     543             :                     {
     544          80 :                         nRestrictInclToThisLevel = nLevel + 1;
     545             :                     }
     546             :                     else
     547             :                     {
     548         200 :                         break;
     549             :                     }
     550          80 :                     ++nLevel;
     551         211 :                 }
     552             :             }
     553             :         }
     554             : 
     555             :         // Determine, if superior list labels have to be included
     556             :         const bool bInclSuperiorNumLabels(
     557         776 :             ( nRestrictInclToThisLevel < rTxtNodeOfReferencedItem.GetActualListLevel() &&
     558         680 :               ( nRefNumFormat == REF_NUMBER || nRefNumFormat == REF_NUMBER_FULL_CONTEXT ) ) );
     559             : 
     560             :         OSL_ENSURE( rTxtNodeOfReferencedItem.GetNumRule(),
     561             :                 "<SwGetRefField::MakeRefNumStr(..)> - referenced numbered paragraph has no numbering rule set --> please inform OD!" );
     562             :         return rTxtNodeOfReferencedItem.GetNumRule()->MakeRefNumString(
     563         457 :                                             *(rTxtNodeOfReferencedItem.GetNum()),
     564             :                                             bInclSuperiorNumLabels,
     565         914 :                                             nRestrictInclToThisLevel );
     566             :     }
     567             : 
     568           0 :     return OUString();
     569             : }
     570             : 
     571         137 : SwField* SwGetRefField::Copy() const
     572             : {
     573         137 :     SwGetRefField* pFld = new SwGetRefField( (SwGetRefFieldType*)GetTyp(),
     574             :                                                 sSetRefName, nSubType,
     575         137 :                                                 nSeqNo, GetFormat() );
     576         137 :     pFld->sTxt = sTxt;
     577         137 :     return pFld;
     578             : }
     579             : 
     580             : /// get reference name
     581           0 : OUString SwGetRefField::GetPar1() const
     582             : {
     583           0 :     return sSetRefName;
     584             : }
     585             : 
     586             : /// set reference name
     587           0 : void SwGetRefField::SetPar1( const OUString& rName )
     588             : {
     589           0 :     sSetRefName = rName;
     590           0 : }
     591             : 
     592           0 : OUString SwGetRefField::GetPar2() const
     593             : {
     594           0 :     return Expand();
     595             : }
     596             : 
     597          72 : bool SwGetRefField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
     598             : {
     599          72 :     switch( nWhichId )
     600             :     {
     601             :     case FIELD_PROP_USHORT1:
     602             :         {
     603          54 :             sal_Int16 nPart = 0;
     604          54 :             switch(GetFormat())
     605             :             {
     606           0 :             case REF_PAGE       : nPart = ReferenceFieldPart::PAGE                ; break;
     607           0 :             case REF_CHAPTER    : nPart = ReferenceFieldPart::CHAPTER             ; break;
     608          18 :             case REF_CONTENT    : nPart = ReferenceFieldPart::TEXT                ; break;
     609           0 :             case REF_UPDOWN     : nPart = ReferenceFieldPart::UP_DOWN             ; break;
     610           0 :             case REF_PAGE_PGDESC: nPart = ReferenceFieldPart::PAGE_DESC           ; break;
     611           0 :             case REF_ONLYNUMBER : nPart = ReferenceFieldPart::CATEGORY_AND_NUMBER ; break;
     612           0 :             case REF_ONLYCAPTION: nPart = ReferenceFieldPart::ONLY_CAPTION        ; break;
     613           0 :             case REF_ONLYSEQNO  : nPart = ReferenceFieldPart::ONLY_SEQUENCE_NUMBER; break;
     614             :             // #i81002#
     615          24 :             case REF_NUMBER:              nPart = ReferenceFieldPart::NUMBER;              break;
     616          12 :             case REF_NUMBER_NO_CONTEXT:   nPart = ReferenceFieldPart::NUMBER_NO_CONTEXT;   break;
     617           0 :             case REF_NUMBER_FULL_CONTEXT: nPart = ReferenceFieldPart::NUMBER_FULL_CONTEXT; break;
     618             :             }
     619          54 :             rAny <<= nPart;
     620             :         }
     621          54 :         break;
     622             :     case FIELD_PROP_USHORT2:
     623             :         {
     624          18 :             sal_Int16 nSource = 0;
     625          18 :             switch(nSubType)
     626             :             {
     627           0 :             case  REF_SETREFATTR : nSource = ReferenceFieldSource::REFERENCE_MARK; break;
     628           0 :             case  REF_SEQUENCEFLD: nSource = ReferenceFieldSource::SEQUENCE_FIELD; break;
     629          18 :             case  REF_BOOKMARK   : nSource = ReferenceFieldSource::BOOKMARK; break;
     630           0 :             case  REF_OUTLINE    : OSL_FAIL("not implemented"); break;
     631           0 :             case  REF_FOOTNOTE   : nSource = ReferenceFieldSource::FOOTNOTE; break;
     632           0 :             case  REF_ENDNOTE    : nSource = ReferenceFieldSource::ENDNOTE; break;
     633             :             }
     634          18 :             rAny <<= nSource;
     635             :         }
     636          18 :         break;
     637             :     case FIELD_PROP_PAR1:
     638             :     {
     639           0 :         OUString sTmp(GetPar1());
     640           0 :         if(REF_SEQUENCEFLD == nSubType)
     641             :         {
     642           0 :             sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( sTmp, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
     643           0 :             switch( nPoolId )
     644             :             {
     645             :                 case RES_POOLCOLL_LABEL_ABB:
     646             :                 case RES_POOLCOLL_LABEL_TABLE:
     647             :                 case RES_POOLCOLL_LABEL_FRAME:
     648             :                 case RES_POOLCOLL_LABEL_DRAWING:
     649           0 :                     SwStyleNameMapper::FillProgName(nPoolId, sTmp) ;
     650           0 :                 break;
     651             :             }
     652             :         }
     653           0 :         rAny <<= sTmp;
     654             :     }
     655           0 :     break;
     656             :     case FIELD_PROP_PAR3:
     657           0 :         rAny <<= Expand();
     658           0 :         break;
     659             :     case FIELD_PROP_SHORT1:
     660           0 :         rAny <<= (sal_Int16)nSeqNo;
     661           0 :         break;
     662             :     default:
     663             :         OSL_FAIL("illegal property");
     664             :     }
     665          72 :     return true;
     666             : }
     667             : 
     668         129 : bool SwGetRefField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
     669             : {
     670         129 :     switch( nWhichId )
     671             :     {
     672             :     case FIELD_PROP_USHORT1:
     673             :         {
     674          67 :             sal_Int16 nPart = 0;
     675          67 :             rAny >>= nPart;
     676          67 :             switch(nPart)
     677             :             {
     678           0 :             case ReferenceFieldPart::PAGE:                  nPart = REF_PAGE; break;
     679           0 :             case ReferenceFieldPart::CHAPTER:               nPart = REF_CHAPTER; break;
     680          19 :             case ReferenceFieldPart::TEXT:                  nPart = REF_CONTENT; break;
     681           0 :             case ReferenceFieldPart::UP_DOWN:               nPart = REF_UPDOWN; break;
     682           0 :             case ReferenceFieldPart::PAGE_DESC:             nPart = REF_PAGE_PGDESC; break;
     683           0 :             case ReferenceFieldPart::CATEGORY_AND_NUMBER:   nPart = REF_ONLYNUMBER; break;
     684           0 :             case ReferenceFieldPart::ONLY_CAPTION:          nPart = REF_ONLYCAPTION; break;
     685           0 :             case ReferenceFieldPart::ONLY_SEQUENCE_NUMBER : nPart = REF_ONLYSEQNO; break;
     686             :             // #i81002#
     687          24 :             case ReferenceFieldPart::NUMBER:              nPart = REF_NUMBER;              break;
     688          12 :             case ReferenceFieldPart::NUMBER_NO_CONTEXT:   nPart = REF_NUMBER_NO_CONTEXT;   break;
     689          12 :             case ReferenceFieldPart::NUMBER_FULL_CONTEXT: nPart = REF_NUMBER_FULL_CONTEXT; break;
     690           0 :             default: return false;
     691             :             }
     692          67 :             SetFormat(nPart);
     693             :         }
     694          67 :         break;
     695             :     case FIELD_PROP_USHORT2:
     696             :         {
     697          31 :             sal_Int16 nSource = 0;
     698          31 :             rAny >>= nSource;
     699          31 :             switch(nSource)
     700             :             {
     701           0 :             case ReferenceFieldSource::REFERENCE_MARK : nSubType = REF_SETREFATTR ; break;
     702             :             case ReferenceFieldSource::SEQUENCE_FIELD :
     703             :             {
     704           0 :                 if(REF_SEQUENCEFLD == nSubType)
     705           0 :                     break;
     706           0 :                 nSubType = REF_SEQUENCEFLD;
     707           0 :                 ConvertProgrammaticToUIName();
     708             :             }
     709           0 :             break;
     710          31 :             case ReferenceFieldSource::BOOKMARK       : nSubType = REF_BOOKMARK   ; break;
     711           0 :             case ReferenceFieldSource::FOOTNOTE       : nSubType = REF_FOOTNOTE   ; break;
     712           0 :             case ReferenceFieldSource::ENDNOTE        : nSubType = REF_ENDNOTE    ; break;
     713             :             }
     714             :         }
     715          31 :         break;
     716             :     case FIELD_PROP_PAR1:
     717             :     {
     718           0 :         OUString sTmpStr;
     719           0 :         rAny >>= sTmpStr;
     720           0 :         SetPar1(sTmpStr);
     721           0 :         ConvertProgrammaticToUIName();
     722             :     }
     723           0 :     break;
     724             :     case FIELD_PROP_PAR3:
     725             :         {
     726           0 :             OUString sTmpStr;
     727           0 :             rAny >>= sTmpStr;
     728           0 :             SetExpand( sTmpStr );
     729             :         }
     730           0 :         break;
     731             :     case FIELD_PROP_SHORT1:
     732             :         {
     733          31 :             sal_Int16 nSetSeq = 0;
     734          31 :             rAny >>= nSetSeq;
     735          31 :             if(nSetSeq >= 0)
     736          31 :                 nSeqNo = nSetSeq;
     737             :         }
     738          31 :         break;
     739             :     default:
     740             :         OSL_FAIL("illegal property");
     741             :     }
     742         129 :     return true;
     743             : }
     744             : 
     745           0 : void SwGetRefField::ConvertProgrammaticToUIName()
     746             : {
     747           0 :     if(GetTyp() && REF_SEQUENCEFLD == nSubType)
     748             :     {
     749           0 :         SwDoc* pDoc = ((SwGetRefFieldType*)GetTyp())->GetDoc();
     750           0 :         const OUString rPar1 = GetPar1();
     751             :         // don't convert when the name points to an existing field type
     752           0 :         if(!pDoc->GetFldType(RES_SETEXPFLD, rPar1, false))
     753             :         {
     754           0 :             sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromProgName( rPar1, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
     755           0 :             sal_uInt16 nResId = USHRT_MAX;
     756           0 :             switch( nPoolId )
     757             :             {
     758             :                 case RES_POOLCOLL_LABEL_ABB:
     759           0 :                     nResId = STR_POOLCOLL_LABEL_ABB;
     760           0 :                 break;
     761             :                 case RES_POOLCOLL_LABEL_TABLE:
     762           0 :                     nResId = STR_POOLCOLL_LABEL_TABLE;
     763           0 :                 break;
     764             :                 case RES_POOLCOLL_LABEL_FRAME:
     765           0 :                     nResId = STR_POOLCOLL_LABEL_FRAME;
     766           0 :                 break;
     767             :                 case RES_POOLCOLL_LABEL_DRAWING:
     768           0 :                     nResId = STR_POOLCOLL_LABEL_DRAWING;
     769           0 :                 break;
     770             :             }
     771           0 :             if( nResId != USHRT_MAX )
     772           0 :                 SetPar1(SW_RESSTR( nResId ));
     773           0 :         }
     774             :     }
     775           0 : }
     776             : 
     777        1852 : SwGetRefFieldType::SwGetRefFieldType( SwDoc* pDc )
     778        1852 :     : SwFieldType( RES_GETREFFLD ), pDoc( pDc )
     779        1852 : {}
     780             : 
     781           0 : SwFieldType* SwGetRefFieldType::Copy() const
     782             : {
     783           0 :     return new SwGetRefFieldType( pDoc );
     784             : }
     785             : 
     786         158 : void SwGetRefFieldType::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
     787             : {
     788             :     // update to all GetReference fields
     789         158 :     if( !pNew && !pOld )
     790             :     {
     791         158 :         SwIterator<SwFmtFld,SwFieldType> aIter( *this );
     792         619 :         for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
     793             :         {
     794             :             // update only the GetRef fields
     795             :             //JP 3.4.2001: Task 71231 - we need the correct language
     796         461 :             SwGetRefField* pGRef = (SwGetRefField*)pFmtFld->GetField();
     797             :             const SwTxtFld* pTFld;
     798         924 :             if( !pGRef->GetLanguage() &&
     799         461 :                 0 != ( pTFld = pFmtFld->GetTxtFld()) &&
     800           0 :                 pTFld->GetpTxtNode() )
     801             :             {
     802             :                 pGRef->SetLanguage( pTFld->GetpTxtNode()->GetLang(
     803           0 :                                                 *pTFld->GetStart() ) );
     804             :             }
     805             : 
     806             :             // #i81002#
     807         461 :             pGRef->UpdateField( pFmtFld->GetTxtFld() );
     808         158 :         }
     809             :     }
     810             :     // forward to text fields, they "expand" the text
     811         158 :     NotifyClients( pOld, pNew );
     812         158 : }
     813             : 
     814         461 : SwTxtNode* SwGetRefFieldType::FindAnchor( SwDoc* pDoc, const OUString& rRefMark,
     815             :                                         sal_uInt16 nSubType, sal_uInt16 nSeqNo,
     816             :                                         sal_Int32* pStt, sal_Int32* pEnd )
     817             : {
     818             :     OSL_ENSURE( pStt, "Why did noone check the StartPos?" );
     819             : 
     820         461 :     SwTxtNode* pTxtNd = 0;
     821         461 :     switch( nSubType )
     822             :     {
     823             :     case REF_SETREFATTR:
     824             :         {
     825           0 :             const SwFmtRefMark *pRef = pDoc->GetRefMark( rRefMark );
     826           0 :             if( pRef && pRef->GetTxtRefMark() )
     827             :             {
     828           0 :                 pTxtNd = (SwTxtNode*)&pRef->GetTxtRefMark()->GetTxtNode();
     829           0 :                 *pStt = *pRef->GetTxtRefMark()->GetStart();
     830           0 :                 if( pEnd )
     831           0 :                     *pEnd = *pRef->GetTxtRefMark()->GetAnyEnd();
     832             :             }
     833             :         }
     834           0 :         break;
     835             : 
     836             :     case REF_SEQUENCEFLD:
     837             :         {
     838           0 :             SwFieldType* pFldType = pDoc->GetFldType( RES_SETEXPFLD, rRefMark, false );
     839           0 :             if( pFldType && pFldType->GetDepends() &&
     840           0 :                 nsSwGetSetExpType::GSE_SEQ & ((SwSetExpFieldType*)pFldType)->GetType() )
     841             :             {
     842           0 :                 SwIterator<SwFmtFld,SwFieldType> aIter( *pFldType );
     843           0 :                 for( SwFmtFld* pFmtFld = aIter.First(); pFmtFld; pFmtFld = aIter.Next() )
     844             :                 {
     845           0 :                     if( pFmtFld->GetTxtFld() && nSeqNo ==
     846           0 :                         ((SwSetExpField*)pFmtFld->GetField())->GetSeqNumber() )
     847             :                     {
     848           0 :                         SwTxtFld* pTxtFld = pFmtFld->GetTxtFld();
     849           0 :                         pTxtNd = (SwTxtNode*)pTxtFld->GetpTxtNode();
     850           0 :                         *pStt = *pTxtFld->GetStart();
     851           0 :                         if( pEnd )
     852           0 :                             *pEnd = (*pStt) + 1;
     853           0 :                         break;
     854             :                     }
     855           0 :                 }
     856             :             }
     857             :         }
     858           0 :         break;
     859             : 
     860             :     case REF_BOOKMARK:
     861             :         {
     862         461 :             IDocumentMarkAccess::const_iterator_t ppMark = pDoc->getIDocumentMarkAccess()->findMark(rRefMark);
     863         461 :             if(ppMark != pDoc->getIDocumentMarkAccess()->getAllMarksEnd())
     864             :             {
     865         461 :                 const ::sw::mark::IMark* pBkmk = ppMark->get();
     866         461 :                 const SwPosition* pPos = &pBkmk->GetMarkStart();
     867             : 
     868         461 :                 pTxtNd = pPos->nNode.GetNode().GetTxtNode();
     869         461 :                 *pStt = pPos->nContent.GetIndex();
     870         461 :                 if(pEnd)
     871             :                 {
     872         461 :                     if(!pBkmk->IsExpanded())
     873             :                     {
     874         460 :                         *pEnd = *pStt;
     875             :                         // #i81002#
     876         460 :                         if(dynamic_cast< ::sw::mark::CrossRefBookmark const *>(pBkmk))
     877             :                         {
     878             :                             OSL_ENSURE( pTxtNd,
     879             :                                     "<SwGetRefFieldType::FindAnchor(..)> - node marked by cross-reference bookmark isn't a text node --> crash" );
     880         460 :                             *pEnd = pTxtNd->Len();
     881             :                         }
     882             :                     }
     883           1 :                     else if(pBkmk->GetOtherMarkPos().nNode == pBkmk->GetMarkPos().nNode)
     884           1 :                         *pEnd = pBkmk->GetMarkEnd().nContent.GetIndex();
     885             :                     else
     886           0 :                         *pEnd = -1;
     887             :                 }
     888             :             }
     889             :         }
     890         461 :         break;
     891             : 
     892             :     case REF_OUTLINE:
     893           0 :         break;
     894             : 
     895             :     case REF_FOOTNOTE:
     896             :     case REF_ENDNOTE:
     897             :         {
     898           0 :             sal_uInt16 n, nFtnCnt = pDoc->GetFtnIdxs().size();
     899             :             SwTxtFtn* pFtnIdx;
     900           0 :             for( n = 0; n < nFtnCnt; ++n )
     901           0 :                 if( nSeqNo == (pFtnIdx = pDoc->GetFtnIdxs()[ n ])->GetSeqRefNo() )
     902             :                 {
     903           0 :                     SwNodeIndex* pIdx = pFtnIdx->GetStartNode();
     904           0 :                     if( pIdx )
     905             :                     {
     906           0 :                         SwNodeIndex aIdx( *pIdx, 1 );
     907           0 :                         if( 0 == ( pTxtNd = aIdx.GetNode().GetTxtNode()))
     908           0 :                             pTxtNd = (SwTxtNode*)pDoc->GetNodes().GoNext( &aIdx );
     909             :                     }
     910           0 :                     *pStt = 0;
     911           0 :                     if( pEnd )
     912           0 :                         *pEnd = 0;
     913           0 :                     break;
     914             :                 }
     915             :         }
     916           0 :         break;
     917             :     }
     918             : 
     919         461 :     return pTxtNd;
     920             : }
     921             : 
     922          15 : struct _RefIdsMap
     923             : {
     924             : private:
     925             :     OUString aName;
     926             :     std::set<sal_uInt16> aIds;
     927             :     std::set<sal_uInt16> aDstIds;
     928             :     std::map<sal_uInt16, sal_uInt16> sequencedIds; /// ID numbers sorted by sequence number.
     929             :     bool bInit;
     930             : 
     931             :     void       Init(SwDoc& rDoc, SwDoc& rDestDoc, bool bField );
     932             :     void       GetNoteIdsFromDoc( SwDoc& rDoc, std::set<sal_uInt16> &rIds );
     933             :     void       GetFieldIdsFromDoc( SwDoc& rDoc, std::set<sal_uInt16> &rIds );
     934             :     void       AddId( sal_uInt16 id, sal_uInt16 seqNum );
     935             :     sal_uInt16 GetFirstUnusedId( std::set<sal_uInt16> &rIds );
     936             : 
     937             : public:
     938          15 :     _RefIdsMap( const OUString& rName ) : aName( rName ), bInit( false ) {}
     939             : 
     940             :     void Check( SwDoc& rDoc, SwDoc& rDestDoc, SwGetRefField& rFld, bool bField );
     941             : 
     942           0 :     OUString GetName() { return aName; }
     943             : };
     944             : 
     945             : typedef boost::ptr_vector<_RefIdsMap> _RefIdsMaps;
     946             : 
     947             : /// Get a sorted list of the field IDs from a document.
     948             : /// @param[in]     rDoc The document to search.
     949             : /// @param[in,out] rIds The list of IDs found in the document.
     950           0 : void _RefIdsMap::GetFieldIdsFromDoc( SwDoc& rDoc, std::set<sal_uInt16> &rIds)
     951             : {
     952           0 :     SwFieldType *const pType = rDoc.GetFldType(RES_SETEXPFLD, aName, false);
     953             : 
     954           0 :     if (!pType)
     955           0 :         return;
     956             : 
     957           0 :     SwIterator<SwFmtFld,SwFieldType> aIter( *pType );
     958           0 :     for (SwFmtFld const* pF = aIter.First(); pF; pF = aIter.Next())
     959             :     {
     960           0 :         if (pF->GetTxtFld())
     961             :         {
     962           0 :             SwTxtNode const*const pNd = pF->GetTxtFld()->GetpTxtNode();
     963           0 :             if (pNd && pNd->GetNodes().IsDocNodes())
     964             :             {
     965           0 :                 rIds.insert(static_cast<SwSetExpField const*>(pF->GetField())
     966           0 :                                 ->GetSeqNumber());
     967             :             }
     968             :         }
     969           0 :     }
     970             : }
     971             : 
     972             : /// Get a sorted list of the footnote/endnote IDs from a document.
     973             : /// @param[in]     rDoc The document to search.
     974             : /// @param[in,out] rIds The list of IDs found in the document.
     975           0 : void _RefIdsMap::GetNoteIdsFromDoc( SwDoc& rDoc, std::set<sal_uInt16> &rIds)
     976             : {
     977           0 :     for( sal_uInt16 n = rDoc.GetFtnIdxs().size(); n; )
     978           0 :         rIds.insert( rDoc.GetFtnIdxs()[ --n ]->GetSeqRefNo() );
     979           0 : }
     980             : 
     981             : /// Initialise the aIds and aDestIds collections from the source documents.
     982             : /// @param[in] rDoc     The source document.
     983             : /// @param[in] rDestDoc The destination document.
     984             : /// @param[in] bField   True if we're interested in all fields, false for footnotes.
     985           0 : void _RefIdsMap::Init( SwDoc& rDoc, SwDoc& rDestDoc, bool bField )
     986             : {
     987           0 :     if( bInit )
     988           0 :         return;
     989             : 
     990           0 :     if( bField )
     991             :     {
     992           0 :         GetFieldIdsFromDoc( rDestDoc, aIds );
     993           0 :         GetFieldIdsFromDoc( rDoc, aDstIds );
     994             : 
     995             :         // Map all the new src fields to the next available unused id
     996           0 :         for ( std::set<sal_uInt16>::iterator pIt = aDstIds.begin(); pIt != aDstIds.end(); ++pIt )
     997           0 :             AddId( GetFirstUnusedId(aIds), *pIt );
     998             : 
     999             :         // Change the Sequence number of all SetExp fields in the source document
    1000           0 :         SwFieldType* pType = rDoc.GetFldType( RES_SETEXPFLD, aName, false );
    1001           0 :         if( pType )
    1002             :         {
    1003           0 :             SwIterator<SwFmtFld,SwFieldType> aIter( *pType );
    1004           0 :             for( SwFmtFld* pF = aIter.First(); pF; pF = aIter.Next() )
    1005           0 :                 if( pF->GetTxtFld() )
    1006             :                 {
    1007             :                     SwSetExpField *const pSetExp(
    1008           0 :                             static_cast<SwSetExpField *>(pF->GetField()));
    1009           0 :                     sal_uInt16 const n = pSetExp->GetSeqNumber();
    1010           0 :                     pSetExp->SetSeqNumber( sequencedIds[n] );
    1011           0 :                 }
    1012             :         }
    1013             :     }
    1014             :     else
    1015             :     {
    1016           0 :         GetNoteIdsFromDoc( rDestDoc, aIds );
    1017           0 :         GetNoteIdsFromDoc( rDoc, aDstIds );
    1018             :     }
    1019           0 :     bInit = true;
    1020             : }
    1021             : 
    1022             : /// Get the lowest number unused in the passed set.
    1023             : /// @param[in] rIds The set of used ID numbers.
    1024             : /// @returns The lowest number unused by the passed set
    1025           0 : sal_uInt16 _RefIdsMap::GetFirstUnusedId( std::set<sal_uInt16> &rIds )
    1026             : {
    1027           0 :     sal_uInt16 num(0);
    1028           0 :     std::set<sal_uInt16>::iterator it;
    1029             : 
    1030           0 :     for( it = rIds.begin(); it != rIds.end(); ++it )
    1031             :     {
    1032           0 :         if( num != *it )
    1033             :         {
    1034           0 :             return num;
    1035             :         }
    1036           0 :         ++num;
    1037             :     }
    1038           0 :     return num;
    1039             : }
    1040             : 
    1041             : /// Add a new ID and sequence number to the "occupied" collection.
    1042             : /// @param[in] id     The ID number.
    1043             : /// @param[in] seqNum The sequence number.
    1044           0 : void _RefIdsMap::AddId( sal_uInt16 id, sal_uInt16 seqNum )
    1045             : {
    1046           0 :     aIds.insert( id );
    1047           0 :     sequencedIds[ seqNum ] = id;
    1048           0 : }
    1049             : 
    1050           0 : void _RefIdsMap::Check( SwDoc& rDoc, SwDoc& rDestDoc, SwGetRefField& rFld,
    1051             :                         bool bField )
    1052             : {
    1053           0 :     Init( rDoc, rDestDoc, bField);
    1054             : 
    1055           0 :     sal_uInt16 nSeqNo = rFld.GetSeqNo();
    1056             : 
    1057             :     // Check if the number is used in both documents
    1058             :     // Note: For fields, aIds contains both the ids of SetExp from rDestDoc
    1059             :     // and the targets of the already remapped ones from rDoc.
    1060             :     // It is possible that aDstIds contains numbers that aIds does not contain!
    1061             :     // For example, copying a selection to clipboard that does not contain
    1062             :     // the first SwSetExpField will result in id 0 missing, then pasting that
    1063             :     // into empty document gives a mapping 1->0 ... N->N-1 (fdo#63553).
    1064           0 :     if (aIds.count(nSeqNo) || aDstIds.count(nSeqNo))
    1065             :     {
    1066             :         // Number already taken, so need a new one.
    1067           0 :         if( sequencedIds.count(nSeqNo) )
    1068           0 :             rFld.SetSeqNo( sequencedIds[nSeqNo] );
    1069             :         else
    1070             :         {
    1071             :             assert(!bField || !aDstIds.count(nSeqNo)); // postcond of Init
    1072             : 
    1073           0 :             sal_uInt16 n = GetFirstUnusedId( aIds );
    1074             : 
    1075             :             // register the new SeqNo, so that it's "in use"
    1076           0 :             AddId( n, nSeqNo );
    1077           0 :             rFld.SetSeqNo( n );
    1078             : 
    1079             :             // and move the footnotes/endnotes to the new ID
    1080           0 :             if( !bField )
    1081             :             {
    1082             :                 SwTxtFtn* pFtnIdx;
    1083           0 :                 for( sal_uInt16 i = 0, nCnt = rDoc.GetFtnIdxs().size(); i < nCnt; ++i )
    1084           0 :                     if( nSeqNo == (pFtnIdx = rDoc.GetFtnIdxs()[ i ])->GetSeqRefNo() )
    1085             :                     {
    1086           0 :                         pFtnIdx->SetSeqNo( n );
    1087           0 :                         break;
    1088             :                     }
    1089             :             }
    1090             :         }
    1091             :     }
    1092             :     else
    1093             :     {
    1094           0 :         AddId( nSeqNo, nSeqNo ); // this requires that nSeqNo is unused in both!
    1095             :     }
    1096           0 : }
    1097             : 
    1098          15 : void SwGetRefFieldType::MergeWithOtherDoc( SwDoc& rDestDoc )
    1099             : {
    1100          15 :     if( &rDestDoc != pDoc )
    1101             :     {
    1102             :         // then there are RefFields in the DescDox - so all RefFields in the SourceDoc
    1103             :         // need to be converted to have unique IDs for both documents
    1104          15 :         _RefIdsMap aFntMap( aEmptyOUStr );
    1105          30 :         _RefIdsMaps aFldMap;
    1106             : 
    1107          30 :         SwIterator<SwFmtFld,SwFieldType> aIter( *this );
    1108          15 :         for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() )
    1109             :         {
    1110           0 :             SwGetRefField& rRefFld = *(SwGetRefField*)pFld->GetField();
    1111           0 :             switch( rRefFld.GetSubType() )
    1112             :             {
    1113             :             case REF_SEQUENCEFLD:
    1114             :                 {
    1115           0 :                     _RefIdsMap* pMap = 0;
    1116           0 :                     for( sal_uInt16 n = aFldMap.size(); n; )
    1117             :                     {
    1118           0 :                         if( aFldMap[ --n ].GetName()==rRefFld.GetSetRefName() )
    1119             :                         {
    1120           0 :                             pMap = &aFldMap[ n ];
    1121           0 :                             break;
    1122             :                         }
    1123             :                     }
    1124           0 :                     if( !pMap )
    1125             :                     {
    1126           0 :                         pMap = new _RefIdsMap( rRefFld.GetSetRefName() );
    1127           0 :                         aFldMap.push_back( pMap );
    1128             :                     }
    1129             : 
    1130           0 :                     pMap->Check( *pDoc, rDestDoc, rRefFld, true );
    1131             :                 }
    1132           0 :                 break;
    1133             : 
    1134             :             case REF_FOOTNOTE:
    1135             :             case REF_ENDNOTE:
    1136           0 :                 aFntMap.Check( *pDoc, rDestDoc, rRefFld, false );
    1137           0 :                 break;
    1138             :             }
    1139          15 :         }
    1140             :     }
    1141          15 : }
    1142             : 
    1143             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10