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