xref: /trunk/main/sw/source/core/doc/doclay.cxx (revision be9fb86be37b3939ae325385d593ec77b4020f18)
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 #include <unotools/linguprops.hxx>
28 #include <unotools/lingucfg.hxx>
29 #include <com/sun/star/embed/EmbedStates.hpp>
30 #include <hintids.hxx>
31 #include <com/sun/star/util/XCloseable.hpp>
32 #include <sfx2/progress.hxx>
33 #include <svx/svdmodel.hxx>
34 #include <svx/svdpage.hxx>
35 #include <editeng/keepitem.hxx>
36 #include <editeng/ulspitem.hxx>
37 #include <editeng/lrspitem.hxx>
38 #include <editeng/boxitem.hxx>
39 #include <editeng/shaditem.hxx>
40 #include <editeng/protitem.hxx>
41 #include <editeng/opaqitem.hxx>
42 #include <editeng/prntitem.hxx>
43 #include <svx/fmglob.hxx>
44 #include <svx/svdouno.hxx>
45 #include <svx/fmpage.hxx>
46 #include <editeng/frmdiritem.hxx>
47 
48 #include <swmodule.hxx>
49 #include <modcfg.hxx>
50 #include <com/sun/star/beans/XPropertySet.hpp>
51 #include <rtl/logfile.hxx>
52 #include <SwStyleNameMapper.hxx>
53 #include <fchrfmt.hxx>
54 #include <errhdl.hxx>
55 #include <frmatr.hxx>
56 #include <txatbase.hxx>
57 #include <fmtfld.hxx>
58 #include <fmtornt.hxx>
59 #include <fmtcntnt.hxx>
60 #include <fmtanchr.hxx>
61 #include <fmtfsize.hxx>
62 #include <fmtsrnd.hxx>
63 #include <fmtflcnt.hxx>
64 #include <fmtcnct.hxx>
65 #include <frmfmt.hxx>
66 #include <dcontact.hxx>
67 #include <txtflcnt.hxx>
68 #include <docfld.hxx>   // fuer Expression-Felder
69 #include <pam.hxx>
70 #include <ndtxt.hxx>
71 #include <ndnotxt.hxx>
72 #include <ndole.hxx>
73 #include <doc.hxx>
74 #include <IDocumentUndoRedo.hxx>
75 #include <rootfrm.hxx>
76 #include <pagefrm.hxx>
77 #include <cntfrm.hxx>
78 #include <flyfrm.hxx>
79 #include <fesh.hxx>
80 #include <docsh.hxx>
81 #include <dflyobj.hxx>
82 #include <dcontact.hxx>
83 #include <swundo.hxx>
84 #include <flypos.hxx>
85 #include <UndoInsert.hxx>
86 #include <expfld.hxx>       // InsertLabel
87 #include <poolfmt.hxx>      // PoolVorlagen-Id's
88 #include <docary.hxx>
89 #include <swtable.hxx>
90 #include <tblsel.hxx>
91 #include <viewopt.hxx>
92 #include <fldupde.hxx>
93 #include <txtftn.hxx>
94 #include <ftnidx.hxx>
95 #include <ftninfo.hxx>
96 #include <pagedesc.hxx>
97 #include <PostItMgr.hxx>
98 #include <comcore.hrc>      // STR-ResId's
99 
100 // #i11176#
101 #include <unoframe.hxx>
102 // OD 2004-05-24 #i28701#
103 #include <sortedobjs.hxx>
104 
105 // --> OD 2004-07-26 #i32089#
106 #include <vector>
107 // <--
108 
109 using namespace ::com::sun::star;
110 using ::rtl::OUString;
111 
112 #define DEF_FLY_WIDTH    2268   //Defaultbreite fuer FlyFrms    (2268 == 4cm)
113 
114 /* #109161# */
115 static bool lcl_IsItemSet(const SwCntntNode & rNode, sal_uInt16 which)
116 {
117     bool bResult = false;
118 
119     if (SFX_ITEM_SET == rNode.GetSwAttrSet().GetItemState(which))
120         bResult = true;
121 
122     return bResult;
123 }
124 
125 /*************************************************************************
126 |*
127 |*  SwDoc::MakeLayoutFmt()
128 |*
129 |*  Beschreibung        Erzeugt ein neues Format das in seinen Einstellungen
130 |*      Defaultmaessig zu dem Request passt. Das Format wird in das
131 |*      entsprechende Formate-Array gestellt.
132 |*      Wenn bereits ein passendes Format existiert, so wird dies
133 |*      zurueckgeliefert.
134 |*  Ersterstellung      MA 22. Sep. 92
135 |*  Letzte Aenderung    JP 08.05.98
136 |*
137 |*************************************************************************/
138 
139 SwFrmFmt *SwDoc::MakeLayoutFmt( RndStdIds eRequest, const SfxItemSet* pSet )
140 {
141     SwFrmFmt *pFmt = 0;
142     const sal_Bool bMod = IsModified();
143     sal_Bool bHeader = sal_False;
144 
145     switch ( eRequest )
146     {
147     case RND_STD_HEADER:
148     case RND_STD_HEADERL:
149     case RND_STD_HEADERR:
150         {
151             bHeader = sal_True;
152             // kein break, es geht unten weiter
153         }
154     case RND_STD_FOOTER:
155     case RND_STD_FOOTERL:
156     case RND_STD_FOOTERR:
157         {
158             pFmt = new SwFrmFmt( GetAttrPool(),
159                                  (bHeader ? "Header" : "Footer"),
160                                  GetDfltFrmFmt() );
161 
162             SwNodeIndex aTmpIdx( GetNodes().GetEndOfAutotext() );
163             SwStartNode* pSttNd =
164                 GetNodes().MakeTextSection
165                 ( aTmpIdx,
166                   bHeader ? SwHeaderStartNode : SwFooterStartNode,
167                   GetTxtCollFromPool(static_cast<sal_uInt16>( bHeader
168                                      ? ( eRequest == RND_STD_HEADERL
169                                          ? RES_POOLCOLL_HEADERL
170                                          : eRequest == RND_STD_HEADERR
171                                          ? RES_POOLCOLL_HEADERR
172                                          : RES_POOLCOLL_HEADER )
173                                      : ( eRequest == RND_STD_FOOTERL
174                                          ? RES_POOLCOLL_FOOTERL
175                                          : eRequest == RND_STD_FOOTERR
176                                          ? RES_POOLCOLL_FOOTERR
177                                          : RES_POOLCOLL_FOOTER )
178                                      ) ) );
179             pFmt->SetFmtAttr( SwFmtCntnt( pSttNd ));
180 
181             if( pSet )      // noch ein paar Attribute setzen ?
182                 pFmt->SetFmtAttr( *pSet );
183 
184             // JP: warum zuruecksetzen ???  Doc. ist doch veraendert ???
185             // bei den Fly auf jedenfall verkehrt !!
186             if ( !bMod )
187                 ResetModified();
188         }
189         break;
190 
191     case RND_DRAW_OBJECT:
192         {
193             pFmt = MakeDrawFrmFmt( aEmptyStr, GetDfltFrmFmt() );
194             if( pSet )      // noch ein paar Attribute setzen ?
195                 pFmt->SetFmtAttr( *pSet );
196 
197             if (GetIDocumentUndoRedo().DoesUndo())
198             {
199                 GetIDocumentUndoRedo().AppendUndo(
200                     new SwUndoInsLayFmt(pFmt, 0, 0));
201             }
202         }
203         break;
204 
205 #ifdef DBG_UTIL
206     case FLY_AT_PAGE:
207     case FLY_AT_CHAR:
208     case FLY_AT_FLY:
209     case FLY_AT_PARA:
210     case FLY_AS_CHAR:
211         ASSERT( false, "use new interface instead: SwDoc::MakeFlySection!" );
212         break;
213 #endif
214 
215     default:
216         ASSERT( !this,
217                 "Layoutformat mit ungueltigem Request angefordert." );
218 
219     }
220     return pFmt;
221 }
222 /*************************************************************************
223 |*
224 |*  SwDoc::DelLayoutFmt()
225 |*
226 |*  Beschreibung        Loescht das angegebene Format, der Inhalt wird mit
227 |*      geloescht.
228 |*  Ersterstellung      MA 23. Sep. 92
229 |*  Letzte Aenderung    MA 05. Feb. 93
230 |*
231 |*************************************************************************/
232 
233 void SwDoc::DelLayoutFmt( SwFrmFmt *pFmt )
234 {
235     //Verkettung von Rahmen muss ggf. zusammengefuehrt werden.
236     //Bevor die Frames vernichtet werden, damit die Inhalte der Rahmen
237     //ggf. entsprechend gerichtet werden.
238     const SwFmtChain &rChain = pFmt->GetChain();
239     if ( rChain.GetPrev() )
240     {
241         SwFmtChain aChain( rChain.GetPrev()->GetChain() );
242         aChain.SetNext( rChain.GetNext() );
243         SetAttr( aChain, *rChain.GetPrev() );
244     }
245     if ( rChain.GetNext() )
246     {
247         SwFmtChain aChain( rChain.GetNext()->GetChain() );
248         aChain.SetPrev( rChain.GetPrev() );
249         SetAttr( aChain, *rChain.GetNext() );
250     }
251 
252     const SwNodeIndex* pCntIdx = pFmt->GetCntnt().GetCntntIdx();
253     if (pCntIdx && !GetIDocumentUndoRedo().DoesUndo())
254     {
255         //Verbindung abbauen, falls es sich um ein OLE-Objekt handelt.
256         SwOLENode* pOLENd = GetNodes()[ pCntIdx->GetIndex()+1 ]->GetOLENode();
257         if( pOLENd && pOLENd->GetOLEObj().IsOleRef() )
258         {
259             /*
260             SwDoc* pDoc = (SwDoc*)pFmt->GetDoc();
261             if( pDoc )
262             {
263                 SfxObjectShell* p = pDoc->GetPersist();
264                 if( p )     // muss da sein
265                 {
266                     SvInfoObjectRef aRef( p->Find( pOLENd->GetOLEObj().GetName() ) );
267                     if( aRef.Is() )
268                         aRef->SetObj(0);
269                 }
270             } */
271 
272             // TODO/MBA: the old object closed the object, cleared all references to it, but didn't remove it from the container.
273             // I have no idea, why, nobody could explain it - so I do my very best to mimic this behavior
274             //uno::Reference < util::XCloseable > xClose( pOLENd->GetOLEObj().GetOleRef(), uno::UNO_QUERY );
275             //if ( xClose.is() )
276             {
277                 try
278                 {
279                     pOLENd->GetOLEObj().GetOleRef()->changeState( embed::EmbedStates::LOADED );
280                 }
281                 catch ( uno::Exception& )
282                 {
283                 }
284             }
285 
286             //pOLENd->GetOLEObj().GetOleRef() = 0;
287         }
288     }
289 
290     //Frms vernichten.
291     pFmt->DelFrms();
292 
293     // erstmal sind nur Fly's Undofaehig
294     const sal_uInt16 nWh = pFmt->Which();
295     if (GetIDocumentUndoRedo().DoesUndo() &&
296         (RES_FLYFRMFMT == nWh || RES_DRAWFRMFMT == nWh))
297     {
298         GetIDocumentUndoRedo().AppendUndo( new SwUndoDelLayFmt( pFmt ));
299     }
300     else
301     {
302         // --> OD 2004-07-26 #i32089# - delete at-frame anchored objects
303         if ( nWh == RES_FLYFRMFMT )
304         {
305             // determine frame formats of at-frame anchored objects
306             const SwNodeIndex* pCntntIdx = pFmt->GetCntnt().GetCntntIdx();
307             if ( pCntntIdx )
308             {
309                 const SwSpzFrmFmts* pTbl = pFmt->GetDoc()->GetSpzFrmFmts();
310                 if ( pTbl )
311                 {
312                     std::vector<SwFrmFmt*> aToDeleteFrmFmts;
313                     const sal_uLong nNodeIdxOfFlyFmt( pCntntIdx->GetIndex() );
314 
315                     for ( sal_uInt16 i = 0; i < pTbl->Count(); ++i )
316                     {
317                         SwFrmFmt* pTmpFmt = (*pTbl)[i];
318                         const SwFmtAnchor &rAnch = pTmpFmt->GetAnchor();
319                         if ( rAnch.GetAnchorId() == FLY_AT_FLY &&
320                              rAnch.GetCntntAnchor()->nNode.GetIndex() == nNodeIdxOfFlyFmt )
321                         {
322                             aToDeleteFrmFmts.push_back( pTmpFmt );
323                         }
324                     }
325 
326                     // delete found frame formats
327                     while ( !aToDeleteFrmFmts.empty() )
328                     {
329                         SwFrmFmt* pTmpFmt = aToDeleteFrmFmts.back();
330                         pFmt->GetDoc()->DelLayoutFmt( pTmpFmt );
331 
332                         aToDeleteFrmFmts.pop_back();
333                     }
334                 }
335             }
336         }
337         // <--
338 
339         //Inhalt Loeschen.
340         if( pCntIdx )
341         {
342             SwNode *pNode = &pCntIdx->GetNode();
343             ((SwFmtCntnt&)pFmt->GetFmtAttr( RES_CNTNT )).SetNewCntntIdx( 0 );
344             DeleteSection( pNode );
345         }
346 
347         // ggfs. bei Zeichengebundenen Flys das Zeichen loeschen
348         const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
349         if ((FLY_AS_CHAR == rAnchor.GetAnchorId()) && rAnchor.GetCntntAnchor())
350         {
351             const SwPosition* pPos = rAnchor.GetCntntAnchor();
352             SwTxtNode *pTxtNd = pPos->nNode.GetNode().GetTxtNode();
353 
354             // attribute is still in text node, delete it
355             if ( pTxtNd )
356             {
357                 SwTxtFlyCnt* const pAttr = static_cast<SwTxtFlyCnt*>(
358                     pTxtNd->GetTxtAttrForCharAt( pPos->nContent.GetIndex(),
359                         RES_TXTATR_FLYCNT ));
360                 if ( pAttr && (pAttr->GetFlyCnt().GetFrmFmt() == pFmt) )
361                 {
362                     // dont delete, set pointer to 0
363                     const_cast<SwFmtFlyCnt&>(pAttr->GetFlyCnt()).SetFlyFmt();
364                     SwIndex aIdx( pPos->nContent );
365                     pTxtNd->EraseText( aIdx, 1 );
366                 }
367             }
368         }
369 
370         DelFrmFmt( pFmt );
371     }
372     SetModified();
373 }
374 
375 /*************************************************************************
376 |*
377 |*  SwDoc::CopyLayoutFmt()
378 |*
379 |*  Beschreibung        Kopiert das angegebene Format pSrc in pDest und
380 |*                      returnt pDest. Wenn es noch kein pDest gibt, wird
381 |*                      eins angelegt.
382 |*                      JP: steht das Source Format in einem anderen
383 |*                          Dokument, so kopiere auch dann noch richtig !!
384 |*                          Vom chaos::Anchor-Attribut wird die Position immer
385 |*                          auf 0 gesetzt !!!
386 |*
387 |*  Ersterstellung      BP 18.12.92
388 |*  Letzte Aenderung    MA 17. Jul. 96
389 |*
390 |*************************************************************************/
391 
392 SwFrmFmt *SwDoc::CopyLayoutFmt(
393     const SwFrmFmt& rSource,
394     const SwFmtAnchor& rNewAnchor,
395     bool bSetTxtFlyAtt,
396     bool bMakeFrms )
397 {
398     const bool bFly = RES_FLYFRMFMT == rSource.Which();
399     const bool bDraw = RES_DRAWFRMFMT == rSource.Which();
400     ASSERT( bFly || bDraw, "this method only works for fly or draw" );
401 
402     SwDoc* pSrcDoc = (SwDoc*)rSource.GetDoc();
403 
404     // #108784# may we copy this object?
405     // We may, unless it's 1) it's a control (and therfore a draw)
406     //                     2) anchored in a header/footer
407     //                     3) anchored (to paragraph?)
408     bool bMayNotCopy = false;
409     if( bDraw )
410     {
411         const SwDrawContact* pDrawContact =
412             static_cast<const SwDrawContact*>( rSource.FindContactObj() );
413 
414         bMayNotCopy =
415             ((FLY_AT_PARA == rNewAnchor.GetAnchorId()) ||
416              (FLY_AT_FLY  == rNewAnchor.GetAnchorId()) ||
417              (FLY_AT_CHAR == rNewAnchor.GetAnchorId())) &&
418             rNewAnchor.GetCntntAnchor() &&
419             IsInHeaderFooter( rNewAnchor.GetCntntAnchor()->nNode ) &&
420             pDrawContact != NULL  &&
421             pDrawContact->GetMaster() != NULL  &&
422             CheckControlLayer( pDrawContact->GetMaster() );
423     }
424 
425     // just return if we can't copy this
426     if( bMayNotCopy )
427         return NULL;
428 
429     SwFrmFmt* pDest = GetDfltFrmFmt();
430     if( rSource.GetRegisteredIn() != pSrcDoc->GetDfltFrmFmt() )
431         pDest = CopyFrmFmt( *(SwFrmFmt*)rSource.GetRegisteredIn() );
432     if( bFly )
433     {
434         // #i11176#
435         // To do a correct cloning concerning the ZOrder for all objects
436         // it is necessary to actually create a draw object for fly frames, too.
437         // These are then added to the DrawingLayer (which needs to exist).
438         // Together with correct sorting of all drawinglayer based objects
439         // before cloning ZOrder transfer works correctly then.
440         SwFlyFrmFmt *pFormat = MakeFlyFrmFmt( rSource.GetName(), pDest );
441         pDest = pFormat;
442 
443         SwXFrame::GetOrCreateSdrObject(pFormat);
444     }
445     else
446         pDest = MakeDrawFrmFmt( aEmptyStr, pDest );
447 
448     // alle anderen/neue Attribute kopieren.
449     pDest->CopyAttrs( rSource );
450 
451     //Chains werden nicht kopiert.
452     pDest->ResetFmtAttr( RES_CHAIN );
453 
454     if( bFly )
455     {
456         //Der Inhalt wird dupliziert.
457         const SwNode& rCSttNd = rSource.GetCntnt().GetCntntIdx()->GetNode();
458         SwNodeRange aRg( rCSttNd, 1, *rCSttNd.EndOfSectionNode() );
459 
460         SwNodeIndex aIdx( GetNodes().GetEndOfAutotext() );
461         SwStartNode* pSttNd = GetNodes().MakeEmptySection( aIdx, SwFlyStartNode );
462 
463         // erst den chaos::Anchor/CntntIndex setzen, innerhalb des Kopierens
464         // auf die Werte zugegriffen werden kann (DrawFmt in Kopf-/Fusszeilen)
465         aIdx = *pSttNd;
466         SwFmtCntnt aAttr( rSource.GetCntnt() );
467         aAttr.SetNewCntntIdx( &aIdx );
468         pDest->SetFmtAttr( aAttr );
469         pDest->SetFmtAttr( rNewAnchor );
470 
471         if( !mbCopyIsMove || this != pSrcDoc )
472         {
473             if( mbInReading )
474                 pDest->SetName( aEmptyStr );
475             else
476             {
477                 // Teste erstmal ob der Name schon vergeben ist.
478                 // Wenn ja -> neuen generieren
479                 sal_Int8 nNdTyp = aRg.aStart.GetNode().GetNodeType();
480 
481                 String sOld( pDest->GetName() );
482                 pDest->SetName( aEmptyStr );
483                 if( FindFlyByName( sOld, nNdTyp ) )     // einen gefunden
484                     switch( nNdTyp )
485                     {
486                     case ND_GRFNODE:    sOld = GetUniqueGrfName();      break;
487                     case ND_OLENODE:    sOld = GetUniqueOLEName();      break;
488                     default:            sOld = GetUniqueFrameName();    break;
489                     }
490 
491                 pDest->SetName( sOld );
492             }
493         }
494 
495         if (GetIDocumentUndoRedo().DoesUndo())
496         {
497             GetIDocumentUndoRedo().AppendUndo(new SwUndoInsLayFmt(pDest,0,0));
498         }
499 
500         // sorge dafuer das auch Fly's in Fly's kopiert werden
501         aIdx = *pSttNd->EndOfSectionNode();
502         pSrcDoc->CopyWithFlyInFly( aRg, 0, aIdx, NULL, sal_False, sal_True, sal_True );
503     }
504     else
505     {
506         ASSERT( RES_DRAWFRMFMT == rSource.Which(), "Weder Fly noch Draw." );
507         // OD 2005-08-02 #i52780# - Note: moving object to visible layer not needed.
508         SwDrawContact* pSourceContact = (SwDrawContact *)rSource.FindContactObj();
509 
510         SwDrawContact* pContact = new SwDrawContact( (SwDrawFrmFmt*)pDest,
511                                 CloneSdrObj( *pSourceContact->GetMaster(),
512                                         mbCopyIsMove && this == pSrcDoc ) );
513         // --> OD 2005-05-23 #i49730# - notify draw frame format
514         // that position attributes are already set, if the position attributes
515         // are already set at the source draw frame format.
516         if ( pDest->ISA(SwDrawFrmFmt) &&
517              rSource.ISA(SwDrawFrmFmt) &&
518              static_cast<const SwDrawFrmFmt&>(rSource).IsPosAttrSet() )
519         {
520             static_cast<SwDrawFrmFmt*>(pDest)->PosAttrSet();
521         }
522         // <--
523 
524         if( pDest->GetAnchor() == rNewAnchor )
525         {
526             // OD 03.07.2003 #108784# - do *not* connect to layout, if
527             // a <MakeFrms> will not be called.
528             if ( bMakeFrms )
529             {
530                 pContact->ConnectToLayout( &rNewAnchor );
531             }
532         }
533         else
534             pDest->SetFmtAttr( rNewAnchor );
535 
536         if (GetIDocumentUndoRedo().DoesUndo())
537         {
538             GetIDocumentUndoRedo().AppendUndo(new SwUndoInsLayFmt(pDest,0,0));
539         }
540     }
541 
542     if (bSetTxtFlyAtt && (FLY_AS_CHAR == rNewAnchor.GetAnchorId()))
543     {
544         const SwPosition* pPos = rNewAnchor.GetCntntAnchor();
545         SwFmtFlyCnt aFmt( pDest );
546         pPos->nNode.GetNode().GetTxtNode()->InsertItem(
547             aFmt, pPos->nContent.GetIndex(), 0 );
548     }
549 
550     if( bMakeFrms )
551         pDest->MakeFrms();
552 
553     return pDest;
554 }
555 
556 SdrObject* SwDoc::CloneSdrObj( const SdrObject& rObj, sal_Bool bMoveWithinDoc,
557                                 sal_Bool bInsInPage )
558 {
559     // --> OD 2005-08-08 #i52858# - method name changed
560     SdrPage *pPg = GetOrCreateDrawModel()->GetPage( 0 );
561     // <--
562     if( !pPg )
563     {
564         pPg = GetDrawModel()->AllocPage( sal_False );
565         GetDrawModel()->InsertPage( pPg );
566     }
567 
568     SdrObject *pObj = rObj.Clone();
569     if( bMoveWithinDoc && FmFormInventor == pObj->GetObjInventor() )
570     {
571         // bei Controls muss der Name erhalten bleiben
572         uno::Reference< awt::XControlModel >  xModel = ((SdrUnoObj*)pObj)->GetUnoControlModel();
573         uno::Any aVal;
574         uno::Reference< beans::XPropertySet >  xSet(xModel, uno::UNO_QUERY);
575         OUString sName( rtl::OUString::createFromAscii("Name") );
576         if( xSet.is() )
577             aVal = xSet->getPropertyValue( sName );
578         if( bInsInPage )
579             pPg->InsertObject( pObj );
580         if( xSet.is() )
581             xSet->setPropertyValue( sName, aVal );
582     }
583     else if( bInsInPage )
584         pPg->InsertObject( pObj );
585 
586     // OD 02.07.2003 #108784# - for drawing objects: set layer of cloned object
587     // to invisible layer
588     SdrLayerID nLayerIdForClone = rObj.GetLayer();
589     if ( !pObj->ISA(SwFlyDrawObj) &&
590          !pObj->ISA(SwVirtFlyDrawObj) &&
591          !IS_TYPE(SdrObject,pObj) )
592     {
593         if ( IsVisibleLayerId( nLayerIdForClone ) )
594         {
595             nLayerIdForClone = GetInvisibleLayerIdByVisibleOne( nLayerIdForClone );
596         }
597     }
598     pObj->SetLayer( nLayerIdForClone );
599 
600 
601     return pObj;
602 }
603 
604 SwFlyFrmFmt* SwDoc::_MakeFlySection( const SwPosition& rAnchPos,
605                                     const SwCntntNode& rNode,
606                                     RndStdIds eRequestId,
607                                     const SfxItemSet* pFlySet,
608                                     SwFrmFmt* pFrmFmt )
609 {
610     if( !pFrmFmt )
611         pFrmFmt = GetFrmFmtFromPool( RES_POOLFRM_FRAME );
612 
613     String sName;
614     if( !mbInReading )
615         switch( rNode.GetNodeType() )
616         {
617         case ND_GRFNODE:        sName = GetUniqueGrfName();     break;
618         case ND_OLENODE:        sName = GetUniqueOLEName();     break;
619         default:                sName = GetUniqueFrameName();       break;
620         }
621     SwFlyFrmFmt* pFmt = MakeFlyFrmFmt( sName, pFrmFmt );
622 
623     //Inhalt erzeugen und mit dem Format verbinden.
624     //CntntNode erzeugen und in die Autotextsection stellen
625     SwNodeRange aRange( GetNodes().GetEndOfAutotext(), -1,
626                         GetNodes().GetEndOfAutotext() );
627     GetNodes().SectionDown( &aRange, SwFlyStartNode );
628 
629     pFmt->SetFmtAttr( SwFmtCntnt( rNode.StartOfSectionNode() ));
630 
631 
632     const SwFmtAnchor* pAnchor = 0;
633     if( pFlySet )
634     {
635         pFlySet->GetItemState( RES_ANCHOR, sal_False,
636                                 (const SfxPoolItem**)&pAnchor );
637         if( SFX_ITEM_SET == pFlySet->GetItemState( RES_CNTNT, sal_False ))
638         {
639             SfxItemSet aTmpSet( *pFlySet );
640             aTmpSet.ClearItem( RES_CNTNT );
641             pFmt->SetFmtAttr( aTmpSet );
642         }
643         else
644             pFmt->SetFmtAttr( *pFlySet );
645     }
646 
647     // Anker noch nicht gesetzt ?
648     RndStdIds eAnchorId = pAnchor ? pAnchor->GetAnchorId()
649                                   : pFmt->GetAnchor().GetAnchorId();
650     // --> OD 2010-01-07 #i107811#
651     // Assure that at-page anchored fly frames have a page num or a content anchor set.
652     if ( !pAnchor ||
653          ( FLY_AT_PAGE != pAnchor->GetAnchorId() &&
654            !pAnchor->GetCntntAnchor() ) ||
655          ( FLY_AT_PAGE == pAnchor->GetAnchorId() &&
656            !pAnchor->GetCntntAnchor() &&
657            pAnchor->GetPageNum() == 0 ) )
658     {
659         // dann setze ihn, wird im Undo gebraucht
660         SwFmtAnchor aAnch( pFmt->GetAnchor() );
661         if (pAnchor && (FLY_AT_FLY == pAnchor->GetAnchorId()))
662         {
663             SwPosition aPos( *rAnchPos.nNode.GetNode().FindFlyStartNode() );
664             aAnch.SetAnchor( &aPos );
665             eAnchorId = FLY_AT_FLY;
666         }
667         else
668         {
669             if( eRequestId != aAnch.GetAnchorId() &&
670                 SFX_ITEM_SET != pFmt->GetItemState( RES_ANCHOR, sal_True ) )
671             {
672                 aAnch.SetType( eRequestId );
673             }
674 
675             eAnchorId = aAnch.GetAnchorId();
676             if ( FLY_AT_PAGE != eAnchorId ||
677                  ( FLY_AT_PAGE == eAnchorId &&
678                    ( !pAnchor ||
679                      aAnch.GetPageNum() == 0 ) ) )
680             {
681                 aAnch.SetAnchor( &rAnchPos );
682             }
683         }
684         // <--
685         pFmt->SetFmtAttr( aAnch );
686     }
687     else
688         eAnchorId = pFmt->GetAnchor().GetAnchorId();
689 
690     if ( FLY_AS_CHAR == eAnchorId )
691     {
692         xub_StrLen nStt = rAnchPos.nContent.GetIndex();
693         SwTxtNode * pTxtNode = rAnchPos.nNode.GetNode().GetTxtNode();
694 
695         ASSERT(pTxtNode!= 0, "There should be a SwTxtNode!");
696 
697         if (pTxtNode != NULL)
698         {
699             SwFmtFlyCnt aFmt( pFmt );
700             pTxtNode->InsertItem( aFmt, nStt, nStt );
701         }
702     }
703 
704     if( SFX_ITEM_SET != pFmt->GetAttrSet().GetItemState( RES_FRM_SIZE ))
705     {
706         SwFmtFrmSize aFmtSize( ATT_VAR_SIZE, 0, DEF_FLY_WIDTH );
707         const SwNoTxtNode* pNoTxtNode = rNode.GetNoTxtNode();
708         if( pNoTxtNode )
709         {
710             //Groesse einstellen.
711             Size aSize( pNoTxtNode->GetTwipSize() );
712             if( MINFLY > aSize.Width() )
713                 aSize.Width() = DEF_FLY_WIDTH;
714             aFmtSize.SetWidth( aSize.Width() );
715             if( aSize.Height() )
716             {
717                 aFmtSize.SetHeight( aSize.Height() );
718                 aFmtSize.SetHeightSizeType( ATT_FIX_SIZE );
719             }
720         }
721         pFmt->SetFmtAttr( aFmtSize );
722     }
723 
724     // Frames anlegen
725     if( GetCurrentViewShell() )
726         pFmt->MakeFrms();           // ???  //swmod 071108//swmod 071225
727 
728     if (GetIDocumentUndoRedo().DoesUndo())
729     {
730         sal_uLong nNodeIdx = rAnchPos.nNode.GetIndex();
731         xub_StrLen nCntIdx = rAnchPos.nContent.GetIndex();
732         GetIDocumentUndoRedo().AppendUndo(
733             new SwUndoInsLayFmt( pFmt, nNodeIdx, nCntIdx ));
734     }
735 
736     SetModified();
737     return pFmt;
738 }
739 
740 SwFlyFrmFmt* SwDoc::MakeFlySection( RndStdIds eAnchorType,
741                                     const SwPosition* pAnchorPos,
742                                     const SfxItemSet* pFlySet,
743                                     SwFrmFmt* pFrmFmt, sal_Bool bCalledFromShell )
744 {
745     SwFlyFrmFmt* pFmt = 0;
746     sal_Bool bCallMake = sal_True;
747     if ( !pAnchorPos && (FLY_AT_PAGE != eAnchorType) )
748     {
749         const SwFmtAnchor* pAnch;
750         if( (pFlySet && SFX_ITEM_SET == pFlySet->GetItemState(
751                 RES_ANCHOR, sal_False, (const SfxPoolItem**)&pAnch )) ||
752             ( pFrmFmt && SFX_ITEM_SET == pFrmFmt->GetItemState(
753                 RES_ANCHOR, sal_True, (const SfxPoolItem**)&pAnch )) )
754         {
755             if ( (FLY_AT_PAGE != pAnch->GetAnchorId()) )
756             {
757                 pAnchorPos = pAnch->GetCntntAnchor();
758                 if (pAnchorPos)
759                 {
760                     bCallMake = sal_False;
761                 }
762             }
763         }
764     }
765 
766     if( bCallMake )
767     {
768         if( !pFrmFmt )
769             pFrmFmt = GetFrmFmtFromPool( RES_POOLFRM_FRAME );
770 
771         sal_uInt16 nCollId = static_cast<sal_uInt16>(
772             get(IDocumentSettingAccess::HTML_MODE) ? RES_POOLCOLL_TEXT : RES_POOLCOLL_FRAME );
773 
774         /* #109161# If there exists no adjust item in the paragraph
775             style for the content node of the new fly section
776             propagate an existing adjust item at the anchor to the new
777             content node. */
778         SwCntntNode * pNewTxtNd = GetNodes().MakeTxtNode
779             (SwNodeIndex( GetNodes().GetEndOfAutotext()),
780              GetTxtCollFromPool( nCollId ));
781         SwCntntNode * pAnchorNode = pAnchorPos->nNode.GetNode().GetCntntNode();
782 
783         const SfxPoolItem * pItem = NULL;
784 
785         if (bCalledFromShell && !lcl_IsItemSet(*pNewTxtNd, RES_PARATR_ADJUST) &&
786             SFX_ITEM_SET == pAnchorNode->GetSwAttrSet().
787             GetItemState(RES_PARATR_ADJUST, sal_True, &pItem))
788             static_cast<SwCntntNode *>(pNewTxtNd)->SetAttr(*pItem);
789 
790         pFmt = _MakeFlySection( *pAnchorPos, *pNewTxtNd,
791                                 eAnchorType, pFlySet, pFrmFmt );
792     }
793     return pFmt;
794 }
795 
796 SwFlyFrmFmt* SwDoc::MakeFlyAndMove( const SwPaM& rPam, const SfxItemSet& rSet,
797                                     const SwSelBoxes* pSelBoxes,
798                                     SwFrmFmt *pParent )
799 {
800     SwFmtAnchor& rAnch = (SwFmtAnchor&)rSet.Get( RES_ANCHOR );
801 
802     GetIDocumentUndoRedo().StartUndo( UNDO_INSLAYFMT, NULL );
803 
804     SwFlyFrmFmt* pFmt = MakeFlySection( rAnch.GetAnchorId(), rPam.GetPoint(),
805                                         &rSet, pParent );
806 
807     // Wenn Inhalt selektiert ist, so wird dieser jetzt zum Inhalt des
808     // neuen Rahmen. Sprich er wird in die entspr. Sektion des NodesArr
809     //gemoved.
810 
811     if( pFmt )
812     {
813         do {        // middle check loop
814             const SwFmtCntnt &rCntnt = pFmt->GetCntnt();
815             ASSERT( rCntnt.GetCntntIdx(), "Kein Inhalt vorbereitet." );
816             SwNodeIndex aIndex( *(rCntnt.GetCntntIdx()), 1 );
817             SwCntntNode *pNode = aIndex.GetNode().GetCntntNode();
818 
819             // ACHTUNG: nicht einen Index auf dem Stack erzeugen, sonst
820             //          kann der CntntnNode am Ende nicht geloscht werden !!
821             SwPosition aPos( aIndex );
822             aPos.nContent.Assign( pNode, 0 );
823 
824             if( pSelBoxes && pSelBoxes->Count() )
825             {
826                 // Tabellenselection
827                 // kopiere Teile aus einer Tabelle: lege eine Tabelle mit der
828                 // Breite der Originalen an und move (kopiere/loesche) die
829                 // selektierten Boxen. Die Groessen werden prozentual
830                 // korrigiert.
831 
832                 SwTableNode* pTblNd = (SwTableNode*)(*pSelBoxes)[0]->
833                                                 GetSttNd()->FindTableNode();
834                 if( !pTblNd )
835                     break;
836 
837                 SwTable& rTbl = pTblNd->GetTable();
838 
839                 // ist die gesamte Tabelle selektiert ?
840                 if( pSelBoxes->Count() == rTbl.GetTabSortBoxes().Count() )
841                 {
842                     // verschiebe die gesamte Tabelle
843                     SwNodeRange aRg( *pTblNd, 0, *pTblNd->EndOfSectionNode(), 1 );
844 
845                     // wird die gesamte Tabelle verschoben und steht diese
846                     // in einem FlyFrame, dann erzeuge dahinter einen neuen
847                     // TextNode. Dadurch bleibt dieser Fly erhalten !
848                     if( aRg.aEnd.GetNode().IsEndNode() )
849                         GetNodes().MakeTxtNode( aRg.aStart,
850                                     (SwTxtFmtColl*)GetDfltTxtFmtColl() );
851 
852                     MoveNodeRange( aRg, aPos.nNode, DOC_MOVEDEFAULT );
853                 }
854                 else
855                 {
856                     rTbl.MakeCopy( this, aPos, *pSelBoxes );
857                     // Don't delete a part of a table with row span!!
858                     // You could delete the content instead -> ToDo
859                     //rTbl.DeleteSel( this, *pSelBoxes, 0, 0, sal_True, sal_True );
860                 }
861 
862                 // wenn Tabelle im Rahmen, dann ohne nachfolgenden TextNode
863                 aIndex = rCntnt.GetCntntIdx()->GetNode().EndOfSectionIndex() - 1;
864                 ASSERT( aIndex.GetNode().GetTxtNode(),
865                         "hier sollte ein TextNode stehen" );
866                 aPos.nContent.Assign( 0, 0 );       // Index abmelden !!
867                 GetNodes().Delete( aIndex, 1 );
868 
869 //JP erstmal ein Hack, solange keine Flys/Headers/Footers Undofaehig sind
870 // werden erstmal alle Undo - Objecte geloescht.
871 if( GetIDocumentUndoRedo().DoesUndo() )
872 {
873     GetIDocumentUndoRedo().DelAllUndoObj();
874 }
875 
876             }
877             else
878             {
879 /*
880                 // alle Pams verschieben
881                 SwPaM* pTmp = (SwPaM*)&rPam;
882                 do {
883                     if( pTmp->HasMark() &&
884                         *pTmp->GetPoint() != *pTmp->GetMark() )
885                         MoveAndJoin( *pTmp, aPos );
886                 } while( &rPam != ( pTmp = (SwPaM*)pTmp->GetNext() ) );
887 */
888                 // copy all Pams and then delete all
889                 SwPaM* pTmp = (SwPaM*)&rPam;
890                 sal_Bool bOldFlag = mbCopyIsMove;
891                 bool const bOldUndo = GetIDocumentUndoRedo().DoesUndo();
892                 mbCopyIsMove = sal_True;
893                 GetIDocumentUndoRedo().DoUndo(false);
894                 do {
895                     if( pTmp->HasMark() &&
896                         *pTmp->GetPoint() != *pTmp->GetMark() )
897                     {
898                         CopyRange( *pTmp, aPos, false );
899                     }
900                     pTmp = static_cast<SwPaM*>(pTmp->GetNext());
901                 } while ( &rPam != pTmp );
902                 mbCopyIsMove = bOldFlag;
903                 GetIDocumentUndoRedo().DoUndo(bOldUndo);
904 
905                 pTmp = (SwPaM*)&rPam;
906                 do {
907                     if( pTmp->HasMark() &&
908                         *pTmp->GetPoint() != *pTmp->GetMark() )
909                     {
910                         DeleteAndJoin( *pTmp );
911                     }
912                     pTmp = static_cast<SwPaM*>(pTmp->GetNext());
913                 } while ( &rPam != pTmp );
914             }
915         } while( sal_False );
916     }
917 
918     SetModified();
919 
920     GetIDocumentUndoRedo().EndUndo( UNDO_INSLAYFMT, NULL );
921 
922     return pFmt;
923 }
924 
925 
926     //Einfuegen eines DrawObjectes. Das Object muss bereits im DrawModel
927     // angemeldet sein.
928 SwDrawFrmFmt* SwDoc::Insert( const SwPaM &rRg,
929                              SdrObject& rDrawObj,
930                              const SfxItemSet* pFlyAttrSet,
931                              SwFrmFmt* pDefFmt )
932 {
933     SwDrawFrmFmt *pFmt = MakeDrawFrmFmt( aEmptyStr,
934                                         pDefFmt ? pDefFmt : GetDfltFrmFmt() );
935 
936     const SwFmtAnchor* pAnchor = 0;
937     if( pFlyAttrSet )
938     {
939         pFlyAttrSet->GetItemState( RES_ANCHOR, sal_False,
940                                     (const SfxPoolItem**)&pAnchor );
941         pFmt->SetFmtAttr( *pFlyAttrSet );
942     }
943 
944     RndStdIds eAnchorId = pAnchor ? pAnchor->GetAnchorId()
945                                   : pFmt->GetAnchor().GetAnchorId();
946 
947     // Anker noch nicht gesetzt ?
948     // DrawObjecte duerfen niemals in Kopf-/Fusszeilen landen.
949     const bool bIsAtCntnt = (FLY_AT_PAGE != eAnchorId);
950 
951     const SwNodeIndex* pChkIdx = 0;
952     if( !pAnchor )
953     {
954         pChkIdx = &rRg.GetPoint()->nNode;
955     }
956     else if( bIsAtCntnt )
957     {
958         pChkIdx = pAnchor->GetCntntAnchor()
959                     ? &pAnchor->GetCntntAnchor()->nNode
960                     : &rRg.GetPoint()->nNode;
961     }
962 
963     // OD 24.06.2003 #108784# - allow drawing objects in header/footer, but
964     // control objects aren't allowed in header/footer.
965     if( pChkIdx &&
966         ::CheckControlLayer( &rDrawObj ) &&
967         IsInHeaderFooter( *pChkIdx ) )
968     {
969        pFmt->SetFmtAttr( SwFmtAnchor( eAnchorId = FLY_AT_PAGE ) );
970     }
971     else if( !pAnchor || (bIsAtCntnt && !pAnchor->GetCntntAnchor() ))
972     {
973         // dann setze ihn, wird im Undo gebraucht
974         SwFmtAnchor aAnch( pAnchor ? *pAnchor : pFmt->GetAnchor() );
975         eAnchorId = aAnch.GetAnchorId();
976         if( FLY_AT_FLY == eAnchorId )
977         {
978             SwPosition aPos( *rRg.GetNode()->FindFlyStartNode() );
979             aAnch.SetAnchor( &aPos );
980         }
981         else
982         {
983             aAnch.SetAnchor( rRg.GetPoint() );
984             if ( FLY_AT_PAGE == eAnchorId )
985             {
986                 eAnchorId = rDrawObj.ISA( SdrUnoObj )
987                                     ? FLY_AS_CHAR : FLY_AT_PARA;
988                 aAnch.SetType( eAnchorId );
989             }
990         }
991         pFmt->SetFmtAttr( aAnch );
992     }
993 
994     // bei als Zeichen gebundenen Draws das Attribut im Absatz setzen
995     if ( FLY_AS_CHAR == eAnchorId )
996     {
997         xub_StrLen nStt = rRg.GetPoint()->nContent.GetIndex();
998         SwFmtFlyCnt aFmt( pFmt );
999         rRg.GetPoint()->nNode.GetNode().GetTxtNode()->InsertItem(
1000                 aFmt, nStt, nStt );
1001     }
1002 
1003     SwDrawContact* pContact = new SwDrawContact( pFmt, &rDrawObj );
1004 
1005     // ggfs. Frames anlegen
1006     if( GetCurrentViewShell() )
1007     {
1008         pFmt->MakeFrms();
1009         // --> OD 2005-02-09 #i42319# - follow-up of #i35635#
1010         // move object to visible layer
1011         // --> OD 2007-07-10 #i79391#
1012         if ( pContact->GetAnchorFrm() )
1013         {
1014             pContact->MoveObjToVisibleLayer( &rDrawObj );
1015         }
1016         // <--
1017     }
1018 
1019     if (GetIDocumentUndoRedo().DoesUndo())
1020     {
1021         GetIDocumentUndoRedo().AppendUndo( new SwUndoInsLayFmt(pFmt, 0, 0) );
1022     }
1023 
1024     SetModified();
1025     return pFmt;
1026 }
1027 
1028 /*************************************************************************
1029 |*
1030 |*  SwDoc::GetAllFlyFmts
1031 |*
1032 |*  Ersterstellung      MA 14. Jul. 93
1033 |*  Letzte Aenderung    MD 23. Feb. 95
1034 |*
1035 |*************************************************************************/
1036 
1037 /*sal_Bool TstFlyRange( const SwPaM* pPam, sal_uInt32 nFlyPos )
1038 {
1039     sal_Bool bOk = sal_False;
1040     const SwPaM* pTmp = pPam;
1041     do {
1042         bOk = pTmp->Start()->nNode.GetIndex() < nFlyPos &&
1043                 pTmp->End()->nNode.GetIndex() > nFlyPos;
1044     } while( !bOk && pPam != ( pTmp = (const SwPaM*)pTmp->GetNext() ));
1045     return bOk;
1046 }
1047 */
1048 /* -----------------------------04.04.00 10:55--------------------------------
1049     paragraph frames - o.k. if the PaM includes the paragraph from the beginning
1050                        to the beginning of the next paragraph at least
1051     frames at character - o.k. if the pam start at least at the same position
1052                         as the frame
1053  ---------------------------------------------------------------------------*/
1054 sal_Bool TstFlyRange( const SwPaM* pPam, const SwPosition* pFlyPos,
1055                         RndStdIds nAnchorId )
1056 {
1057     sal_Bool bOk = sal_False;
1058     const SwPaM* pTmp = pPam;
1059     do {
1060         const sal_uInt32 nFlyIndex = pFlyPos->nNode.GetIndex();
1061         const SwPosition* pPaMStart = pTmp->Start();
1062         const SwPosition* pPaMEnd = pTmp->End();
1063         const sal_uInt32 nPamStartIndex = pPaMStart->nNode.GetIndex();
1064         const sal_uInt32 nPamEndIndex = pPaMEnd->nNode.GetIndex();
1065         if (FLY_AT_PARA == nAnchorId)
1066             bOk = (nPamStartIndex < nFlyIndex && nPamEndIndex > nFlyIndex) ||
1067                (((nPamStartIndex == nFlyIndex) && (pPaMStart->nContent.GetIndex() == 0)) &&
1068                (nPamEndIndex > nFlyIndex));
1069         else
1070         {
1071             xub_StrLen nFlyContentIndex = pFlyPos->nContent.GetIndex();
1072             xub_StrLen nPamEndContentIndex = pPaMEnd->nContent.GetIndex();
1073             bOk = (nPamStartIndex < nFlyIndex &&
1074                 (( nPamEndIndex > nFlyIndex )||
1075                  ((nPamEndIndex == nFlyIndex) &&
1076                   (nPamEndContentIndex > nFlyContentIndex))) )
1077                 ||
1078                     (((nPamStartIndex == nFlyIndex) &&
1079                       (pPaMStart->nContent.GetIndex() <= nFlyContentIndex)) &&
1080                      ((nPamEndIndex > nFlyIndex) ||
1081                      (nPamEndContentIndex > nFlyContentIndex )));
1082         }
1083 
1084     } while( !bOk && pPam != ( pTmp = (const SwPaM*)pTmp->GetNext() ));
1085     return bOk;
1086 }
1087 
1088 
1089 SwPosFlyFrms SwDoc::GetAllFlyFmts( const SwPaM* pCmpRange, sal_Bool bDrawAlso ) const
1090 {
1091     SwPosFlyFrms aRetval;
1092     SwFrmFmt *pFly;
1093 
1094     // erstmal alle Absatzgebundenen einsammeln
1095     for( sal_uInt16 n = 0; n < GetSpzFrmFmts()->Count(); ++n )
1096     {
1097         pFly = (*GetSpzFrmFmts())[ n ];
1098         bool bDrawFmt = bDrawAlso ? RES_DRAWFRMFMT == pFly->Which() : false;
1099         bool bFlyFmt = RES_FLYFRMFMT == pFly->Which();
1100         if( bFlyFmt || bDrawFmt )
1101         {
1102             const SwFmtAnchor& rAnchor = pFly->GetAnchor();
1103             SwPosition const*const pAPos = rAnchor.GetCntntAnchor();
1104             if (pAPos &&
1105                 ((FLY_AT_PARA == rAnchor.GetAnchorId()) ||
1106                  (FLY_AT_FLY  == rAnchor.GetAnchorId()) ||
1107                  (FLY_AT_CHAR == rAnchor.GetAnchorId())))
1108             {
1109                 if( pCmpRange &&
1110                     !TstFlyRange( pCmpRange, pAPos, rAnchor.GetAnchorId() ))
1111                         continue;       // kein gueltiger FlyFrame
1112                 aRetval.insert(SwPosFlyFrmPtr(new SwPosFlyFrm(pAPos->nNode, pFly, aRetval.size())));
1113             }
1114         }
1115     }
1116 
1117     // kein Layout oder nur ein Teil, dann wars das
1118     // Seitenbezogen Flys nur, wenn vollstaendig "gewuenscht" wird !
1119     if( !GetCurrentViewShell() || pCmpRange )   //swmod 071108//swmod 071225
1120     {
1121         return aRetval;
1122     }
1123 
1124     SwPageFrm *pPage = (SwPageFrm*)GetCurrentLayout()->GetLower();  //swmod 080218
1125     while( pPage )
1126     {
1127         if( pPage->GetSortedObjs() )
1128         {
1129             SwSortedObjs &rObjs = *pPage->GetSortedObjs();
1130             for( sal_uInt16 i = 0; i < rObjs.Count(); ++i)
1131             {
1132                 SwAnchoredObject* pAnchoredObj = rObjs[i];
1133                 if ( pAnchoredObj->ISA(SwFlyFrm) )
1134                     pFly = &(pAnchoredObj->GetFrmFmt());
1135                 else if ( bDrawAlso )
1136                     pFly = &(pAnchoredObj->GetFrmFmt());
1137                 else
1138                     continue;
1139 
1140                 const SwFmtAnchor& rAnchor = pFly->GetAnchor();
1141                 if ((FLY_AT_PARA != rAnchor.GetAnchorId()) &&
1142                     (FLY_AT_FLY  != rAnchor.GetAnchorId()) &&
1143                     (FLY_AT_CHAR != rAnchor.GetAnchorId()))
1144                 {
1145                     const SwCntntFrm * pCntntFrm = pPage->FindFirstBodyCntnt();
1146                     if ( !pCntntFrm )
1147                     {
1148                         //Oops! Eine leere Seite. Damit der Rahmen nicht ganz
1149                         //verlorengeht (RTF) suchen wir schnell den letzen
1150                         //Cntnt der vor der Seite steht.
1151                         SwPageFrm *pPrv = (SwPageFrm*)pPage->GetPrev();
1152                         while ( !pCntntFrm && pPrv )
1153                         {
1154                             pCntntFrm = pPrv->FindFirstBodyCntnt();
1155                             pPrv = (SwPageFrm*)pPrv->GetPrev();
1156                         }
1157                     }
1158                     if ( pCntntFrm )
1159                     {
1160                         SwNodeIndex aIdx( *pCntntFrm->GetNode() );
1161                         aRetval.insert(SwPosFlyFrmPtr(new SwPosFlyFrm(aIdx, pFly, aRetval.size())));
1162                     }
1163                 }
1164             }
1165         }
1166         pPage = (SwPageFrm*)pPage->GetNext();
1167     }
1168 
1169     return aRetval;
1170 }
1171 
1172 /*************************************************************************
1173 |*
1174 |*  SwDoc::InsertLabel()
1175 |*
1176 |*  Ersterstellung      MA 11. Feb. 94
1177 |*  Letzte Aenderung    MA 12. Nov. 97
1178 |*
1179 |*************************************************************************/
1180 
1181 /* #i6447# changed behaviour if lcl_CpyAttr:
1182 
1183    If the old item set contains the item to set (no inheritance) copy the item
1184    into the new set.
1185 
1186    If the old item set contains the item by inheritance and the new set
1187    contains the item, too:
1188       If the two items differ copy the item from the old set to the new set.
1189 
1190    Otherwise the new set will not be changed.
1191 */
1192 
1193 void lcl_CpyAttr( SfxItemSet &rNewSet, const SfxItemSet &rOldSet, sal_uInt16 nWhich )
1194 {
1195     const SfxPoolItem *pOldItem = NULL, *pNewItem = NULL;
1196 
1197     rOldSet.GetItemState( nWhich, sal_False, &pOldItem);
1198     if (pOldItem != NULL)
1199         rNewSet.Put( *pOldItem );
1200     else
1201     {
1202         pOldItem = rOldSet.GetItem( nWhich, sal_True);
1203         if (pOldItem != NULL)
1204         {
1205             pNewItem = rNewSet.GetItem( nWhich, sal_True);
1206             if (pNewItem != NULL)
1207             {
1208                 if (*pOldItem != *pNewItem)
1209                     rNewSet.Put( *pOldItem );
1210             }
1211             else {
1212                 ASSERT(0, "What am I doing here?");
1213             }
1214         }
1215         else {
1216             ASSERT(0, "What am I doing here?");
1217         }
1218     }
1219 
1220 }
1221 
1222 
1223 static SwFlyFrmFmt *
1224 lcl_InsertLabel(SwDoc & rDoc, SwTxtFmtColls *const pTxtFmtCollTbl,
1225         SwUndoInsertLabel *const pUndo,
1226         SwLabelType const eType, String const& rTxt, String const& rSeparator,
1227             const String& rNumberingSeparator,
1228             const sal_Bool bBefore, const sal_uInt16 nId, const sal_uLong nNdIdx,
1229             const String& rCharacterStyle,
1230             const sal_Bool bCpyBrd )
1231 {
1232     ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
1233 
1234     sal_Bool bTable = sal_False;    //Um etwas Code zu sparen.
1235 
1236     //Erstmal das Feld bauen, weil ueber den Namen die TxtColl besorgt werden
1237     //muss
1238     OSL_ENSURE( nId == USHRT_MAX  || nId < rDoc.GetFldTypes()->Count(),
1239             "FldType index out of bounds." );
1240     SwFieldType *pType = (nId != USHRT_MAX) ? (*rDoc.GetFldTypes())[nId] : NULL;
1241     OSL_ENSURE(!pType || pType->Which() == RES_SETEXPFLD, "wrong Id for Label");
1242 
1243     SwTxtFmtColl * pColl = NULL;
1244     if( pType )
1245     {
1246         for( sal_uInt16 i = pTxtFmtCollTbl->Count(); i; )
1247         {
1248             if( (*pTxtFmtCollTbl)[ --i ]->GetName() == pType->GetName() )
1249             {
1250                 pColl = (*pTxtFmtCollTbl)[i];
1251                 break;
1252             }
1253         }
1254         DBG_ASSERT( pColl, "no text collection found" );
1255     }
1256 
1257     if( !pColl )
1258     {
1259         pColl = rDoc.GetTxtCollFromPool( RES_POOLCOLL_LABEL );
1260     }
1261 
1262     SwTxtNode *pNew = NULL;
1263     SwFlyFrmFmt* pNewFmt = NULL;
1264 
1265     switch ( eType )
1266     {
1267         case LTYPE_TABLE:
1268             bTable = sal_True;
1269             /* Kein Break hier */
1270         case LTYPE_FLY:
1271             //Am Anfang/Ende der Fly-Section den entsprechenden Node mit Feld
1272             //einfuegen (Frame wird automatisch erzeugt).
1273             {
1274                 SwStartNode *pSttNd = rDoc.GetNodes()[nNdIdx]->GetStartNode();
1275                 ASSERT( pSttNd, "Kein StartNode in InsertLabel." );
1276                 sal_uLong nNode;
1277                 if( bBefore )
1278                 {
1279                     nNode = pSttNd->GetIndex();
1280                     if( !bTable )
1281                         ++nNode;
1282                 }
1283                 else
1284                 {
1285                     nNode = pSttNd->EndOfSectionIndex();
1286                     if( bTable )
1287                         ++nNode;
1288                 }
1289 
1290                 if( pUndo )
1291                     pUndo->SetNodePos( nNode );
1292 
1293                 //Node fuer Beschriftungsabsatz erzeugen.
1294                 SwNodeIndex aIdx( rDoc.GetNodes(), nNode );
1295                 pNew = rDoc.GetNodes().MakeTxtNode( aIdx, pColl );
1296             }
1297             break;
1298 
1299         case LTYPE_OBJECT:
1300             {
1301                 //Rahmen zerstoeren, neuen Rahmen einfuegen, entsprechenden
1302                 // Node mit Feld in den neuen Rahmen, den alten Rahmen mit
1303                 // dem Object (Grafik/Ole) absatzgebunden in den neuen Rahmen,
1304                 // Frames erzeugen.
1305 
1306                 //Erstmal das Format zum Fly besorgen und das Layout entkoppeln.
1307                 SwFrmFmt *pOldFmt = rDoc.GetNodes()[nNdIdx]->GetFlyFmt();
1308                 ASSERT( pOldFmt, "Format des Fly nicht gefunden." );
1309                 // --> OD #i115719#
1310                 // <title> and <description> attributes are lost when calling <DelFrms()>.
1311                 // Thus, keep them and restore them after the calling <MakeFrms()>
1312                 const bool bIsSwFlyFrmFmtInstance( dynamic_cast<SwFlyFrmFmt*>(pOldFmt) != 0 );
1313                 const String sTitle( bIsSwFlyFrmFmtInstance
1314                                      ? static_cast<SwFlyFrmFmt*>(pOldFmt)->GetObjTitle()
1315                                      : String() );
1316                 const String sDescription( bIsSwFlyFrmFmtInstance
1317                                            ? static_cast<SwFlyFrmFmt*>(pOldFmt)->GetObjDescription()
1318                                            : String() );
1319                 // <--
1320                 pOldFmt->DelFrms();
1321 
1322                 pNewFmt = rDoc.MakeFlyFrmFmt( rDoc.GetUniqueFrameName(),
1323                                 rDoc.GetFrmFmtFromPool(RES_POOLFRM_FRAME) );
1324 
1325                 /* #i6447#: Only the selected items are copied from the old
1326                    format. */
1327                 SfxItemSet* pNewSet = pNewFmt->GetAttrSet().Clone( sal_True );
1328 
1329 
1330                 //Diejenigen Attribute uebertragen die auch gesetzt sind,
1331                 //andere sollen weiterhin aus den Vorlagen gueltig werden.
1332                 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_PRINT );
1333                 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_OPAQUE );
1334                 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_PROTECT );
1335                 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_SURROUND );
1336                 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_VERT_ORIENT );
1337                 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_HORI_ORIENT );
1338                 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_LR_SPACE );
1339                 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_UL_SPACE );
1340                 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_BACKGROUND );
1341                 if( bCpyBrd )
1342                 {
1343                     // JP 07.07.99: Bug 67029 - if at Grafik no BoxItem but
1344                     //              in the new Format is any, then set the
1345                     //              default item in the new Set. Because
1346                     //              the Size of the Grafik have never been
1347                     //              changed!
1348                     const SfxPoolItem *pItem;
1349                     if( SFX_ITEM_SET == pOldFmt->GetAttrSet().
1350                             GetItemState( RES_BOX, sal_True, &pItem ))
1351                         pNewSet->Put( *pItem );
1352                     else if( SFX_ITEM_SET == pNewFmt->GetAttrSet().
1353                             GetItemState( RES_BOX, sal_True ))
1354                         pNewSet->Put( *GetDfltAttr( RES_BOX ) );
1355 
1356                     if( SFX_ITEM_SET == pOldFmt->GetAttrSet().
1357                             GetItemState( RES_SHADOW, sal_True, &pItem ))
1358                         pNewSet->Put( *pItem );
1359                     else if( SFX_ITEM_SET == pNewFmt->GetAttrSet().
1360                             GetItemState( RES_SHADOW, sal_True ))
1361                         pNewSet->Put( *GetDfltAttr( RES_SHADOW ) );
1362                 }
1363                 else
1364                 {
1365                     //Die Attribute hart setzen, weil sie sonst aus der
1366                     // Vorlage kommen koenten und dann passt die
1367                     // Grossenberechnung nicht mehr.
1368                     pNewSet->Put( SvxBoxItem(RES_BOX) );
1369                     pNewSet->Put( SvxShadowItem(RES_SHADOW) );
1370 
1371                 }
1372 
1373                 //Anker immer uebertragen, ist sowieso ein hartes Attribut.
1374                 pNewSet->Put( pOldFmt->GetAnchor() );
1375 
1376                 //In der Hoehe soll der neue Varabel sein!
1377                 SwFmtFrmSize aFrmSize( pOldFmt->GetFrmSize() );
1378                 aFrmSize.SetHeightSizeType( ATT_MIN_SIZE );
1379                 pNewSet->Put( aFrmSize );
1380 
1381                 SwStartNode* pSttNd = rDoc.GetNodes().MakeTextSection(
1382                             SwNodeIndex( rDoc.GetNodes().GetEndOfAutotext() ),
1383                             SwFlyStartNode, pColl );
1384                 pNewSet->Put( SwFmtCntnt( pSttNd ));
1385 
1386                 pNewFmt->SetFmtAttr( *pNewSet );
1387 
1388                 //Bei InCntnt's wird es spannend: Das TxtAttribut muss
1389                 //vernichtet werden. Leider reisst dies neben den Frms auch
1390                 //noch das Format mit in sein Grab. Um dass zu unterbinden
1391                 //loesen wir vorher die Verbindung zwischen Attribut und Format.
1392 
1393                 const SwFmtAnchor& rAnchor = pNewFmt->GetAnchor();
1394                 if ( FLY_AS_CHAR == rAnchor.GetAnchorId() )
1395                 {
1396                     const SwPosition *pPos = rAnchor.GetCntntAnchor();
1397                     SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
1398                     ASSERT( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
1399                     const xub_StrLen nIdx = pPos->nContent.GetIndex();
1400                     SwTxtAttr * const pHnt =
1401                         pTxtNode->GetTxtAttrForCharAt(nIdx, RES_TXTATR_FLYCNT);
1402 
1403                     ASSERT( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
1404                                 "Missing FlyInCnt-Hint." );
1405                     ASSERT( pHnt && pHnt->GetFlyCnt().GetFrmFmt() == pOldFmt,
1406                                 "Wrong TxtFlyCnt-Hint." );
1407 
1408                     const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt(
1409                             pNewFmt );
1410                 }
1411 
1412 
1413                 //Der Alte soll keinen Umlauf haben, und er soll oben/mittig
1414                 //ausgerichtet sein.
1415                 //Ausserdem soll die Breite 100% betragen und bei Aenderungen
1416                 //Die Hoehe mit anpassen.
1417                 pNewSet->ClearItem();
1418 
1419                 pNewSet->Put( SwFmtSurround( SURROUND_NONE ) );
1420                 pNewSet->Put( SvxOpaqueItem( RES_OPAQUE, sal_True ) );
1421                 pNewSet->Put( SwFmtVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME ) );
1422                 pNewSet->Put( SwFmtHoriOrient( 0, text::HoriOrientation::CENTER, text::RelOrientation::FRAME ) );
1423 
1424                 aFrmSize = pOldFmt->GetFrmSize();
1425                 aFrmSize.SetWidthPercent( 0 );
1426                 aFrmSize.SetHeightPercent( 255 );
1427                 pNewSet->Put( aFrmSize );
1428 
1429                 //Die Attribute setzen wir hart, weil sie sonst aus der Vorlage
1430                 //kommen koenten und dann passt die Grossenberechnung nicht mehr.
1431                 if( bCpyBrd )
1432                 {
1433                     pNewSet->Put( SvxBoxItem(RES_BOX) );
1434                     pNewSet->Put( SvxShadowItem(RES_SHADOW) );
1435                 }
1436                 pNewSet->Put( SvxLRSpaceItem(RES_LR_SPACE) );
1437                 pNewSet->Put( SvxULSpaceItem(RES_UL_SPACE) );
1438 
1439                 //Der Alte ist absatzgebunden, und zwar am Absatz im neuen.
1440                 SwFmtAnchor aAnch( FLY_AT_PARA );
1441                 SwNodeIndex aAnchIdx( *pNewFmt->GetCntnt().GetCntntIdx(), 1 );
1442                 pNew = aAnchIdx.GetNode().GetTxtNode();
1443                 SwPosition aPos( aAnchIdx );
1444                 aAnch.SetAnchor( &aPos );
1445                 pNewSet->Put( aAnch );
1446 
1447                 if( pUndo )
1448                     pUndo->SetFlys( *pOldFmt, *pNewSet, *pNewFmt );
1449                 else
1450                     pOldFmt->SetFmtAttr( *pNewSet );
1451 
1452                 delete pNewSet;
1453 
1454                 //Nun nur noch die Flys erzeugen lassen. Das ueberlassen
1455                 //wir vorhanden Methoden (insb. fuer InCntFlys etwas aufwendig).
1456                 pNewFmt->MakeFrms();
1457                 // --> OD #i115719#
1458                 if ( bIsSwFlyFrmFmtInstance )
1459                 {
1460                     static_cast<SwFlyFrmFmt*>(pOldFmt)->SetObjTitle( sTitle );
1461                     static_cast<SwFlyFrmFmt*>(pOldFmt)->SetObjDescription( sDescription );
1462                 }
1463                 // <--
1464             }
1465             break;
1466 
1467         default:
1468             OSL_ENSURE(false, "unknown LabelType?");
1469     }
1470     ASSERT( pNew, "No Label inserted" );
1471     if( pNew )
1472     {
1473         //#i61007# order of captions
1474         sal_Bool bOrderNumberingFirst = SW_MOD()->GetModuleConfig()->IsCaptionOrderNumberingFirst();
1475         //String aufbereiten
1476         String aTxt;
1477         if( bOrderNumberingFirst )
1478         {
1479             aTxt = rNumberingSeparator;
1480         }
1481         if( pType)
1482         {
1483             aTxt += pType->GetName();
1484             if( !bOrderNumberingFirst )
1485                 aTxt += ' ';
1486         }
1487         xub_StrLen nIdx = aTxt.Len();
1488         if( rTxt.Len() > 0 )
1489         {
1490             aTxt += rSeparator;
1491         }
1492         xub_StrLen nSepIdx = aTxt.Len();
1493         aTxt += rTxt;
1494 
1495         //String einfuegen
1496         SwIndex aIdx( pNew, 0 );
1497         pNew->InsertText( aTxt, aIdx );
1498 
1499         //
1500         //Feld einfuegen
1501         if(pType)
1502         {
1503             SwSetExpField aFld( (SwSetExpFieldType*)pType, aEmptyStr, SVX_NUM_ARABIC);
1504             if( bOrderNumberingFirst )
1505                 nIdx = 0;
1506             SwFmtFld aFmt( aFld );
1507             pNew->InsertItem( aFmt, nIdx, nIdx );
1508             if(rCharacterStyle.Len())
1509             {
1510                 SwCharFmt* pCharFmt = rDoc.FindCharFmtByName(rCharacterStyle);
1511                 if( !pCharFmt )
1512                 {
1513                     const sal_uInt16 nMyId = SwStyleNameMapper::GetPoolIdFromUIName(rCharacterStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT);
1514                     pCharFmt = rDoc.GetCharFmtFromPool( nMyId );
1515                 }
1516                 if (pCharFmt)
1517                 {
1518                     SwFmtCharFmt aCharFmt( pCharFmt );
1519                     pNew->InsertItem( aCharFmt, 0,
1520                         nSepIdx + 1, nsSetAttrMode::SETATTR_DONTEXPAND );
1521                 }
1522             }
1523         }
1524 
1525         if ( bTable )
1526         {
1527             if ( bBefore )
1528             {
1529                 if ( !pNew->GetSwAttrSet().GetKeep().GetValue()  )
1530                     pNew->SetAttr( SvxFmtKeepItem( sal_True, RES_KEEP ) );
1531             }
1532             else
1533             {
1534                 SwTableNode *const pNd =
1535                     rDoc.GetNodes()[nNdIdx]->GetStartNode()->GetTableNode();
1536                 SwTable &rTbl = pNd->GetTable();
1537                 if ( !rTbl.GetFrmFmt()->GetKeep().GetValue() )
1538                     rTbl.GetFrmFmt()->SetFmtAttr( SvxFmtKeepItem( sal_True, RES_KEEP ) );
1539                 if ( pUndo )
1540                     pUndo->SetUndoKeep();
1541             }
1542         }
1543         rDoc.SetModified();
1544     }
1545 
1546     return pNewFmt;
1547 }
1548 
1549 SwFlyFrmFmt *
1550 SwDoc::InsertLabel(
1551         SwLabelType const eType, String const& rTxt, String const& rSeparator,
1552         String const& rNumberingSeparator,
1553         sal_Bool const bBefore, sal_uInt16 const nId, sal_uLong const nNdIdx,
1554         String const& rCharacterStyle,
1555         sal_Bool const bCpyBrd )
1556 {
1557     SwUndoInsertLabel * pUndo(0);
1558     if (GetIDocumentUndoRedo().DoesUndo())
1559     {
1560         pUndo = new SwUndoInsertLabel(
1561                         eType, rTxt, rSeparator, rNumberingSeparator,
1562                         bBefore, nId, rCharacterStyle, bCpyBrd );
1563     }
1564 
1565     SwFlyFrmFmt *const pNewFmt = lcl_InsertLabel(*this, pTxtFmtCollTbl, pUndo,
1566             eType, rTxt, rSeparator, rNumberingSeparator, bBefore,
1567             nId, nNdIdx, rCharacterStyle, bCpyBrd);
1568 
1569     if (pUndo)
1570     {
1571         GetIDocumentUndoRedo().AppendUndo(pUndo);
1572     }
1573     else
1574     {
1575         GetIDocumentUndoRedo().DelAllUndoObj();
1576     }
1577 
1578     return pNewFmt;
1579 }
1580 
1581 
1582 /*************************************************************************
1583 |*
1584 |*  SwDoc::InsertDrawLabel()
1585 |*
1586 |*  Ersterstellung      MIB 7. Dez. 98
1587 |*  Letzte Aenderung    MIB 7. Dez. 98
1588 |*
1589 |*************************************************************************/
1590 
1591 static SwFlyFrmFmt *
1592 lcl_InsertDrawLabel( SwDoc & rDoc, SwTxtFmtColls *const pTxtFmtCollTbl,
1593         SwUndoInsertLabel *const pUndo, SwDrawFrmFmt *const pOldFmt,
1594         String const& rTxt,
1595                                      const String& rSeparator,
1596                                      const String& rNumberSeparator,
1597                                      const sal_uInt16 nId,
1598                                      const String& rCharacterStyle,
1599                                      SdrObject& rSdrObj )
1600 {
1601     ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
1602     ::sw::DrawUndoGuard const drawUndoGuard(rDoc.GetIDocumentUndoRedo());
1603 
1604     // Erstmal das Feld bauen, weil ueber den Namen die TxtColl besorgt
1605     // werden muss
1606     OSL_ENSURE( nId == USHRT_MAX  || nId < rDoc.GetFldTypes()->Count(),
1607             "FldType index out of bounds" );
1608     SwFieldType *pType = nId != USHRT_MAX ? (*rDoc.GetFldTypes())[nId] : 0;
1609     OSL_ENSURE( !pType || pType->Which() == RES_SETEXPFLD, "Wrong label id" );
1610 
1611     SwTxtFmtColl *pColl = NULL;
1612     if( pType )
1613     {
1614         for( sal_uInt16 i = pTxtFmtCollTbl->Count(); i; )
1615         {
1616             if( (*pTxtFmtCollTbl)[ --i ]->GetName() == pType->GetName() )
1617             {
1618                 pColl = (*pTxtFmtCollTbl)[i];
1619                 break;
1620             }
1621         }
1622         DBG_ASSERT( pColl, "no text collection found" );
1623     }
1624 
1625     if( !pColl )
1626     {
1627         pColl = rDoc.GetTxtCollFromPool( RES_POOLCOLL_LABEL );
1628     }
1629 
1630     SwTxtNode* pNew = NULL;
1631     SwFlyFrmFmt* pNewFmt = NULL;
1632 
1633     // Rahmen zerstoeren, neuen Rahmen einfuegen, entsprechenden
1634     // Node mit Feld in den neuen Rahmen, den alten Rahmen mit
1635     // dem Object (Grafik/Ole) absatzgebunden in den neuen Rahmen,
1636     // Frames erzeugen.
1637 
1638     // OD 27.11.2003 #112045# - Keep layer ID of drawing object before removing
1639     // its frames.
1640     // Note: The layer ID is passed to the undo and have to be the correct value.
1641     //       Removing the frames of the drawing object changes its layer.
1642     const SdrLayerID nLayerId = rSdrObj.GetLayer();
1643 
1644     pOldFmt->DelFrms();
1645 
1646     //Bei InCntnt's wird es spannend: Das TxtAttribut muss
1647     //vernichtet werden. Leider reisst dies neben den Frms auch
1648     //noch das Format mit in sein Grab. Um dass zu unterbinden
1649     //loesen wir vorher die Verbindung zwischen Attribut und Format.
1650     SfxItemSet* pNewSet = pOldFmt->GetAttrSet().Clone( sal_False );
1651 
1652     // Ggf. Groesse und Position des Rahmens schuetzen
1653     if ( rSdrObj.IsMoveProtect() || rSdrObj.IsResizeProtect() )
1654     {
1655         SvxProtectItem aProtect(RES_PROTECT);
1656         aProtect.SetCntntProtect( sal_False );
1657         aProtect.SetPosProtect( rSdrObj.IsMoveProtect() );
1658         aProtect.SetSizeProtect( rSdrObj.IsResizeProtect() );
1659         pNewSet->Put( aProtect );
1660     }
1661 
1662     // Umlauf uebernehmen
1663     lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_SURROUND );
1664 
1665     // Den Rahmen ggf. in den Hintergrund schicken.
1666     // OD 02.07.2003 #108784# - consider 'invisible' hell layer.
1667     if ( rDoc.GetHellId() != nLayerId &&
1668          rDoc.GetInvisibleHellId() != nLayerId )
1669     {
1670         SvxOpaqueItem aOpaque( RES_OPAQUE );
1671         aOpaque.SetValue( sal_True );
1672         pNewSet->Put( aOpaque );
1673     }
1674 
1675     // Position uebernehmen
1676     // OD 2004-04-15 #i26791# - use directly the positioning attributes of
1677     // the drawing object.
1678     pNewSet->Put( pOldFmt->GetHoriOrient() );
1679     pNewSet->Put( pOldFmt->GetVertOrient() );
1680 
1681     pNewSet->Put( pOldFmt->GetAnchor() );
1682 
1683     //In der Hoehe soll der neue Varabel sein!
1684     Size aSz( rSdrObj.GetCurrentBoundRect().GetSize() );
1685     SwFmtFrmSize aFrmSize( ATT_MIN_SIZE, aSz.Width(), aSz.Height() );
1686     pNewSet->Put( aFrmSize );
1687 
1688     // Abstaende auf den neuen Rahmen uebertragen. Eine Umrandung
1689     // gibt es beu Zeichen-Objekten nicht, also muss sie geloescht
1690     // werden.
1691     // MA: Falsch sie wird nicht gesetzt, denn die aus der Vorlage
1692     // soll ruhig wirksam werden
1693     pNewSet->Put( pOldFmt->GetLRSpace() );
1694     pNewSet->Put( pOldFmt->GetULSpace() );
1695 
1696     SwStartNode* pSttNd =
1697         rDoc.GetNodes().MakeTextSection(
1698             SwNodeIndex( rDoc.GetNodes().GetEndOfAutotext() ),
1699                                     SwFlyStartNode, pColl );
1700 
1701     pNewFmt = rDoc.MakeFlyFrmFmt( rDoc.GetUniqueFrameName(),
1702                  rDoc.GetFrmFmtFromPool( RES_POOLFRM_FRAME ) );
1703 
1704     // JP 28.10.99: Bug 69487 - set border and shadow to default if the
1705     //              template contains any.
1706     if( SFX_ITEM_SET == pNewFmt->GetAttrSet().GetItemState( RES_BOX, sal_True ))
1707         pNewSet->Put( *GetDfltAttr( RES_BOX ) );
1708 
1709     if( SFX_ITEM_SET == pNewFmt->GetAttrSet().GetItemState(RES_SHADOW,sal_True))
1710         pNewSet->Put( *GetDfltAttr( RES_SHADOW ) );
1711 
1712     pNewFmt->SetFmtAttr( SwFmtCntnt( pSttNd ));
1713     pNewFmt->SetFmtAttr( *pNewSet );
1714 
1715     const SwFmtAnchor& rAnchor = pNewFmt->GetAnchor();
1716     if ( FLY_AS_CHAR == rAnchor.GetAnchorId() )
1717     {
1718         const SwPosition *pPos = rAnchor.GetCntntAnchor();
1719         SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
1720         ASSERT( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
1721         const xub_StrLen nIdx = pPos->nContent.GetIndex();
1722         SwTxtAttr * const pHnt =
1723             pTxtNode->GetTxtAttrForCharAt( nIdx, RES_TXTATR_FLYCNT );
1724 
1725 #ifdef DBG_UTIL
1726         ASSERT( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
1727                     "Missing FlyInCnt-Hint." );
1728         ASSERT( pHnt && ((SwFmtFlyCnt&)pHnt->GetFlyCnt()).
1729                     GetFrmFmt() == (SwFrmFmt*)pOldFmt,
1730                     "Wrong TxtFlyCnt-Hint." );
1731 #endif
1732         const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt( pNewFmt );
1733     }
1734 
1735 
1736     //Der Alte soll keinen Umlauf haben, und er soll oben/mittig
1737     //ausgerichtet sein.
1738     pNewSet->ClearItem();
1739 
1740     pNewSet->Put( SwFmtSurround( SURROUND_NONE ) );
1741     if (nLayerId == rDoc.GetHellId())
1742     {
1743         rSdrObj.SetLayer( rDoc.GetHeavenId() );
1744     }
1745     // OD 02.07.2003 #108784# - consider drawing objects in 'invisible' hell layer
1746     else if (nLayerId == rDoc.GetInvisibleHellId())
1747     {
1748         rSdrObj.SetLayer( rDoc.GetInvisibleHeavenId() );
1749     }
1750     pNewSet->Put( SvxLRSpaceItem( RES_LR_SPACE ) );
1751     pNewSet->Put( SvxULSpaceItem( RES_UL_SPACE ) );
1752 
1753     // OD 2004-04-15 #i26791# - set position of the drawing object, which is labeled.
1754     pNewSet->Put( SwFmtVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME ) );
1755     pNewSet->Put( SwFmtHoriOrient( 0, text::HoriOrientation::CENTER, text::RelOrientation::FRAME ) );
1756 
1757     //Der Alte ist absatzgebunden, und zwar am Absatz im neuen.
1758     SwFmtAnchor aAnch( FLY_AT_PARA );
1759     SwNodeIndex aAnchIdx( *pNewFmt->GetCntnt().GetCntntIdx(), 1 );
1760     pNew = aAnchIdx.GetNode().GetTxtNode();
1761     SwPosition aPos( aAnchIdx );
1762     aAnch.SetAnchor( &aPos );
1763     pNewSet->Put( aAnch );
1764 
1765     if( pUndo )
1766     {
1767         pUndo->SetFlys( *pOldFmt, *pNewSet, *pNewFmt );
1768         // OD 2004-04-15 #i26791# - position no longer needed
1769         pUndo->SetDrawObj( nLayerId );
1770     }
1771     else
1772         pOldFmt->SetFmtAttr( *pNewSet );
1773 
1774     delete pNewSet;
1775 
1776     //Nun nur noch die Flys erzeugen lassen. Das ueberlassen
1777     //wir vorhanden Methoden (insb. fuer InCntFlys etwas aufwendig).
1778     pNewFmt->MakeFrms();
1779 
1780     ASSERT( pNew, "No Label inserted" );
1781 
1782     if( pNew )
1783     {
1784         //#i61007# order of captions
1785         sal_Bool bOrderNumberingFirst = SW_MOD()->GetModuleConfig()->IsCaptionOrderNumberingFirst();
1786 
1787         // prepare string
1788         String aTxt;
1789         if( bOrderNumberingFirst )
1790         {
1791             aTxt = rNumberSeparator;
1792         }
1793         if ( pType )
1794         {
1795             aTxt += pType->GetName();
1796             if( !bOrderNumberingFirst )
1797                 aTxt += ' ';
1798         }
1799         xub_StrLen nIdx = aTxt.Len();
1800         aTxt += rSeparator;
1801         xub_StrLen nSepIdx = aTxt.Len();
1802         aTxt += rTxt;
1803 
1804         // insert text
1805         SwIndex aIdx( pNew, 0 );
1806         pNew->InsertText( aTxt, aIdx );
1807 
1808         // insert field
1809         if ( pType )
1810         {
1811             SwSetExpField aFld( (SwSetExpFieldType*)pType, aEmptyStr, SVX_NUM_ARABIC );
1812             if( bOrderNumberingFirst )
1813                 nIdx = 0;
1814             SwFmtFld aFmt( aFld );
1815             pNew->InsertItem( aFmt, nIdx, nIdx );
1816             if ( rCharacterStyle.Len() )
1817             {
1818                 SwCharFmt * pCharFmt = rDoc.FindCharFmtByName(rCharacterStyle);
1819                 if ( !pCharFmt )
1820                 {
1821                     const sal_uInt16 nMyId = SwStyleNameMapper::GetPoolIdFromUIName( rCharacterStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
1822                     pCharFmt = rDoc.GetCharFmtFromPool( nMyId );
1823                 }
1824                 if ( pCharFmt )
1825                 {
1826                     SwFmtCharFmt aCharFmt( pCharFmt );
1827                     pNew->InsertItem( aCharFmt, 0, nSepIdx + 1,
1828                             nsSetAttrMode::SETATTR_DONTEXPAND );
1829                 }
1830             }
1831         }
1832     }
1833 
1834     return pNewFmt;
1835 }
1836 
1837 SwFlyFrmFmt* SwDoc::InsertDrawLabel(
1838         String const& rTxt,
1839         String const& rSeparator,
1840         String const& rNumberSeparator,
1841         sal_uInt16 const nId,
1842         String const& rCharacterStyle,
1843         SdrObject& rSdrObj )
1844 {
1845     SwDrawContact *const pContact =
1846         static_cast<SwDrawContact*>(GetUserCall( &rSdrObj ));
1847     OSL_ENSURE( RES_DRAWFRMFMT == pContact->GetFmt()->Which(),
1848             "InsertDrawLabel(): not a DrawFrmFmt" );
1849     if (!pContact)
1850         return 0;
1851 
1852     SwDrawFrmFmt* pOldFmt = (SwDrawFrmFmt *)pContact->GetFmt();
1853     if (!pOldFmt)
1854         return 0;
1855 
1856     SwUndoInsertLabel * pUndo = 0;
1857     if (GetIDocumentUndoRedo().DoesUndo())
1858     {
1859         GetIDocumentUndoRedo().ClearRedo();
1860         pUndo = new SwUndoInsertLabel(
1861             LTYPE_DRAW, rTxt, rSeparator, rNumberSeparator, sal_False,
1862             nId, rCharacterStyle, sal_False );
1863     }
1864 
1865     SwFlyFrmFmt *const pNewFmt = lcl_InsertDrawLabel(
1866         *this, pTxtFmtCollTbl, pUndo, pOldFmt,
1867         rTxt, rSeparator, rNumberSeparator, nId, rCharacterStyle, rSdrObj);
1868 
1869     if (pUndo)
1870     {
1871         GetIDocumentUndoRedo().AppendUndo( pUndo );
1872     }
1873     else
1874     {
1875         GetIDocumentUndoRedo().DelAllUndoObj();
1876     }
1877 
1878     return pNewFmt;
1879 }
1880 
1881 
1882 /*************************************************************************
1883 |*
1884 |*  IDocumentTimerAccess-methods
1885 |*
1886 |*************************************************************************/
1887 
1888 void SwDoc::StartIdling()
1889 {
1890     mbStartIdleTimer = sal_True;
1891     if( !mIdleBlockCount )
1892         aIdleTimer.Start();
1893 }
1894 
1895 void SwDoc::StopIdling()
1896 {
1897     mbStartIdleTimer = sal_False;
1898     aIdleTimer.Stop();
1899 }
1900 
1901 void SwDoc::BlockIdling()
1902 {
1903     aIdleTimer.Stop();
1904     ++mIdleBlockCount;
1905 }
1906 
1907 void SwDoc::UnblockIdling()
1908 {
1909     --mIdleBlockCount;
1910     if( !mIdleBlockCount && mbStartIdleTimer && !aIdleTimer.IsActive() )
1911         aIdleTimer.Start();
1912 }
1913 
1914 
1915 /*************************************************************************
1916 |*
1917 |*  SwDoc::DoIdleJobs()
1918 |*
1919 |*  Ersterstellung      OK 30.03.94
1920 |*  Letzte Aenderung    MA 09. Jun. 95
1921 |*
1922 |*************************************************************************/
1923 
1924 IMPL_LINK( SwDoc, DoIdleJobs, Timer *, pTimer )
1925 {
1926 #ifdef TIMELOG
1927     static ::rtl::Logfile* pModLogFile = 0;
1928     if( !pModLogFile )
1929         pModLogFile = new ::rtl::Logfile( "First DoIdleJobs" );
1930 #endif
1931 
1932     SwRootFrm* pTmpRoot = GetCurrentLayout();//swmod 080219
1933     if( pTmpRoot &&
1934         !SfxProgress::GetActiveProgress( pDocShell ) )
1935     {
1936         ViewShell *pSh, *pStartSh;
1937         pSh = pStartSh = GetCurrentViewShell();
1938         do {
1939             if( pSh->ActionPend() )
1940             {
1941                 if( pTimer )
1942                     pTimer->Start();
1943                 return 0;
1944             }
1945             pSh = (ViewShell*)pSh->GetNext();
1946         } while( pSh != pStartSh );
1947 
1948         if( pTmpRoot->IsNeedGrammarCheck() )
1949         {
1950             sal_Bool bIsOnlineSpell = pSh->GetViewOptions()->IsOnlineSpell();
1951             sal_Bool bIsAutoGrammar = sal_False;
1952             SvtLinguConfig().GetProperty( ::rtl::OUString::createFromAscii(
1953                         UPN_IS_GRAMMAR_AUTO ) ) >>= bIsAutoGrammar;
1954 
1955             if (bIsOnlineSpell && bIsAutoGrammar)
1956                 StartGrammarChecking( *this );
1957         }
1958         SwFldUpdateFlags nFldUpdFlag;
1959         std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();//swmod 080320
1960         std::set<SwRootFrm*>::iterator pLayIter = aAllLayouts.begin();
1961         for ( ;pLayIter != aAllLayouts.end();pLayIter++ )
1962         {
1963             if ((*pLayIter)->IsIdleFormat())
1964             {
1965                 (*pLayIter)->GetCurrShell()->LayoutIdle();
1966                 break;
1967             }
1968         }
1969         bool bAllValid = pLayIter == aAllLayouts.end() ? 1 : 0;
1970         if( bAllValid && ( AUTOUPD_FIELD_ONLY ==
1971                  ( nFldUpdFlag = getFieldUpdateFlags(true) )
1972                     || AUTOUPD_FIELD_AND_CHARTS == nFldUpdFlag ) &&
1973                 GetUpdtFlds().IsFieldsDirty() &&
1974                 !GetUpdtFlds().IsInUpdateFlds() &&
1975                 !IsExpFldsLocked()
1976                 // das umschalten der Feldname fuehrt zu keinem Update der
1977                 // Felder, also der "Hintergrund-Update" immer erfolgen
1978                 /* && !pStartSh->GetViewOptions()->IsFldName()*/ )
1979         {
1980             // chaos::Action-Klammerung!
1981             GetUpdtFlds().SetInUpdateFlds( sal_True );
1982 
1983             pTmpRoot->StartAllAction();
1984 
1985             // no jump on update of fields #i85168#
1986             const sal_Bool bOldLockView = pStartSh->IsViewLocked();
1987             pStartSh->LockView( sal_True );
1988 
1989             GetSysFldType( RES_CHAPTERFLD )->ModifyNotification( 0, 0 );    // KapitelFld
1990             UpdateExpFlds( 0, sal_False );      // Expression-Felder Updaten
1991             UpdateTblFlds(NULL);                // Tabellen
1992             UpdateRefFlds(NULL);                // Referenzen
1993 
1994             pTmpRoot->EndAllAction();
1995 
1996             pStartSh->LockView( bOldLockView );
1997 
1998             GetUpdtFlds().SetInUpdateFlds( sal_False );
1999             GetUpdtFlds().SetFieldsDirty( sal_False );
2000         }
2001     }   //swmod 080219
2002 #ifdef TIMELOG
2003     if( pModLogFile && 1 != (long)pModLogFile )
2004         delete pModLogFile, ((long&)pModLogFile) = 1;
2005 #endif
2006     if( pTimer )
2007         pTimer->Start();
2008     return 0;
2009 }
2010 
2011 IMPL_STATIC_LINK( SwDoc, BackgroundDone, SvxBrushItem*, EMPTYARG )
2012 {
2013     ViewShell *pSh, *pStartSh;
2014     pSh = pStartSh = pThis->GetCurrentViewShell();  //swmod 071108//swmod 071225
2015     if( pStartSh )
2016         do {
2017             if( pSh->GetWin() )
2018             {
2019                 //Fuer Repaint mir virtuellen Device sorgen.
2020                 pSh->LockPaint();
2021                 pSh->UnlockPaint( sal_True );
2022             }
2023             pSh = (ViewShell*)pSh->GetNext();
2024         } while( pSh != pStartSh );
2025     return 0;
2026 }
2027 
2028 static String lcl_GetUniqueFlyName( const SwDoc* pDoc, sal_uInt16 nDefStrId )
2029 {
2030     ResId aId( nDefStrId, *pSwResMgr );
2031     String aName( aId );
2032     xub_StrLen nNmLen = aName.Len();
2033 
2034     const SwSpzFrmFmts& rFmts = *pDoc->GetSpzFrmFmts();
2035 
2036     sal_uInt16 nNum, nTmp, nFlagSize = ( rFmts.Count() / 8 ) +2;
2037     sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ];
2038     sal_uInt16 n;
2039 
2040     memset( pSetFlags, 0, nFlagSize );
2041 
2042     for( n = 0; n < rFmts.Count(); ++n )
2043     {
2044         const SwFrmFmt* pFlyFmt = rFmts[ n ];
2045         if( RES_FLYFRMFMT == pFlyFmt->Which() &&
2046             pFlyFmt->GetName().Match( aName ) == nNmLen )
2047         {
2048             // Nummer bestimmen und das Flag setzen
2049             nNum = static_cast< sal_uInt16 >( pFlyFmt->GetName().Copy( nNmLen ).ToInt32() );
2050             if( nNum-- && nNum < rFmts.Count() )
2051                 pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
2052         }
2053     }
2054 
2055     // alle Nummern entsprechend geflag, also bestimme die richtige Nummer
2056     nNum = rFmts.Count();
2057     for( n = 0; n < nFlagSize; ++n )
2058         if( 0xff != ( nTmp = pSetFlags[ n ] ))
2059         {
2060             // also die Nummer bestimmen
2061             nNum = n * 8;
2062             while( nTmp & 1 )
2063                 ++nNum, nTmp >>= 1;
2064             break;
2065         }
2066 
2067     delete [] pSetFlags;
2068     return aName += String::CreateFromInt32( ++nNum );
2069 }
2070 
2071 String SwDoc::GetUniqueGrfName() const
2072 {
2073     return lcl_GetUniqueFlyName( this, STR_GRAPHIC_DEFNAME );
2074 }
2075 
2076 String SwDoc::GetUniqueOLEName() const
2077 {
2078     return lcl_GetUniqueFlyName( this, STR_OBJECT_DEFNAME );
2079 }
2080 
2081 String SwDoc::GetUniqueFrameName() const
2082 {
2083     return lcl_GetUniqueFlyName( this, STR_FRAME_DEFNAME );
2084 }
2085 
2086 const SwFlyFrmFmt* SwDoc::FindFlyByName( const String& rName, sal_Int8 nNdTyp ) const
2087 {
2088     const SwSpzFrmFmts& rFmts = *GetSpzFrmFmts();
2089     for( sal_uInt16 n = rFmts.Count(); n; )
2090     {
2091         const SwFrmFmt* pFlyFmt = rFmts[ --n ];
2092         const SwNodeIndex* pIdx;
2093         if( RES_FLYFRMFMT == pFlyFmt->Which() && pFlyFmt->GetName() == rName &&
2094             0 != ( pIdx = pFlyFmt->GetCntnt().GetCntntIdx() ) &&
2095             pIdx->GetNode().GetNodes().IsDocNodes() )
2096         {
2097             if( nNdTyp )
2098             {
2099                 // dann noch auf den richtigen Node-Typ abfragen
2100                 const SwNode* pNd = GetNodes()[ pIdx->GetIndex()+1 ];
2101                 if( nNdTyp == ND_TEXTNODE
2102                         ? !pNd->IsNoTxtNode()
2103                         : nNdTyp == pNd->GetNodeType() )
2104                     return (SwFlyFrmFmt*)pFlyFmt;
2105             }
2106             else
2107                 return (SwFlyFrmFmt*)pFlyFmt;
2108         }
2109     }
2110     return 0;
2111 }
2112 
2113 void SwDoc::SetFlyName( SwFlyFrmFmt& rFmt, const String& rName )
2114 {
2115     String sName( rName );
2116     if( !rName.Len() || FindFlyByName( rName ) )
2117     {
2118         sal_uInt16 nTyp = STR_FRAME_DEFNAME;
2119         const SwNodeIndex* pIdx = rFmt.GetCntnt().GetCntntIdx();
2120         if( pIdx && pIdx->GetNode().GetNodes().IsDocNodes() )
2121             switch( GetNodes()[ pIdx->GetIndex() + 1 ]->GetNodeType() )
2122             {
2123             case ND_GRFNODE:    nTyp = STR_GRAPHIC_DEFNAME; break;
2124             case ND_OLENODE:    nTyp = STR_OBJECT_DEFNAME;  break;
2125             }
2126         sName = lcl_GetUniqueFlyName( this, nTyp );
2127     }
2128     rFmt.SetName( sName, sal_True );
2129     SetModified();
2130 }
2131 
2132 void SwDoc::SetAllUniqueFlyNames()
2133 {
2134     sal_uInt16 n, nFlyNum = 0, nGrfNum = 0, nOLENum = 0;
2135 
2136     ResId nFrmId( STR_FRAME_DEFNAME, *pSwResMgr ),
2137           nGrfId( STR_GRAPHIC_DEFNAME, *pSwResMgr ),
2138           nOLEId( STR_OBJECT_DEFNAME, *pSwResMgr );
2139     String sFlyNm( nFrmId );
2140     String sGrfNm( nGrfId );
2141     String sOLENm( nOLEId );
2142 
2143     if( 255 < ( n = GetSpzFrmFmts()->Count() ))
2144         n = 255;
2145     SwSpzFrmFmts aArr( (sal_Int8)n, 10 );
2146     SwFrmFmtPtr pFlyFmt;
2147     bool bContainsAtPageObjWithContentAnchor = false;
2148 
2149     for( n = GetSpzFrmFmts()->Count(); n; )
2150     {
2151         if( RES_FLYFRMFMT == (pFlyFmt = (*GetSpzFrmFmts())[ --n ])->Which() )
2152         {
2153             sal_uInt16 *pNum = 0;
2154             xub_StrLen nLen;
2155             const String& rNm = pFlyFmt->GetName();
2156             if( rNm.Len() )
2157             {
2158                 if( rNm.Match( sGrfNm ) == ( nLen = sGrfNm.Len() ))
2159                     pNum = &nGrfNum;
2160                 else if( rNm.Match( sFlyNm ) == ( nLen = sFlyNm.Len() ))
2161                     pNum = &nFlyNum;
2162                 else if( rNm.Match( sOLENm ) == ( nLen = sOLENm.Len() ))
2163                     pNum = &nOLENum;
2164 
2165                 if ( pNum && *pNum < ( nLen = static_cast< xub_StrLen >( rNm.Copy( nLen ).ToInt32() ) ) )
2166                     *pNum = nLen;
2167             }
2168             else
2169                 // das wollen wir nachher setzen
2170                 aArr.Insert( pFlyFmt, aArr.Count() );
2171 
2172         }
2173         if ( !bContainsAtPageObjWithContentAnchor )
2174         {
2175             const SwFmtAnchor& rAnchor = pFlyFmt->GetAnchor();
2176             if ( (FLY_AT_PAGE == rAnchor.GetAnchorId()) &&
2177                  rAnchor.GetCntntAnchor() )
2178             {
2179                 bContainsAtPageObjWithContentAnchor = true;
2180             }
2181         }
2182     }
2183     SetContainsAtPageObjWithContentAnchor( bContainsAtPageObjWithContentAnchor );
2184 
2185     const SwNodeIndex* pIdx;
2186 
2187     for( n = aArr.Count(); n; )
2188         if( 0 != ( pIdx = ( pFlyFmt = aArr[ --n ])->GetCntnt().GetCntntIdx() )
2189             && pIdx->GetNode().GetNodes().IsDocNodes() )
2190         {
2191             sal_uInt16 nNum;
2192             String sNm;
2193             switch( GetNodes()[ pIdx->GetIndex() + 1 ]->GetNodeType() )
2194             {
2195             case ND_GRFNODE:
2196                 sNm = sGrfNm;
2197                 nNum = ++nGrfNum;
2198                 break;
2199             case ND_OLENODE:
2200                 sNm = sOLENm;
2201                 nNum = ++nOLENum;
2202                 break;
2203             default:
2204                 sNm = sFlyNm;
2205                 nNum = ++nFlyNum;
2206                 break;
2207             }
2208             pFlyFmt->SetName( sNm += String::CreateFromInt32( nNum ));
2209         }
2210     aArr.Remove( 0, aArr.Count() );
2211 
2212     if( GetFtnIdxs().Count() )
2213     {
2214         SwTxtFtn::SetUniqueSeqRefNo( *this );
2215         // --> FME 2005-08-02 #i52775# Chapter footnotes did not
2216         // get updated correctly. Calling UpdateAllFtn() instead of
2217         // UpdateFtn() solves this problem, but I do not dare to
2218         // call UpdateAllFtn() in all cases: Safety first.
2219         if ( FTNNUM_CHAPTER == GetFtnInfo().eNum )
2220         {
2221             GetFtnIdxs().UpdateAllFtn();
2222         }
2223         // <--
2224         else
2225         {
2226             SwNodeIndex aTmp( GetNodes() );
2227             GetFtnIdxs().UpdateFtn( aTmp );
2228         }
2229     }
2230 }
2231 
2232 sal_Bool SwDoc::IsInHeaderFooter( const SwNodeIndex& rIdx ) const
2233 {
2234     // gibt es ein Layout, dann ueber das laufen!!
2235     //  (Das kann dann auch Fly in Fly in Kopfzeile !)
2236     // MIB 9.2.98: Wird auch vom sw3io benutzt, um festzustellen, ob sich
2237     // ein Redline-Objekt in einer Kopf- oder Fusszeile befindet. Da
2238     // Redlines auch an Start- und Endnodes haengen, muss der Index nicht
2239     // unbedingt der eines Content-Nodes sein.
2240     SwNode* pNd = &rIdx.GetNode();
2241     if( pNd->IsCntntNode() && pCurrentView )//swmod 071029//swmod 071225
2242     {
2243         const SwFrm *pFrm = pNd->GetCntntNode()->getLayoutFrm( GetCurrentLayout() );
2244         if( pFrm )
2245         {
2246             const SwFrm *pUp = pFrm->GetUpper();
2247             while ( pUp && !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() )
2248             {
2249                 if ( pUp->IsFlyFrm() )
2250                     pUp = ((SwFlyFrm*)pUp)->GetAnchorFrm();
2251                 pUp = pUp->GetUpper();
2252             }
2253             if ( pUp )
2254                 return sal_True;
2255 
2256             return sal_False;
2257         }
2258     }
2259 
2260 
2261     const SwNode* pFlyNd = pNd->FindFlyStartNode();
2262     while( pFlyNd )
2263     {
2264         // dann ueber den Anker nach oben "hangeln"
2265         sal_uInt16 n;
2266         for( n = 0; n < GetSpzFrmFmts()->Count(); ++n )
2267         {
2268             const SwFrmFmt* pFmt = (*GetSpzFrmFmts())[ n ];
2269             const SwNodeIndex* pIdx = pFmt->GetCntnt().GetCntntIdx();
2270             if( pIdx && pFlyNd == &pIdx->GetNode() )
2271             {
2272                 const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
2273                 if ((FLY_AT_PAGE == rAnchor.GetAnchorId()) ||
2274                     !rAnchor.GetCntntAnchor() )
2275                 {
2276                     return sal_False;
2277                 }
2278 
2279                 pNd = &rAnchor.GetCntntAnchor()->nNode.GetNode();
2280                 pFlyNd = pNd->FindFlyStartNode();
2281                 break;
2282             }
2283         }
2284         if( n >= GetSpzFrmFmts()->Count() )
2285         {
2286             ASSERT( mbInReading, "Fly-Section aber kein Format gefunden" );
2287             return sal_False;
2288         }
2289     }
2290 
2291     return 0 != pNd->FindHeaderStartNode() ||
2292             0 != pNd->FindFooterStartNode();
2293 }
2294 
2295 short SwDoc::GetTextDirection( const SwPosition& rPos,
2296                                const Point* pPt ) const
2297 {
2298     short nRet = -1;
2299 
2300     SwCntntNode *pNd = rPos.nNode.GetNode().GetCntntNode();
2301 
2302     // --> OD 2005-02-21 #i42921# - use new method <SwCntntNode::GetTextDirection(..)>
2303     if ( pNd )
2304     {
2305         nRet = pNd->GetTextDirection( rPos, pPt );
2306     }
2307     if ( nRet == -1 )
2308     // <--
2309     {
2310         const SvxFrameDirectionItem* pItem = 0;
2311         if( pNd )
2312         {
2313             // in a flyframe? Then look at that for the correct attribute
2314             const SwFrmFmt* pFlyFmt = pNd->GetFlyFmt();
2315             while( pFlyFmt )
2316             {
2317                 pItem = &pFlyFmt->GetFrmDir();
2318                 if( FRMDIR_ENVIRONMENT == pItem->GetValue() )
2319                 {
2320                     pItem = 0;
2321                     const SwFmtAnchor* pAnchor = &pFlyFmt->GetAnchor();
2322                     if ((FLY_AT_PAGE != pAnchor->GetAnchorId()) &&
2323                         pAnchor->GetCntntAnchor())
2324                     {
2325                         pFlyFmt = pAnchor->GetCntntAnchor()->nNode.
2326                                             GetNode().GetFlyFmt();
2327                     }
2328                     else
2329                         pFlyFmt = 0;
2330                 }
2331                 else
2332                     pFlyFmt = 0;
2333             }
2334 
2335             if( !pItem )
2336             {
2337                 const SwPageDesc* pPgDsc = pNd->FindPageDesc( sal_False );
2338                 if( pPgDsc )
2339                     pItem = &pPgDsc->GetMaster().GetFrmDir();
2340             }
2341         }
2342         if( !pItem )
2343             pItem = (SvxFrameDirectionItem*)&GetAttrPool().GetDefaultItem(
2344                                                             RES_FRAMEDIR );
2345         nRet = pItem->GetValue();
2346     }
2347     return nRet;
2348 }
2349 
2350 sal_Bool SwDoc::IsInVerticalText( const SwPosition& rPos, const Point* pPt ) const
2351 {
2352     const short nDir = GetTextDirection( rPos, pPt );
2353     return FRMDIR_VERT_TOP_RIGHT == nDir || FRMDIR_VERT_TOP_LEFT == nDir;
2354 }
2355 
2356 void SwDoc::SetCurrentViewShell( ViewShell* pNew )
2357 {
2358     pCurrentView = pNew;
2359 }
2360 
2361 SwLayouter* SwDoc::GetLayouter()
2362 {
2363     return pLayouter;
2364 }
2365 
2366 const SwLayouter* SwDoc::GetLayouter() const
2367 {
2368     return pLayouter;
2369 }
2370 
2371 void SwDoc::SetLayouter( SwLayouter* pNew )
2372 {
2373     pLayouter = pNew;
2374 }
2375 
2376 const ViewShell *SwDoc::GetCurrentViewShell() const
2377 {
2378     return pCurrentView;
2379 }
2380 
2381 ViewShell *SwDoc::GetCurrentViewShell()
2382 {
2383     return pCurrentView;
2384 }   //swmod 080219 It must be able to communicate to a ViewShell.This is going to be removedd later.
2385 
2386 const SwRootFrm *SwDoc::GetCurrentLayout() const
2387 {
2388     if(GetCurrentViewShell())
2389         return GetCurrentViewShell()->GetLayout();
2390     return 0;
2391 }
2392 
2393 SwRootFrm *SwDoc::GetCurrentLayout()
2394 {
2395     if(GetCurrentViewShell())
2396         return GetCurrentViewShell()->GetLayout();
2397     return 0;
2398 }
2399 
2400 bool SwDoc::HasLayout() const
2401 {
2402     // if there is a view, there is always a layout
2403     return (pCurrentView != 0);
2404 }
2405 
2406 std::set<SwRootFrm*> SwDoc::GetAllLayouts()
2407 {
2408     std::set<SwRootFrm*> aAllLayouts;
2409     ViewShell *pStart = GetCurrentViewShell();
2410     ViewShell *pTemp = pStart;
2411     if ( pTemp )
2412     {
2413         do
2414         {
2415             if (pTemp->GetLayout())
2416             {
2417                 aAllLayouts.insert(pTemp->GetLayout());
2418                 pTemp = (ViewShell*)pTemp->GetNext();
2419             }
2420         } while(pTemp!=pStart);
2421     }
2422 
2423     return aAllLayouts;
2424 }//swmod 070825
2425 
2426 
2427 void SwDoc::ShareLayout(boost::shared_ptr<SwRootFrm>& rPtr)
2428 {
2429     pLayoutPtr = rPtr;
2430 }
2431 
2432