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: */
|