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

Generated by: LCOV version 1.11