Update ooo320-m1
[ooovba.git] / sw / source / core / doc / doclay.cxx
blobfe244d495700ced056f2a7204529fa741d5cbb13
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: doclay.cxx,v $
10 * $Revision: 1.59 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
34 #include <svtools/linguprops.hxx>
35 #include <svtools/lingucfg.hxx>
36 #include <com/sun/star/embed/EmbedStates.hpp>
37 #include <hintids.hxx>
38 #include <com/sun/star/util/XCloseable.hpp>
39 #include <sfx2/progress.hxx>
40 #include <svx/svdmodel.hxx>
41 #include <svx/svdpage.hxx>
42 #include <svx/keepitem.hxx>
43 #include <svx/ulspitem.hxx>
44 #include <svx/lrspitem.hxx>
45 #include <svx/boxitem.hxx>
46 #include <svx/shaditem.hxx>
47 #include <svx/protitem.hxx>
48 #include <svx/opaqitem.hxx>
49 #include <svx/prntitem.hxx>
50 #include <svx/fmglob.hxx>
51 #include <svx/svdouno.hxx>
52 #include <svx/fmpage.hxx>
53 #include <svx/frmdiritem.hxx>
55 #include <swmodule.hxx>
56 #include <modcfg.hxx>
57 #include <com/sun/star/beans/XPropertySet.hpp>
58 #include <rtl/logfile.hxx>
59 #include <SwStyleNameMapper.hxx>
60 #include <fchrfmt.hxx>
61 #include <errhdl.hxx>
62 #include <frmatr.hxx>
63 #include <txatbase.hxx>
64 #include <fmtfld.hxx>
65 #include <fmtornt.hxx>
66 #include <fmtcntnt.hxx>
67 #include <fmtanchr.hxx>
68 #include <fmtfsize.hxx>
69 #include <fmtsrnd.hxx>
70 #include <fmtflcnt.hxx>
71 #ifndef _FRMCNCT_HXX //autogen
72 #include <fmtcnct.hxx>
73 #endif
74 #include <frmfmt.hxx>
75 #include <dcontact.hxx>
76 #include <txtflcnt.hxx>
77 #include <docfld.hxx> // fuer Expression-Felder
78 #include <pam.hxx>
79 #include <ndtxt.hxx>
80 #include <ndnotxt.hxx>
81 #include <ndole.hxx>
82 #include <doc.hxx>
83 #include <rootfrm.hxx>
84 #include <pagefrm.hxx>
85 #include <cntfrm.hxx>
86 #include <flyfrm.hxx>
87 #include <fesh.hxx>
88 #ifndef _DOCSH_HXX
89 #include <docsh.hxx>
90 #endif
91 #include <dflyobj.hxx>
92 #include <dcontact.hxx>
93 #include <swundo.hxx>
94 #include <flypos.hxx>
95 #include <undobj.hxx>
96 #include <expfld.hxx> // InsertLabel
97 #include <poolfmt.hxx> // PoolVorlagen-Id's
98 #include <docary.hxx>
99 #include <swtable.hxx>
100 #include <tblsel.hxx>
101 #include <viewopt.hxx>
102 #include <fldupde.hxx>
103 #include <txtftn.hxx>
104 #include <ftnidx.hxx>
105 #include <ftninfo.hxx>
106 #include <pagedesc.hxx>
107 #include <PostItMgr.hxx>
108 #include <comcore.hrc> // STR-ResId's
110 // #i11176#
111 #include <unoframe.hxx>
112 // OD 2004-05-24 #i28701#
113 #include <sortedobjs.hxx>
115 // --> OD 2004-07-26 #i32089#
116 #include <vector>
117 // <--
119 using namespace ::com::sun::star;
120 using ::rtl::OUString;
122 #define DEF_FLY_WIDTH 2268 //Defaultbreite fuer FlyFrms (2268 == 4cm)
124 /* #109161# */
125 static bool lcl_IsItemSet(const SwCntntNode & rNode, USHORT which)
127 bool bResult = false;
129 if (SFX_ITEM_SET == rNode.GetSwAttrSet().GetItemState(which))
130 bResult = true;
132 return bResult;
135 /*************************************************************************
137 |* SwDoc::MakeLayoutFmt()
139 |* Beschreibung Erzeugt ein neues Format das in seinen Einstellungen
140 |* Defaultmaessig zu dem Request passt. Das Format wird in das
141 |* entsprechende Formate-Array gestellt.
142 |* Wenn bereits ein passendes Format existiert, so wird dies
143 |* zurueckgeliefert.
144 |* Ersterstellung MA 22. Sep. 92
145 |* Letzte Aenderung JP 08.05.98
147 |*************************************************************************/
149 SwFrmFmt *SwDoc::MakeLayoutFmt( RndStdIds eRequest, const SfxItemSet* pSet )
151 SwFrmFmt *pFmt = 0;
152 const sal_Bool bMod = IsModified();
153 sal_Bool bHeader = sal_False;
155 switch ( eRequest )
157 case RND_STD_HEADER:
158 case RND_STD_HEADERL:
159 case RND_STD_HEADERR:
161 bHeader = sal_True;
162 // kein break, es geht unten weiter
164 case RND_STD_FOOTER:
165 case RND_STD_FOOTERL:
166 case RND_STD_FOOTERR:
168 pFmt = new SwFrmFmt( GetAttrPool(),
169 (bHeader ? "Header" : "Footer"),
170 GetDfltFrmFmt() );
172 SwNodeIndex aTmpIdx( GetNodes().GetEndOfAutotext() );
173 SwStartNode* pSttNd =
174 GetNodes().MakeTextSection
175 ( aTmpIdx,
176 bHeader ? SwHeaderStartNode : SwFooterStartNode,
177 GetTxtCollFromPool(static_cast<sal_uInt16>( bHeader
178 ? ( eRequest == RND_STD_HEADERL
179 ? RES_POOLCOLL_HEADERL
180 : eRequest == RND_STD_HEADERR
181 ? RES_POOLCOLL_HEADERR
182 : RES_POOLCOLL_HEADER )
183 : ( eRequest == RND_STD_FOOTERL
184 ? RES_POOLCOLL_FOOTERL
185 : eRequest == RND_STD_FOOTERR
186 ? RES_POOLCOLL_FOOTERR
187 : RES_POOLCOLL_FOOTER )
188 ) ) );
189 pFmt->SetFmtAttr( SwFmtCntnt( pSttNd ));
191 if( pSet ) // noch ein paar Attribute setzen ?
192 pFmt->SetFmtAttr( *pSet );
194 // JP: warum zuruecksetzen ??? Doc. ist doch veraendert ???
195 // bei den Fly auf jedenfall verkehrt !!
196 if ( !bMod )
197 ResetModified();
199 break;
201 case RND_DRAW_OBJECT:
203 pFmt = MakeDrawFrmFmt( aEmptyStr, GetDfltFrmFmt() );
204 if( pSet ) // noch ein paar Attribute setzen ?
205 pFmt->SetFmtAttr( *pSet );
207 if( DoesUndo() )
209 ClearRedo();
210 AppendUndo( new SwUndoInsLayFmt( pFmt,0,0 ));
213 break;
215 #ifndef PRODUCT
216 case FLY_PAGE:
217 case FLY_AUTO_CNTNT:
218 case FLY_AT_FLY:
219 case FLY_AT_CNTNT:
220 case FLY_IN_CNTNT:
221 ASSERT( !this,
222 "neue Schnittstelle benutzen: SwDoc::MakeFlySection!" );
223 break;
224 #endif
226 default:
227 ASSERT( !this,
228 "Layoutformat mit ungueltigem Request angefordert." );
231 return pFmt;
233 /*************************************************************************
235 |* SwDoc::DelLayoutFmt()
237 |* Beschreibung Loescht das angegebene Format, der Inhalt wird mit
238 |* geloescht.
239 |* Ersterstellung MA 23. Sep. 92
240 |* Letzte Aenderung MA 05. Feb. 93
242 |*************************************************************************/
244 void SwDoc::DelLayoutFmt( SwFrmFmt *pFmt )
246 //Verkettung von Rahmen muss ggf. zusammengefuehrt werden.
247 //Bevor die Frames vernichtet werden, damit die Inhalte der Rahmen
248 //ggf. entsprechend gerichtet werden.
249 const SwFmtChain &rChain = pFmt->GetChain();
250 if ( rChain.GetPrev() )
252 SwFmtChain aChain( rChain.GetPrev()->GetChain() );
253 aChain.SetNext( rChain.GetNext() );
254 SetAttr( aChain, *rChain.GetPrev() );
256 if ( rChain.GetNext() )
258 SwFmtChain aChain( rChain.GetNext()->GetChain() );
259 aChain.SetPrev( rChain.GetPrev() );
260 SetAttr( aChain, *rChain.GetNext() );
263 const SwNodeIndex* pCntIdx = pFmt->GetCntnt().GetCntntIdx();
264 if( pCntIdx && !DoesUndo() )
266 //Verbindung abbauen, falls es sich um ein OLE-Objekt handelt.
267 SwOLENode* pOLENd = GetNodes()[ pCntIdx->GetIndex()+1 ]->GetOLENode();
268 if( pOLENd && pOLENd->GetOLEObj().IsOleRef() )
271 SwDoc* pDoc = (SwDoc*)pFmt->GetDoc();
272 if( pDoc )
274 SfxObjectShell* p = pDoc->GetPersist();
275 if( p ) // muss da sein
277 SvInfoObjectRef aRef( p->Find( pOLENd->GetOLEObj().GetName() ) );
278 if( aRef.Is() )
279 aRef->SetObj(0);
281 } */
283 // TODO/MBA: the old object closed the object, cleared all references to it, but didn't remove it from the container.
284 // I have no idea, why, nobody could explain it - so I do my very best to mimic this behavior
285 //uno::Reference < util::XCloseable > xClose( pOLENd->GetOLEObj().GetOleRef(), uno::UNO_QUERY );
286 //if ( xClose.is() )
290 pOLENd->GetOLEObj().GetOleRef()->changeState( embed::EmbedStates::LOADED );
292 catch ( uno::Exception& )
297 //pOLENd->GetOLEObj().GetOleRef() = 0;
301 //Frms vernichten.
302 pFmt->DelFrms();
304 // erstmal sind nur Fly's Undofaehig
305 const sal_uInt16 nWh = pFmt->Which();
306 if( DoesUndo() && (RES_FLYFRMFMT == nWh || RES_DRAWFRMFMT == nWh) )
308 // erstmal werden alle Undo - Objecte geloescht.
309 ClearRedo();
310 AppendUndo( new SwUndoDelLayFmt( pFmt ));
312 else
314 // --> OD 2004-07-26 #i32089# - delete at-frame anchored objects
315 if ( nWh == RES_FLYFRMFMT )
317 // determine frame formats of at-frame anchored objects
318 const SwNodeIndex* pCntntIdx = pFmt->GetCntnt().GetCntntIdx();
319 if ( pCntntIdx )
321 const SwSpzFrmFmts* pTbl = pFmt->GetDoc()->GetSpzFrmFmts();
322 if ( pTbl )
324 std::vector<SwFrmFmt*> aToDeleteFrmFmts;
325 const ULONG nNodeIdxOfFlyFmt( pCntntIdx->GetIndex() );
327 for ( USHORT i = 0; i < pTbl->Count(); ++i )
329 SwFrmFmt* pTmpFmt = (*pTbl)[i];
330 const SwFmtAnchor &rAnch = pTmpFmt->GetAnchor();
331 if ( rAnch.GetAnchorId() == FLY_AT_FLY &&
332 rAnch.GetCntntAnchor()->nNode.GetIndex() == nNodeIdxOfFlyFmt )
334 aToDeleteFrmFmts.push_back( pTmpFmt );
338 // delete found frame formats
339 while ( !aToDeleteFrmFmts.empty() )
341 SwFrmFmt* pTmpFmt = aToDeleteFrmFmts.back();
342 pFmt->GetDoc()->DelLayoutFmt( pTmpFmt );
344 aToDeleteFrmFmts.pop_back();
349 // <--
351 //Inhalt Loeschen.
352 if( pCntIdx )
354 SwNode *pNode = &pCntIdx->GetNode();
355 ((SwFmtCntnt&)pFmt->GetFmtAttr( RES_CNTNT )).SetNewCntntIdx( 0 );
356 DeleteSection( pNode );
359 // ggfs. bei Zeichengebundenen Flys das Zeichen loeschen
360 const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
361 if( FLY_IN_CNTNT == rAnchor.GetAnchorId() && rAnchor.GetCntntAnchor())
363 const SwPosition* pPos = rAnchor.GetCntntAnchor();
364 SwTxtNode *pTxtNd = pPos->nNode.GetNode().GetTxtNode();
366 // attribute is still in text node, delete it
367 if ( pTxtNd )
369 SwTxtFlyCnt* const pAttr = static_cast<SwTxtFlyCnt*>(
370 pTxtNd->GetTxtAttrForCharAt( pPos->nContent.GetIndex(),
371 RES_TXTATR_FLYCNT ));
372 if ( pAttr && (pAttr->GetFlyCnt().GetFrmFmt() == pFmt) )
374 // dont delete, set pointer to 0
375 const_cast<SwFmtFlyCnt&>(pAttr->GetFlyCnt()).SetFlyFmt();
376 SwIndex aIdx( pPos->nContent );
377 pTxtNd->EraseText( aIdx, 1 );
382 DelFrmFmt( pFmt );
384 SetModified();
387 /*************************************************************************
389 |* SwDoc::CopyLayoutFmt()
391 |* Beschreibung Kopiert das angegebene Format pSrc in pDest und
392 |* returnt pDest. Wenn es noch kein pDest gibt, wird
393 |* eins angelegt.
394 |* JP: steht das Source Format in einem anderen
395 |* Dokument, so kopiere auch dann noch richtig !!
396 |* Vom chaos::Anchor-Attribut wird die Position immer
397 |* auf 0 gesetzt !!!
399 |* Ersterstellung BP 18.12.92
400 |* Letzte Aenderung MA 17. Jul. 96
402 |*************************************************************************/
404 SwFrmFmt *SwDoc::CopyLayoutFmt( const SwFrmFmt& rSource,
405 const SwFmtAnchor& rNewAnchor,
406 bool bSetTxtFlyAtt, bool bMakeFrms )
408 const bool bFly = RES_FLYFRMFMT == rSource.Which();
409 const bool bDraw = RES_DRAWFRMFMT == rSource.Which();
410 ASSERT( bFly || bDraw, "this method only works for fly or draw" );
412 SwDoc* pSrcDoc = (SwDoc*)rSource.GetDoc();
414 // #108784# may we copy this object?
415 // We may, unless it's 1) it's a control (and therfore a draw)
416 // 2) anchored in a header/footer
417 // 3) anchored (to paragraph?)
418 bool bMayNotCopy = false;
419 if( bDraw )
421 const SwDrawContact* pDrawContact =
422 static_cast<const SwDrawContact*>( rSource.FindContactObj() );
424 bMayNotCopy =
425 ( FLY_AT_CNTNT == rNewAnchor.GetAnchorId() ||
426 FLY_AT_FLY == rNewAnchor.GetAnchorId() ||
427 FLY_AUTO_CNTNT == rNewAnchor.GetAnchorId() ) &&
428 rNewAnchor.GetCntntAnchor() &&
429 IsInHeaderFooter( rNewAnchor.GetCntntAnchor()->nNode ) &&
430 pDrawContact != NULL &&
431 pDrawContact->GetMaster() != NULL &&
432 CheckControlLayer( pDrawContact->GetMaster() );
435 // just return if we can't copy this
436 if( bMayNotCopy )
437 return NULL;
439 SwFrmFmt* pDest = GetDfltFrmFmt();
440 if( rSource.GetRegisteredIn() != pSrcDoc->GetDfltFrmFmt() )
441 pDest = CopyFrmFmt( *(SwFrmFmt*)rSource.GetRegisteredIn() );
442 if( bFly )
444 // #i11176#
445 // To do a correct cloning concerning the ZOrder for all objects
446 // it is necessary to actually create a draw object for fly frames, too.
447 // These are then added to the DrawingLayer (which needs to exist).
448 // Together with correct sorting of all drawinglayer based objects
449 // before cloning ZOrder transfer works correctly then.
450 SwFlyFrmFmt *pFormat = MakeFlyFrmFmt( rSource.GetName(), pDest );
451 pDest = pFormat;
453 SwXFrame::GetOrCreateSdrObject(pFormat);
455 else
456 pDest = MakeDrawFrmFmt( aEmptyStr, pDest );
458 // alle anderen/neue Attribute kopieren.
459 pDest->CopyAttrs( rSource );
461 //Chains werden nicht kopiert.
462 pDest->ResetFmtAttr( RES_CHAIN );
464 if( bFly )
466 //Der Inhalt wird dupliziert.
467 const SwNode& rCSttNd = rSource.GetCntnt().GetCntntIdx()->GetNode();
468 SwNodeRange aRg( rCSttNd, 1, *rCSttNd.EndOfSectionNode() );
470 SwNodeIndex aIdx( GetNodes().GetEndOfAutotext() );
471 SwStartNode* pSttNd = GetNodes().MakeEmptySection( aIdx, SwFlyStartNode );
473 // erst den chaos::Anchor/CntntIndex setzen, innerhalb des Kopierens
474 // auf die Werte zugegriffen werden kann (DrawFmt in Kopf-/Fusszeilen)
475 aIdx = *pSttNd;
476 SwFmtCntnt aAttr( rSource.GetCntnt() );
477 aAttr.SetNewCntntIdx( &aIdx );
478 pDest->SetFmtAttr( aAttr );
479 pDest->SetFmtAttr( rNewAnchor );
481 if( !mbCopyIsMove || this != pSrcDoc )
483 if( mbInReading )
484 pDest->SetName( aEmptyStr );
485 else
487 // Teste erstmal ob der Name schon vergeben ist.
488 // Wenn ja -> neuen generieren
489 sal_Int8 nNdTyp = aRg.aStart.GetNode().GetNodeType();
491 String sOld( pDest->GetName() );
492 pDest->SetName( aEmptyStr );
493 if( FindFlyByName( sOld, nNdTyp ) ) // einen gefunden
494 switch( nNdTyp )
496 case ND_GRFNODE: sOld = GetUniqueGrfName(); break;
497 case ND_OLENODE: sOld = GetUniqueOLEName(); break;
498 default: sOld = GetUniqueFrameName(); break;
501 pDest->SetName( sOld );
505 if( DoesUndo() )
507 ClearRedo();
508 AppendUndo( new SwUndoInsLayFmt( pDest,0,0 ));
511 // sorge dafuer das auch Fly's in Fly's kopiert werden
512 aIdx = *pSttNd->EndOfSectionNode();
513 pSrcDoc->CopyWithFlyInFly( aRg, 0, aIdx, sal_False, sal_True, sal_True );
515 else
517 ASSERT( RES_DRAWFRMFMT == rSource.Which(), "Weder Fly noch Draw." );
518 // OD 2005-08-02 #i52780# - Note: moving object to visible layer not needed.
519 SwDrawContact* pSourceContact = (SwDrawContact *)rSource.FindContactObj();
521 SwDrawContact* pContact = new SwDrawContact( (SwDrawFrmFmt*)pDest,
522 CloneSdrObj( *pSourceContact->GetMaster(),
523 mbCopyIsMove && this == pSrcDoc ) );
524 // --> OD 2005-05-23 #i49730# - notify draw frame format
525 // that position attributes are already set, if the position attributes
526 // are already set at the source draw frame format.
527 if ( pDest->ISA(SwDrawFrmFmt) &&
528 rSource.ISA(SwDrawFrmFmt) &&
529 static_cast<const SwDrawFrmFmt&>(rSource).IsPosAttrSet() )
531 static_cast<SwDrawFrmFmt*>(pDest)->PosAttrSet();
533 // <--
535 if( pDest->GetAnchor() == rNewAnchor )
537 // OD 03.07.2003 #108784# - do *not* connect to layout, if
538 // a <MakeFrms> will not be called.
539 if ( bMakeFrms )
541 pContact->ConnectToLayout( &rNewAnchor );
544 else
545 pDest->SetFmtAttr( rNewAnchor );
547 if( DoesUndo() )
549 ClearRedo();
550 AppendUndo( new SwUndoInsLayFmt( pDest,0,0 ));
554 if( bSetTxtFlyAtt && FLY_IN_CNTNT == rNewAnchor.GetAnchorId() )
556 const SwPosition* pPos = rNewAnchor.GetCntntAnchor();
557 SwFmtFlyCnt aFmt( pDest );
558 pPos->nNode.GetNode().GetTxtNode()->InsertItem(
559 aFmt, pPos->nContent.GetIndex(), 0 );
562 if( bMakeFrms )
563 pDest->MakeFrms();
565 return pDest;
568 SdrObject* SwDoc::CloneSdrObj( const SdrObject& rObj, sal_Bool bMoveWithinDoc,
569 sal_Bool bInsInPage )
571 // --> OD 2005-08-08 #i52858# - method name changed
572 SdrPage *pPg = GetOrCreateDrawModel()->GetPage( 0 );
573 // <--
574 if( !pPg )
576 pPg = GetDrawModel()->AllocPage( sal_False );
577 GetDrawModel()->InsertPage( pPg );
580 SdrObject *pObj = rObj.Clone();
581 if( bMoveWithinDoc && FmFormInventor == pObj->GetObjInventor() )
583 // bei Controls muss der Name erhalten bleiben
584 uno::Reference< awt::XControlModel > xModel = ((SdrUnoObj*)pObj)->GetUnoControlModel();
585 uno::Any aVal;
586 uno::Reference< beans::XPropertySet > xSet(xModel, uno::UNO_QUERY);
587 OUString sName( rtl::OUString::createFromAscii("Name") );
588 if( xSet.is() )
589 aVal = xSet->getPropertyValue( sName );
590 if( bInsInPage )
591 pPg->InsertObject( pObj );
592 if( xSet.is() )
593 xSet->setPropertyValue( sName, aVal );
595 else if( bInsInPage )
596 pPg->InsertObject( pObj );
598 // OD 02.07.2003 #108784# - for drawing objects: set layer of cloned object
599 // to invisible layer
600 SdrLayerID nLayerIdForClone = rObj.GetLayer();
601 if ( !pObj->ISA(SwFlyDrawObj) &&
602 !pObj->ISA(SwVirtFlyDrawObj) &&
603 !IS_TYPE(SdrObject,pObj) )
605 if ( IsVisibleLayerId( nLayerIdForClone ) )
607 nLayerIdForClone = GetInvisibleLayerIdByVisibleOne( nLayerIdForClone );
610 pObj->SetLayer( nLayerIdForClone );
613 return pObj;
616 SwFlyFrmFmt* SwDoc::_MakeFlySection( const SwPosition& rAnchPos,
617 const SwCntntNode& rNode,
618 RndStdIds eRequestId,
619 const SfxItemSet* pFlySet,
620 SwFrmFmt* pFrmFmt )
622 if( !pFrmFmt )
623 pFrmFmt = GetFrmFmtFromPool( RES_POOLFRM_FRAME );
625 String sName;
626 if( !mbInReading )
627 switch( rNode.GetNodeType() )
629 case ND_GRFNODE: sName = GetUniqueGrfName(); break;
630 case ND_OLENODE: sName = GetUniqueOLEName(); break;
631 default: sName = GetUniqueFrameName(); break;
633 SwFlyFrmFmt* pFmt = MakeFlyFrmFmt( sName, pFrmFmt );
635 //Inhalt erzeugen und mit dem Format verbinden.
636 //CntntNode erzeugen und in die Autotextsection stellen
637 SwNodeRange aRange( GetNodes().GetEndOfAutotext(), -1,
638 GetNodes().GetEndOfAutotext() );
639 GetNodes().SectionDown( &aRange, SwFlyStartNode );
641 pFmt->SetFmtAttr( SwFmtCntnt( rNode.StartOfSectionNode() ));
644 const SwFmtAnchor* pAnchor = 0;
645 if( pFlySet )
647 pFlySet->GetItemState( RES_ANCHOR, sal_False,
648 (const SfxPoolItem**)&pAnchor );
649 if( SFX_ITEM_SET == pFlySet->GetItemState( RES_CNTNT, sal_False ))
651 SfxItemSet aTmpSet( *pFlySet );
652 aTmpSet.ClearItem( RES_CNTNT );
653 pFmt->SetFmtAttr( aTmpSet );
655 else
656 pFmt->SetFmtAttr( *pFlySet );
659 // Anker noch nicht gesetzt ?
660 RndStdIds eAnchorId = pAnchor ? pAnchor->GetAnchorId()
661 : pFmt->GetAnchor().GetAnchorId();
662 if( !pAnchor ||
663 (FLY_PAGE != pAnchor->GetAnchorId() &&
664 //Nur Page und nicht:
665 // FLY_AT_CNTNT == pAnchor->GetAnchorId() ||
666 // FLY_IN_CNTNT == pAnchor->GetAnchorId() ||
667 // FLY_AT_FLY == pAnchor->GetAnchorId() ||
668 // FLY_AUTO_CNTNT == pAnchor->GetAnchorId() ) &&
669 !pAnchor->GetCntntAnchor() ))
671 // dann setze ihn, wird im Undo gebraucht
672 SwFmtAnchor aAnch( pFmt->GetAnchor() );
673 if( pAnchor && FLY_AT_FLY == pAnchor->GetAnchorId() )
675 SwPosition aPos( *rAnchPos.nNode.GetNode().FindFlyStartNode() );
676 aAnch.SetAnchor( &aPos );
677 eAnchorId = FLY_AT_FLY;
679 else
681 if( eRequestId != aAnch.GetAnchorId() &&
682 SFX_ITEM_SET != pFmt->GetItemState( RES_ANCHOR, sal_True ) )
683 aAnch.SetType( eRequestId );
685 eAnchorId = aAnch.GetAnchorId();
686 if ( FLY_PAGE != eAnchorId )
687 //Nur Page und nicht:
688 // if( FLY_AT_CNTNT == eAnchorId || FLY_IN_CNTNT == eAnchorId ||
689 // FLY_AT_FLY == eAnchorId || FLY_AUTO_CNTNT == eAnchorId )
690 aAnch.SetAnchor( &rAnchPos );
692 pFmt->SetFmtAttr( aAnch );
694 else
695 eAnchorId = pFmt->GetAnchor().GetAnchorId();
697 if( FLY_IN_CNTNT == eAnchorId )
699 xub_StrLen nStt = rAnchPos.nContent.GetIndex();
700 SwTxtNode * pTxtNode = rAnchPos.nNode.GetNode().GetTxtNode();
702 ASSERT(pTxtNode!= 0, "There should be a SwTxtNode!");
704 if (pTxtNode != NULL)
706 SwFmtFlyCnt aFmt( pFmt );
707 pTxtNode->InsertItem( aFmt, nStt, nStt );
711 if( SFX_ITEM_SET != pFmt->GetAttrSet().GetItemState( RES_FRM_SIZE ))
713 SwFmtFrmSize aFmtSize( ATT_VAR_SIZE, 0, DEF_FLY_WIDTH );
714 const SwNoTxtNode* pNoTxtNode = rNode.GetNoTxtNode();
715 if( pNoTxtNode )
717 //Groesse einstellen.
718 Size aSize( pNoTxtNode->GetTwipSize() );
719 if( MINFLY > aSize.Width() )
720 aSize.Width() = DEF_FLY_WIDTH;
721 aFmtSize.SetWidth( aSize.Width() );
722 if( aSize.Height() )
724 aFmtSize.SetHeight( aSize.Height() );
725 aFmtSize.SetHeightSizeType( ATT_FIX_SIZE );
728 pFmt->SetFmtAttr( aFmtSize );
731 // Frames anlegen
732 if( GetRootFrm() )
733 pFmt->MakeFrms(); // ???
735 if( DoesUndo() )
737 ClearRedo();
738 ULONG nNodeIdx = rAnchPos.nNode.GetIndex();
739 xub_StrLen nCntIdx = rAnchPos.nContent.GetIndex();
740 AppendUndo( new SwUndoInsLayFmt( pFmt, nNodeIdx, nCntIdx ));
743 SetModified();
744 return pFmt;
747 SwFlyFrmFmt* SwDoc::MakeFlySection( RndStdIds eAnchorType,
748 const SwPosition* pAnchorPos,
749 const SfxItemSet* pFlySet,
750 SwFrmFmt* pFrmFmt, BOOL bCalledFromShell )
752 SwFlyFrmFmt* pFmt = 0;
753 sal_Bool bCallMake = sal_True;
754 if( !pAnchorPos && FLY_PAGE != eAnchorType )
756 const SwFmtAnchor* pAnch;
757 if( (pFlySet && SFX_ITEM_SET == pFlySet->GetItemState(
758 RES_ANCHOR, sal_False, (const SfxPoolItem**)&pAnch )) ||
759 ( pFrmFmt && SFX_ITEM_SET == pFrmFmt->GetItemState(
760 RES_ANCHOR, sal_True, (const SfxPoolItem**)&pAnch )) )
762 if( FLY_PAGE != pAnch->GetAnchorId() &&
763 0 == ( pAnchorPos = pAnch->GetCntntAnchor() ) )
764 bCallMake = sal_False;
768 if( bCallMake )
770 if( !pFrmFmt )
771 pFrmFmt = GetFrmFmtFromPool( RES_POOLFRM_FRAME );
773 sal_uInt16 nCollId = static_cast<sal_uInt16>(
774 get(IDocumentSettingAccess::HTML_MODE) ? RES_POOLCOLL_TEXT : RES_POOLCOLL_FRAME );
776 /* #109161# If there exists no adjust item in the paragraph
777 style for the content node of the new fly section
778 propagate an existing adjust item at the anchor to the new
779 content node. */
780 SwCntntNode * pNewTxtNd = GetNodes().MakeTxtNode
781 (SwNodeIndex( GetNodes().GetEndOfAutotext()),
782 GetTxtCollFromPool( nCollId ));
783 SwCntntNode * pAnchorNode = pAnchorPos->nNode.GetNode().GetCntntNode();
785 const SfxPoolItem * pItem = NULL;
787 if (bCalledFromShell && !lcl_IsItemSet(*pNewTxtNd, RES_PARATR_ADJUST) &&
788 SFX_ITEM_SET == pAnchorNode->GetSwAttrSet().
789 GetItemState(RES_PARATR_ADJUST, TRUE, &pItem))
790 static_cast<SwCntntNode *>(pNewTxtNd)->SetAttr(*pItem);
792 pFmt = _MakeFlySection( *pAnchorPos, *pNewTxtNd,
793 eAnchorType, pFlySet, pFrmFmt );
795 return pFmt;
798 SwFlyFrmFmt* SwDoc::MakeFlyAndMove( const SwPaM& rPam, const SfxItemSet& rSet,
799 const SwSelBoxes* pSelBoxes,
800 SwFrmFmt *pParent )
802 SwFmtAnchor& rAnch = (SwFmtAnchor&)rSet.Get( RES_ANCHOR );
804 StartUndo( UNDO_INSLAYFMT, NULL );
806 SwFlyFrmFmt* pFmt = MakeFlySection( rAnch.GetAnchorId(), rPam.GetPoint(),
807 &rSet, pParent );
809 // Wenn Inhalt selektiert ist, so wird dieser jetzt zum Inhalt des
810 // neuen Rahmen. Sprich er wird in die entspr. Sektion des NodesArr
811 //gemoved.
813 if( pFmt )
815 do { // middle check loop
816 const SwFmtCntnt &rCntnt = pFmt->GetCntnt();
817 ASSERT( rCntnt.GetCntntIdx(), "Kein Inhalt vorbereitet." );
818 SwNodeIndex aIndex( *(rCntnt.GetCntntIdx()), 1 );
819 SwCntntNode *pNode = aIndex.GetNode().GetCntntNode();
821 // ACHTUNG: nicht einen Index auf dem Stack erzeugen, sonst
822 // kann der CntntnNode am Ende nicht geloscht werden !!
823 SwPosition aPos( aIndex );
824 aPos.nContent.Assign( pNode, 0 );
826 if( pSelBoxes && pSelBoxes->Count() )
828 // Tabellenselection
829 // kopiere Teile aus einer Tabelle: lege eine Tabelle mit der
830 // Breite der Originalen an und move (kopiere/loesche) die
831 // selektierten Boxen. Die Groessen werden prozentual
832 // korrigiert.
834 SwTableNode* pTblNd = (SwTableNode*)(*pSelBoxes)[0]->
835 GetSttNd()->FindTableNode();
836 if( !pTblNd )
837 break;
839 SwTable& rTbl = pTblNd->GetTable();
841 // ist die gesamte Tabelle selektiert ?
842 if( pSelBoxes->Count() == rTbl.GetTabSortBoxes().Count() )
844 // verschiebe die gesamte Tabelle
845 SwNodeRange aRg( *pTblNd, 0, *pTblNd->EndOfSectionNode(), 1 );
847 // wird die gesamte Tabelle verschoben und steht diese
848 // in einem FlyFrame, dann erzeuge dahinter einen neuen
849 // TextNode. Dadurch bleibt dieser Fly erhalten !
850 if( aRg.aEnd.GetNode().IsEndNode() )
851 GetNodes().MakeTxtNode( aRg.aStart,
852 (SwTxtFmtColl*)GetDfltTxtFmtColl() );
854 MoveNodeRange( aRg, aPos.nNode, DOC_MOVEDEFAULT );
856 else
858 rTbl.MakeCopy( this, aPos, *pSelBoxes );
859 // Don't delete a part of a table with row span!!
860 // You could delete the content instead -> ToDo
861 //rTbl.DeleteSel( this, *pSelBoxes, 0, 0, TRUE, TRUE );
864 // wenn Tabelle im Rahmen, dann ohne nachfolgenden TextNode
865 aIndex = rCntnt.GetCntntIdx()->GetNode().EndOfSectionIndex() - 1;
866 ASSERT( aIndex.GetNode().GetTxtNode(),
867 "hier sollte ein TextNode stehen" );
868 aPos.nContent.Assign( 0, 0 ); // Index abmelden !!
869 GetNodes().Delete( aIndex, 1 );
871 //JP erstmal ein Hack, solange keine Flys/Headers/Footers Undofaehig sind
872 if( DoesUndo() ) // werden erstmal alle Undo - Objecte geloescht.
873 DelAllUndoObj();
876 else
879 // alle Pams verschieben
880 SwPaM* pTmp = (SwPaM*)&rPam;
881 do {
882 if( pTmp->HasMark() &&
883 *pTmp->GetPoint() != *pTmp->GetMark() )
884 MoveAndJoin( *pTmp, aPos );
885 } while( &rPam != ( pTmp = (SwPaM*)pTmp->GetNext() ) );
887 // copy all Pams and then delete all
888 SwPaM* pTmp = (SwPaM*)&rPam;
889 BOOL bOldFlag = mbCopyIsMove, bOldUndo = mbUndo;
890 mbCopyIsMove = TRUE;
891 mbUndo = FALSE;
892 do {
893 if( pTmp->HasMark() &&
894 *pTmp->GetPoint() != *pTmp->GetMark() )
896 CopyRange( *pTmp, aPos, false );
898 pTmp = static_cast<SwPaM*>(pTmp->GetNext());
899 } while ( &rPam != pTmp );
900 mbCopyIsMove = bOldFlag;
901 mbUndo = bOldUndo;
903 pTmp = (SwPaM*)&rPam;
904 do {
905 if( pTmp->HasMark() &&
906 *pTmp->GetPoint() != *pTmp->GetMark() )
908 DeleteAndJoin( *pTmp );
910 pTmp = static_cast<SwPaM*>(pTmp->GetNext());
911 } while ( &rPam != pTmp );
913 } while( sal_False );
916 SetModified();
918 EndUndo( UNDO_INSLAYFMT, NULL );
920 return pFmt;
924 //Einfuegen eines DrawObjectes. Das Object muss bereits im DrawModel
925 // angemeldet sein.
926 SwDrawFrmFmt* SwDoc::Insert( const SwPaM &rRg,
927 SdrObject& rDrawObj,
928 const SfxItemSet* pFlyAttrSet,
929 SwFrmFmt* pDefFmt )
931 SwDrawFrmFmt *pFmt = MakeDrawFrmFmt( aEmptyStr,
932 pDefFmt ? pDefFmt : GetDfltFrmFmt() );
934 const SwFmtAnchor* pAnchor = 0;
935 if( pFlyAttrSet )
937 pFlyAttrSet->GetItemState( RES_ANCHOR, sal_False,
938 (const SfxPoolItem**)&pAnchor );
939 pFmt->SetFmtAttr( *pFlyAttrSet );
942 RndStdIds eAnchorId = pAnchor ? pAnchor->GetAnchorId()
943 : pFmt->GetAnchor().GetAnchorId();
945 // Anker noch nicht gesetzt ?
946 // DrawObjecte duerfen niemals in Kopf-/Fusszeilen landen.
947 sal_Bool bIsAtCntnt = FLY_PAGE != eAnchorId;
948 // FLY_AT_CNTNT == eAnchorId || FLY_IN_CNTNT == eAnchorId ||
949 // FLY_AT_FLY == eAnchorId || FLY_AUTO_CNTNT == eAnchorId;
951 const SwNodeIndex* pChkIdx = 0;
952 if( !pAnchor )
954 pChkIdx = &rRg.GetPoint()->nNode;
956 else if( bIsAtCntnt )
958 pChkIdx = pAnchor->GetCntntAnchor()
959 ? &pAnchor->GetCntntAnchor()->nNode
960 : &rRg.GetPoint()->nNode;
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 ) )
969 pFmt->SetFmtAttr( SwFmtAnchor( eAnchorId = FLY_PAGE ) );
971 else if( !pAnchor || (bIsAtCntnt && !pAnchor->GetCntntAnchor() ))
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 )
978 SwPosition aPos( *rRg.GetNode()->FindFlyStartNode() );
979 aAnch.SetAnchor( &aPos );
981 else
983 aAnch.SetAnchor( rRg.GetPoint() );
984 if( FLY_PAGE == eAnchorId )
986 eAnchorId = rDrawObj.ISA( SdrUnoObj )
987 ? FLY_IN_CNTNT : FLY_AT_CNTNT;
988 aAnch.SetType( eAnchorId );
991 pFmt->SetFmtAttr( aAnch );
994 // bei als Zeichen gebundenen Draws das Attribut im Absatz setzen
995 if( FLY_IN_CNTNT == eAnchorId )
997 xub_StrLen nStt = rRg.GetPoint()->nContent.GetIndex();
998 SwFmtFlyCnt aFmt( pFmt );
999 rRg.GetPoint()->nNode.GetNode().GetTxtNode()->InsertItem(
1000 aFmt, nStt, nStt );
1003 SwDrawContact* pContact = new SwDrawContact( pFmt, &rDrawObj );
1005 // ggfs. Frames anlegen
1006 if( GetRootFrm() )
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() )
1014 pContact->MoveObjToVisibleLayer( &rDrawObj );
1016 // <--
1019 if( DoesUndo() )
1021 ClearRedo();
1022 AppendUndo( new SwUndoInsLayFmt( pFmt,0,0 ));
1025 SetModified();
1026 return pFmt;
1029 /*************************************************************************
1031 |* SwDoc::GetAllFlyFmts
1033 |* Ersterstellung MA 14. Jul. 93
1034 |* Letzte Aenderung MD 23. Feb. 95
1036 |*************************************************************************/
1038 /*sal_Bool TstFlyRange( const SwPaM* pPam, sal_uInt32 nFlyPos )
1040 sal_Bool bOk = sal_False;
1041 const SwPaM* pTmp = pPam;
1042 do {
1043 bOk = pTmp->Start()->nNode.GetIndex() < nFlyPos &&
1044 pTmp->End()->nNode.GetIndex() > nFlyPos;
1045 } while( !bOk && pPam != ( pTmp = (const SwPaM*)pTmp->GetNext() ));
1046 return bOk;
1049 /* -----------------------------04.04.00 10:55--------------------------------
1050 paragraph frames - o.k. if the PaM includes the paragraph from the beginning
1051 to the beginning of the next paragraph at least
1052 frames at character - o.k. if the pam start at least at the same position
1053 as the frame
1054 ---------------------------------------------------------------------------*/
1055 sal_Bool TstFlyRange( const SwPaM* pPam, const SwPosition* pFlyPos,
1056 RndStdIds nAnchorId )
1058 sal_Bool bOk = FALSE;
1059 const SwPaM* pTmp = pPam;
1060 do {
1061 const sal_uInt32 nFlyIndex = pFlyPos->nNode.GetIndex();
1062 const SwPosition* pPaMStart = pTmp->Start();
1063 const SwPosition* pPaMEnd = pTmp->End();
1064 const sal_uInt32 nPamStartIndex = pPaMStart->nNode.GetIndex();
1065 const sal_uInt32 nPamEndIndex = pPaMEnd->nNode.GetIndex();
1066 if(FLY_AT_CNTNT == nAnchorId)
1067 bOk = (nPamStartIndex < nFlyIndex && nPamEndIndex > nFlyIndex) ||
1068 (((nPamStartIndex == nFlyIndex) && (pPaMStart->nContent.GetIndex() == 0)) &&
1069 (nPamEndIndex > nFlyIndex));
1070 else
1072 xub_StrLen nFlyContentIndex = pFlyPos->nContent.GetIndex();
1073 xub_StrLen nPamEndContentIndex = pPaMEnd->nContent.GetIndex();
1074 bOk = (nPamStartIndex < nFlyIndex &&
1075 (( nPamEndIndex > nFlyIndex )||
1076 ((nPamEndIndex == nFlyIndex) &&
1077 (nPamEndContentIndex > nFlyContentIndex))) )
1079 (((nPamStartIndex == nFlyIndex) &&
1080 (pPaMStart->nContent.GetIndex() <= nFlyContentIndex)) &&
1081 ((nPamEndIndex > nFlyIndex) ||
1082 (nPamEndContentIndex > nFlyContentIndex )));
1085 } while( !bOk && pPam != ( pTmp = (const SwPaM*)pTmp->GetNext() ));
1086 return bOk;
1090 void SwDoc::GetAllFlyFmts( SwPosFlyFrms& rPosFlyFmts,
1091 const SwPaM* pCmpRange, sal_Bool bDrawAlso ) const
1093 SwPosFlyFrm *pFPos = 0;
1094 const SwPosition* pAPos;
1095 SwFrmFmt *pFly;
1097 // erstmal alle Absatzgebundenen einsammeln
1098 for( sal_uInt16 n = 0; n < GetSpzFrmFmts()->Count(); ++n )
1100 pFly = (*GetSpzFrmFmts())[ n ];
1101 bool bDrawFmt = bDrawAlso ? RES_DRAWFRMFMT == pFly->Which() : false;
1102 bool bFlyFmt = RES_FLYFRMFMT == pFly->Which();
1103 if( bFlyFmt || bDrawFmt )
1105 const SwFmtAnchor& rAnchor = pFly->GetAnchor();
1106 if( ( FLY_AT_CNTNT == rAnchor.GetAnchorId() ||
1107 FLY_AT_FLY == rAnchor.GetAnchorId() ||
1108 FLY_AUTO_CNTNT == rAnchor.GetAnchorId() ) &&
1109 0 != ( pAPos = rAnchor.GetCntntAnchor()) )
1111 if( pCmpRange &&
1112 !TstFlyRange( pCmpRange, pAPos, rAnchor.GetAnchorId() ))
1113 continue; // kein gueltiger FlyFrame
1114 pFPos = new SwPosFlyFrm( pAPos->nNode, pFly, rPosFlyFmts.Count() );
1115 rPosFlyFmts.Insert( pFPos );
1120 // kein Layout oder nur ein Teil, dann wars das
1121 // Seitenbezogen Flys nur, wenn vollstaendig "gewuenscht" wird !
1122 if( !GetRootFrm() || pCmpRange )
1123 return;
1125 pFPos = 0;
1126 SwPageFrm *pPage = (SwPageFrm*)GetRootFrm()->GetLower();
1127 while( pPage )
1129 if( pPage->GetSortedObjs() )
1131 SwSortedObjs &rObjs = *pPage->GetSortedObjs();
1132 for( sal_uInt16 i = 0; i < rObjs.Count(); ++i)
1134 SwAnchoredObject* pAnchoredObj = rObjs[i];
1135 if ( pAnchoredObj->ISA(SwFlyFrm) )
1136 pFly = &(pAnchoredObj->GetFrmFmt());
1137 else if ( bDrawAlso )
1138 pFly = &(pAnchoredObj->GetFrmFmt());
1139 else
1140 continue;
1142 const SwFmtAnchor& rAnchor = pFly->GetAnchor();
1143 if( FLY_AT_CNTNT != rAnchor.GetAnchorId() &&
1144 FLY_AT_FLY != rAnchor.GetAnchorId() &&
1145 FLY_AUTO_CNTNT != rAnchor.GetAnchorId() )
1147 const SwCntntFrm * pCntntFrm = pPage->FindFirstBodyCntnt();
1148 if ( !pCntntFrm )
1150 //Oops! Eine leere Seite. Damit der Rahmen nicht ganz
1151 //verlorengeht (RTF) suchen wir schnell den letzen
1152 //Cntnt der vor der Seite steht.
1153 SwPageFrm *pPrv = (SwPageFrm*)pPage->GetPrev();
1154 while ( !pCntntFrm && pPrv )
1156 pCntntFrm = pPrv->FindFirstBodyCntnt();
1157 pPrv = (SwPageFrm*)pPrv->GetPrev();
1160 if ( pCntntFrm )
1162 SwNodeIndex aIdx( *pCntntFrm->GetNode() );
1163 pFPos = new SwPosFlyFrm( aIdx, pFly, rPosFlyFmts.Count() );
1166 if ( pFPos )
1168 rPosFlyFmts.Insert( pFPos );
1169 pFPos = 0;
1173 pPage = (SwPageFrm*)pPage->GetNext();
1177 /*************************************************************************
1179 |* SwDoc::InsertLabel()
1181 |* Ersterstellung MA 11. Feb. 94
1182 |* Letzte Aenderung MA 12. Nov. 97
1184 |*************************************************************************/
1186 /* #i6447# changed behaviour if lcl_CpyAttr:
1188 If the old item set contains the item to set (no inheritance) copy the item
1189 into the new set.
1191 If the old item set contains the item by inheritance and the new set
1192 contains the item, too:
1193 If the two items differ copy the item from the old set to the new set.
1195 Otherwise the new set will not be changed.
1198 void lcl_CpyAttr( SfxItemSet &rNewSet, const SfxItemSet &rOldSet, sal_uInt16 nWhich )
1200 const SfxPoolItem *pOldItem = NULL, *pNewItem = NULL;
1202 rOldSet.GetItemState( nWhich, sal_False, &pOldItem);
1203 if (pOldItem != NULL)
1204 rNewSet.Put( *pOldItem );
1205 else
1207 pOldItem = rOldSet.GetItem( nWhich, sal_True);
1208 if (pOldItem != NULL)
1210 pNewItem = rNewSet.GetItem( nWhich, sal_True);
1211 if (pNewItem != NULL)
1213 if (*pOldItem != *pNewItem)
1214 rNewSet.Put( *pOldItem );
1216 else {
1217 ASSERT(0, "What am I doing here?");
1220 else {
1221 ASSERT(0, "What am I doing here?");
1228 SwFlyFrmFmt* SwDoc::InsertLabel( const SwLabelType eType, const String &rTxt, const String& rSeparator,
1229 const String& rNumberingSeparator,
1230 const sal_Bool bBefore, const sal_uInt16 nId, const ULONG nNdIdx,
1231 const String& rCharacterStyle,
1232 const sal_Bool bCpyBrd )
1234 sal_Bool bWasUndo = DoesUndo();
1235 SwUndoInsertLabel* pUndo = 0;
1236 if( bWasUndo )
1238 ClearRedo();
1239 pUndo = new SwUndoInsertLabel( eType, rTxt, rSeparator, rNumberingSeparator,
1240 bBefore, nId, rCharacterStyle, bCpyBrd );
1241 DoUndo( sal_False );
1244 sal_Bool bTable = sal_False; //Um etwas Code zu sparen.
1246 //Erstmal das Feld bauen, weil ueber den Namen die TxtColl besorgt werden
1247 //muss
1248 ASSERT( nId == USHRT_MAX || nId < GetFldTypes()->Count(), "FldType ueberindiziert." );
1249 SwFieldType *pType = nId != USHRT_MAX ? (*GetFldTypes())[nId] : NULL;
1250 ASSERT( !pType || pType->Which() == RES_SETEXPFLD, "Falsche Id fuer Label" );
1252 SwTxtFmtColl *pColl = NULL;
1253 if( pType )
1255 for( sal_uInt16 i = pTxtFmtCollTbl->Count(); i; )
1257 if( (*pTxtFmtCollTbl)[ --i ]->GetName() == pType->GetName() )
1259 pColl = (*pTxtFmtCollTbl)[i];
1260 break;
1263 DBG_ASSERT( pColl, "no text collection found" );
1266 if( !pColl )
1267 pColl = GetTxtCollFromPool( RES_POOLCOLL_LABEL );
1269 SwTxtNode *pNew = NULL;
1270 SwFlyFrmFmt* pNewFmt = NULL;
1272 switch ( eType )
1274 case LTYPE_TABLE:
1275 bTable = sal_True;
1276 /* Kein Break hier */
1277 case LTYPE_FLY:
1278 //Am Anfang/Ende der Fly-Section den entsprechenden Node mit Feld
1279 //einfuegen (Frame wird automatisch erzeugt).
1281 SwStartNode *pSttNd = GetNodes()[nNdIdx]->GetStartNode();
1282 ASSERT( pSttNd, "Kein StartNode in InsertLabel." );
1283 ULONG nNode;
1284 if( bBefore )
1286 nNode = pSttNd->GetIndex();
1287 if( !bTable )
1288 ++nNode;
1290 else
1292 nNode = pSttNd->EndOfSectionIndex();
1293 if( bTable )
1294 ++nNode;
1297 if( pUndo )
1298 pUndo->SetNodePos( nNode );
1300 //Node fuer Beschriftungsabsatz erzeugen.
1301 SwNodeIndex aIdx( GetNodes(), nNode );
1302 pNew = GetNodes().MakeTxtNode( aIdx, pColl );
1304 break;
1306 case LTYPE_OBJECT:
1308 //Rahmen zerstoeren, neuen Rahmen einfuegen, entsprechenden
1309 // Node mit Feld in den neuen Rahmen, den alten Rahmen mit
1310 // dem Object (Grafik/Ole) absatzgebunden in den neuen Rahmen,
1311 // Frames erzeugen.
1313 //Erstmal das Format zum Fly besorgen und das Layout entkoppeln.
1314 SwFrmFmt *pOldFmt = GetNodes()[nNdIdx]->GetFlyFmt();
1315 ASSERT( pOldFmt, "Format des Fly nicht gefunden." );
1316 pOldFmt->DelFrms();
1318 pNewFmt = MakeFlyFrmFmt( GetUniqueFrameName(),
1319 GetFrmFmtFromPool( RES_POOLFRM_FRAME ));
1321 /* #i6447#: Only the selected items are copied from the old
1322 format. */
1323 SfxItemSet* pNewSet = pNewFmt->GetAttrSet().Clone( sal_True );
1326 //Diejenigen Attribute uebertragen die auch gesetzt sind,
1327 //andere sollen weiterhin aus den Vorlagen gueltig werden.
1328 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_PRINT );
1329 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_OPAQUE );
1330 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_PROTECT );
1331 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_SURROUND );
1332 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_VERT_ORIENT );
1333 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_HORI_ORIENT );
1334 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_LR_SPACE );
1335 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_UL_SPACE );
1336 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_BACKGROUND );
1337 if( bCpyBrd )
1339 // JP 07.07.99: Bug 67029 - if at Grafik no BoxItem but
1340 // in the new Format is any, then set the
1341 // default item in the new Set. Because
1342 // the Size of the Grafik have never been
1343 // changed!
1344 const SfxPoolItem *pItem;
1345 if( SFX_ITEM_SET == pOldFmt->GetAttrSet().
1346 GetItemState( RES_BOX, sal_True, &pItem ))
1347 pNewSet->Put( *pItem );
1348 else if( SFX_ITEM_SET == pNewFmt->GetAttrSet().
1349 GetItemState( RES_BOX, sal_True ))
1350 pNewSet->Put( *GetDfltAttr( RES_BOX ) );
1352 if( SFX_ITEM_SET == pOldFmt->GetAttrSet().
1353 GetItemState( RES_SHADOW, sal_True, &pItem ))
1354 pNewSet->Put( *pItem );
1355 else if( SFX_ITEM_SET == pNewFmt->GetAttrSet().
1356 GetItemState( RES_SHADOW, sal_True ))
1357 pNewSet->Put( *GetDfltAttr( RES_SHADOW ) );
1359 else
1361 //Die Attribute hart setzen, weil sie sonst aus der
1362 // Vorlage kommen koenten und dann passt die
1363 // Grossenberechnung nicht mehr.
1364 pNewSet->Put( SvxBoxItem(RES_BOX) );
1365 pNewSet->Put( SvxShadowItem(RES_SHADOW) );
1369 //Anker immer uebertragen, ist sowieso ein hartes Attribut.
1370 pNewSet->Put( pOldFmt->GetAnchor() );
1372 //In der Hoehe soll der neue Varabel sein!
1373 SwFmtFrmSize aFrmSize( pOldFmt->GetFrmSize() );
1374 aFrmSize.SetHeightSizeType( ATT_MIN_SIZE );
1375 pNewSet->Put( aFrmSize );
1377 SwStartNode* pSttNd = GetNodes().MakeTextSection(
1378 SwNodeIndex( GetNodes().GetEndOfAutotext() ),
1379 SwFlyStartNode, pColl );
1380 pNewSet->Put( SwFmtCntnt( pSttNd ));
1382 pNewFmt->SetFmtAttr( *pNewSet );
1384 //Bei InCntnt's wird es spannend: Das TxtAttribut muss
1385 //vernichtet werden. Leider reisst dies neben den Frms auch
1386 //noch das Format mit in sein Grab. Um dass zu unterbinden
1387 //loesen wir vorher die Verbindung zwischen Attribut und Format.
1389 const SwFmtAnchor& rAnchor = pNewFmt->GetAnchor();
1390 if( FLY_IN_CNTNT == rAnchor.GetAnchorId() )
1392 const SwPosition *pPos = rAnchor.GetCntntAnchor();
1393 SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
1394 ASSERT( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
1395 const xub_StrLen nIdx = pPos->nContent.GetIndex();
1396 SwTxtAttr * const pHnt =
1397 pTxtNode->GetTxtAttrForCharAt(nIdx, RES_TXTATR_FLYCNT);
1399 ASSERT( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
1400 "Missing FlyInCnt-Hint." );
1401 ASSERT( pHnt && pHnt->GetFlyCnt().GetFrmFmt() == pOldFmt,
1402 "Wrong TxtFlyCnt-Hint." );
1404 const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt(
1405 pNewFmt );
1409 //Der Alte soll keinen Umlauf haben, und er soll oben/mittig
1410 //ausgerichtet sein.
1411 //Ausserdem soll die Breite 100% betragen und bei Aenderungen
1412 //Die Hoehe mit anpassen.
1413 pNewSet->ClearItem();
1415 pNewSet->Put( SwFmtSurround( SURROUND_NONE ) );
1416 pNewSet->Put( SvxOpaqueItem( RES_OPAQUE, sal_True ) );
1417 pNewSet->Put( SwFmtVertOrient( text::VertOrientation::TOP ) );
1418 pNewSet->Put( SwFmtHoriOrient( text::HoriOrientation::CENTER ) );
1420 aFrmSize = pOldFmt->GetFrmSize();
1421 aFrmSize.SetWidthPercent( 100 );
1422 aFrmSize.SetHeightPercent( 255 );
1423 pNewSet->Put( aFrmSize );
1425 //Die Attribute setzen wir hart, weil sie sonst aus der Vorlage
1426 //kommen koenten und dann passt die Grossenberechnung nicht mehr.
1427 if( bCpyBrd )
1429 pNewSet->Put( SvxBoxItem(RES_BOX) );
1430 pNewSet->Put( SvxShadowItem(RES_SHADOW) );
1432 pNewSet->Put( SvxLRSpaceItem(RES_LR_SPACE) );
1433 pNewSet->Put( SvxULSpaceItem(RES_UL_SPACE) );
1435 //Der Alte ist absatzgebunden, und zwar am Absatz im neuen.
1436 SwFmtAnchor aAnch( FLY_AT_CNTNT );
1437 SwNodeIndex aAnchIdx( *pNewFmt->GetCntnt().GetCntntIdx(), 1 );
1438 pNew = aAnchIdx.GetNode().GetTxtNode();
1439 SwPosition aPos( aAnchIdx );
1440 aAnch.SetAnchor( &aPos );
1441 pNewSet->Put( aAnch );
1443 if( pUndo )
1444 pUndo->SetFlys( *pOldFmt, *pNewSet, *pNewFmt );
1445 else
1446 pOldFmt->SetFmtAttr( *pNewSet );
1448 delete pNewSet;
1450 //Nun nur noch die Flys erzeugen lassen. Das ueberlassen
1451 //wir vorhanden Methoden (insb. fuer InCntFlys etwas aufwendig).
1452 pNewFmt->MakeFrms();
1454 break;
1456 default:
1457 ASSERT( !this, "Neuer LabelType?." );
1459 ASSERT( pNew, "No Label inserted" );
1460 if( pNew )
1462 //#i61007# order of captions
1463 sal_Bool bOrderNumberingFirst = SW_MOD()->GetModuleConfig()->IsCaptionOrderNumberingFirst();
1464 //String aufbereiten
1465 String aTxt;
1466 if( bOrderNumberingFirst )
1468 aTxt = rNumberingSeparator;
1470 if( pType)
1472 aTxt += pType->GetName();
1473 if( !bOrderNumberingFirst )
1474 aTxt += ' ';
1476 xub_StrLen nIdx = aTxt.Len();
1477 aTxt += rSeparator;
1478 xub_StrLen nSepIdx = aTxt.Len();
1479 aTxt += rTxt;
1481 //String einfuegen
1482 SwIndex aIdx( pNew, 0 );
1483 pNew->InsertText( aTxt, aIdx );
1486 //Feld einfuegen
1487 if(pType)
1489 SwSetExpField aFld( (SwSetExpFieldType*)pType, aEmptyStr, SVX_NUM_ARABIC);
1490 if( bOrderNumberingFirst )
1491 nIdx = 0;
1492 SwFmtFld aFmt( aFld );
1493 pNew->InsertItem( aFmt, nIdx, nIdx );
1494 if(rCharacterStyle.Len())
1496 SwCharFmt* pCharFmt = FindCharFmtByName( rCharacterStyle );
1497 if( !pCharFmt )
1499 const USHORT nMyId = SwStyleNameMapper::GetPoolIdFromUIName(rCharacterStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT);
1500 pCharFmt = GetCharFmtFromPool( nMyId );
1502 if (pCharFmt)
1504 SwFmtCharFmt aCharFmt( pCharFmt );
1505 pNew->InsertItem( aCharFmt, 0,
1506 nSepIdx + 1, nsSetAttrMode::SETATTR_DONTEXPAND );
1511 if ( bTable )
1513 if ( bBefore )
1515 if ( !pNew->GetSwAttrSet().GetKeep().GetValue() )
1516 pNew->SetAttr( SvxFmtKeepItem( sal_True, RES_KEEP ) );
1518 else
1520 SwTableNode *pNd = GetNodes()[nNdIdx]->GetStartNode()->GetTableNode();
1521 SwTable &rTbl = pNd->GetTable();
1522 if ( !rTbl.GetFrmFmt()->GetKeep().GetValue() )
1523 rTbl.GetFrmFmt()->SetFmtAttr( SvxFmtKeepItem( sal_True, RES_KEEP ) );
1524 if ( pUndo )
1525 pUndo->SetUndoKeep();
1528 SetModified();
1531 if( pUndo )
1532 AppendUndo( pUndo );
1533 else
1534 DelAllUndoObj();
1535 DoUndo( bWasUndo );
1537 return pNewFmt;
1540 /*************************************************************************
1542 |* SwDoc::InsertDrawLabel()
1544 |* Ersterstellung MIB 7. Dez. 98
1545 |* Letzte Aenderung MIB 7. Dez. 98
1547 |*************************************************************************/
1549 SwFlyFrmFmt* SwDoc::InsertDrawLabel( const String &rTxt,
1550 const String& rSeparator,
1551 const String& rNumberSeparator,
1552 const sal_uInt16 nId,
1553 const String& rCharacterStyle,
1554 SdrObject& rSdrObj )
1557 SwDrawContact* pContact = (SwDrawContact*)GetUserCall( &rSdrObj );
1558 ASSERT( RES_DRAWFRMFMT == pContact->GetFmt()->Which(),
1559 "Kein DrawFrmFmt" );
1560 if ( !pContact )
1561 return 0;
1563 SwDrawFrmFmt* pOldFmt = (SwDrawFrmFmt *)pContact->GetFmt();
1564 if( !pOldFmt )
1565 return 0;
1567 sal_Bool bWasUndo = DoesUndo();
1568 sal_Bool bWasNoDrawUndo = IsNoDrawUndoObj();
1569 SwUndoInsertLabel* pUndo = 0;
1570 if( bWasUndo )
1572 ClearRedo();
1573 pUndo = new SwUndoInsertLabel(
1574 LTYPE_DRAW, rTxt, rSeparator, rNumberSeparator, sal_False, nId, rCharacterStyle, sal_False );
1575 DoUndo( sal_False );
1576 SetNoDrawUndoObj( sal_True );
1579 // Erstmal das Feld bauen, weil ueber den Namen die TxtColl besorgt
1580 // werden muss
1581 ASSERT( nId == USHRT_MAX || nId < GetFldTypes()->Count(), "FldType overflow" );
1582 SwFieldType *pType = nId != USHRT_MAX ? (*GetFldTypes())[nId] : 0;
1583 ASSERT( !pType || pType->Which() == RES_SETEXPFLD, "Wrong label id" );
1585 SwTxtFmtColl *pColl = NULL;
1586 if( pType )
1588 for( sal_uInt16 i = pTxtFmtCollTbl->Count(); i; )
1590 if( (*pTxtFmtCollTbl)[ --i ]->GetName() == pType->GetName() )
1592 pColl = (*pTxtFmtCollTbl)[i];
1593 break;
1596 DBG_ASSERT( pColl, "no text collection found" );
1599 if( !pColl )
1600 pColl = GetTxtCollFromPool( RES_POOLCOLL_LABEL );
1602 SwTxtNode* pNew = NULL;
1603 SwFlyFrmFmt* pNewFmt = NULL;
1605 // Rahmen zerstoeren, neuen Rahmen einfuegen, entsprechenden
1606 // Node mit Feld in den neuen Rahmen, den alten Rahmen mit
1607 // dem Object (Grafik/Ole) absatzgebunden in den neuen Rahmen,
1608 // Frames erzeugen.
1610 // OD 27.11.2003 #112045# - Keep layer ID of drawing object before removing
1611 // its frames.
1612 // Note: The layer ID is passed to the undo and have to be the correct value.
1613 // Removing the frames of the drawing object changes its layer.
1614 const SdrLayerID nLayerId = rSdrObj.GetLayer();
1616 pOldFmt->DelFrms();
1618 //Bei InCntnt's wird es spannend: Das TxtAttribut muss
1619 //vernichtet werden. Leider reisst dies neben den Frms auch
1620 //noch das Format mit in sein Grab. Um dass zu unterbinden
1621 //loesen wir vorher die Verbindung zwischen Attribut und Format.
1622 SfxItemSet* pNewSet = pOldFmt->GetAttrSet().Clone( sal_False );
1624 // Ggf. Groesse und Position des Rahmens schuetzen
1625 if ( rSdrObj.IsMoveProtect() || rSdrObj.IsResizeProtect() )
1627 SvxProtectItem aProtect(RES_PROTECT);
1628 aProtect.SetCntntProtect( sal_False );
1629 aProtect.SetPosProtect( rSdrObj.IsMoveProtect() );
1630 aProtect.SetSizeProtect( rSdrObj.IsResizeProtect() );
1631 pNewSet->Put( aProtect );
1634 // Umlauf uebernehmen
1635 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_SURROUND );
1637 // Den Rahmen ggf. in den Hintergrund schicken.
1638 // OD 02.07.2003 #108784# - consider 'invisible' hell layer.
1639 if ( GetHellId() != nLayerId &&
1640 GetInvisibleHellId() != nLayerId )
1642 SvxOpaqueItem aOpaque( RES_OPAQUE );
1643 aOpaque.SetValue( sal_True );
1644 pNewSet->Put( aOpaque );
1647 // Position uebernehmen
1648 // OD 2004-04-15 #i26791# - use directly the positioning attributes of
1649 // the drawing object.
1650 pNewSet->Put( pOldFmt->GetHoriOrient() );
1651 pNewSet->Put( pOldFmt->GetVertOrient() );
1653 pNewSet->Put( pOldFmt->GetAnchor() );
1655 //In der Hoehe soll der neue Varabel sein!
1656 Size aSz( rSdrObj.GetCurrentBoundRect().GetSize() );
1657 SwFmtFrmSize aFrmSize( ATT_MIN_SIZE, aSz.Width(), aSz.Height() );
1658 pNewSet->Put( aFrmSize );
1660 // Abstaende auf den neuen Rahmen uebertragen. Eine Umrandung
1661 // gibt es beu Zeichen-Objekten nicht, also muss sie geloescht
1662 // werden.
1663 // MA: Falsch sie wird nicht gesetzt, denn die aus der Vorlage
1664 // soll ruhig wirksam werden
1665 pNewSet->Put( pOldFmt->GetLRSpace() );
1666 pNewSet->Put( pOldFmt->GetULSpace() );
1668 SwStartNode* pSttNd =
1669 GetNodes().MakeTextSection( SwNodeIndex( GetNodes().GetEndOfAutotext() ),
1670 SwFlyStartNode, pColl );
1672 pNewFmt = MakeFlyFrmFmt( GetUniqueFrameName(),
1673 GetFrmFmtFromPool( RES_POOLFRM_FRAME ) );
1675 // JP 28.10.99: Bug 69487 - set border and shadow to default if the
1676 // template contains any.
1677 if( SFX_ITEM_SET == pNewFmt->GetAttrSet().GetItemState( RES_BOX, sal_True ))
1678 pNewSet->Put( *GetDfltAttr( RES_BOX ) );
1680 if( SFX_ITEM_SET == pNewFmt->GetAttrSet().GetItemState(RES_SHADOW,sal_True))
1681 pNewSet->Put( *GetDfltAttr( RES_SHADOW ) );
1683 pNewFmt->SetFmtAttr( SwFmtCntnt( pSttNd ));
1684 pNewFmt->SetFmtAttr( *pNewSet );
1686 const SwFmtAnchor& rAnchor = pNewFmt->GetAnchor();
1687 if( FLY_IN_CNTNT == rAnchor.GetAnchorId() )
1689 const SwPosition *pPos = rAnchor.GetCntntAnchor();
1690 SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
1691 ASSERT( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
1692 const xub_StrLen nIdx = pPos->nContent.GetIndex();
1693 SwTxtAttr * const pHnt =
1694 pTxtNode->GetTxtAttrForCharAt( nIdx, RES_TXTATR_FLYCNT );
1696 #ifndef PRODUCT
1697 ASSERT( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
1698 "Missing FlyInCnt-Hint." );
1699 ASSERT( pHnt && ((SwFmtFlyCnt&)pHnt->GetFlyCnt()).
1700 GetFrmFmt() == (SwFrmFmt*)pOldFmt,
1701 "Wrong TxtFlyCnt-Hint." );
1702 #endif
1703 const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt( pNewFmt );
1707 //Der Alte soll keinen Umlauf haben, und er soll oben/mittig
1708 //ausgerichtet sein.
1709 pNewSet->ClearItem();
1711 pNewSet->Put( SwFmtSurround( SURROUND_NONE ) );
1712 if( nLayerId == GetHellId() )
1713 rSdrObj.SetLayer( GetHeavenId() );
1714 // OD 02.07.2003 #108784# - consider drawing objects in 'invisible' hell layer
1715 else if( nLayerId == GetInvisibleHellId() )
1716 rSdrObj.SetLayer( GetInvisibleHeavenId() );
1717 pNewSet->Put( SvxLRSpaceItem( RES_LR_SPACE ) );
1718 pNewSet->Put( SvxULSpaceItem( RES_UL_SPACE ) );
1720 // OD 2004-04-15 #i26791# - set position of the drawing object, which is labeled.
1721 pNewSet->Put( SwFmtVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME ) );
1722 pNewSet->Put( SwFmtHoriOrient( 0, text::HoriOrientation::CENTER, text::RelOrientation::FRAME ) );
1724 //Der Alte ist absatzgebunden, und zwar am Absatz im neuen.
1725 SwFmtAnchor aAnch( FLY_AT_CNTNT );
1726 SwNodeIndex aAnchIdx( *pNewFmt->GetCntnt().GetCntntIdx(), 1 );
1727 pNew = aAnchIdx.GetNode().GetTxtNode();
1728 SwPosition aPos( aAnchIdx );
1729 aAnch.SetAnchor( &aPos );
1730 pNewSet->Put( aAnch );
1732 if( pUndo )
1734 pUndo->SetFlys( *pOldFmt, *pNewSet, *pNewFmt );
1735 // OD 2004-04-15 #i26791# - position no longer needed
1736 pUndo->SetDrawObj( nLayerId );
1738 else
1739 pOldFmt->SetFmtAttr( *pNewSet );
1741 delete pNewSet;
1743 //Nun nur noch die Flys erzeugen lassen. Das ueberlassen
1744 //wir vorhanden Methoden (insb. fuer InCntFlys etwas aufwendig).
1745 pNewFmt->MakeFrms();
1747 ASSERT( pNew, "No Label inserted" );
1749 if( pNew )
1751 //#i61007# order of captions
1752 sal_Bool bOrderNumberingFirst = SW_MOD()->GetModuleConfig()->IsCaptionOrderNumberingFirst();
1754 // prepare string
1755 String aTxt;
1756 if( bOrderNumberingFirst )
1758 aTxt = rNumberSeparator;
1760 if ( pType )
1762 aTxt += pType->GetName();
1763 if( !bOrderNumberingFirst )
1764 aTxt += ' ';
1766 xub_StrLen nIdx = aTxt.Len();
1767 aTxt += rSeparator;
1768 xub_StrLen nSepIdx = aTxt.Len();
1769 aTxt += rTxt;
1771 // insert text
1772 SwIndex aIdx( pNew, 0 );
1773 pNew->InsertText( aTxt, aIdx );
1775 // insert field
1776 if ( pType )
1778 SwSetExpField aFld( (SwSetExpFieldType*)pType, aEmptyStr, SVX_NUM_ARABIC );
1779 if( bOrderNumberingFirst )
1780 nIdx = 0;
1781 SwFmtFld aFmt( aFld );
1782 pNew->InsertItem( aFmt, nIdx, nIdx );
1783 if ( rCharacterStyle.Len() )
1785 SwCharFmt* pCharFmt = FindCharFmtByName( rCharacterStyle );
1786 if ( !pCharFmt )
1788 const USHORT nMyId = SwStyleNameMapper::GetPoolIdFromUIName( rCharacterStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
1789 pCharFmt = GetCharFmtFromPool( nMyId );
1791 if ( pCharFmt )
1793 SwFmtCharFmt aCharFmt( pCharFmt );
1794 pNew->InsertItem( aCharFmt, 0, nSepIdx + 1,
1795 nsSetAttrMode::SETATTR_DONTEXPAND );
1801 if( pUndo )
1803 AppendUndo( pUndo );
1804 SetNoDrawUndoObj( bWasNoDrawUndo );
1806 else
1807 DelAllUndoObj();
1808 DoUndo( bWasUndo );
1810 return pNewFmt;
1813 /*************************************************************************
1815 |* IDocumentTimerAccess-methods
1817 |*************************************************************************/
1819 void SwDoc::StartIdling()
1821 mbStartIdleTimer = sal_True;
1822 if( !mIdleBlockCount )
1823 aIdleTimer.Start();
1826 void SwDoc::StopIdling()
1828 mbStartIdleTimer = sal_False;
1829 aIdleTimer.Stop();
1832 void SwDoc::BlockIdling()
1834 aIdleTimer.Stop();
1835 ++mIdleBlockCount;
1838 void SwDoc::UnblockIdling()
1840 --mIdleBlockCount;
1841 if( !mIdleBlockCount && mbStartIdleTimer && !aIdleTimer.IsActive() )
1842 aIdleTimer.Start();
1846 /*************************************************************************
1848 |* SwDoc::DoIdleJobs()
1850 |* Ersterstellung OK 30.03.94
1851 |* Letzte Aenderung MA 09. Jun. 95
1853 |*************************************************************************/
1855 IMPL_LINK( SwDoc, DoIdleJobs, Timer *, pTimer )
1857 #ifdef TIMELOG
1858 static ::rtl::Logfile* pModLogFile = 0;
1859 if( !pModLogFile )
1860 pModLogFile = new ::rtl::Logfile( "First DoIdleJobs" );
1861 #endif
1863 if( GetRootFrm() && GetRootFrm()->GetCurrShell() &&
1864 !SfxProgress::GetActiveProgress( pDocShell ) )
1866 ViewShell *pSh, *pStartSh;
1867 pSh = pStartSh = GetRootFrm()->GetCurrShell();
1868 do {
1869 if( pSh->ActionPend() )
1871 if( pTimer )
1872 pTimer->Start();
1873 return 0;
1875 pSh = (ViewShell*)pSh->GetNext();
1876 } while( pSh != pStartSh );
1878 if (GetRootFrm()->IsNeedGrammarCheck())
1880 BOOL bIsOnlineSpell = pSh->GetViewOptions()->IsOnlineSpell();
1882 sal_Bool bIsAutoGrammar = sal_False;
1883 SvtLinguConfig().GetProperty( C2U( UPN_IS_GRAMMAR_AUTO ) ) >>= bIsAutoGrammar;
1885 if (bIsOnlineSpell && bIsAutoGrammar)
1886 StartGrammarChecking( *this );
1889 sal_uInt16 nFldUpdFlag;
1890 if( GetRootFrm()->IsIdleFormat() )
1891 GetRootFrm()->GetCurrShell()->LayoutIdle();
1892 else if( ( AUTOUPD_FIELD_ONLY ==
1893 ( nFldUpdFlag = static_cast<sal_uInt16>(getFieldUpdateFlags(true)) )
1894 || AUTOUPD_FIELD_AND_CHARTS == nFldUpdFlag ) &&
1895 GetUpdtFlds().IsFieldsDirty() &&
1896 !GetUpdtFlds().IsInUpdateFlds() &&
1897 !IsExpFldsLocked()
1898 // das umschalten der Feldname fuehrt zu keinem Update der
1899 // Felder, also der "Hintergrund-Update" immer erfolgen
1900 /* && !pStartSh->GetViewOptions()->IsFldName()*/ )
1902 // chaos::Action-Klammerung!
1903 GetUpdtFlds().SetInUpdateFlds( sal_True );
1905 GetRootFrm()->StartAllAction();
1907 // no jump on update of fields #i85168#
1908 const sal_Bool bOldLockView = pStartSh->IsViewLocked();
1909 pStartSh->LockView( sal_True );
1911 GetSysFldType( RES_CHAPTERFLD )->Modify( 0, 0 ); // KapitelFld
1912 UpdateExpFlds( 0, sal_False ); // Expression-Felder Updaten
1913 UpdateTblFlds(NULL); // Tabellen
1914 UpdateRefFlds(NULL); // Referenzen
1916 GetRootFrm()->EndAllAction();
1918 pStartSh->LockView( bOldLockView );
1920 GetUpdtFlds().SetInUpdateFlds( sal_False );
1921 GetUpdtFlds().SetFieldsDirty( sal_False );
1924 #ifdef TIMELOG
1925 if( pModLogFile && 1 != (long)pModLogFile )
1926 delete pModLogFile, ((long&)pModLogFile) = 1;
1927 #endif
1928 if( pTimer )
1929 pTimer->Start();
1930 return 0;
1933 IMPL_STATIC_LINK( SwDoc, BackgroundDone, SvxBrushItem*, EMPTYARG )
1935 ViewShell *pSh, *pStartSh;
1936 pSh = pStartSh = pThis->GetRootFrm()->GetCurrShell();
1937 if( pStartSh )
1938 do {
1939 if( pSh->GetWin() )
1941 //Fuer Repaint mir virtuellen Device sorgen.
1942 pSh->LockPaint();
1943 pSh->UnlockPaint( sal_True );
1945 pSh = (ViewShell*)pSh->GetNext();
1946 } while( pSh != pStartSh );
1947 return 0;
1950 static String lcl_GetUniqueFlyName( const SwDoc* pDoc, sal_uInt16 nDefStrId )
1952 ResId aId( nDefStrId, *pSwResMgr );
1953 String aName( aId );
1954 xub_StrLen nNmLen = aName.Len();
1956 const SwSpzFrmFmts& rFmts = *pDoc->GetSpzFrmFmts();
1958 sal_uInt16 nNum, nTmp, nFlagSize = ( rFmts.Count() / 8 ) +2;
1959 sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ];
1960 sal_uInt16 n;
1962 memset( pSetFlags, 0, nFlagSize );
1964 for( n = 0; n < rFmts.Count(); ++n )
1966 const SwFrmFmt* pFlyFmt = rFmts[ n ];
1967 if( RES_FLYFRMFMT == pFlyFmt->Which() &&
1968 pFlyFmt->GetName().Match( aName ) == nNmLen )
1970 // Nummer bestimmen und das Flag setzen
1971 nNum = static_cast< sal_uInt16 >( pFlyFmt->GetName().Copy( nNmLen ).ToInt32() );
1972 if( nNum-- && nNum < rFmts.Count() )
1973 pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
1977 // alle Nummern entsprechend geflag, also bestimme die richtige Nummer
1978 nNum = rFmts.Count();
1979 for( n = 0; n < nFlagSize; ++n )
1980 if( 0xff != ( nTmp = pSetFlags[ n ] ))
1982 // also die Nummer bestimmen
1983 nNum = n * 8;
1984 while( nTmp & 1 )
1985 ++nNum, nTmp >>= 1;
1986 break;
1989 delete [] pSetFlags;
1990 return aName += String::CreateFromInt32( ++nNum );
1993 String SwDoc::GetUniqueGrfName() const
1995 return lcl_GetUniqueFlyName( this, STR_GRAPHIC_DEFNAME );
1998 String SwDoc::GetUniqueOLEName() const
2000 return lcl_GetUniqueFlyName( this, STR_OBJECT_DEFNAME );
2003 String SwDoc::GetUniqueFrameName() const
2005 return lcl_GetUniqueFlyName( this, STR_FRAME_DEFNAME );
2008 const SwFlyFrmFmt* SwDoc::FindFlyByName( const String& rName, sal_Int8 nNdTyp ) const
2010 const SwSpzFrmFmts& rFmts = *GetSpzFrmFmts();
2011 for( sal_uInt16 n = rFmts.Count(); n; )
2013 const SwFrmFmt* pFlyFmt = rFmts[ --n ];
2014 const SwNodeIndex* pIdx;
2015 if( RES_FLYFRMFMT == pFlyFmt->Which() && pFlyFmt->GetName() == rName &&
2016 0 != ( pIdx = pFlyFmt->GetCntnt().GetCntntIdx() ) &&
2017 pIdx->GetNode().GetNodes().IsDocNodes() )
2019 if( nNdTyp )
2021 // dann noch auf den richtigen Node-Typ abfragen
2022 const SwNode* pNd = GetNodes()[ pIdx->GetIndex()+1 ];
2023 if( nNdTyp == ND_TEXTNODE
2024 ? !pNd->IsNoTxtNode()
2025 : nNdTyp == pNd->GetNodeType() )
2026 return (SwFlyFrmFmt*)pFlyFmt;
2028 else
2029 return (SwFlyFrmFmt*)pFlyFmt;
2032 return 0;
2035 void SwDoc::SetFlyName( SwFlyFrmFmt& rFmt, const String& rName )
2037 String sName( rName );
2038 if( !rName.Len() || FindFlyByName( rName ) )
2040 sal_uInt16 nTyp = STR_FRAME_DEFNAME;
2041 const SwNodeIndex* pIdx = rFmt.GetCntnt().GetCntntIdx();
2042 if( pIdx && pIdx->GetNode().GetNodes().IsDocNodes() )
2043 switch( GetNodes()[ pIdx->GetIndex() + 1 ]->GetNodeType() )
2045 case ND_GRFNODE: nTyp = STR_GRAPHIC_DEFNAME; break;
2046 case ND_OLENODE: nTyp = STR_OBJECT_DEFNAME; break;
2048 sName = lcl_GetUniqueFlyName( this, nTyp );
2050 rFmt.SetName( sName, sal_True );
2051 SetModified();
2054 void SwDoc::SetAllUniqueFlyNames()
2056 sal_uInt16 n, nFlyNum = 0, nGrfNum = 0, nOLENum = 0;
2058 ResId nFrmId( STR_FRAME_DEFNAME, *pSwResMgr ),
2059 nGrfId( STR_GRAPHIC_DEFNAME, *pSwResMgr ),
2060 nOLEId( STR_OBJECT_DEFNAME, *pSwResMgr );
2061 String sFlyNm( nFrmId );
2062 String sGrfNm( nGrfId );
2063 String sOLENm( nOLEId );
2065 if( 255 < ( n = GetSpzFrmFmts()->Count() ))
2066 n = 255;
2067 SwSpzFrmFmts aArr( (sal_Int8)n, 10 );
2068 SwFrmFmtPtr pFlyFmt;
2069 sal_Bool bLoadedFlag = sal_True; // noch etwas fuers Layout
2071 for( n = GetSpzFrmFmts()->Count(); n; )
2073 if( RES_FLYFRMFMT == (pFlyFmt = (*GetSpzFrmFmts())[ --n ])->Which() )
2075 sal_uInt16 *pNum = 0;
2076 xub_StrLen nLen;
2077 const String& rNm = pFlyFmt->GetName();
2078 if( rNm.Len() )
2080 if( rNm.Match( sGrfNm ) == ( nLen = sGrfNm.Len() ))
2081 pNum = &nGrfNum;
2082 else if( rNm.Match( sFlyNm ) == ( nLen = sFlyNm.Len() ))
2083 pNum = &nFlyNum;
2084 else if( rNm.Match( sOLENm ) == ( nLen = sOLENm.Len() ))
2085 pNum = &nOLENum;
2087 if ( pNum && *pNum < ( nLen = static_cast< xub_StrLen >( rNm.Copy( nLen ).ToInt32() ) ) )
2088 *pNum = nLen;
2090 else
2091 // das wollen wir nachher setzen
2092 aArr.Insert( pFlyFmt, aArr.Count() );
2095 if( bLoadedFlag )
2097 const SwFmtAnchor& rAnchor = pFlyFmt->GetAnchor();
2098 if( ( FLY_PAGE == rAnchor.GetAnchorId() &&
2099 rAnchor.GetCntntAnchor() ) ||
2100 // oder werden DrawObjecte rel. zu irgendetwas ausgerichtet?
2101 ( RES_DRAWFRMFMT == pFlyFmt->Which() && (
2102 SFX_ITEM_SET == pFlyFmt->GetItemState(
2103 RES_VERT_ORIENT )||
2104 SFX_ITEM_SET == pFlyFmt->GetItemState(
2105 RES_HORI_ORIENT ))) )
2106 bLoadedFlag = sal_False;
2110 const SwNodeIndex* pIdx;
2112 for( n = aArr.Count(); n; )
2113 if( 0 != ( pIdx = ( pFlyFmt = aArr[ --n ])->GetCntnt().GetCntntIdx() )
2114 && pIdx->GetNode().GetNodes().IsDocNodes() )
2116 sal_uInt16 nNum;
2117 String sNm;
2118 switch( GetNodes()[ pIdx->GetIndex() + 1 ]->GetNodeType() )
2120 case ND_GRFNODE:
2121 sNm = sGrfNm;
2122 nNum = ++nGrfNum;
2123 break;
2124 case ND_OLENODE:
2125 sNm = sOLENm;
2126 nNum = ++nOLENum;
2127 break;
2128 default:
2129 sNm = sFlyNm;
2130 nNum = ++nFlyNum;
2131 break;
2133 pFlyFmt->SetName( sNm += String::CreateFromInt32( nNum ));
2135 aArr.Remove( 0, aArr.Count() );
2137 if( GetFtnIdxs().Count() )
2139 SwTxtFtn::SetUniqueSeqRefNo( *this );
2140 // --> FME 2005-08-02 #i52775# Chapter footnotes did not
2141 // get updated correctly. Calling UpdateAllFtn() instead of
2142 // UpdateFtn() solves this problem, but I do not dare to
2143 // call UpdateAllFtn() in all cases: Safety first.
2144 if ( FTNNUM_CHAPTER == GetFtnInfo().eNum )
2146 GetFtnIdxs().UpdateAllFtn();
2148 // <--
2149 else
2151 SwNodeIndex aTmp( GetNodes() );
2152 GetFtnIdxs().UpdateFtn( aTmp );
2156 // neues Document und keine seitengebundenen Rahmen/DrawObjecte gefunden,
2157 // die an einem Node verankert sind.
2158 if( bLoadedFlag )
2159 SetLoaded( sal_True );
2162 sal_Bool SwDoc::IsInHeaderFooter( const SwNodeIndex& rIdx ) const
2164 // gibt es ein Layout, dann ueber das laufen!!
2165 // (Das kann dann auch Fly in Fly in Kopfzeile !)
2166 // MIB 9.2.98: Wird auch vom sw3io benutzt, um festzustellen, ob sich
2167 // ein Redline-Objekt in einer Kopf- oder Fusszeile befindet. Da
2168 // Redlines auch an Start- und Endnodes haengen, muss der Index nicht
2169 // unbedingt der eines Content-Nodes sein.
2170 SwNode* pNd = &rIdx.GetNode();
2171 if( pNd->IsCntntNode() && pLayout )
2173 const SwFrm *pFrm = pNd->GetCntntNode()->GetFrm();
2174 if( pFrm )
2176 const SwFrm *pUp = pFrm->GetUpper();
2177 while ( pUp && !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() )
2179 if ( pUp->IsFlyFrm() )
2180 pUp = ((SwFlyFrm*)pUp)->GetAnchorFrm();
2181 pUp = pUp->GetUpper();
2183 if ( pUp )
2184 return sal_True;
2186 return sal_False;
2191 const SwNode* pFlyNd = pNd->FindFlyStartNode();
2192 while( pFlyNd )
2194 // dann ueber den Anker nach oben "hangeln"
2195 sal_uInt16 n;
2196 for( n = 0; n < GetSpzFrmFmts()->Count(); ++n )
2198 const SwFrmFmt* pFmt = (*GetSpzFrmFmts())[ n ];
2199 const SwNodeIndex* pIdx = pFmt->GetCntnt().GetCntntIdx();
2200 if( pIdx && pFlyNd == &pIdx->GetNode() )
2202 const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
2203 if( FLY_PAGE == rAnchor.GetAnchorId() ||
2204 !rAnchor.GetCntntAnchor() )
2205 return sal_False;
2207 pNd = &rAnchor.GetCntntAnchor()->nNode.GetNode();
2208 pFlyNd = pNd->FindFlyStartNode();
2209 break;
2212 if( n >= GetSpzFrmFmts()->Count() )
2214 ASSERT( mbInReading, "Fly-Section aber kein Format gefunden" );
2215 return sal_False;
2219 return 0 != pNd->FindHeaderStartNode() ||
2220 0 != pNd->FindFooterStartNode();
2223 short SwDoc::GetTextDirection( const SwPosition& rPos,
2224 const Point* pPt ) const
2226 short nRet = -1;
2228 SwCntntNode *pNd = rPos.nNode.GetNode().GetCntntNode();
2230 // --> OD 2005-02-21 #i42921# - use new method <SwCntntNode::GetTextDirection(..)>
2231 if ( pNd )
2233 nRet = pNd->GetTextDirection( rPos, pPt );
2235 if ( nRet == -1 )
2236 // <--
2238 const SvxFrameDirectionItem* pItem = 0;
2239 if( pNd )
2241 // in a flyframe? Then look at that for the correct attribute
2242 const SwFrmFmt* pFlyFmt = pNd->GetFlyFmt();
2243 while( pFlyFmt )
2245 pItem = &pFlyFmt->GetFrmDir();
2246 if( FRMDIR_ENVIRONMENT == pItem->GetValue() )
2248 pItem = 0;
2249 const SwFmtAnchor* pAnchor = &pFlyFmt->GetAnchor();
2250 if( FLY_PAGE != pAnchor->GetAnchorId() &&
2251 pAnchor->GetCntntAnchor() )
2252 pFlyFmt = pAnchor->GetCntntAnchor()->nNode.
2253 GetNode().GetFlyFmt();
2254 else
2255 pFlyFmt = 0;
2257 else
2258 pFlyFmt = 0;
2261 if( !pItem )
2263 const SwPageDesc* pPgDsc = pNd->FindPageDesc( FALSE );
2264 if( pPgDsc )
2265 pItem = &pPgDsc->GetMaster().GetFrmDir();
2268 if( !pItem )
2269 pItem = (SvxFrameDirectionItem*)&GetAttrPool().GetDefaultItem(
2270 RES_FRAMEDIR );
2271 nRet = pItem->GetValue();
2273 return nRet;
2276 sal_Bool SwDoc::IsInVerticalText( const SwPosition& rPos, const Point* pPt ) const
2278 const short nDir = GetTextDirection( rPos, pPt );
2279 return FRMDIR_VERT_TOP_RIGHT == nDir || FRMDIR_VERT_TOP_LEFT == nDir;
2282 const SwRootFrm* SwDoc::GetRootFrm() const { return pLayout; }
2283 SwRootFrm* SwDoc::GetRootFrm() { return pLayout; }
2284 void SwDoc::SetRootFrm( SwRootFrm* pNew ) { pLayout = pNew; }
2285 SwLayouter* SwDoc::GetLayouter() { return pLayouter; }
2286 const SwLayouter* SwDoc::GetLayouter() const { return pLayouter; }
2287 void SwDoc::SetLayouter( SwLayouter* pNew ) { pLayouter = pNew; }