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