xref: /aoo41x/main/sw/source/core/fields/reffld.cxx (revision cdf0e10c)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 
32 #define _SVSTDARR_USHORTSSORT
33 #define _SVSTDARR_USHORTS
34 #include <svl/svstdarr.hxx>
35 #include <com/sun/star/text/ReferenceFieldPart.hpp>
36 #include <com/sun/star/text/ReferenceFieldSource.hpp>
37 #include <unotools/localedatawrapper.hxx>
38 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
39 #include <comphelper/processfactory.hxx>
40 #include <editeng/unolingu.hxx>
41 #include <doc.hxx>
42 #include <pam.hxx>
43 #include <cntfrm.hxx>
44 #include <pagefrm.hxx>
45 #include <docary.hxx>
46 #include <fmtfld.hxx>
47 #include <txtfld.hxx>
48 #include <txtftn.hxx>
49 #include <fmtrfmrk.hxx>
50 #include <txtrfmrk.hxx>
51 #include <fmtftn.hxx>
52 #include <ndtxt.hxx>
53 #include <chpfld.hxx>
54 #include <reffld.hxx>
55 #include <expfld.hxx>
56 #include <txtfrm.hxx>
57 #include <flyfrm.hxx>
58 #include <pagedesc.hxx>
59 #include <IMark.hxx>
60 #include <crossrefbookmark.hxx>
61 #include <ftnidx.hxx>
62 #include <viewsh.hxx>
63 #include <unofldmid.h>
64 #include <SwStyleNameMapper.hxx>
65 #include <shellres.hxx>
66 #include <poolfmt.hxx>
67 #include <poolfmt.hrc>
68 #include <comcore.hrc>
69 #include <numrule.hxx>
70 #include <SwNodeNum.hxx>
71 #include <switerator.hxx>
72 
73 using namespace ::com::sun::star;
74 using namespace ::com::sun::star::text;
75 using namespace ::com::sun::star::lang;
76 using ::rtl::OUString;
77 
78 extern void InsertSort( SvUShorts& rArr, sal_uInt16 nIdx, sal_uInt16* pInsPos = 0 );
79 
80 void lcl_GetLayTree( const SwFrm* pFrm, SvPtrarr& rArr )
81 {
82 	while( pFrm )
83 	{
84 		if( pFrm->IsBodyFrm() )		// soll uns nicht weiter interessieren
85 			pFrm = pFrm->GetUpper();
86 		else
87 		{
88 			void* p = (void*)pFrm;
89 			rArr.Insert( p, rArr.Count() );
90 
91 			// bei der Seite ist schluss
92 			if( pFrm->IsPageFrm() )
93 				break;
94 
95 			if( pFrm->IsFlyFrm() )
96                 pFrm = ((SwFlyFrm*)pFrm)->GetAnchorFrm();
97 			else
98 				pFrm = pFrm->GetUpper();
99 		}
100 	}
101 }
102 
103 
104 sal_Bool IsFrameBehind( const SwTxtNode& rMyNd, sal_uInt16 nMySttPos,
105 					const SwTxtNode& rBehindNd, sal_uInt16 nSttPos )
106 {
107 	const SwTxtFrm *pMyFrm = (SwTxtFrm*)rMyNd.getLayoutFrm( rMyNd.GetDoc()->GetCurrentLayout(), 0,0,sal_False),
108 				   *pFrm = (SwTxtFrm*)rBehindNd.getLayoutFrm( rBehindNd.GetDoc()->GetCurrentLayout(), 0,0,sal_False);
109 
110 	while( pFrm && !pFrm->IsInside( nSttPos ) )
111 		pFrm = (SwTxtFrm*)pFrm->GetFollow();
112 	while( pMyFrm && !pMyFrm->IsInside( nMySttPos ) )
113 		pMyFrm = (SwTxtFrm*)pMyFrm->GetFollow();
114 
115 	if( !pFrm || !pMyFrm || pFrm == pMyFrm )
116 		return sal_False;
117 
118 	SvPtrarr aRefArr( 10, 10 ), aArr( 10, 10 );
119 	::lcl_GetLayTree( pFrm, aRefArr );
120 	::lcl_GetLayTree( pMyFrm, aArr );
121 
122 	sal_uInt16 nRefCnt = aRefArr.Count() - 1, nCnt = aArr.Count() - 1;
123     sal_Bool bVert = sal_False;
124     sal_Bool bR2L = sal_False;
125 
126 	// solange bis ein Frame ungleich ist ?
127 	while( nRefCnt && nCnt && aRefArr[ nRefCnt ] == aArr[ nCnt ] )
128     {
129         const SwFrm* pTmpFrm = (const SwFrm*)aArr[ nCnt ];
130         bVert = pTmpFrm->IsVertical();
131         bR2L = pTmpFrm->IsRightToLeft();
132         --nCnt, --nRefCnt;
133     }
134 
135 	// sollte einer der Counter ueberlaeufen?
136 	if( aRefArr[ nRefCnt ] == aArr[ nCnt ] )
137 	{
138 		if( nCnt )
139 			--nCnt;
140 		else
141 			--nRefCnt;
142 	}
143 
144 	const SwFrm* pRefFrm = (const SwFrm*)aRefArr[ nRefCnt ];
145 	const SwFrm* pFldFrm = (const SwFrm*)aArr[ nCnt ];
146 
147 	// unterschiedliche Frames, dann ueberpruefe deren Y-/X-Position
148 	sal_Bool bRefIsLower = sal_False;
149 	if( ( FRM_COLUMN | FRM_CELL ) & pFldFrm->GetType() ||
150 		( FRM_COLUMN | FRM_CELL ) & pRefFrm->GetType() )
151 	{
152 		if( pFldFrm->GetType() == pRefFrm->GetType() )
153 		{
154 			// hier ist die X-Pos wichtiger!
155             if( bVert )
156             {
157                 if( bR2L )
158                     bRefIsLower = pRefFrm->Frm().Top() < pFldFrm->Frm().Top() ||
159                             ( pRefFrm->Frm().Top() == pFldFrm->Frm().Top() &&
160                               pRefFrm->Frm().Left() < pFldFrm->Frm().Left() );
161                 else
162                     bRefIsLower = pRefFrm->Frm().Top() < pFldFrm->Frm().Top() ||
163                             ( pRefFrm->Frm().Top() == pFldFrm->Frm().Top() &&
164                               pRefFrm->Frm().Left() > pFldFrm->Frm().Left() );
165             }
166             else if( bR2L )
167                 bRefIsLower = pRefFrm->Frm().Left() > pFldFrm->Frm().Left() ||
168                             ( pRefFrm->Frm().Left() == pFldFrm->Frm().Left() &&
169                               pRefFrm->Frm().Top() < pFldFrm->Frm().Top() );
170             else
171                 bRefIsLower = pRefFrm->Frm().Left() < pFldFrm->Frm().Left() ||
172                             ( pRefFrm->Frm().Left() == pFldFrm->Frm().Left() &&
173                               pRefFrm->Frm().Top() < pFldFrm->Frm().Top() );
174             pRefFrm = 0;
175 		}
176 		else if( ( FRM_COLUMN | FRM_CELL ) & pFldFrm->GetType() )
177 			pFldFrm = (const SwFrm*)aArr[ nCnt - 1 ];
178 		else
179 			pRefFrm = (const SwFrm*)aRefArr[ nRefCnt - 1 ];
180 	}
181 
182 	if( pRefFrm ) 				// als Flag missbrauchen
183     {
184         if( bVert )
185         {
186             if( bR2L )
187                 bRefIsLower = pRefFrm->Frm().Left() < pFldFrm->Frm().Left() ||
188                             ( pRefFrm->Frm().Left() == pFldFrm->Frm().Left() &&
189                                 pRefFrm->Frm().Top() < pFldFrm->Frm().Top() );
190             else
191                 bRefIsLower = pRefFrm->Frm().Left() > pFldFrm->Frm().Left() ||
192                             ( pRefFrm->Frm().Left() == pFldFrm->Frm().Left() &&
193                                 pRefFrm->Frm().Top() < pFldFrm->Frm().Top() );
194         }
195         else if( bR2L )
196             bRefIsLower = pRefFrm->Frm().Top() < pFldFrm->Frm().Top() ||
197                         ( pRefFrm->Frm().Top() == pFldFrm->Frm().Top() &&
198                             pRefFrm->Frm().Left() > pFldFrm->Frm().Left() );
199         else
200             bRefIsLower = pRefFrm->Frm().Top() < pFldFrm->Frm().Top() ||
201                         ( pRefFrm->Frm().Top() == pFldFrm->Frm().Top() &&
202                             pRefFrm->Frm().Left() < pFldFrm->Frm().Left() );
203     }
204     return bRefIsLower;
205 }
206 
207 /*--------------------------------------------------------------------
208 	Beschreibung: Referenzen holen
209  --------------------------------------------------------------------*/
210 
211 
212 SwGetRefField::SwGetRefField( SwGetRefFieldType* pFldType,
213 							  const String& rSetRef, sal_uInt16 nSubTyp,
214 							  sal_uInt16 nSeqenceNo, sal_uLong nFmt )
215     : SwField( pFldType, nFmt ),
216       sSetRefName( rSetRef ),
217       nSubType( nSubTyp ),
218       nSeqNo( nSeqenceNo )
219 {
220 }
221 
222 SwGetRefField::~SwGetRefField()
223 {
224 }
225 
226 String SwGetRefField::GetDescription() const
227 {
228     return SW_RES(STR_REFERENCE);
229 }
230 
231 sal_uInt16 SwGetRefField::GetSubType() const
232 {
233 	return nSubType;
234 }
235 
236 void SwGetRefField::SetSubType( sal_uInt16 n )
237 {
238 	nSubType = n;
239 }
240 
241 // --> OD 2007-11-09 #i81002#
242 bool SwGetRefField::IsRefToHeadingCrossRefBookmark() const
243 {
244     return GetSubType() == REF_BOOKMARK &&
245         ::sw::mark::CrossRefHeadingBookmark::IsLegalName(sSetRefName);
246 }
247 
248 bool SwGetRefField::IsRefToNumItemCrossRefBookmark() const
249 {
250     return GetSubType() == REF_BOOKMARK &&
251         ::sw::mark::CrossRefNumItemBookmark::IsLegalName(sSetRefName);
252 }
253 
254 const SwTxtNode* SwGetRefField::GetReferencedTxtNode() const
255 {
256     SwDoc* pDoc = dynamic_cast<SwGetRefFieldType*>(GetTyp())->GetDoc();
257     sal_uInt16 nDummy = USHRT_MAX;
258     return SwGetRefFieldType::FindAnchor( pDoc, sSetRefName, nSubType, nSeqNo, &nDummy );
259 }
260 // <--
261 // --> OD 2008-01-09 #i85090#
262 String SwGetRefField::GetExpandedTxtOfReferencedTxtNode() const
263 {
264     const SwTxtNode* pReferencedTxtNode( GetReferencedTxtNode() );
265     return pReferencedTxtNode
266            ? pReferencedTxtNode->GetExpandTxt( 0, STRING_LEN, true, true )
267            : aEmptyStr;
268 }
269 
270 String SwGetRefField::Expand() const
271 {
272 	return sTxt;
273 }
274 
275 
276 String SwGetRefField::GetFieldName() const
277 {
278 	String aStr(GetTyp()->GetName());
279 	aStr += ' ';
280 	aStr += sSetRefName;
281 	return aStr;
282 }
283 
284 // --> OD 2007-09-07 #i81002# - parameter <pFldTxtAttr> added
285 void SwGetRefField::UpdateField( const SwTxtFld* pFldTxtAttr )
286 {
287 	sTxt.Erase();
288 
289     SwDoc* pDoc = ((SwGetRefFieldType*)GetTyp())->GetDoc();
290     sal_uInt16 nStt = USHRT_MAX;
291     sal_uInt16 nEnd = USHRT_MAX;
292 	SwTxtNode* pTxtNd = SwGetRefFieldType::FindAnchor( pDoc, sSetRefName,
293 										nSubType, nSeqNo, &nStt, &nEnd );
294     if ( !pTxtNd )
295     {
296         sTxt = ViewShell::GetShellRes()->aGetRefFld_RefItemNotFound;
297 		return ;
298     }
299 
300 	switch( GetFormat() )
301 	{
302 	case REF_CONTENT:
303 	case REF_ONLYNUMBER:
304 	case REF_ONLYCAPTION:
305 	case REF_ONLYSEQNO:
306 		{
307 			switch( nSubType )
308 			{
309 			case REF_SEQUENCEFLD:
310 				nEnd = pTxtNd->GetTxt().Len();
311 				switch( GetFormat() )
312 				{
313 				case REF_ONLYNUMBER:
314 					if( nStt + 1 < nEnd )
315 						nEnd = nStt + 1;
316 					nStt = 0;
317 					break;
318 
319 				case REF_ONLYCAPTION:
320 					{
321                         const SwTxtAttr* const pTxtAttr =
322                             pTxtNd->GetTxtAttrForCharAt(nStt, RES_TXTATR_FIELD);
323 						if( pTxtAttr )
324 							nStt = SwGetExpField::GetReferenceTextPos(
325 												pTxtAttr->GetFld(), *pDoc );
326 						else if( nStt + 1 < nEnd )
327 							++nStt;
328 					}
329 					break;
330 
331 				case REF_ONLYSEQNO:
332 					if( nStt + 1 < nEnd )
333 						nEnd = nStt + 1;
334 					break;
335 
336 				default:
337 					nStt = 0;
338 					break;
339 				}
340 				break;
341 
342 			case REF_BOOKMARK:
343 				if( USHRT_MAX == nEnd )
344 				{
345 					// Text steht ueber verschiedene Nodes verteilt.
346 					// Gesamten Text oder nur bis zum Ende vom Node?
347 					nEnd = pTxtNd->GetTxt().Len();
348 				}
349 				break;
350 
351 			case REF_OUTLINE:
352 				break;
353 
354 			case REF_FOOTNOTE:
355 			case REF_ENDNOTE:
356 				{
357 					// die Nummer oder den NumString besorgen
358 					sal_uInt16 n, nFtnCnt = pDoc->GetFtnIdxs().Count();
359 					SwTxtFtn* pFtnIdx;
360 					for( n = 0; n < nFtnCnt; ++n )
361 						if( nSeqNo == (pFtnIdx = pDoc->GetFtnIdxs()[ n ])->GetSeqRefNo() )
362 						{
363 							sTxt = pFtnIdx->GetFtn().GetViewNumStr( *pDoc );
364 							break;
365 						}
366 					nStt = nEnd;		// kein Bereich, der String ist fertig
367 				}
368 				break;
369 			}
370 
371 			if( nStt != nEnd )		// ein Bereich?
372 			{
373                 sTxt = pTxtNd->GetExpandTxt( nStt, nEnd - nStt );
374 
375 				// alle Sonderzeichen entfernen (durch Blanks ersetzen):
376 				if( sTxt.Len() )
377                 {
378                     sTxt.EraseAllChars( 0xad );
379                     for( sal_Unicode* p = sTxt.GetBufferAccess(); *p; ++p )
380 					{
381 						if( *p < 0x20 )
382 							*p = 0x20;
383                         else if(*p == 0x2011)
384 							*p = '-';
385 					}
386                 }
387 			}
388 		}
389 		break;
390 
391 	case REF_PAGE:
392 	case REF_PAGE_PGDESC:
393 		{
394 			const SwTxtFrm* pFrm = (SwTxtFrm*)pTxtNd->getLayoutFrm( pDoc->GetCurrentLayout(), 0,0,sal_False),
395 						*pSave = pFrm;
396 			while( pFrm && !pFrm->IsInside( nStt ) )
397 				pFrm = (SwTxtFrm*)pFrm->GetFollow();
398 
399 			if( pFrm || 0 != ( pFrm = pSave ))
400 			{
401 				sal_uInt16 nPageNo = pFrm->GetVirtPageNum();
402 				const SwPageFrm *pPage;
403 				if( REF_PAGE_PGDESC == GetFormat() &&
404 					0 != ( pPage = pFrm->FindPageFrm() ) &&
405 					pPage->GetPageDesc() )
406 					sTxt = pPage->GetPageDesc()->GetNumType().GetNumStr( nPageNo );
407 				else
408 					sTxt = String::CreateFromInt32(nPageNo);
409 			}
410 		}
411 		break;
412 
413 	case REF_CHAPTER:
414 		{
415 			// ein bischen trickreich: suche irgend einen Frame
416 			const SwFrm* pFrm = pTxtNd->getLayoutFrm( pDoc->GetCurrentLayout() );
417 			if( pFrm )
418 			{
419 				SwChapterFieldType aFldTyp;
420 				SwChapterField aFld( &aFldTyp, 0 );
421 				aFld.SetLevel( MAXLEVEL - 1 );
422 				aFld.ChangeExpansion( pFrm, pTxtNd, sal_True );
423 				sTxt = aFld.GetNumber();
424 			}
425 		}
426 		break;
427 
428 	case REF_UPDOWN:
429 		{
430             // --> OD 2007-09-07 #i81002#
431             // simplified: use parameter <pFldTxtAttr>
432             if( !pFldTxtAttr || !pFldTxtAttr->GetpTxtNode() )
433 				break;
434 
435 			LocaleDataWrapper aLocaleData(
436 							::comphelper::getProcessServiceFactory(),
437 							SvxCreateLocale( GetLanguage() ) );
438 
439 			// erstmal ein "Kurz" - Test - falls beide im selben
440 			// Node stehen!
441             if( pFldTxtAttr->GetpTxtNode() == pTxtNd )
442 			{
443                 sTxt = nStt < *pFldTxtAttr->GetStart()
444 							? aLocaleData.getAboveWord()
445 							: aLocaleData.getBelowWord();
446 				break;
447 			}
448 
449             sTxt = ::IsFrameBehind( *pFldTxtAttr->GetpTxtNode(), *pFldTxtAttr->GetStart(),
450 									*pTxtNd, nStt )
451 						? aLocaleData.getAboveWord()
452 						: aLocaleData.getBelowWord();
453 		}
454 		break;
455     // --> OD 2007-08-24 #i81002#
456     case REF_NUMBER:
457     case REF_NUMBER_NO_CONTEXT:
458     case REF_NUMBER_FULL_CONTEXT:
459         {
460             if ( pFldTxtAttr && pFldTxtAttr->GetpTxtNode() )
461             {
462                 sTxt = MakeRefNumStr( pFldTxtAttr->GetTxtNode(), *pTxtNd, GetFormat() );
463             }
464         }
465         break;
466     // <--
467     default:
468         DBG_ERROR("<SwGetRefField::UpdateField(..)> - unknown format type");
469 	}
470 }
471 
472 // --> OD 2007-09-06 #i81002#
473 String SwGetRefField::MakeRefNumStr( const SwTxtNode& rTxtNodeOfField,
474                                      const SwTxtNode& rTxtNodeOfReferencedItem,
475                                      const sal_uInt32 nRefNumFormat ) const
476 {
477     if ( rTxtNodeOfReferencedItem.HasNumber() &&
478          rTxtNodeOfReferencedItem.IsCountedInList() )
479     {
480         ASSERT( rTxtNodeOfReferencedItem.GetNum(),
481                 "<SwGetRefField::MakeRefNumStr(..)> - referenced paragraph has number, but no <SwNodeNum> instance --> please inform OD!" );
482 
483         // Determine, up to which level the superior list labels have to be
484         // included - default is to include all superior list labels.
485         sal_uInt8 nRestrictInclToThisLevel( 0 );
486         // Determine for format REF_NUMBER the level, up to which the superior
487         // list labels have to be restricted, if the text node of the reference
488         // field and the text node of the referenced item are in the same
489         // document context.
490         if ( nRefNumFormat == REF_NUMBER &&
491              rTxtNodeOfField.FindFlyStartNode()
492                             == rTxtNodeOfReferencedItem.FindFlyStartNode() &&
493              rTxtNodeOfField.FindFootnoteStartNode()
494                             == rTxtNodeOfReferencedItem.FindFootnoteStartNode() &&
495              rTxtNodeOfField.FindHeaderStartNode()
496                             == rTxtNodeOfReferencedItem.FindHeaderStartNode() &&
497              rTxtNodeOfField.FindFooterStartNode()
498                             == rTxtNodeOfReferencedItem.FindFooterStartNode() )
499         {
500             const SwNodeNum* pNodeNumForTxtNodeOfField( 0 );
501             if ( rTxtNodeOfField.HasNumber() &&
502                  rTxtNodeOfField.GetNumRule() == rTxtNodeOfReferencedItem.GetNumRule() )
503             {
504                 pNodeNumForTxtNodeOfField = rTxtNodeOfField.GetNum();
505             }
506             else
507             {
508                 pNodeNumForTxtNodeOfField =
509                     rTxtNodeOfReferencedItem.GetNum()->GetPrecedingNodeNumOf( rTxtNodeOfField );
510             }
511             if ( pNodeNumForTxtNodeOfField )
512             {
513                 const SwNumberTree::tNumberVector rFieldNumVec = pNodeNumForTxtNodeOfField->GetNumberVector();
514                 const SwNumberTree::tNumberVector rRefItemNumVec = rTxtNodeOfReferencedItem.GetNum()->GetNumberVector();
515                 sal_uInt8 nLevel( 0 );
516                 while ( nLevel < rFieldNumVec.size() && nLevel < rRefItemNumVec.size() )
517                 {
518                     if ( rRefItemNumVec[nLevel] == rFieldNumVec[nLevel] )
519                     {
520                         nRestrictInclToThisLevel = nLevel + 1;
521                     }
522                     else
523                     {
524                         break;
525                     }
526                     ++nLevel;
527                 }
528             }
529         }
530 
531         // Determine, if superior list labels have to be included
532         const bool bInclSuperiorNumLabels(
533             ( nRestrictInclToThisLevel < rTxtNodeOfReferencedItem.GetActualListLevel() &&
534               ( nRefNumFormat == REF_NUMBER || nRefNumFormat == REF_NUMBER_FULL_CONTEXT ) ) );
535 
536         ASSERT( rTxtNodeOfReferencedItem.GetNumRule(),
537                 "<SwGetRefField::MakeRefNumStr(..)> - referenced numbered paragraph has no numbering rule set --> please inform OD!" );
538         return rTxtNodeOfReferencedItem.GetNumRule()->MakeRefNumString(
539                                             *(rTxtNodeOfReferencedItem.GetNum()),
540                                             bInclSuperiorNumLabels,
541                                             nRestrictInclToThisLevel );
542     }
543 
544     return String();
545 }
546 // <--
547 
548 SwField* SwGetRefField::Copy() const
549 {
550 	SwGetRefField* pFld = new SwGetRefField( (SwGetRefFieldType*)GetTyp(),
551 												sSetRefName, nSubType,
552 												nSeqNo, GetFormat() );
553 	pFld->sTxt = sTxt;
554 	return pFld;
555 }
556 
557 /*--------------------------------------------------------------------
558 	Beschreibung: ReferenzName holen
559  --------------------------------------------------------------------*/
560 
561 
562 const String& SwGetRefField::GetPar1() const
563 {
564 	return sSetRefName;
565 }
566 
567 
568 void SwGetRefField::SetPar1( const String& rName )
569 {
570 	sSetRefName = rName;
571 }
572 
573 
574 String SwGetRefField::GetPar2() const
575 {
576 	return Expand();
577 }
578 
579 sal_Bool SwGetRefField::QueryValue( uno::Any& rAny, sal_uInt16 nWhichId ) const
580 {
581     switch( nWhichId )
582 	{
583 	case FIELD_PROP_USHORT1:
584 		{
585 			sal_Int16 nPart = 0;
586 			switch(GetFormat())
587 			{
588 			case REF_PAGE		: nPart = ReferenceFieldPart::PAGE 				  ; break;
589 			case REF_CHAPTER	: nPart = ReferenceFieldPart::CHAPTER	 		  ; break;
590 			case REF_CONTENT	: nPart = ReferenceFieldPart::TEXT 				  ; break;
591 			case REF_UPDOWN		: nPart = ReferenceFieldPart::UP_DOWN 			  ; break;
592 			case REF_PAGE_PGDESC: nPart = ReferenceFieldPart::PAGE_DESC 		  ; break;
593 			case REF_ONLYNUMBER	: nPart = ReferenceFieldPart::CATEGORY_AND_NUMBER ; break;
594 			case REF_ONLYCAPTION: nPart = ReferenceFieldPart::ONLY_CAPTION 		  ; break;
595 			case REF_ONLYSEQNO	: nPart = ReferenceFieldPart::ONLY_SEQUENCE_NUMBER; break;
596             // --> OD 2007-09-06 #i81002#
597             case REF_NUMBER:              nPart = ReferenceFieldPart::NUMBER;              break;
598             case REF_NUMBER_NO_CONTEXT:   nPart = ReferenceFieldPart::NUMBER_NO_CONTEXT;   break;
599             case REF_NUMBER_FULL_CONTEXT: nPart = ReferenceFieldPart::NUMBER_FULL_CONTEXT; break;
600             // <--
601 			}
602 			rAny <<= nPart;
603 		}
604 		break;
605 	case FIELD_PROP_USHORT2:
606 		{
607 			sal_Int16 nSource = 0;
608 			switch(nSubType)
609 			{
610 			case  REF_SETREFATTR : nSource = ReferenceFieldSource::REFERENCE_MARK; break;
611 			case  REF_SEQUENCEFLD: nSource = ReferenceFieldSource::SEQUENCE_FIELD; break;
612 			case  REF_BOOKMARK   : nSource = ReferenceFieldSource::BOOKMARK; break;
613 			case  REF_OUTLINE    : DBG_ERROR("not implemented"); break;
614 			case  REF_FOOTNOTE   : nSource = ReferenceFieldSource::FOOTNOTE; break;
615 			case  REF_ENDNOTE    : nSource = ReferenceFieldSource::ENDNOTE; break;
616 			}
617 			rAny <<= nSource;
618 		}
619 		break;
620 	case FIELD_PROP_PAR1:
621     {
622         String  sTmp(GetPar1());
623         if(REF_SEQUENCEFLD == nSubType)
624         {
625             sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( sTmp, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
626             switch( nPoolId )
627             {
628                 case RES_POOLCOLL_LABEL_ABB:
629                 case RES_POOLCOLL_LABEL_TABLE:
630                 case RES_POOLCOLL_LABEL_FRAME:
631                 case RES_POOLCOLL_LABEL_DRAWING:
632                     SwStyleNameMapper::FillProgName(nPoolId, sTmp) ;
633                 break;
634             }
635         }
636         rAny <<= rtl::OUString(sTmp);
637     }
638     break;
639 	case FIELD_PROP_PAR3:
640 		rAny <<= rtl::OUString(Expand());
641 		break;
642 	case FIELD_PROP_SHORT1:
643 		rAny <<= (sal_Int16)nSeqNo;
644 		break;
645 	default:
646 		DBG_ERROR("illegal property");
647 	}
648 	return sal_True;
649 }
650 
651 sal_Bool SwGetRefField::PutValue( const uno::Any& rAny, sal_uInt16 nWhichId )
652 {
653 	String sTmp;
654     switch( nWhichId )
655 	{
656 	case FIELD_PROP_USHORT1:
657 		{
658 			sal_Int16 nPart = 0;
659 			rAny >>= nPart;
660 			switch(nPart)
661 			{
662 			case ReferenceFieldPart::PAGE: 					nPart = REF_PAGE; break;
663 			case ReferenceFieldPart::CHAPTER:	 			nPart = REF_CHAPTER; break;
664 			case ReferenceFieldPart::TEXT: 					nPart = REF_CONTENT; break;
665 			case ReferenceFieldPart::UP_DOWN: 				nPart = REF_UPDOWN; break;
666 			case ReferenceFieldPart::PAGE_DESC: 			nPart = REF_PAGE_PGDESC; break;
667 			case ReferenceFieldPart::CATEGORY_AND_NUMBER: 	nPart = REF_ONLYNUMBER; break;
668 			case ReferenceFieldPart::ONLY_CAPTION: 			nPart = REF_ONLYCAPTION; break;
669 			case ReferenceFieldPart::ONLY_SEQUENCE_NUMBER : nPart = REF_ONLYSEQNO; break;
670             // --> OD 2007-09-06 #i81002#
671             case ReferenceFieldPart::NUMBER:              nPart = REF_NUMBER;              break;
672             case ReferenceFieldPart::NUMBER_NO_CONTEXT:   nPart = REF_NUMBER_NO_CONTEXT;   break;
673             case ReferenceFieldPart::NUMBER_FULL_CONTEXT: nPart = REF_NUMBER_FULL_CONTEXT; break;
674             // <--
675 			default: return sal_False;
676 			}
677 			SetFormat(nPart);
678 		}
679 		break;
680 	case FIELD_PROP_USHORT2:
681 		{
682 			sal_Int16 nSource = 0;
683 			rAny >>= nSource;
684 			switch(nSource)
685 			{
686 			case ReferenceFieldSource::REFERENCE_MARK : nSubType = REF_SETREFATTR ; break;
687             case ReferenceFieldSource::SEQUENCE_FIELD :
688             {
689                 if(REF_SEQUENCEFLD == nSubType)
690                     break;
691                 nSubType = REF_SEQUENCEFLD;
692                 ConvertProgrammaticToUIName();
693             }
694             break;
695 			case ReferenceFieldSource::BOOKMARK		  : nSubType = REF_BOOKMARK   ; break;
696 			case ReferenceFieldSource::FOOTNOTE		  : nSubType = REF_FOOTNOTE   ; break;
697 			case ReferenceFieldSource::ENDNOTE		  : nSubType = REF_ENDNOTE    ; break;
698 			}
699 		}
700 		break;
701 	case FIELD_PROP_PAR1:
702     {
703         OUString sTmpStr;
704         rAny >>= sTmpStr;
705         SetPar1(sTmpStr);
706         ConvertProgrammaticToUIName();
707     }
708     break;
709 	case FIELD_PROP_PAR3:
710 		SetExpand( ::GetString( rAny, sTmp ));
711 		break;
712 	case FIELD_PROP_SHORT1:
713 		{
714 			sal_Int16 nSetSeq = 0;
715 			rAny >>= nSetSeq;
716 			if(nSetSeq >= 0)
717 				nSeqNo = nSetSeq;
718 		}
719 		break;
720 	default:
721 		DBG_ERROR("illegal property");
722 	}
723 	return sal_True;
724 }
725 
726 void SwGetRefField::ConvertProgrammaticToUIName()
727 {
728     if(GetTyp() && REF_SEQUENCEFLD == nSubType)
729     {
730         SwDoc* pDoc = ((SwGetRefFieldType*)GetTyp())->GetDoc();
731         const String& rPar1 = GetPar1();
732         //don't convert when the name points to an existing field type
733         if(!pDoc->GetFldType(RES_SETEXPFLD, rPar1, false))
734         {
735             sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromProgName( rPar1, nsSwGetPoolIdFromName::GET_POOLID_TXTCOLL );
736             sal_uInt16 nResId = USHRT_MAX;
737             switch( nPoolId )
738             {
739                 case RES_POOLCOLL_LABEL_ABB:
740                     nResId = STR_POOLCOLL_LABEL_ABB;
741                 break;
742                 case RES_POOLCOLL_LABEL_TABLE:
743                     nResId = STR_POOLCOLL_LABEL_TABLE;
744                 break;
745                 case RES_POOLCOLL_LABEL_FRAME:
746                     nResId = STR_POOLCOLL_LABEL_FRAME;
747                 break;
748                 case RES_POOLCOLL_LABEL_DRAWING:
749                     nResId = STR_POOLCOLL_LABEL_DRAWING;
750                 break;
751             }
752             if( nResId != USHRT_MAX )
753                 SetPar1(SW_RESSTR( nResId ));
754         }
755     }
756 }
757 
758 SwGetRefFieldType::SwGetRefFieldType( SwDoc* pDc )
759 	: SwFieldType( RES_GETREFFLD ), pDoc( pDc )
760 {}
761 
762 
763 SwFieldType* SwGetRefFieldType::Copy() const
764 {
765 	return new SwGetRefFieldType( pDoc );
766 }
767 
768 
769 void SwGetRefFieldType::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
770 {
771 	// Update auf alle GetReferenz-Felder
772 	if( !pNew && !pOld )
773 	{
774 		SwIterator<SwFmtFld,SwFieldType> aIter( *this );
775 		for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() )
776 		{
777 			// nur die GetRef-Felder Updaten
778 			//JP 3.4.2001: Task 71231 - we need the correct language
779 			SwGetRefField* pGRef = (SwGetRefField*)pFld->GetFld();
780 			const SwTxtFld* pTFld;
781 			if( !pGRef->GetLanguage() &&
782 				0 != ( pTFld = pFld->GetTxtFld()) &&
783                 pTFld->GetpTxtNode() )
784             {
785 				pGRef->SetLanguage( pTFld->GetpTxtNode()->GetLang(
786 												*pTFld->GetStart() ) );
787             }
788 
789             // --> OD 2007-09-06 #i81002#
790             pGRef->UpdateField( pFld->GetTxtFld() );
791             // <--
792 		}
793 	}
794 	// weiter an die Text-Felder, diese "Expandieren" den Text
795 	NotifyClients( pOld, pNew );
796 }
797 
798 SwTxtNode* SwGetRefFieldType::FindAnchor( SwDoc* pDoc, const String& rRefMark,
799 										sal_uInt16 nSubType, sal_uInt16 nSeqNo,
800 										sal_uInt16* pStt, sal_uInt16* pEnd )
801 {
802 	ASSERT( pStt, "warum wird keine StartPos abgefragt?" );
803 
804 	SwTxtNode* pTxtNd = 0;
805 	switch( nSubType )
806 	{
807 	case REF_SETREFATTR:
808 		{
809 			const SwFmtRefMark *pRef = pDoc->GetRefMark( rRefMark );
810 			if( pRef && pRef->GetTxtRefMark() )
811 			{
812 				pTxtNd = (SwTxtNode*)&pRef->GetTxtRefMark()->GetTxtNode();
813 				*pStt = *pRef->GetTxtRefMark()->GetStart();
814 				if( pEnd )
815 					*pEnd = *pRef->GetTxtRefMark()->GetAnyEnd();
816 			}
817 		}
818 		break;
819 
820 	case REF_SEQUENCEFLD:
821 		{
822 			SwFieldType* pFldType = pDoc->GetFldType( RES_SETEXPFLD, rRefMark, false );
823 			if( pFldType && pFldType->GetDepends() &&
824 				nsSwGetSetExpType::GSE_SEQ & ((SwSetExpFieldType*)pFldType)->GetType() )
825 			{
826 				SwIterator<SwFmtFld,SwFieldType> aIter( *pFldType );
827 				for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() )
828 				{
829 					if( pFld->GetTxtFld() && nSeqNo ==
830 						((SwSetExpField*)pFld->GetFld())->GetSeqNumber() )
831 					{
832 						SwTxtFld* pTxtFld = pFld->GetTxtFld();
833 						pTxtNd = (SwTxtNode*)pTxtFld->GetpTxtNode();
834 						*pStt = *pTxtFld->GetStart();
835 						if( pEnd )
836 							*pEnd = (*pStt) + 1;
837 						break;
838 					}
839 				}
840 			}
841 		}
842 		break;
843 
844     case REF_BOOKMARK:
845         {
846             IDocumentMarkAccess::const_iterator_t ppMark = pDoc->getIDocumentMarkAccess()->findMark(rRefMark);
847             if(ppMark != pDoc->getIDocumentMarkAccess()->getMarksEnd())
848             {
849                 const ::sw::mark::IMark* pBkmk = ppMark->get();
850                 const SwPosition* pPos = &pBkmk->GetMarkStart();
851 
852                 pTxtNd = pPos->nNode.GetNode().GetTxtNode();
853                 *pStt = pPos->nContent.GetIndex();
854                 if(pEnd)
855                 {
856                     if(!pBkmk->IsExpanded())
857                     {
858                         *pEnd = *pStt;
859                         // --> OD 2007-10-18 #i81002#
860                         if(dynamic_cast< ::sw::mark::CrossRefBookmark const *>(pBkmk))
861                         {
862                             ASSERT( pTxtNd,
863                                     "<SwGetRefFieldType::FindAnchor(..)> - node marked by cross-reference bookmark isn't a text node --> crash" );
864                             *pEnd = pTxtNd->Len();
865                         }
866                         // <--
867                     }
868                     else if(pBkmk->GetOtherMarkPos().nNode == pBkmk->GetMarkPos().nNode)
869                         *pEnd = pBkmk->GetMarkEnd().nContent.GetIndex();
870                     else
871                         *pEnd = USHRT_MAX;
872                 }
873             }
874         }
875         break;
876 
877 	case REF_OUTLINE:
878 		break;
879 
880 	case REF_FOOTNOTE:
881 	case REF_ENDNOTE:
882 		{
883 			sal_uInt16 n, nFtnCnt = pDoc->GetFtnIdxs().Count();
884 			SwTxtFtn* pFtnIdx;
885 			for( n = 0; n < nFtnCnt; ++n )
886 				if( nSeqNo == (pFtnIdx = pDoc->GetFtnIdxs()[ n ])->GetSeqRefNo() )
887 				{
888 					SwNodeIndex* pIdx = pFtnIdx->GetStartNode();
889 					if( pIdx )
890 					{
891 						SwNodeIndex aIdx( *pIdx, 1 );
892 						if( 0 == ( pTxtNd = aIdx.GetNode().GetTxtNode()))
893 							pTxtNd = (SwTxtNode*)pDoc->GetNodes().GoNext( &aIdx );
894 					}
895 					*pStt = 0;
896 					if( pEnd )
897 						*pEnd = 0;
898 					break;
899 				}
900 		}
901 		break;
902 	}
903 
904 	return pTxtNd;
905 }
906 
907 
908 struct _RefIdsMap
909 {
910 	String aName;
911 	SvUShortsSort aIds, aDstIds, aIdsMap;
912 	SvUShorts aMap;
913 	sal_Bool bInit;
914 
915 	_RefIdsMap( const String& rName )
916 		: aName( rName ), aIds( 16, 16 ), aIdsMap( 16, 16 ), aMap( 16, 16 ),
917 		bInit( sal_False )
918 	{}
919 
920 	void Check( SwDoc& rDoc, SwDoc& rDestDoc, SwGetRefField& rFld,
921 					sal_Bool bField = sal_True );
922 
923 	sal_Bool IsInit() const { return bInit; }
924 };
925 
926 SV_DECL_PTRARR_DEL( _RefIdsMaps, _RefIdsMap*, 5, 5 )
927 SV_IMPL_PTRARR( _RefIdsMaps, _RefIdsMap* )
928 
929 void _RefIdsMap::Check( SwDoc& rDoc, SwDoc& rDestDoc, SwGetRefField& rFld,
930 						sal_Bool bField )
931 {
932 
933 	if( !bInit )
934 	{
935 		if( bField )
936 		{
937 			const SwTxtNode* pNd;
938 			SwFieldType* pType;
939 			if( 0 != ( pType = rDestDoc.GetFldType( RES_SETEXPFLD, aName, false ) ))
940 			{
941 				SwIterator<SwFmtFld,SwFieldType> aIter( *pType );
942 				for( SwFmtFld* pF = aIter.First(); pF; pF = aIter.Next() )
943 					if( pF->GetTxtFld() &&
944 						0 != ( pNd = pF->GetTxtFld()->GetpTxtNode() ) &&
945 						pNd->GetNodes().IsDocNodes() )
946 						aIds.Insert( ((SwSetExpField*)pF->GetFld())->GetSeqNumber() );
947 			}
948 			if( 0 != ( pType = rDoc.GetFldType( RES_SETEXPFLD, aName, false ) ))
949 			{
950 				SwIterator<SwFmtFld,SwFieldType> aIter( *pType );
951 				for( SwFmtFld* pF = aIter.First(); pF; pF = aIter.Next() )
952 					if( pF->GetTxtFld() &&
953 						0 != ( pNd = pF->GetTxtFld()->GetpTxtNode() ) &&
954 						pNd->GetNodes().IsDocNodes() )
955 						aDstIds.Insert( ((SwSetExpField*)pF->GetFld())->GetSeqNumber() );
956 			}
957 		}
958 		else
959 		{
960 			sal_uInt16 n;
961 
962 			for( n = rDestDoc.GetFtnIdxs().Count(); n; )
963 				aIds.Insert( rDestDoc.GetFtnIdxs()[ --n ]->GetSeqRefNo() );
964 			for( n = rDoc.GetFtnIdxs().Count(); n; )
965 				aDstIds.Insert( rDoc.GetFtnIdxs()[ --n ]->GetSeqRefNo() );
966 		}
967 		bInit = sal_True;
968 	}
969 
970 	// dann teste mal, ob die Nummer schon vergeben ist
971 	// oder ob eine neue bestimmt werden muss.
972 	sal_uInt16 nPos, nSeqNo = rFld.GetSeqNo();
973 	if( aIds.Seek_Entry( nSeqNo ) && aDstIds.Seek_Entry( nSeqNo ))
974 	{
975 		// ist schon vergeben, also muss eine neue
976 		// erzeugt werden.
977 		if( aIdsMap.Seek_Entry( nSeqNo, &nPos ))
978 			rFld.SetSeqNo( aMap[ nPos ] );
979 		else
980 		{
981 			sal_uInt16 n;
982 
983 			for( n = 0; n < aIds.Count(); ++n )
984 				if( n != aIds[ n ] )
985 					break;
986 
987 			// die neue SeqNo eintragen, damit die "belegt" ist
988 			aIds.Insert( n );
989 			aIdsMap.Insert( nSeqNo, nPos );
990 			aMap.Insert( n, nPos );
991 			rFld.SetSeqNo( n );
992 
993 			// und noch die Felder oder Fuss-/EndNote auf die neue
994 			// Id umsetzen
995 			if( bField )
996 			{
997 				SwFieldType* pType = rDoc.GetFldType( RES_SETEXPFLD, aName, false );
998 				if( pType )
999 				{
1000 				    SwIterator<SwFmtFld,SwFieldType> aIter( *pType );
1001 				    for( SwFmtFld* pF = aIter.First(); pF; pF = aIter.Next() )
1002 						if( pF->GetTxtFld() && nSeqNo ==
1003 							((SwSetExpField*)pF->GetFld())->GetSeqNumber() )
1004 							((SwSetExpField*)pF->GetFld())->SetSeqNumber( n );
1005 				}
1006 			}
1007 			else
1008 			{
1009 				SwTxtFtn* pFtnIdx;
1010 				for( sal_uInt16 i = 0, nCnt = rDoc.GetFtnIdxs().Count(); i < nCnt; ++i )
1011 					if( nSeqNo == (pFtnIdx = rDoc.GetFtnIdxs()[ i ])->GetSeqRefNo() )
1012 					{
1013 						pFtnIdx->SetSeqNo( n );
1014 						break;
1015 					}
1016 			}
1017 		}
1018 	}
1019 	else
1020 	{
1021 		aIds.Insert( nSeqNo );
1022 		aIdsMap.Insert( nSeqNo, nPos );
1023 		aMap.Insert( nSeqNo, nPos );
1024 	}
1025 }
1026 
1027 
1028 void SwGetRefFieldType::MergeWithOtherDoc( SwDoc& rDestDoc )
1029 {
1030 	if( &rDestDoc != pDoc &&
1031 		rDestDoc.GetSysFldType( RES_GETREFFLD )->GetDepends() )
1032 	{
1033 		// dann gibt es im DestDoc RefFelder, also muessen im SourceDoc
1034 		// alle RefFelder auf einduetige Ids in beiden Docs umgestellt
1035 		// werden.
1036 		_RefIdsMap aFntMap( aEmptyStr );
1037 		_RefIdsMaps aFldMap;
1038 
1039 		SwIterator<SwFmtFld,SwFieldType> aIter( *this );
1040 		for( SwFmtFld* pFld = aIter.First(); pFld; pFld = aIter.Next() )
1041 		{
1042 			SwGetRefField& rRefFld = *(SwGetRefField*)pFld->GetFld();
1043 			switch( rRefFld.GetSubType() )
1044 			{
1045 			case REF_SEQUENCEFLD:
1046 				{
1047 					_RefIdsMap* pMap = 0;
1048 					for( sal_uInt16 n = aFldMap.Count(); n; )
1049 						if( aFldMap[ --n ]->aName == rRefFld.GetSetRefName() )
1050 						{
1051 							pMap = aFldMap[ n ];
1052 							break;
1053 						}
1054 					if( !pMap )
1055 					{
1056 						pMap = new _RefIdsMap( rRefFld.GetSetRefName() );
1057 						aFldMap.C40_INSERT( _RefIdsMap, pMap, aFldMap.Count() );
1058 					}
1059 
1060 					pMap->Check( *pDoc, rDestDoc, rRefFld, sal_True );
1061 				}
1062 				break;
1063 
1064 			case REF_FOOTNOTE:
1065 			case REF_ENDNOTE:
1066 				aFntMap.Check( *pDoc, rDestDoc, rRefFld, sal_False );
1067 				break;
1068 			}
1069 		}
1070 	}
1071 }
1072 
1073