update dev300-m58
[ooovba.git] / sw / source / core / txtnode / atrftn.cxx
blob3edd5758cbbe67076374aaba3231c647a8f64100
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: atrftn.cxx,v $
10 * $Revision: 1.9 $
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"
36 #define _SVSTDARR_USHORTS
37 #define _SVSTDARR_USHORTSSORT
38 #include <svtools/svstdarr.hxx>
39 #include <doc.hxx>
40 #include <cntfrm.hxx> // ASSERT in ~SwTxtFtn()
41 #include <pagefrm.hxx> // RemoveFtn()
42 #include <fmtftn.hxx>
43 #include <txtftn.hxx>
44 #include <ftnidx.hxx>
45 #include <ftninfo.hxx>
46 #include <swfont.hxx>
47 #include <ndtxt.hxx>
48 #include <poolfmt.hxx>
49 #include <ftnfrm.hxx>
50 #include <ndindex.hxx>
51 #include <fmtftntx.hxx>
52 #include <section.hxx>
54 /*************************************************************************
56 |* class SwFmtFtn
58 |* Beschreibung
59 |* Ersterstellung JP 09.08.94
60 |* Letzte Aenderung JP 08.08.94
62 *************************************************************************/
65 SwFmtFtn::SwFmtFtn( bool bEndNote )
66 : SfxPoolItem( RES_TXTATR_FTN ),
67 pTxtAttr( 0 ),
68 nNumber( 0 ),
69 m_bEndNote( bEndNote )
74 int SwFmtFtn::operator==( const SfxPoolItem& rAttr ) const
76 ASSERT( SfxPoolItem::operator==( rAttr ), "keine gleichen Attribute" );
77 return nNumber == ((SwFmtFtn&)rAttr).nNumber &&
78 aNumber == ((SwFmtFtn&)rAttr).aNumber &&
79 m_bEndNote == ((SwFmtFtn&)rAttr).m_bEndNote;
83 SfxPoolItem* SwFmtFtn::Clone( SfxItemPool* ) const
85 SwFmtFtn* pNew = new SwFmtFtn;
86 pNew->aNumber = aNumber;
87 pNew->nNumber = nNumber;
88 pNew->m_bEndNote = m_bEndNote;
89 return pNew;
92 void SwFmtFtn::SetEndNote( bool b )
94 if ( b != m_bEndNote )
96 if ( GetTxtFtn() )
98 GetTxtFtn()->DelFrms();
100 m_bEndNote = b;
104 SwFmtFtn::~SwFmtFtn()
109 void SwFmtFtn::GetFtnText( XubString& rStr ) const
111 if( pTxtAttr->GetStartNode() )
113 SwNodeIndex aIdx( *pTxtAttr->GetStartNode(), 1 );
114 SwCntntNode* pCNd = aIdx.GetNode().GetTxtNode();
115 if( !pCNd )
116 pCNd = aIdx.GetNodes().GoNext( &aIdx );
118 if( pCNd->IsTxtNode() )
119 rStr = ((SwTxtNode*)pCNd)->GetExpandTxt();
123 // returnt den anzuzeigenden String der Fuss-/Endnote
124 XubString SwFmtFtn::GetViewNumStr( const SwDoc& rDoc, BOOL bInclStrings ) const
126 XubString sRet( GetNumStr() );
127 if( !sRet.Len() )
129 // dann ist die Nummer von Interesse, also ueber die Info diese
130 // besorgen.
131 BOOL bMakeNum = TRUE;
132 const SwSectionNode* pSectNd = pTxtAttr
133 ? SwUpdFtnEndNtAtEnd::FindSectNdWithEndAttr( *pTxtAttr )
134 : 0;
136 if( pSectNd )
138 const SwFmtFtnEndAtTxtEnd& rFtnEnd = (SwFmtFtnEndAtTxtEnd&)
139 pSectNd->GetSection().GetFmt()->GetFmtAttr(
140 IsEndNote() ?
141 static_cast<USHORT>(RES_END_AT_TXTEND) :
142 static_cast<USHORT>(RES_FTN_AT_TXTEND) );
144 if( FTNEND_ATTXTEND_OWNNUMANDFMT == rFtnEnd.GetValue() )
146 bMakeNum = FALSE;
147 sRet = rFtnEnd.GetSwNumType().GetNumStr( GetNumber() );
148 if( bInclStrings )
150 sRet.Insert( rFtnEnd.GetPrefix(), 0 );
151 sRet += rFtnEnd.GetSuffix();
156 if( bMakeNum )
158 const SwEndNoteInfo* pInfo;
159 if( IsEndNote() )
160 pInfo = &rDoc.GetEndNoteInfo();
161 else
162 pInfo = &rDoc.GetFtnInfo();
163 sRet = pInfo->aFmt.GetNumStr( GetNumber() );
164 if( bInclStrings )
166 sRet.Insert( pInfo->GetPrefix(), 0 );
167 sRet += pInfo->GetSuffix();
171 return sRet;
174 /*************************************************************************
175 * class SwTxt/FmtFnt
176 *************************************************************************/
178 SwTxtFtn::SwTxtFtn( SwFmtFtn& rAttr, xub_StrLen nStartPos )
179 : SwTxtAttr( rAttr, nStartPos )
180 , m_pStartNode( 0 )
181 , m_pTxtNode( 0 )
182 , m_nSeqNo( USHRT_MAX )
184 rAttr.pTxtAttr = this;
188 SwTxtFtn::~SwTxtFtn()
190 SetStartNode( 0 );
195 void SwTxtFtn::SetStartNode( const SwNodeIndex *pNewNode, BOOL bDelNode )
197 if( pNewNode )
199 if ( !m_pStartNode )
201 m_pStartNode = new SwNodeIndex( *pNewNode );
203 else
205 *m_pStartNode = *pNewNode;
208 else if ( m_pStartNode )
210 // Zwei Dinge muessen erledigt werden:
211 // 1) Die Fussnoten muessen bei ihren Seiten abgemeldet werden
212 // 2) Die Fussnoten-Sektion in den Inserts muss geloescht werden.
213 SwDoc* pDoc;
214 if ( m_pTxtNode )
216 pDoc = m_pTxtNode->GetDoc();
218 else
220 //JP 27.01.97: der sw3-Reader setzt einen StartNode aber das
221 // Attribut ist noch nicht im TextNode verankert.
222 // Wird es geloescht (z.B. bei Datei einfuegen mit
223 // Ftn in einen Rahmen), muss auch der Inhalt
224 // geloescht werden
225 pDoc = m_pStartNode->GetNodes().GetDoc();
228 // Wir duerfen die Fussnotennodes nicht loeschen
229 // und brauchen die Fussnotenframes nicht loeschen, wenn
230 // wir im ~SwDoc() stehen.
231 if( !pDoc->IsInDtor() )
233 if( bDelNode )
235 // 1) Die Section fuer die Fussnote wird beseitigt
236 // Es kann sein, dass die Inserts schon geloescht wurden.
237 pDoc->DeleteSection( &m_pStartNode->GetNode() );
239 else
240 // Werden die Nodes nicht geloescht mussen sie bei den Seiten
241 // abmeldet (Frms loeschen) werden, denn sonst bleiben sie
242 // stehen (Undo loescht sie nicht!)
243 DelFrms();
245 DELETEZ( m_pStartNode );
247 // loesche die Fussnote noch aus dem Array am Dokument
248 for( USHORT n = 0; n < pDoc->GetFtnIdxs().Count(); ++n )
249 if( this == pDoc->GetFtnIdxs()[n] )
251 pDoc->GetFtnIdxs().Remove( n );
252 // gibt noch weitere Fussnoten
253 if( !pDoc->IsInDtor() && n < pDoc->GetFtnIdxs().Count() )
255 SwNodeIndex aTmp( pDoc->GetFtnIdxs()[n]->GetTxtNode() );
256 pDoc->GetFtnIdxs().UpdateFtn( aTmp );
258 break;
264 void SwTxtFtn::SetNumber( const USHORT nNewNum, const XubString* pStr )
266 SwFmtFtn& rFtn = (SwFmtFtn&)GetFtn();
267 if( pStr && pStr->Len() )
268 rFtn.aNumber = *pStr;
269 else
271 rFtn.nNumber = nNewNum;
272 rFtn.aNumber = aEmptyStr;
275 ASSERT( m_pTxtNode, "SwTxtFtn: where is my TxtNode?" );
276 SwNodes &rNodes = m_pTxtNode->GetDoc()->GetNodes();
277 m_pTxtNode->Modify( 0, &rFtn );
278 if ( m_pStartNode )
280 // must iterate over all TxtNodes because of footnotes on other pages
281 SwNode* pNd;
282 ULONG nSttIdx = m_pStartNode->GetIndex() + 1;
283 ULONG nEndIdx = m_pStartNode->GetNode().EndOfSectionIndex();
284 for( ; nSttIdx < nEndIdx; ++nSttIdx )
286 // Es koennen ja auch Grafiken in der Fussnote stehen ...
287 if( ( pNd = rNodes[ nSttIdx ] )->IsTxtNode() )
288 ((SwTxtNode*)pNd)->Modify( 0, &rFtn );
293 // Die Fussnoten duplizieren
294 void SwTxtFtn::CopyFtn( SwTxtFtn *pDest )
296 if ( m_pStartNode && pDest->GetStartNode() )
298 // die Fussnoten koennen in unterschiedlichen Dokumenten stehen !!
299 SwDoc* pDstDoc = pDest->m_pTxtNode->GetDoc();
300 SwNodes &rDstNodes = pDstDoc->GetNodes();
302 // Wir kopieren nur den Inhalt der Sektion
303 SwNodeRange aRg( *m_pStartNode, 1,
304 *m_pStartNode->GetNode().EndOfSectionNode() );
306 // Wir fuegen auf dem Ende von pDest ein, d.h. die Nodes
307 // werden angehaengt. nDestLen haelt die Anzahl der CntNodes
308 // in pDest _vor_ dem Kopieren.
309 SwNodeIndex aStart( *(pDest->GetStartNode()) );
310 SwNodeIndex aEnd( *aStart.GetNode().EndOfSectionNode() );
311 ULONG nDestLen = aEnd.GetIndex() - aStart.GetIndex() - 1;
313 m_pTxtNode->GetDoc()->CopyWithFlyInFly( aRg, 0, aEnd, TRUE );
315 // Wenn die Dest-Sektion nicht leer war, so muessen die alten
316 // Nodes geloescht werden:
317 // Vorher: Src: SxxxE, Dst: SnE
318 // Nachher: Src: SxxxE, Dst: SnxxxE
319 // und Src: SxxxE, Dst: SxxxE
320 aStart++;
321 rDstNodes.Delete( aStart, nDestLen );
324 // Der benutzerdefinierte String muss auch uebertragen werden.
325 if( GetFtn().aNumber.Len() )
326 ((SwFmtFtn&)pDest->GetFtn()).aNumber = GetFtn().aNumber;
330 // lege eine neue leere TextSection fuer diese Fussnote an
331 void SwTxtFtn::MakeNewTextSection( SwNodes& rNodes )
333 if ( m_pStartNode )
334 return;
336 // Nun verpassen wir dem TxtNode noch die Fussnotenvorlage.
337 SwTxtFmtColl *pFmtColl;
338 const SwEndNoteInfo* pInfo;
339 USHORT nPoolId;
341 if( GetFtn().IsEndNote() )
343 pInfo = &rNodes.GetDoc()->GetEndNoteInfo();
344 nPoolId = RES_POOLCOLL_ENDNOTE;
346 else
348 pInfo = &rNodes.GetDoc()->GetFtnInfo();
349 nPoolId = RES_POOLCOLL_FOOTNOTE;
352 if( 0 == (pFmtColl = pInfo->GetFtnTxtColl() ) )
353 pFmtColl = rNodes.GetDoc()->GetTxtCollFromPool( nPoolId );
355 SwStartNode* pSttNd = rNodes.MakeTextSection( SwNodeIndex( rNodes.GetEndOfInserts() ),
356 SwFootnoteStartNode, pFmtColl );
357 m_pStartNode = new SwNodeIndex( *pSttNd );
361 void SwTxtFtn::DelFrms()
363 // delete the FtnFrames from the pages
364 ASSERT( m_pTxtNode, "SwTxtFtn: where is my TxtNode?" );
365 if ( !m_pTxtNode )
366 return;
368 BOOL bFrmFnd = FALSE;
370 SwClientIter aIter( *m_pTxtNode );
371 for( SwCntntFrm* pFnd = (SwCntntFrm*)aIter.First( TYPE( SwCntntFrm ));
372 pFnd; pFnd = (SwCntntFrm*)aIter.Next() )
374 SwPageFrm* pPage = pFnd->FindPageFrm();
375 if( pPage )
377 pPage->RemoveFtn( pFnd, this );
378 bFrmFnd = TRUE;
382 //JP 13.05.97: falls das Layout vorm loeschen der Fussnoten entfernt
383 // wird, sollte man das ueber die Fussnote selbst tun
384 if ( !bFrmFnd && m_pStartNode )
386 SwNodeIndex aIdx( *m_pStartNode );
387 SwCntntNode* pCNd = m_pTxtNode->GetNodes().GoNext( &aIdx );
388 if( pCNd )
390 SwClientIter aIter( *pCNd );
391 for( SwCntntFrm* pFnd = (SwCntntFrm*)aIter.First( TYPE( SwCntntFrm ));
392 pFnd; pFnd = (SwCntntFrm*)aIter.Next() )
394 SwPageFrm* pPage = pFnd->FindPageFrm();
396 SwFrm *pFrm = pFnd->GetUpper();
397 while ( pFrm && !pFrm->IsFtnFrm() )
398 pFrm = pFrm->GetUpper();
400 SwFtnFrm *pFtn = (SwFtnFrm*)pFrm;
401 while ( pFtn && pFtn->GetMaster() )
402 pFtn = pFtn->GetMaster();
403 ASSERT( pFtn->GetAttr() == this, "Ftn mismatch error." );
405 while ( pFtn )
407 SwFtnFrm *pFoll = pFtn->GetFollow();
408 pFtn->Cut();
409 delete pFtn;
410 pFtn = pFoll;
413 // #i20556# During hiding of a section, the connection
414 // to the layout is already lost. pPage may be 0:
415 if ( pPage )
416 pPage->UpdateFtnNum();
423 USHORT SwTxtFtn::SetSeqRefNo()
425 if( !m_pTxtNode )
426 return USHRT_MAX;
428 SwDoc* pDoc = m_pTxtNode->GetDoc();
429 if( pDoc->IsInReading() )
430 return USHRT_MAX;
432 USHORT n, nFtnCnt = pDoc->GetFtnIdxs().Count();
434 const BYTE nTmp = 255 < nFtnCnt ? 255 : static_cast<BYTE>(nFtnCnt);
435 SvUShortsSort aArr( nTmp, nTmp );
437 // dann testmal, ob die Nummer schon vergeben ist oder ob eine neue
438 // bestimmt werden muss.
439 SwTxtFtn* pTxtFtn;
440 for( n = 0; n < nFtnCnt; ++n )
442 pTxtFtn = pDoc->GetFtnIdxs()[ n ];
443 if ( pTxtFtn != this )
445 aArr.Insert( pTxtFtn->m_nSeqNo );
449 // test if number is already in use
450 if ( USHRT_MAX != m_nSeqNo )
452 for( n = 0; n < aArr.Count(); ++n )
454 if ( aArr[ n ] > m_nSeqNo )
456 return m_nSeqNo; // free -> use
458 else if ( aArr[ n ] == m_nSeqNo )
460 break; // used -> create new one
464 if ( n == aArr.Count() )
466 return m_nSeqNo; // free -> use
470 // alle Nummern entsprechend geflag, also bestimme die richtige Nummer
471 for( n = 0; n < aArr.Count(); ++n )
472 if( n != aArr[ n ] )
473 break;
475 return m_nSeqNo = n;
478 void SwTxtFtn::SetUniqueSeqRefNo( SwDoc& rDoc )
480 USHORT n, nStt = 0, nFtnCnt = rDoc.GetFtnIdxs().Count();
482 const BYTE nTmp = 255 < nFtnCnt ? 255 : static_cast<BYTE>(nFtnCnt);
483 SvUShortsSort aArr( nTmp, nTmp );
485 // dann alle Nummern zusammensammeln die schon existieren
486 SwTxtFtn* pTxtFtn;
487 for( n = 0; n < nFtnCnt; ++n )
489 pTxtFtn = rDoc.GetFtnIdxs()[ n ];
490 if ( USHRT_MAX != pTxtFtn->m_nSeqNo )
492 aArr.Insert( pTxtFtn->m_nSeqNo );
497 for( n = 0; n < nFtnCnt; ++n )
499 pTxtFtn = rDoc.GetFtnIdxs()[ n ];
500 if ( USHRT_MAX == pTxtFtn->m_nSeqNo )
502 for( ; nStt < aArr.Count(); ++nStt )
504 if ( nStt != aArr[ nStt ] )
506 pTxtFtn->m_nSeqNo = nStt;
507 break;
511 if ( USHRT_MAX == pTxtFtn->m_nSeqNo )
513 break; // found nothing
518 // alle Nummern schon vergeben, also mit nStt++ weitermachen
519 for( ; n < nFtnCnt; ++n )
521 pTxtFtn = rDoc.GetFtnIdxs()[ n ];
522 if ( USHRT_MAX == pTxtFtn->m_nSeqNo )
524 pTxtFtn->m_nSeqNo = nStt++;
529 void SwTxtFtn::CheckCondColl()
531 //FEATURE::CONDCOLL
532 if( GetStartNode() )
533 ((SwStartNode&)GetStartNode()->GetNode()).CheckSectionCondColl();
534 //FEATURE::CONDCOLL