xref: /trunk/main/sw/source/core/doc/docftn.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
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 #include <ftnidx.hxx>
33 #include <rootfrm.hxx>
34 #include <txtftn.hxx>
35 #include <fmtftn.hxx>
36 #include <pam.hxx>
37 #include <pagedesc.hxx>
38 #include <charfmt.hxx>
39 #include <UndoAttribute.hxx>
40 #include <hints.hxx>
41 #include <rolbck.hxx>
42 #include <doc.hxx>
43 #include <IDocumentUndoRedo.hxx>
44 #include <ndtxt.hxx>
45 #include <poolfmt.hxx>
46 #include <ftninfo.hxx>
47 
48 /*********************** SwFtnInfo ***************************/
49 
50 SwEndNoteInfo& SwEndNoteInfo::operator=(const SwEndNoteInfo& rInfo)
51 {
52     if( rInfo.GetFtnTxtColl() )
53         rInfo.GetFtnTxtColl()->Add(this);
54     else if ( GetRegisteredIn())
55         GetRegisteredInNonConst()->Remove(this);
56 
57     if ( rInfo.aPageDescDep.GetRegisteredIn() )
58         ((SwModify*)rInfo.aPageDescDep.GetRegisteredIn())->Add( &aPageDescDep );
59     else if ( aPageDescDep.GetRegisteredIn() )
60         ((SwModify*)aPageDescDep.GetRegisteredIn())->Remove( &aPageDescDep );
61 
62     if ( rInfo.aCharFmtDep.GetRegisteredIn() )
63         ((SwModify*)rInfo.aCharFmtDep.GetRegisteredIn())->Add( &aCharFmtDep );
64     else if ( aCharFmtDep.GetRegisteredIn() )
65         ((SwModify*)aCharFmtDep.GetRegisteredIn())->Remove( &aCharFmtDep );
66 
67     if ( rInfo.aAnchorCharFmtDep.GetRegisteredIn() )
68         ((SwModify*)rInfo.aAnchorCharFmtDep.GetRegisteredIn())->Add(
69                                                     &aAnchorCharFmtDep );
70     else if( aAnchorCharFmtDep.GetRegisteredIn() )
71         ((SwModify*)aAnchorCharFmtDep.GetRegisteredIn())->Remove(
72                                                     &aAnchorCharFmtDep );
73 
74     aFmt = rInfo.aFmt;
75     nFtnOffset = rInfo.nFtnOffset;
76     m_bEndNote = rInfo.m_bEndNote;
77     sPrefix = rInfo.sPrefix;
78     sSuffix = rInfo.sSuffix;
79     return *this;
80 }
81 
82 
83 sal_Bool SwEndNoteInfo::operator==( const SwEndNoteInfo& rInfo ) const
84 {
85     return  aPageDescDep.GetRegisteredIn() ==
86                                 rInfo.aPageDescDep.GetRegisteredIn() &&
87             aCharFmtDep.GetRegisteredIn() ==
88                                 rInfo.aCharFmtDep.GetRegisteredIn() &&
89             aAnchorCharFmtDep.GetRegisteredIn() ==
90                                 rInfo.aAnchorCharFmtDep.GetRegisteredIn() &&
91             GetFtnTxtColl() == rInfo.GetFtnTxtColl() &&
92             aFmt.GetNumberingType() == rInfo.aFmt.GetNumberingType() &&
93             nFtnOffset == rInfo.nFtnOffset &&
94             m_bEndNote == rInfo.m_bEndNote &&
95             sPrefix == rInfo.sPrefix &&
96             sSuffix == rInfo.sSuffix;
97 }
98 
99 
100 SwEndNoteInfo::SwEndNoteInfo(const SwEndNoteInfo& rInfo) :
101     SwClient( rInfo.GetFtnTxtColl() ),
102     aPageDescDep( this, 0 ),
103     aCharFmtDep( this, 0 ),
104     aAnchorCharFmtDep( this, 0 ),
105     sPrefix( rInfo.sPrefix ),
106     sSuffix( rInfo.sSuffix ),
107     m_bEndNote( true ),
108     aFmt( rInfo.aFmt ),
109     nFtnOffset( rInfo.nFtnOffset )
110 {
111     if( rInfo.aPageDescDep.GetRegisteredIn() )
112         ((SwModify*)rInfo.aPageDescDep.GetRegisteredIn())->Add( &aPageDescDep );
113 
114     if( rInfo.aCharFmtDep.GetRegisteredIn() )
115         ((SwModify*)rInfo.aCharFmtDep.GetRegisteredIn())->Add( &aCharFmtDep );
116 
117     if( rInfo.aAnchorCharFmtDep.GetRegisteredIn() )
118         ((SwModify*)rInfo.aAnchorCharFmtDep.GetRegisteredIn())->Add(
119                 &aAnchorCharFmtDep );
120 }
121 
122 SwEndNoteInfo::SwEndNoteInfo(SwTxtFmtColl *pFmt) :
123     SwClient(pFmt),
124     aPageDescDep( this, 0 ),
125     aCharFmtDep( this, 0 ),
126     aAnchorCharFmtDep( this, 0 ),
127     m_bEndNote( true ),
128     nFtnOffset( 0 )
129 {
130     aFmt.SetNumberingType(SVX_NUM_ROMAN_LOWER);
131 }
132 
133 SwPageDesc *SwEndNoteInfo::GetPageDesc( SwDoc &rDoc ) const
134 {
135     if ( !aPageDescDep.GetRegisteredIn() )
136     {
137         SwPageDesc *pDesc = rDoc.GetPageDescFromPool( static_cast<sal_uInt16>(
138             m_bEndNote ? RES_POOLPAGE_ENDNOTE   : RES_POOLPAGE_FOOTNOTE ) );
139         pDesc->Add( &((SwClient&)aPageDescDep) );
140     }
141 
142     return (SwPageDesc*)( aPageDescDep.GetRegisteredIn() );
143 }
144 
145 bool SwEndNoteInfo::KnowsPageDesc() const
146 {
147     return (aPageDescDep.GetRegisteredIn() != 0);
148 }
149 
150 bool SwEndNoteInfo::DependsOn( const SwPageDesc* pDesc ) const
151 {
152     return ( aPageDescDep.GetRegisteredIn() == pDesc );
153 }
154 
155 void SwEndNoteInfo::ChgPageDesc( SwPageDesc *pDesc )
156 {
157     pDesc->Add( &((SwClient&)aPageDescDep) );
158 }
159 
160 void SwEndNoteInfo::SetFtnTxtColl(SwTxtFmtColl& rFmt)
161 {
162     rFmt.Add(this);
163 }
164 
165 SwCharFmt* SwEndNoteInfo::GetCharFmt(SwDoc &rDoc) const
166 {
167     if ( !aCharFmtDep.GetRegisteredIn() )
168     {
169         SwCharFmt* pFmt = rDoc.GetCharFmtFromPool( static_cast<sal_uInt16>(
170             m_bEndNote ? RES_POOLCHR_ENDNOTE : RES_POOLCHR_FOOTNOTE ) );
171         pFmt->Add( &((SwClient&)aCharFmtDep) );
172     }
173     return (SwCharFmt*)aCharFmtDep.GetRegisteredIn();
174 }
175 
176 void SwEndNoteInfo::SetCharFmt( SwCharFmt* pChFmt )
177 {
178     DBG_ASSERT(pChFmt, "kein CharFmt?");
179     pChFmt->Add( &((SwClient&)aCharFmtDep) );
180 }
181 
182 SwCharFmt* SwEndNoteInfo::GetAnchorCharFmt(SwDoc &rDoc) const
183 {
184     if( !aAnchorCharFmtDep.GetRegisteredIn() )
185     {
186         SwCharFmt* pFmt = rDoc.GetCharFmtFromPool( static_cast<sal_uInt16>(
187             m_bEndNote ? RES_POOLCHR_ENDNOTE_ANCHOR : RES_POOLCHR_FOOTNOTE_ANCHOR ) );
188         pFmt->Add( &((SwClient&)aAnchorCharFmtDep) );
189     }
190     return (SwCharFmt*)aAnchorCharFmtDep.GetRegisteredIn();
191 }
192 
193 void SwEndNoteInfo::SetAnchorCharFmt( SwCharFmt* pChFmt )
194 {
195     DBG_ASSERT(pChFmt, "kein CharFmt?");
196     pChFmt->Add( &((SwClient&)aAnchorCharFmtDep) );
197 }
198 
199 void SwEndNoteInfo::Modify( const SfxPoolItem* pOld, const SfxPoolItem* pNew )
200 {
201     sal_uInt16 nWhich = pOld ? pOld->Which() : pNew ? pNew->Which() : 0 ;
202 
203     if( RES_ATTRSET_CHG == nWhich ||
204         RES_FMT_CHG == nWhich )
205     {
206         SwDoc* pDoc;
207         if( aCharFmtDep.GetRegisteredIn() )
208             pDoc = ((SwCharFmt*)aCharFmtDep.GetRegisteredIn())->GetDoc();
209         else
210             pDoc = ((SwCharFmt*)aAnchorCharFmtDep.GetRegisteredIn())->GetDoc();
211         SwFtnIdxs& rFtnIdxs = pDoc->GetFtnIdxs();
212         for( sal_uInt16 nPos = 0; nPos < rFtnIdxs.Count(); ++nPos )
213         {
214             SwTxtFtn *pTxtFtn = rFtnIdxs[ nPos ];
215             const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
216             if ( rFtn.IsEndNote() == m_bEndNote )
217             {
218                 pTxtFtn->SetNumber( rFtn.GetNumber(), &rFtn.GetNumStr());
219             }
220         }
221     }
222     else
223         CheckRegistration( pOld, pNew );
224 }
225 
226 SwFtnInfo& SwFtnInfo::operator=(const SwFtnInfo& rInfo)
227 {
228     SwEndNoteInfo::operator=(rInfo);
229     aQuoVadis =  rInfo.aQuoVadis;
230     aErgoSum = rInfo.aErgoSum;
231     ePos = rInfo.ePos;
232     eNum = rInfo.eNum;
233     return *this;
234 }
235 
236 
237 sal_Bool SwFtnInfo::operator==( const SwFtnInfo& rInfo ) const
238 {
239     return  ePos == rInfo.ePos &&
240             eNum == rInfo.eNum &&
241             SwEndNoteInfo::operator==(rInfo) &&
242             aQuoVadis == rInfo.aQuoVadis &&
243             aErgoSum == rInfo.aErgoSum;
244 }
245 
246 
247 SwFtnInfo::SwFtnInfo(const SwFtnInfo& rInfo) :
248     SwEndNoteInfo( rInfo ),
249     aQuoVadis( rInfo.aQuoVadis ),
250     aErgoSum( rInfo.aErgoSum ),
251     ePos( rInfo.ePos ),
252     eNum( rInfo.eNum )
253 {
254     m_bEndNote = false;
255 }
256 
257 SwFtnInfo::SwFtnInfo(SwTxtFmtColl *pFmt) :
258     SwEndNoteInfo( pFmt ),
259     ePos( FTNPOS_PAGE ),
260     eNum( FTNNUM_DOC )
261 {
262     aFmt.SetNumberingType(SVX_NUM_ARABIC);
263     m_bEndNote = false;
264 }
265 
266 /*********************** SwDoc ***************************/
267 
268 
269 void SwDoc::SetFtnInfo(const SwFtnInfo& rInfo)
270 {
271     SwRootFrm* pTmpRoot = GetCurrentLayout();//swmod 080219
272     if( !(GetFtnInfo() == rInfo) )
273     {
274         const SwFtnInfo &rOld = GetFtnInfo();
275 
276         if (GetIDocumentUndoRedo().DoesUndo())
277         {
278             GetIDocumentUndoRedo().AppendUndo( new SwUndoFootNoteInfo(rOld) );
279         }
280 
281         sal_Bool bFtnPos  = rInfo.ePos != rOld.ePos;
282         sal_Bool bFtnDesc = rOld.ePos == FTNPOS_CHAPTER &&
283                             rInfo.GetPageDesc( *this ) != rOld.GetPageDesc( *this );
284         sal_Bool bExtra   = rInfo.aQuoVadis != rOld.aQuoVadis ||
285                             rInfo.aErgoSum != rOld.aErgoSum ||
286                             rInfo.aFmt.GetNumberingType() != rOld.aFmt.GetNumberingType() ||
287                             rInfo.GetPrefix() != rOld.GetPrefix() ||
288                             rInfo.GetSuffix() != rOld.GetSuffix();
289         SwCharFmt *pOldChrFmt = rOld.GetCharFmt( *this ),
290                   *pNewChrFmt = rInfo.GetCharFmt( *this );
291         sal_Bool bFtnChrFmts = pOldChrFmt != pNewChrFmt;
292 
293         *pFtnInfo = rInfo;
294 
295         if (pTmpRoot)
296         {
297             std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();//swmod 080304
298             if ( bFtnPos )
299                 //pTmpRoot->RemoveFtns();
300                 std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::AllRemoveFtns));//swmod 080305
301             else
302             {
303                 //pTmpRoot->UpdateFtnNums();
304                 std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::UpdateFtnNums));//swmod 080304
305                 if ( bFtnDesc )
306                     //pTmpRoot->CheckFtnPageDescs( FALSE );
307                     std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::bind2nd(std::mem_fun(&SwRootFrm::CheckFtnPageDescs), sal_False));//swmod 080304
308                 if ( bExtra )
309                 {
310                     //Fuer die Benachrichtung bezueglich ErgoSum usw. sparen wir uns
311                     //extra-Code und nutzen die vorhandenen Wege.
312                     SwFtnIdxs& rFtnIdxs = GetFtnIdxs();
313                     for( sal_uInt16 nPos = 0; nPos < rFtnIdxs.Count(); ++nPos )
314                     {
315                         SwTxtFtn *pTxtFtn = rFtnIdxs[ nPos ];
316                         const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
317                         if ( !rFtn.IsEndNote() )
318                             pTxtFtn->SetNumber( rFtn.GetNumber(), &rFtn.GetNumStr());
319                     }
320                 }
321             }
322         }   //swmod 080219
323         if( FTNNUM_PAGE != rInfo.eNum )
324             GetFtnIdxs().UpdateAllFtn();
325         else if( bFtnChrFmts )
326         {
327             SwFmtChg aOld( pOldChrFmt );
328             SwFmtChg aNew( pNewChrFmt );
329             pFtnInfo->ModifyNotification( &aOld, &aNew );
330         }
331 
332         // --> OD 2008-01-09 #i81002#
333         // no update during loading
334         if ( !IsInReading() )
335         {
336             UpdateRefFlds(NULL);
337         }
338         SetModified();
339     }
340 }
341 
342 void SwDoc::SetEndNoteInfo(const SwEndNoteInfo& rInfo)
343 {
344     SwRootFrm* pTmpRoot = GetCurrentLayout();//swmod 080219
345     if( !(GetEndNoteInfo() == rInfo) )
346     {
347         if(GetIDocumentUndoRedo().DoesUndo())
348         {
349             SwUndo *const pUndo( new SwUndoEndNoteInfo( GetEndNoteInfo() ) );
350             GetIDocumentUndoRedo().AppendUndo(pUndo);
351         }
352 
353         sal_Bool bNumChg  = rInfo.nFtnOffset != GetEndNoteInfo().nFtnOffset;
354         // this seems to be an optimization: UpdateAllFtn() is only called
355         // if the offset changes; if the offset is the same,
356         // but type/prefix/suffix changes, just set new numbers.
357         bool const bExtra = !bNumChg &&
358                 (   (rInfo.aFmt.GetNumberingType() !=
359                         GetEndNoteInfo().aFmt.GetNumberingType())
360                 ||  (rInfo.GetPrefix() != GetEndNoteInfo().GetPrefix())
361                 ||  (rInfo.GetSuffix() != GetEndNoteInfo().GetSuffix())
362                 );
363         sal_Bool bFtnDesc = rInfo.GetPageDesc( *this ) !=
364                             GetEndNoteInfo().GetPageDesc( *this );
365         SwCharFmt *pOldChrFmt = GetEndNoteInfo().GetCharFmt( *this ),
366                   *pNewChrFmt = rInfo.GetCharFmt( *this );
367         sal_Bool bFtnChrFmts = pOldChrFmt != pNewChrFmt;
368 
369         *pEndNoteInfo = rInfo;
370 
371         if ( pTmpRoot )
372         {
373             if ( bFtnDesc )
374                 //pTmpRoot->CheckFtnPageDescs( TRUE );
375             {
376                 std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
377                 std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::bind2nd(std::mem_fun(&SwRootFrm::CheckFtnPageDescs), sal_True));//swmod 080304
378             }
379             if ( bExtra )
380             {
381                 //Fuer die Benachrichtung bezueglich ErgoSum usw. sparen wir uns
382                 //extra-Code und nutzen die vorhandenen Wege.
383                 SwFtnIdxs& rFtnIdxs = GetFtnIdxs();
384                 for( sal_uInt16 nPos = 0; nPos < rFtnIdxs.Count(); ++nPos )
385                 {
386                     SwTxtFtn *pTxtFtn = rFtnIdxs[ nPos ];
387                     const SwFmtFtn &rFtn = pTxtFtn->GetFtn();
388                     if ( rFtn.IsEndNote() )
389                         pTxtFtn->SetNumber( rFtn.GetNumber(), &rFtn.GetNumStr());
390                 }
391             }
392         }   //swmod 080219
393         if( bNumChg )
394             GetFtnIdxs().UpdateAllFtn();
395         else if( bFtnChrFmts )
396         {
397             SwFmtChg aOld( pOldChrFmt );
398             SwFmtChg aNew( pNewChrFmt );
399             pEndNoteInfo->ModifyNotification( &aOld, &aNew );
400         }
401 
402         // --> OD 2008-01-09 #i81002#
403         // no update during loading
404         if ( !IsInReading() )
405         {
406             UpdateRefFlds(NULL);
407         }
408         SetModified();
409     }
410 }
411 
412 
413 bool SwDoc::SetCurFtn( const SwPaM& rPam, const String& rNumStr,
414                        sal_uInt16 nNumber, bool bIsEndNote )
415 {
416     SwFtnIdxs& rFtnArr = GetFtnIdxs();
417     SwRootFrm* pTmpRoot = GetCurrentLayout();//swmod 080219
418 
419     const SwPosition* pStt = rPam.Start(), *pEnd = rPam.End();
420     const sal_uLong nSttNd = pStt->nNode.GetIndex();
421     const xub_StrLen nSttCnt = pStt->nContent.GetIndex();
422     const sal_uLong nEndNd = pEnd->nNode.GetIndex();
423     const xub_StrLen nEndCnt = pEnd->nContent.GetIndex();
424 
425     sal_uInt16 nPos;
426     rFtnArr.SeekEntry( pStt->nNode, &nPos );
427 
428     SwUndoChangeFootNote* pUndo = 0;
429     if (GetIDocumentUndoRedo().DoesUndo())
430     {
431         GetIDocumentUndoRedo().ClearRedo(); // AppendUndo far below, so leave it
432         pUndo = new SwUndoChangeFootNote( rPam, rNumStr, nNumber, bIsEndNote );
433     }
434 
435     SwTxtFtn* pTxtFtn;
436     sal_uLong nIdx;
437     sal_Bool bChg = sal_False;
438     sal_Bool bTypeChgd = sal_False;
439     sal_uInt16 n = nPos;        // sichern
440     while( nPos < rFtnArr.Count() &&
441             (( nIdx = _SwTxtFtn_GetIndex((pTxtFtn = rFtnArr[ nPos++ ] )))
442                 < nEndNd || ( nIdx == nEndNd &&
443                 nEndCnt >= *pTxtFtn->GetStart() )) )
444         if( nIdx > nSttNd || ( nIdx == nSttNd &&
445                 nSttCnt <= *pTxtFtn->GetStart() ) )
446         {
447             const SwFmtFtn& rFtn = pTxtFtn->GetFtn();
448             if( /*rFtn.GetNumber() != nNumber ||*/
449                 rFtn.GetNumStr() != rNumStr ||
450                 rFtn.IsEndNote() != bIsEndNote )
451             {
452                 bChg = sal_True;
453                 if ( pUndo )
454                 {
455                     pUndo->GetHistory().Add( *pTxtFtn );
456                 }
457 
458                 pTxtFtn->SetNumber( nNumber, &rNumStr );
459                 if( rFtn.IsEndNote() != bIsEndNote )
460                 {
461                     ((SwFmtFtn&)rFtn).SetEndNote( bIsEndNote );
462                     bTypeChgd = sal_True;
463                     pTxtFtn->CheckCondColl();
464                     //#i11339# dispose UNO wrapper when a footnote is changed to an endnote or vice versa
465                     SwPtrMsgPoolItem aMsgHint( RES_FOOTNOTE_DELETED, (void*)&pTxtFtn->GetAttr() );
466                     GetUnoCallBack()->ModifyNotification( &aMsgHint, &aMsgHint );
467                 }
468             }
469         }
470 
471     nPos = n;       // nach vorne gibt es auch noch welche !
472     while( nPos &&
473             (( nIdx = _SwTxtFtn_GetIndex((pTxtFtn = rFtnArr[ --nPos ] )))
474                 > nSttNd || ( nIdx == nSttNd &&
475                 nSttCnt <= *pTxtFtn->GetStart() )) )
476         if( nIdx < nEndNd || ( nIdx == nEndNd &&
477             nEndCnt >= *pTxtFtn->GetStart() ) )
478         {
479             const SwFmtFtn& rFtn = pTxtFtn->GetFtn();
480             if( /*rFtn.GetNumber() != nNumber ||*/
481                 rFtn.GetNumStr() != rNumStr ||
482                 rFtn.IsEndNote() != bIsEndNote )
483             {
484                 bChg = sal_True;
485                 if ( pUndo )
486                 {
487                     pUndo->GetHistory().Add( *pTxtFtn );
488                 }
489 
490                 pTxtFtn->SetNumber( nNumber, &rNumStr );
491                 if( rFtn.IsEndNote() != bIsEndNote )
492                 {
493                     ((SwFmtFtn&)rFtn).SetEndNote( bIsEndNote );
494                     bTypeChgd = sal_True;
495                     pTxtFtn->CheckCondColl();
496                 }
497             }
498         }
499 
500     // wer muss angestossen werden ??
501     if( bChg )
502     {
503         if( pUndo )
504         {
505             GetIDocumentUndoRedo().AppendUndo(pUndo);
506         }
507 
508         if ( bTypeChgd )
509             rFtnArr.UpdateAllFtn();
510         if( FTNNUM_PAGE != GetFtnInfo().eNum )
511         {
512             if ( !bTypeChgd )
513                 rFtnArr.UpdateAllFtn();
514         }
515         else if( pTmpRoot )
516             //
517         {
518             std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();
519             std::for_each( aAllLayouts.begin(), aAllLayouts.end(),std::mem_fun(&SwRootFrm::UpdateFtnNums));
520         }   //swmod 080304pTmpRoot->UpdateFtnNums();    //swmod 080219
521         SetModified();
522     }
523     else
524         delete pUndo;
525     return bChg;
526 }
527 
528 
529 
530 
531 
532