Update ooo320-m1
[ooovba.git] / sw / source / core / fields / reffld.cxx
blob7204947d1a61869dfab4c970aca51f017783283f
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: reffld.cxx,v $
10 * $Revision: 1.27 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #define _SVSTDARR_USHORTSSORT
36 #define _SVSTDARR_USHORTS
37 #include <svtools/svstdarr.hxx>
38 #include <com/sun/star/text/ReferenceFieldPart.hpp>
39 #include <com/sun/star/text/ReferenceFieldSource.hpp>
40 #include <unotools/localedatawrapper.hxx>
41 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
42 #include <comphelper/processfactory.hxx>
43 #include <svx/unolingu.hxx>
44 #include <doc.hxx>
45 #include <pam.hxx>
46 #include <cntfrm.hxx>
47 #include <pagefrm.hxx>
48 #include <docary.hxx>
49 #include <fmtfld.hxx>
50 #include <txtfld.hxx>
51 #include <txtftn.hxx>
52 #include <fmtrfmrk.hxx>
53 #include <txtrfmrk.hxx>
54 #include <fmtftn.hxx>
55 #include <ndtxt.hxx>
56 #include <chpfld.hxx>
57 #include <reffld.hxx>
58 #include <expfld.hxx>
59 #include <txtfrm.hxx>
60 #include <flyfrm.hxx>
61 #include <pagedesc.hxx>
62 #include <IMark.hxx>
63 // --> OD 2007-10-18 #i81002#
64 #include <crossrefbookmark.hxx>
65 // <--
66 #include <ftnidx.hxx>
67 #include <viewsh.hxx>
68 #ifndef _UNOFLDMID_H
69 #include <unofldmid.h>
70 #endif
71 #include <SwStyleNameMapper.hxx>
72 #include <shellres.hxx>
73 #include <poolfmt.hxx>
74 #ifndef _POOLFMT_HRC
75 #include <poolfmt.hrc>
76 #endif
77 #ifndef _COMCORE_HRC
78 #include <comcore.hrc>
79 #endif
80 #include <numrule.hxx>
81 #include <SwNodeNum.hxx>
83 using namespace ::com::sun::star;
84 using namespace ::com::sun::star::text;
85 using namespace ::com::sun::star::lang;
86 using ::rtl::OUString;
88 extern void InsertSort( SvUShorts& rArr, USHORT nIdx, USHORT* pInsPos = 0 );
90 void lcl_GetLayTree( const SwFrm* pFrm, SvPtrarr& rArr )
92 while( pFrm )
94 if( pFrm->IsBodyFrm() ) // soll uns nicht weiter interessieren
95 pFrm = pFrm->GetUpper();
96 else
98 void* p = (void*)pFrm;
99 rArr.Insert( p, rArr.Count() );
101 // bei der Seite ist schluss
102 if( pFrm->IsPageFrm() )
103 break;
105 if( pFrm->IsFlyFrm() )
106 pFrm = ((SwFlyFrm*)pFrm)->GetAnchorFrm();
107 else
108 pFrm = pFrm->GetUpper();
114 BOOL IsFrameBehind( const SwTxtNode& rMyNd, USHORT nMySttPos,
115 const SwTxtNode& rBehindNd, USHORT nSttPos )
117 const SwTxtFrm *pMyFrm = (SwTxtFrm*)rMyNd.GetFrm(0,0,FALSE),
118 *pFrm = (SwTxtFrm*)rBehindNd.GetFrm(0,0,FALSE);
120 while( pFrm && !pFrm->IsInside( nSttPos ) )
121 pFrm = (SwTxtFrm*)pFrm->GetFollow();
122 while( pMyFrm && !pMyFrm->IsInside( nMySttPos ) )
123 pMyFrm = (SwTxtFrm*)pMyFrm->GetFollow();
125 if( !pFrm || !pMyFrm || pFrm == pMyFrm )
126 return FALSE;
128 SvPtrarr aRefArr( 10, 10 ), aArr( 10, 10 );
129 ::lcl_GetLayTree( pFrm, aRefArr );
130 ::lcl_GetLayTree( pMyFrm, aArr );
132 USHORT nRefCnt = aRefArr.Count() - 1, nCnt = aArr.Count() - 1;
133 BOOL bVert = FALSE;
134 BOOL bR2L = FALSE;
136 // solange bis ein Frame ungleich ist ?
137 while( nRefCnt && nCnt && aRefArr[ nRefCnt ] == aArr[ nCnt ] )
139 const SwFrm* pTmpFrm = (const SwFrm*)aArr[ nCnt ];
140 bVert = pTmpFrm->IsVertical();
141 bR2L = pTmpFrm->IsRightToLeft();
142 --nCnt, --nRefCnt;
145 // sollte einer der Counter ueberlaeufen?
146 if( aRefArr[ nRefCnt ] == aArr[ nCnt ] )
148 if( nCnt )
149 --nCnt;
150 else
151 --nRefCnt;
154 const SwFrm* pRefFrm = (const SwFrm*)aRefArr[ nRefCnt ];
155 const SwFrm* pFldFrm = (const SwFrm*)aArr[ nCnt ];
157 // unterschiedliche Frames, dann ueberpruefe deren Y-/X-Position
158 BOOL bRefIsLower = FALSE;
159 if( ( FRM_COLUMN | FRM_CELL ) & pFldFrm->GetType() ||
160 ( FRM_COLUMN | FRM_CELL ) & pRefFrm->GetType() )
162 if( pFldFrm->GetType() == pRefFrm->GetType() )
164 // hier ist die X-Pos wichtiger!
165 if( bVert )
167 if( bR2L )
168 bRefIsLower = pRefFrm->Frm().Top() < pFldFrm->Frm().Top() ||
169 ( pRefFrm->Frm().Top() == pFldFrm->Frm().Top() &&
170 pRefFrm->Frm().Left() < pFldFrm->Frm().Left() );
171 else
172 bRefIsLower = pRefFrm->Frm().Top() < pFldFrm->Frm().Top() ||
173 ( pRefFrm->Frm().Top() == pFldFrm->Frm().Top() &&
174 pRefFrm->Frm().Left() > pFldFrm->Frm().Left() );
176 else if( bR2L )
177 bRefIsLower = pRefFrm->Frm().Left() > pFldFrm->Frm().Left() ||
178 ( pRefFrm->Frm().Left() == pFldFrm->Frm().Left() &&
179 pRefFrm->Frm().Top() < pFldFrm->Frm().Top() );
180 else
181 bRefIsLower = pRefFrm->Frm().Left() < pFldFrm->Frm().Left() ||
182 ( pRefFrm->Frm().Left() == pFldFrm->Frm().Left() &&
183 pRefFrm->Frm().Top() < pFldFrm->Frm().Top() );
184 pRefFrm = 0;
186 else if( ( FRM_COLUMN | FRM_CELL ) & pFldFrm->GetType() )
187 pFldFrm = (const SwFrm*)aArr[ nCnt - 1 ];
188 else
189 pRefFrm = (const SwFrm*)aRefArr[ nRefCnt - 1 ];
192 if( pRefFrm ) // als Flag missbrauchen
194 if( bVert )
196 if( bR2L )
197 bRefIsLower = pRefFrm->Frm().Left() < pFldFrm->Frm().Left() ||
198 ( pRefFrm->Frm().Left() == pFldFrm->Frm().Left() &&
199 pRefFrm->Frm().Top() < pFldFrm->Frm().Top() );
200 else
201 bRefIsLower = pRefFrm->Frm().Left() > pFldFrm->Frm().Left() ||
202 ( pRefFrm->Frm().Left() == pFldFrm->Frm().Left() &&
203 pRefFrm->Frm().Top() < pFldFrm->Frm().Top() );
205 else if( bR2L )
206 bRefIsLower = pRefFrm->Frm().Top() < pFldFrm->Frm().Top() ||
207 ( pRefFrm->Frm().Top() == pFldFrm->Frm().Top() &&
208 pRefFrm->Frm().Left() > pFldFrm->Frm().Left() );
209 else
210 bRefIsLower = pRefFrm->Frm().Top() < pFldFrm->Frm().Top() ||
211 ( pRefFrm->Frm().Top() == pFldFrm->Frm().Top() &&
212 pRefFrm->Frm().Left() < pFldFrm->Frm().Left() );
214 return bRefIsLower;
217 /*--------------------------------------------------------------------
218 Beschreibung: Referenzen holen
219 --------------------------------------------------------------------*/
222 SwGetRefField::SwGetRefField( SwGetRefFieldType* pFldType,
223 const String& rSetRef, USHORT nSubTyp,
224 USHORT nSeqenceNo, ULONG nFmt )
225 : SwField( pFldType, nFmt ),
226 sSetRefName( rSetRef ),
227 nSubType( nSubTyp ),
228 nSeqNo( nSeqenceNo )
232 SwGetRefField::~SwGetRefField()
236 String SwGetRefField::GetDescription() const
238 return SW_RES(STR_REFERENCE);
241 USHORT SwGetRefField::GetSubType() const
243 return nSubType;
246 void SwGetRefField::SetSubType( USHORT n )
248 nSubType = n;
251 // --> OD 2007-11-09 #i81002#
252 bool SwGetRefField::IsRefToHeadingCrossRefBookmark() const
254 return GetSubType() == REF_BOOKMARK &&
255 ::sw::mark::CrossRefHeadingBookmark::IsLegalName(sSetRefName);
258 bool SwGetRefField::IsRefToNumItemCrossRefBookmark() const
260 return GetSubType() == REF_BOOKMARK &&
261 ::sw::mark::CrossRefNumItemBookmark::IsLegalName(sSetRefName);
264 const SwTxtNode* SwGetRefField::GetReferencedTxtNode() const
266 SwDoc* pDoc = dynamic_cast<SwGetRefFieldType*>(GetTyp())->GetDoc();
267 USHORT nDummy = USHRT_MAX;
268 return SwGetRefFieldType::FindAnchor( pDoc, sSetRefName, nSubType, nSeqNo, &nDummy );
270 // <--
271 // --> OD 2008-01-09 #i85090#
272 String SwGetRefField::GetExpandedTxtOfReferencedTxtNode() const
274 const SwTxtNode* pReferencedTxtNode( GetReferencedTxtNode() );
275 return pReferencedTxtNode
276 ? pReferencedTxtNode->GetExpandTxt( 0, STRING_LEN, true, true )
277 : aEmptyStr;
280 String SwGetRefField::Expand() const
282 return sTxt;
286 String SwGetRefField::GetCntnt(BOOL bName) const
288 if( !bName )
289 return Expand();
291 String aStr(GetTyp()->GetName());
292 aStr += ' ';
293 aStr += sSetRefName;
294 return aStr;
297 // --> OD 2007-09-07 #i81002# - parameter <pFldTxtAttr> added
298 void SwGetRefField::UpdateField( const SwTxtFld* pFldTxtAttr )
300 sTxt.Erase();
302 SwDoc* pDoc = ((SwGetRefFieldType*)GetTyp())->GetDoc();
303 USHORT nStt = USHRT_MAX;
304 USHORT nEnd = USHRT_MAX;
305 SwTxtNode* pTxtNd = SwGetRefFieldType::FindAnchor( pDoc, sSetRefName,
306 nSubType, nSeqNo, &nStt, &nEnd );
307 if ( !pTxtNd )
309 sTxt = ViewShell::GetShellRes()->aGetRefFld_RefItemNotFound;
310 return ;
313 switch( GetFormat() )
315 case REF_CONTENT:
316 case REF_ONLYNUMBER:
317 case REF_ONLYCAPTION:
318 case REF_ONLYSEQNO:
320 switch( nSubType )
322 case REF_SEQUENCEFLD:
323 nEnd = pTxtNd->GetTxt().Len();
324 switch( GetFormat() )
326 case REF_ONLYNUMBER:
327 if( nStt + 1 < nEnd )
328 nEnd = nStt + 1;
329 nStt = 0;
330 break;
332 case REF_ONLYCAPTION:
334 const SwTxtAttr* const pTxtAttr =
335 pTxtNd->GetTxtAttrForCharAt(nStt, RES_TXTATR_FIELD);
336 if( pTxtAttr )
337 nStt = SwGetExpField::GetReferenceTextPos(
338 pTxtAttr->GetFld(), *pDoc );
339 else if( nStt + 1 < nEnd )
340 ++nStt;
342 break;
344 case REF_ONLYSEQNO:
345 if( nStt + 1 < nEnd )
346 nEnd = nStt + 1;
347 break;
349 default:
350 nStt = 0;
351 break;
353 break;
355 case REF_BOOKMARK:
356 if( USHRT_MAX == nEnd )
358 // Text steht ueber verschiedene Nodes verteilt.
359 // Gesamten Text oder nur bis zum Ende vom Node?
360 nEnd = pTxtNd->GetTxt().Len();
362 break;
364 case REF_OUTLINE:
365 break;
367 case REF_FOOTNOTE:
368 case REF_ENDNOTE:
370 // die Nummer oder den NumString besorgen
371 USHORT n, nFtnCnt = pDoc->GetFtnIdxs().Count();
372 SwTxtFtn* pFtnIdx;
373 for( n = 0; n < nFtnCnt; ++n )
374 if( nSeqNo == (pFtnIdx = pDoc->GetFtnIdxs()[ n ])->GetSeqRefNo() )
376 sTxt = pFtnIdx->GetFtn().GetViewNumStr( *pDoc );
377 break;
379 nStt = nEnd; // kein Bereich, der String ist fertig
381 break;
384 if( nStt != nEnd ) // ein Bereich?
386 sTxt = pTxtNd->GetExpandTxt( nStt, nEnd - nStt );
388 // alle Sonderzeichen entfernen (durch Blanks ersetzen):
389 if( sTxt.Len() )
391 sTxt.EraseAllChars( 0xad );
392 for( sal_Unicode* p = sTxt.GetBufferAccess(); *p; ++p )
394 if( *p < 0x20 )
395 *p = 0x20;
396 else if(*p == 0x2011)
397 *p = '-';
402 break;
404 case REF_PAGE:
405 case REF_PAGE_PGDESC:
407 const SwTxtFrm* pFrm = (SwTxtFrm*)pTxtNd->GetFrm(0,0,FALSE),
408 *pSave = pFrm;
409 while( pFrm && !pFrm->IsInside( nStt ) )
410 pFrm = (SwTxtFrm*)pFrm->GetFollow();
412 if( pFrm || 0 != ( pFrm = pSave ))
414 USHORT nPageNo = pFrm->GetVirtPageNum();
415 const SwPageFrm *pPage;
416 if( REF_PAGE_PGDESC == GetFormat() &&
417 0 != ( pPage = pFrm->FindPageFrm() ) &&
418 pPage->GetPageDesc() )
419 sTxt = pPage->GetPageDesc()->GetNumType().GetNumStr( nPageNo );
420 else
421 sTxt = String::CreateFromInt32(nPageNo);
424 break;
426 case REF_CHAPTER:
428 // ein bischen trickreich: suche irgend einen Frame
429 const SwFrm* pFrm = pTxtNd->GetFrm();
430 if( pFrm )
432 SwChapterFieldType aFldTyp;
433 SwChapterField aFld( &aFldTyp, 0 );
434 aFld.SetLevel( MAXLEVEL - 1 );
435 aFld.ChangeExpansion( pFrm, pTxtNd, TRUE );
436 sTxt = aFld.GetNumber();
439 break;
441 case REF_UPDOWN:
443 // --> OD 2007-09-07 #i81002#
444 // simplified: use parameter <pFldTxtAttr>
445 if( !pFldTxtAttr || !pFldTxtAttr->GetpTxtNode() )
446 break;
448 LocaleDataWrapper aLocaleData(
449 ::comphelper::getProcessServiceFactory(),
450 SvxCreateLocale( GetLanguage() ) );
452 // erstmal ein "Kurz" - Test - falls beide im selben
453 // Node stehen!
454 if( pFldTxtAttr->GetpTxtNode() == pTxtNd )
456 sTxt = nStt < *pFldTxtAttr->GetStart()
457 ? aLocaleData.getAboveWord()
458 : aLocaleData.getBelowWord();
459 break;
462 sTxt = ::IsFrameBehind( *pFldTxtAttr->GetpTxtNode(), *pFldTxtAttr->GetStart(),
463 *pTxtNd, nStt )
464 ? aLocaleData.getAboveWord()
465 : aLocaleData.getBelowWord();
467 break;
468 // --> OD 2007-08-24 #i81002#
469 case REF_NUMBER:
470 case REF_NUMBER_NO_CONTEXT:
471 case REF_NUMBER_FULL_CONTEXT:
473 if ( pFldTxtAttr && pFldTxtAttr->GetpTxtNode() )
475 sTxt = MakeRefNumStr( pFldTxtAttr->GetTxtNode(), *pTxtNd, GetFormat() );
478 break;
479 // <--
480 default:
481 DBG_ERROR("<SwGetRefField::UpdateField(..)> - unknown format type");
485 // --> OD 2007-09-06 #i81002#
486 String SwGetRefField::MakeRefNumStr( const SwTxtNode& rTxtNodeOfField,
487 const SwTxtNode& rTxtNodeOfReferencedItem,
488 const sal_uInt32 nRefNumFormat ) const
490 if ( rTxtNodeOfReferencedItem.HasNumber() &&
491 rTxtNodeOfReferencedItem.IsCountedInList() )
493 ASSERT( rTxtNodeOfReferencedItem.GetNum(),
494 "<SwGetRefField::MakeRefNumStr(..)> - referenced paragraph has number, but no <SwNodeNum> instance --> please inform OD!" );
496 // Determine, up to which level the superior list labels have to be
497 // included - default is to include all superior list labels.
498 sal_uInt8 nRestrictInclToThisLevel( 0 );
499 // Determine for format REF_NUMBER the level, up to which the superior
500 // list labels have to be restricted, if the text node of the reference
501 // field and the text node of the referenced item are in the same
502 // document context.
503 if ( nRefNumFormat == REF_NUMBER &&
504 rTxtNodeOfField.FindFlyStartNode()
505 == rTxtNodeOfReferencedItem.FindFlyStartNode() &&
506 rTxtNodeOfField.FindFootnoteStartNode()
507 == rTxtNodeOfReferencedItem.FindFootnoteStartNode() &&
508 rTxtNodeOfField.FindHeaderStartNode()
509 == rTxtNodeOfReferencedItem.FindHeaderStartNode() &&
510 rTxtNodeOfField.FindFooterStartNode()
511 == rTxtNodeOfReferencedItem.FindFooterStartNode() )
513 const SwNodeNum* pNodeNumForTxtNodeOfField( 0 );
514 if ( rTxtNodeOfField.HasNumber() &&
515 rTxtNodeOfField.GetNumRule() == rTxtNodeOfReferencedItem.GetNumRule() )
517 pNodeNumForTxtNodeOfField = rTxtNodeOfField.GetNum();
519 else
521 pNodeNumForTxtNodeOfField =
522 rTxtNodeOfReferencedItem.GetNum()->GetPrecedingNodeNumOf( rTxtNodeOfField );
524 if ( pNodeNumForTxtNodeOfField )
526 const SwNumberTree::tNumberVector rFieldNumVec = pNodeNumForTxtNodeOfField->GetNumberVector();
527 const SwNumberTree::tNumberVector rRefItemNumVec = rTxtNodeOfReferencedItem.GetNum()->GetNumberVector();
528 sal_uInt8 nLevel( 0 );
529 while ( nLevel < rFieldNumVec.size() && nLevel < rRefItemNumVec.size() )
531 if ( rRefItemNumVec[nLevel] == rFieldNumVec[nLevel] )
533 nRestrictInclToThisLevel = nLevel + 1;
535 else
537 break;
539 ++nLevel;
544 // Determine, if superior list labels have to be included
545 const bool bInclSuperiorNumLabels(
546 ( nRestrictInclToThisLevel < rTxtNodeOfReferencedItem.GetActualListLevel() &&
547 ( nRefNumFormat == REF_NUMBER || nRefNumFormat == REF_NUMBER_FULL_CONTEXT ) ) );
549 ASSERT( rTxtNodeOfReferencedItem.GetNumRule(),
550 "<SwGetRefField::MakeRefNumStr(..)> - referenced numbered paragraph has no numbering rule set --> please inform OD!" );
551 return rTxtNodeOfReferencedItem.GetNumRule()->MakeRefNumString(
552 *(rTxtNodeOfReferencedItem.GetNum()),
553 bInclSuperiorNumLabels,
554 nRestrictInclToThisLevel );
557 return String();
559 // <--
561 SwField* SwGetRefField::Copy() const
563 SwGetRefField* pFld = new SwGetRefField( (SwGetRefFieldType*)GetTyp(),
564 sSetRefName, nSubType,
565 nSeqNo, GetFormat() );
566 pFld->sTxt = sTxt;
567 return pFld;
570 /*--------------------------------------------------------------------
571 Beschreibung: ReferenzName holen
572 --------------------------------------------------------------------*/
575 const String& SwGetRefField::GetPar1() const
577 return sSetRefName;
581 void SwGetRefField::SetPar1( const String& rName )
583 sSetRefName = rName;
587 String SwGetRefField::GetPar2() const
589 return Expand();
592 /*-----------------06.03.98 13:34-------------------
594 --------------------------------------------------*/
595 BOOL SwGetRefField::QueryValue( uno::Any& rAny, USHORT nWhichId ) const
597 switch( nWhichId )
599 case FIELD_PROP_USHORT1:
601 sal_Int16 nPart = 0;
602 switch(GetFormat())
604 case REF_PAGE : nPart = ReferenceFieldPart::PAGE ; break;
605 case REF_CHAPTER : nPart = ReferenceFieldPart::CHAPTER ; break;
606 case REF_CONTENT : nPart = ReferenceFieldPart::TEXT ; break;
607 case REF_UPDOWN : nPart = ReferenceFieldPart::UP_DOWN ; break;
608 case REF_PAGE_PGDESC: nPart = ReferenceFieldPart::PAGE_DESC ; break;
609 case REF_ONLYNUMBER : nPart = ReferenceFieldPart::CATEGORY_AND_NUMBER ; break;
610 case REF_ONLYCAPTION: nPart = ReferenceFieldPart::ONLY_CAPTION ; break;
611 case REF_ONLYSEQNO : nPart = ReferenceFieldPart::ONLY_SEQUENCE_NUMBER; break;
612 // --> OD 2007-09-06 #i81002#
613 case REF_NUMBER: nPart = ReferenceFieldPart::NUMBER; break;
614 case REF_NUMBER_NO_CONTEXT: nPart = ReferenceFieldPart::NUMBER_NO_CONTEXT; break;
615 case REF_NUMBER_FULL_CONTEXT: nPart = ReferenceFieldPart::NUMBER_FULL_CONTEXT; break;
616 // <--
618 rAny <<= nPart;
620 break;
621 case FIELD_PROP_USHORT2:
623 sal_Int16 nSource = 0;
624 switch(nSubType)
626 case REF_SETREFATTR : nSource = ReferenceFieldSource::REFERENCE_MARK; break;
627 case REF_SEQUENCEFLD: nSource = ReferenceFieldSource::SEQUENCE_FIELD; break;
628 case REF_BOOKMARK : nSource = ReferenceFieldSource::BOOKMARK; break;
629 case REF_OUTLINE : DBG_ERROR("not implemented"); break;
630 case REF_FOOTNOTE : nSource = ReferenceFieldSource::FOOTNOTE; break;
631 case REF_ENDNOTE : nSource = ReferenceFieldSource::ENDNOTE; break;
633 rAny <<= nSource;
635 break;
636 case FIELD_PROP_PAR1:
638 String sTmp(GetPar1());
639 if(REF_SEQUENCEFLD == nSubType)
641 sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( sTmp, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
642 switch( nPoolId )
644 case RES_POOLCOLL_LABEL_ABB:
645 case RES_POOLCOLL_LABEL_TABLE:
646 case RES_POOLCOLL_LABEL_FRAME:
647 case RES_POOLCOLL_LABEL_DRAWING:
648 SwStyleNameMapper::FillProgName(nPoolId, sTmp) ;
649 break;
652 rAny <<= rtl::OUString(sTmp);
654 break;
655 case FIELD_PROP_PAR3:
656 rAny <<= rtl::OUString(Expand());
657 break;
658 case FIELD_PROP_SHORT1:
659 rAny <<= (sal_Int16)nSeqNo;
660 break;
661 default:
662 DBG_ERROR("illegal property");
664 return TRUE;
666 /*-----------------06.03.98 13:34-------------------
668 --------------------------------------------------*/
669 BOOL SwGetRefField::PutValue( const uno::Any& rAny, USHORT nWhichId )
671 String sTmp;
672 switch( nWhichId )
674 case FIELD_PROP_USHORT1:
676 sal_Int16 nPart = 0;
677 rAny >>= nPart;
678 switch(nPart)
680 case ReferenceFieldPart::PAGE: nPart = REF_PAGE; break;
681 case ReferenceFieldPart::CHAPTER: nPart = REF_CHAPTER; break;
682 case ReferenceFieldPart::TEXT: nPart = REF_CONTENT; break;
683 case ReferenceFieldPart::UP_DOWN: nPart = REF_UPDOWN; break;
684 case ReferenceFieldPart::PAGE_DESC: nPart = REF_PAGE_PGDESC; break;
685 case ReferenceFieldPart::CATEGORY_AND_NUMBER: nPart = REF_ONLYNUMBER; break;
686 case ReferenceFieldPart::ONLY_CAPTION: nPart = REF_ONLYCAPTION; break;
687 case ReferenceFieldPart::ONLY_SEQUENCE_NUMBER : nPart = REF_ONLYSEQNO; break;
688 // --> OD 2007-09-06 #i81002#
689 case ReferenceFieldPart::NUMBER: nPart = REF_NUMBER; break;
690 case ReferenceFieldPart::NUMBER_NO_CONTEXT: nPart = REF_NUMBER_NO_CONTEXT; break;
691 case ReferenceFieldPart::NUMBER_FULL_CONTEXT: nPart = REF_NUMBER_FULL_CONTEXT; break;
692 // <--
693 default: return FALSE;
695 SetFormat(nPart);
697 break;
698 case FIELD_PROP_USHORT2:
700 sal_Int16 nSource = 0;
701 rAny >>= nSource;
702 switch(nSource)
704 case ReferenceFieldSource::REFERENCE_MARK : nSubType = REF_SETREFATTR ; break;
705 case ReferenceFieldSource::SEQUENCE_FIELD :
707 if(REF_SEQUENCEFLD == nSubType)
708 break;
709 nSubType = REF_SEQUENCEFLD;
710 ConvertProgrammaticToUIName();
712 break;
713 case ReferenceFieldSource::BOOKMARK : nSubType = REF_BOOKMARK ; break;
714 case ReferenceFieldSource::FOOTNOTE : nSubType = REF_FOOTNOTE ; break;
715 case ReferenceFieldSource::ENDNOTE : nSubType = REF_ENDNOTE ; break;
718 break;
719 case FIELD_PROP_PAR1:
721 OUString sTmpStr;
722 rAny >>= sTmpStr;
723 SetPar1(sTmpStr);
724 ConvertProgrammaticToUIName();
726 break;
727 case FIELD_PROP_PAR3:
728 SetExpand( ::GetString( rAny, sTmp ));
729 break;
730 case FIELD_PROP_SHORT1:
732 sal_Int16 nSetSeq = 0;
733 rAny >>= nSetSeq;
734 if(nSetSeq >= 0)
735 nSeqNo = nSetSeq;
737 break;
738 default:
739 DBG_ERROR("illegal property");
741 return TRUE;
743 /* -----------------------------11.01.2002 12:50------------------------------
745 ---------------------------------------------------------------------------*/
746 void SwGetRefField::ConvertProgrammaticToUIName()
748 if(GetTyp() && REF_SEQUENCEFLD == nSubType)
750 SwDoc* pDoc = ((SwGetRefFieldType*)GetTyp())->GetDoc();
751 const String& rPar1 = GetPar1();
752 //don't convert when the name points to an existing field type
753 if(!pDoc->GetFldType(RES_SETEXPFLD, rPar1, false))
755 sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromProgName( rPar1, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
756 USHORT nResId = USHRT_MAX;
757 switch( nPoolId )
759 case RES_POOLCOLL_LABEL_ABB:
760 nResId = STR_POOLCOLL_LABEL_ABB;
761 break;
762 case RES_POOLCOLL_LABEL_TABLE:
763 nResId = STR_POOLCOLL_LABEL_TABLE;
764 break;
765 case RES_POOLCOLL_LABEL_FRAME:
766 nResId = STR_POOLCOLL_LABEL_FRAME;
767 break;
768 case RES_POOLCOLL_LABEL_DRAWING:
769 nResId = STR_POOLCOLL_LABEL_DRAWING;
770 break;
772 if( nResId != USHRT_MAX )
773 SetPar1(SW_RESSTR( nResId ));
777 /*-----------------JP: 18.06.93 -------------------
778 Get-Referenz-Type
779 --------------------------------------------------*/
782 SwGetRefFieldType::SwGetRefFieldType( SwDoc* pDc )
783 : SwFieldType( RES_GETREFFLD ), pDoc( pDc )
787 SwFieldType* SwGetRefFieldType::Copy() const
789 return new SwGetRefFieldType( pDoc );
793 void SwGetRefFieldType::Modify( SfxPoolItem* pOld, SfxPoolItem* pNew )
795 // Update auf alle GetReferenz-Felder
796 if( !pNew && !pOld )
798 SwClientIter aIter( *this );
799 for( SwFmtFld* pFld = (SwFmtFld*)aIter.First( TYPE(SwFmtFld) );
800 pFld; pFld = (SwFmtFld*)aIter.Next() )
802 // nur die GetRef-Felder Updaten
803 //JP 3.4.2001: Task 71231 - we need the correct language
804 SwGetRefField* pGRef = (SwGetRefField*)pFld->GetFld();
805 const SwTxtFld* pTFld;
806 if( !pGRef->GetLanguage() &&
807 0 != ( pTFld = pFld->GetTxtFld()) &&
808 pTFld->GetpTxtNode() )
810 pGRef->SetLanguage( pTFld->GetpTxtNode()->GetLang(
811 *pTFld->GetStart() ) );
814 // --> OD 2007-09-06 #i81002#
815 pGRef->UpdateField( pFld->GetTxtFld() );
816 // <--
819 // weiter an die Text-Felder, diese "Expandieren" den Text
820 SwModify::Modify( pOld, pNew );
823 SwTxtNode* SwGetRefFieldType::FindAnchor( SwDoc* pDoc, const String& rRefMark,
824 USHORT nSubType, USHORT nSeqNo,
825 USHORT* pStt, USHORT* pEnd )
827 ASSERT( pStt, "warum wird keine StartPos abgefragt?" );
829 SwTxtNode* pTxtNd = 0;
830 switch( nSubType )
832 case REF_SETREFATTR:
834 const SwFmtRefMark *pRef = pDoc->GetRefMark( rRefMark );
835 if( pRef && pRef->GetTxtRefMark() )
837 pTxtNd = (SwTxtNode*)&pRef->GetTxtRefMark()->GetTxtNode();
838 *pStt = *pRef->GetTxtRefMark()->GetStart();
839 if( pEnd )
840 *pEnd = *pRef->GetTxtRefMark()->GetAnyEnd();
843 break;
845 case REF_SEQUENCEFLD:
847 SwFieldType* pFldType = pDoc->GetFldType( RES_SETEXPFLD, rRefMark, false );
848 if( pFldType && pFldType->GetDepends() &&
849 nsSwGetSetExpType::GSE_SEQ & ((SwSetExpFieldType*)pFldType)->GetType() )
851 SwClientIter aIter( *pFldType );
852 for( SwFmtFld* pFld = (SwFmtFld*)aIter.First( TYPE(SwFmtFld) );
853 pFld; pFld = (SwFmtFld*)aIter.Next() )
855 if( pFld->GetTxtFld() && nSeqNo ==
856 ((SwSetExpField*)pFld->GetFld())->GetSeqNumber() )
858 SwTxtFld* pTxtFld = pFld->GetTxtFld();
859 pTxtNd = (SwTxtNode*)pTxtFld->GetpTxtNode();
860 *pStt = *pTxtFld->GetStart();
861 if( pEnd )
862 *pEnd = (*pStt) + 1;
863 break;
868 break;
870 case REF_BOOKMARK:
872 IDocumentMarkAccess::const_iterator_t ppMark = pDoc->getIDocumentMarkAccess()->findMark(rRefMark);
873 if(ppMark != pDoc->getIDocumentMarkAccess()->getMarksEnd())
875 const ::sw::mark::IMark* pBkmk = ppMark->get();
876 const SwPosition* pPos = &pBkmk->GetMarkStart();
878 pTxtNd = pDoc->GetNodes()[ pPos->nNode ]->GetTxtNode();
879 *pStt = pPos->nContent.GetIndex();
880 if(pEnd)
882 if(!pBkmk->IsExpanded())
884 *pEnd = *pStt;
885 // --> OD 2007-10-18 #i81002#
886 if(dynamic_cast< ::sw::mark::CrossRefBookmark const *>(pBkmk))
888 ASSERT( pTxtNd,
889 "<SwGetRefFieldType::FindAnchor(..)> - node marked by cross-reference bookmark isn't a text node --> crash" );
890 *pEnd = pTxtNd->Len();
892 // <--
894 else if(pBkmk->GetOtherMarkPos().nNode == pBkmk->GetMarkPos().nNode)
895 *pEnd = pBkmk->GetMarkEnd().nContent.GetIndex();
896 else
897 *pEnd = USHRT_MAX;
901 break;
903 case REF_OUTLINE:
904 break;
906 case REF_FOOTNOTE:
907 case REF_ENDNOTE:
909 USHORT n, nFtnCnt = pDoc->GetFtnIdxs().Count();
910 SwTxtFtn* pFtnIdx;
911 for( n = 0; n < nFtnCnt; ++n )
912 if( nSeqNo == (pFtnIdx = pDoc->GetFtnIdxs()[ n ])->GetSeqRefNo() )
914 SwNodeIndex* pIdx = pFtnIdx->GetStartNode();
915 if( pIdx )
917 SwNodeIndex aIdx( *pIdx, 1 );
918 if( 0 == ( pTxtNd = aIdx.GetNode().GetTxtNode()))
919 pTxtNd = (SwTxtNode*)pDoc->GetNodes().GoNext( &aIdx );
921 *pStt = 0;
922 if( pEnd )
923 *pEnd = 0;
924 break;
927 break;
930 return pTxtNd;
934 struct _RefIdsMap
936 String aName;
937 SvUShortsSort aIds, aDstIds, aIdsMap;
938 SvUShorts aMap;
939 BOOL bInit;
941 _RefIdsMap( const String& rName )
942 : aName( rName ), aIds( 16, 16 ), aIdsMap( 16, 16 ), aMap( 16, 16 ),
943 bInit( FALSE )
946 void Check( SwDoc& rDoc, SwDoc& rDestDoc, SwGetRefField& rFld,
947 BOOL bField = TRUE );
949 BOOL IsInit() const { return bInit; }
952 SV_DECL_PTRARR_DEL( _RefIdsMaps, _RefIdsMap*, 5, 5 )
953 SV_IMPL_PTRARR( _RefIdsMaps, _RefIdsMap* )
955 void _RefIdsMap::Check( SwDoc& rDoc, SwDoc& rDestDoc, SwGetRefField& rFld,
956 BOOL bField )
959 if( !bInit )
961 if( bField )
963 const SwTxtNode* pNd;
964 SwModify* pMod;
965 if( 0 != ( pMod = rDestDoc.GetFldType( RES_SETEXPFLD, aName, false ) ))
967 SwClientIter aIter( *pMod );
968 for( SwFmtFld* pF = (SwFmtFld*)aIter.First( TYPE( SwFmtFld )); pF;
969 pF = (SwFmtFld*)aIter.Next() )
970 if( pF->GetTxtFld() &&
971 0 != ( pNd = pF->GetTxtFld()->GetpTxtNode() ) &&
972 pNd->GetNodes().IsDocNodes() )
973 aIds.Insert( ((SwSetExpField*)pF->GetFld())->GetSeqNumber() );
975 if( 0 != ( pMod = rDoc.GetFldType( RES_SETEXPFLD, aName, false ) ))
977 SwClientIter aIter( *pMod );
978 for( SwFmtFld* pF = (SwFmtFld*)aIter.First( TYPE( SwFmtFld )); pF;
979 pF = (SwFmtFld*)aIter.Next() )
980 if( pF->GetTxtFld() &&
981 0 != ( pNd = pF->GetTxtFld()->GetpTxtNode() ) &&
982 pNd->GetNodes().IsDocNodes() )
983 aDstIds.Insert( ((SwSetExpField*)pF->GetFld())->GetSeqNumber() );
986 else
988 USHORT n;
990 for( n = rDestDoc.GetFtnIdxs().Count(); n; )
991 aIds.Insert( rDestDoc.GetFtnIdxs()[ --n ]->GetSeqRefNo() );
992 for( n = rDoc.GetFtnIdxs().Count(); n; )
993 aDstIds.Insert( rDoc.GetFtnIdxs()[ --n ]->GetSeqRefNo() );
995 bInit = TRUE;
998 // dann teste mal, ob die Nummer schon vergeben ist
999 // oder ob eine neue bestimmt werden muss.
1000 USHORT nPos, nSeqNo = rFld.GetSeqNo();
1001 if( aIds.Seek_Entry( nSeqNo ) && aDstIds.Seek_Entry( nSeqNo ))
1003 // ist schon vergeben, also muss eine neue
1004 // erzeugt werden.
1005 if( aIdsMap.Seek_Entry( nSeqNo, &nPos ))
1006 rFld.SetSeqNo( aMap[ nPos ] );
1007 else
1009 USHORT n;
1011 for( n = 0; n < aIds.Count(); ++n )
1012 if( n != aIds[ n ] )
1013 break;
1015 // die neue SeqNo eintragen, damit die "belegt" ist
1016 aIds.Insert( n );
1017 aIdsMap.Insert( nSeqNo, nPos );
1018 aMap.Insert( n, nPos );
1019 rFld.SetSeqNo( n );
1021 // und noch die Felder oder Fuss-/EndNote auf die neue
1022 // Id umsetzen
1023 if( bField )
1025 SwModify* pMod = rDoc.GetFldType( RES_SETEXPFLD, aName, false );
1026 if( pMod )
1028 SwClientIter aIter( *pMod );
1029 for( SwFmtFld* pF = (SwFmtFld*)aIter.First( TYPE( SwFmtFld )); pF;
1030 pF = (SwFmtFld*)aIter.Next() )
1031 if( pF->GetTxtFld() && nSeqNo ==
1032 ((SwSetExpField*)pF->GetFld())->GetSeqNumber() )
1033 ((SwSetExpField*)pF->GetFld())->SetSeqNumber( n );
1036 else
1038 SwTxtFtn* pFtnIdx;
1039 for( USHORT i = 0, nCnt = rDoc.GetFtnIdxs().Count(); i < nCnt; ++i )
1040 if( nSeqNo == (pFtnIdx = rDoc.GetFtnIdxs()[ i ])->GetSeqRefNo() )
1042 pFtnIdx->SetSeqNo( n );
1043 break;
1048 else
1050 aIds.Insert( nSeqNo );
1051 aIdsMap.Insert( nSeqNo, nPos );
1052 aMap.Insert( nSeqNo, nPos );
1057 void SwGetRefFieldType::MergeWithOtherDoc( SwDoc& rDestDoc )
1059 if( &rDestDoc != pDoc &&
1060 rDestDoc.GetSysFldType( RES_GETREFFLD )->GetDepends() )
1062 // dann gibt es im DestDoc RefFelder, also muessen im SourceDoc
1063 // alle RefFelder auf einduetige Ids in beiden Docs umgestellt
1064 // werden.
1065 _RefIdsMap aFntMap( aEmptyStr );
1066 _RefIdsMaps aFldMap;
1068 SwClientIter aIter( *this );
1069 for( SwClient* pFld = aIter.First( TYPE( SwFmtFld ));
1070 pFld; pFld = aIter.Next() )
1072 SwGetRefField& rRefFld = *(SwGetRefField*)((SwFmtFld*)pFld)->GetFld();
1073 switch( rRefFld.GetSubType() )
1075 case REF_SEQUENCEFLD:
1077 _RefIdsMap* pMap = 0;
1078 for( USHORT n = aFldMap.Count(); n; )
1079 if( aFldMap[ --n ]->aName == rRefFld.GetSetRefName() )
1081 pMap = aFldMap[ n ];
1082 break;
1084 if( !pMap )
1086 pMap = new _RefIdsMap( rRefFld.GetSetRefName() );
1087 aFldMap.C40_INSERT( _RefIdsMap, pMap, aFldMap.Count() );
1090 pMap->Check( *pDoc, rDestDoc, rRefFld, TRUE );
1092 break;
1094 case REF_FOOTNOTE:
1095 case REF_ENDNOTE:
1096 aFntMap.Check( *pDoc, rDestDoc, rRefFld, FALSE );
1097 break;