update credits
[LibreOffice.git] / sw / source / core / doc / doclay.cxx
blob926a8c701f2f0e84ac5df16e4d3700c8460c3a1a
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <unotools/linguprops.hxx>
22 #include <unotools/lingucfg.hxx>
23 #include <com/sun/star/embed/EmbedStates.hpp>
24 #include <hintids.hxx>
25 #include <com/sun/star/util/XCloseable.hpp>
26 #include <sfx2/progress.hxx>
27 #include <svx/svdmodel.hxx>
28 #include <svx/svdpage.hxx>
29 #include <editeng/keepitem.hxx>
30 #include <editeng/ulspitem.hxx>
31 #include <editeng/lrspitem.hxx>
32 #include <editeng/boxitem.hxx>
33 #include <editeng/shaditem.hxx>
34 #include <editeng/protitem.hxx>
35 #include <editeng/opaqitem.hxx>
36 #include <editeng/prntitem.hxx>
37 #include <svx/fmglob.hxx>
38 #include <svx/svdouno.hxx>
39 #include <svx/fmpage.hxx>
40 #include <editeng/frmdiritem.hxx>
42 #include <swmodule.hxx>
43 #include <modcfg.hxx>
44 #include <com/sun/star/beans/XPropertySet.hpp>
45 #include <rtl/logfile.hxx>
46 #include <SwStyleNameMapper.hxx>
47 #include <fchrfmt.hxx>
48 #include <frmatr.hxx>
49 #include <txatbase.hxx>
50 #include <fmtfld.hxx>
51 #include <fmtornt.hxx>
52 #include <fmtcntnt.hxx>
53 #include <fmtanchr.hxx>
54 #include <fmtfsize.hxx>
55 #include <fmtsrnd.hxx>
56 #include <fmtflcnt.hxx>
57 #include <fmtcnct.hxx>
58 #include <frmfmt.hxx>
59 #include <txtflcnt.hxx>
60 #include <docfld.hxx> // for ExpressionFields
61 #include <pam.hxx>
62 #include <ndtxt.hxx>
63 #include <ndnotxt.hxx>
64 #include <ndole.hxx>
65 #include <doc.hxx>
66 #include <IDocumentUndoRedo.hxx>
67 #include <rootfrm.hxx>
68 #include <pagefrm.hxx>
69 #include <cntfrm.hxx>
70 #include <flyfrm.hxx>
71 #include <fesh.hxx>
72 #include <docsh.hxx>
73 #include <dflyobj.hxx>
74 #include <dcontact.hxx>
75 #include <swundo.hxx>
76 #include <flypos.hxx>
77 #include <UndoInsert.hxx>
78 #include <expfld.hxx> // InsertLabel
79 #include <poolfmt.hxx> // PoolTemplate Ids
80 #include <docary.hxx>
81 #include <swtable.hxx>
82 #include <tblsel.hxx>
83 #include <viewopt.hxx>
84 #include <fldupde.hxx>
85 #include <txtftn.hxx>
86 #include <ftnidx.hxx>
87 #include <ftninfo.hxx>
88 #include <pagedesc.hxx>
89 #include <PostItMgr.hxx>
90 #include <comcore.hrc> // STR ResIds
92 #include <unoframe.hxx>
94 #include <sortedobjs.hxx>
96 #include <vector>
98 using namespace ::com::sun::star;
100 #define DEF_FLY_WIDTH 2268 // Default width for FlyFrms (2268 == 4cm)
103 static bool lcl_IsItemSet(const SwCntntNode & rNode, sal_uInt16 which)
105 bool bResult = false;
107 if (SFX_ITEM_SET == rNode.GetSwAttrSet().GetItemState(which))
108 bResult = true;
110 return bResult;
113 /** Create a new format whose settings fit to the Request by default.
115 The format is put into the respective format array.
116 If there already is a fitting format, it is returned instead. */
117 SwFrmFmt *SwDoc::MakeLayoutFmt( RndStdIds eRequest, const SfxItemSet* pSet )
119 SwFrmFmt *pFmt = 0;
120 const sal_Bool bMod = IsModified();
121 bool bHeader = false;
123 switch ( eRequest )
125 case RND_STD_HEADER:
126 case RND_STD_HEADERL:
127 case RND_STD_HEADERR:
129 bHeader = true;
130 // no break, we continue further down
132 case RND_STD_FOOTER:
133 case RND_STD_FOOTERL:
134 case RND_STD_FOOTERR:
136 pFmt = new SwFrmFmt( GetAttrPool(),
137 (bHeader ? "Right header" : "Right footer"),
138 GetDfltFrmFmt() );
140 SwNodeIndex aTmpIdx( GetNodes().GetEndOfAutotext() );
141 SwStartNode* pSttNd =
142 GetNodes().MakeTextSection
143 ( aTmpIdx,
144 bHeader ? SwHeaderStartNode : SwFooterStartNode,
145 GetTxtCollFromPool(static_cast<sal_uInt16>( bHeader
146 ? ( eRequest == RND_STD_HEADERL
147 ? RES_POOLCOLL_HEADERL
148 : eRequest == RND_STD_HEADERR
149 ? RES_POOLCOLL_HEADERR
150 : RES_POOLCOLL_HEADER )
151 : ( eRequest == RND_STD_FOOTERL
152 ? RES_POOLCOLL_FOOTERL
153 : eRequest == RND_STD_FOOTERR
154 ? RES_POOLCOLL_FOOTERR
155 : RES_POOLCOLL_FOOTER )
156 ) ) );
157 pFmt->SetFmtAttr( SwFmtCntnt( pSttNd ));
159 if( pSet ) // Set a few more attributes
160 pFmt->SetFmtAttr( *pSet );
162 // Why set it back? Doc has changed, or not?
163 // In any case, wrong for the FlyFrames!
164 if ( !bMod )
165 ResetModified();
167 break;
169 case RND_DRAW_OBJECT:
171 pFmt = MakeDrawFrmFmt( aEmptyStr, GetDfltFrmFmt() );
172 if( pSet ) // Set a few more attributes
173 pFmt->SetFmtAttr( *pSet );
175 if (GetIDocumentUndoRedo().DoesUndo())
177 GetIDocumentUndoRedo().AppendUndo(
178 new SwUndoInsLayFmt(pFmt, 0, 0));
181 break;
183 #if OSL_DEBUG_LEVEL > 0
184 case FLY_AT_PAGE:
185 case FLY_AT_CHAR:
186 case FLY_AT_FLY:
187 case FLY_AT_PARA:
188 case FLY_AS_CHAR:
189 OSL_FAIL( "use new interface instead: SwDoc::MakeFlySection!" );
190 break;
191 #endif
193 default:
194 OSL_ENSURE( !this,
195 "LayoutFormat was requested with an invalid Request." );
198 return pFmt;
201 /// Deletes the denoted format and its content.
202 void SwDoc::DelLayoutFmt( SwFrmFmt *pFmt )
204 // A chain of frames needs to be merged, if necessary,
205 // so that the Frame's contents are adjusted accordingly before we destroy the Frames.
206 const SwFmtChain &rChain = pFmt->GetChain();
207 if ( rChain.GetPrev() )
209 SwFmtChain aChain( rChain.GetPrev()->GetChain() );
210 aChain.SetNext( rChain.GetNext() );
211 SetAttr( aChain, *rChain.GetPrev() );
213 if ( rChain.GetNext() )
215 SwFmtChain aChain( rChain.GetNext()->GetChain() );
216 aChain.SetPrev( rChain.GetPrev() );
217 SetAttr( aChain, *rChain.GetNext() );
220 const SwNodeIndex* pCntIdx = pFmt->GetCntnt().GetCntntIdx();
221 if (pCntIdx && !GetIDocumentUndoRedo().DoesUndo())
223 // Disconnect if it's an OLE object
224 SwOLENode* pOLENd = GetNodes()[ pCntIdx->GetIndex()+1 ]->GetOLENode();
225 if( pOLENd && pOLENd->GetOLEObj().IsOleRef() )
228 // TODO: the old object closed the object and cleared all references to it, but didn't remove it from the container.
229 // I have no idea, why, nobody could explain it - so I do my very best to mimic this behavior
230 //uno::Reference < util::XCloseable > xClose( pOLENd->GetOLEObj().GetOleRef(), uno::UNO_QUERY );
231 //if ( xClose.is() )
235 pOLENd->GetOLEObj().GetOleRef()->changeState( embed::EmbedStates::LOADED );
237 catch ( uno::Exception& )
245 // Destroy Frames
246 pFmt->DelFrms();
248 // Only FlyFrames are undoable at first
249 const sal_uInt16 nWh = pFmt->Which();
250 if (GetIDocumentUndoRedo().DoesUndo() &&
251 (RES_FLYFRMFMT == nWh || RES_DRAWFRMFMT == nWh))
253 GetIDocumentUndoRedo().AppendUndo( new SwUndoDelLayFmt( pFmt ));
255 else
257 // #i32089# - delete at-frame anchored objects
258 if ( nWh == RES_FLYFRMFMT )
260 // determine frame formats of at-frame anchored objects
261 const SwNodeIndex* pCntntIdx = pFmt->GetCntnt().GetCntntIdx();
262 if ( pCntntIdx )
264 const SwFrmFmts* pTbl = pFmt->GetDoc()->GetSpzFrmFmts();
265 if ( pTbl )
267 std::vector<SwFrmFmt*> aToDeleteFrmFmts;
268 const sal_uLong nNodeIdxOfFlyFmt( pCntntIdx->GetIndex() );
270 for ( sal_uInt16 i = 0; i < pTbl->size(); ++i )
272 SwFrmFmt* pTmpFmt = (*pTbl)[i];
273 const SwFmtAnchor &rAnch = pTmpFmt->GetAnchor();
274 if ( rAnch.GetAnchorId() == FLY_AT_FLY &&
275 rAnch.GetCntntAnchor()->nNode.GetIndex() == nNodeIdxOfFlyFmt )
277 aToDeleteFrmFmts.push_back( pTmpFmt );
281 // delete found frame formats
282 while ( !aToDeleteFrmFmts.empty() )
284 SwFrmFmt* pTmpFmt = aToDeleteFrmFmts.back();
285 pFmt->GetDoc()->DelLayoutFmt( pTmpFmt );
287 aToDeleteFrmFmts.pop_back();
293 // Delete content
294 if( pCntIdx )
296 SwNode *pNode = &pCntIdx->GetNode();
297 ((SwFmtCntnt&)pFmt->GetFmtAttr( RES_CNTNT )).SetNewCntntIdx( 0 );
298 DeleteSection( pNode );
301 // Delete the character for FlyFrames anchored as char (if necessary)
302 const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
303 if ((FLY_AS_CHAR == rAnchor.GetAnchorId()) && rAnchor.GetCntntAnchor())
305 const SwPosition* pPos = rAnchor.GetCntntAnchor();
306 SwTxtNode *pTxtNd = pPos->nNode.GetNode().GetTxtNode();
308 // attribute is still in text node, delete it
309 if ( pTxtNd )
311 SwTxtFlyCnt* const pAttr = static_cast<SwTxtFlyCnt*>(
312 pTxtNd->GetTxtAttrForCharAt( pPos->nContent.GetIndex(),
313 RES_TXTATR_FLYCNT ));
314 if ( pAttr && (pAttr->GetFlyCnt().GetFrmFmt() == pFmt) )
316 // dont delete, set pointer to 0
317 const_cast<SwFmtFlyCnt&>(pAttr->GetFlyCnt()).SetFlyFmt();
318 SwIndex aIdx( pPos->nContent );
319 pTxtNd->EraseText( aIdx, 1 );
324 DelFrmFmt( pFmt );
326 SetModified();
329 /** Copies the stated format (pSrc) to pDest and returns pDest.
331 If there's no pDest, it is created.
332 If the source format is located in another document, also copy correctly
333 in this case.
334 The Anchor attribute's position is always set to 0! */
335 SwFrmFmt *SwDoc::CopyLayoutFmt( const SwFrmFmt& rSource,
336 const SwFmtAnchor& rNewAnchor,
337 bool bSetTxtFlyAtt, bool bMakeFrms )
339 const bool bFly = RES_FLYFRMFMT == rSource.Which();
340 const bool bDraw = RES_DRAWFRMFMT == rSource.Which();
341 OSL_ENSURE( bFly || bDraw, "this method only works for fly or draw" );
343 SwDoc* pSrcDoc = (SwDoc*)rSource.GetDoc();
345 // May we copy this object?
346 // We may, unless it's 1) it's a control (and therfore a draw)
347 // 2) anchored in a header/footer
348 // 3) anchored (to paragraph?)
349 bool bMayNotCopy = false;
350 if( bDraw )
352 const SwDrawContact* pDrawContact =
353 static_cast<const SwDrawContact*>( rSource.FindContactObj() );
355 bMayNotCopy =
356 ((FLY_AT_PARA == rNewAnchor.GetAnchorId()) ||
357 (FLY_AT_FLY == rNewAnchor.GetAnchorId()) ||
358 (FLY_AT_CHAR == rNewAnchor.GetAnchorId())) &&
359 rNewAnchor.GetCntntAnchor() &&
360 IsInHeaderFooter( rNewAnchor.GetCntntAnchor()->nNode ) &&
361 pDrawContact != NULL &&
362 pDrawContact->GetMaster() != NULL &&
363 CheckControlLayer( pDrawContact->GetMaster() );
366 // just return if we can't copy this
367 if( bMayNotCopy )
368 return NULL;
370 SwFrmFmt* pDest = GetDfltFrmFmt();
371 if( rSource.GetRegisteredIn() != pSrcDoc->GetDfltFrmFmt() )
372 pDest = CopyFrmFmt( *(SwFrmFmt*)rSource.GetRegisteredIn() );
373 if( bFly )
375 // #i11176#
376 // To do a correct cloning concerning the ZOrder for all objects
377 // it is necessary to actually create a draw object for fly frames, too.
378 // These are then added to the DrawingLayer (which needs to exist).
379 // Together with correct sorting of all drawinglayer based objects
380 // before cloning ZOrder transfer works correctly then.
381 SwFlyFrmFmt *pFormat = MakeFlyFrmFmt( rSource.GetName(), pDest );
382 pDest = pFormat;
384 SwXFrame::GetOrCreateSdrObject(pFormat);
386 else
387 pDest = MakeDrawFrmFmt( aEmptyStr, pDest );
389 // Copy all other or new attributes
390 pDest->CopyAttrs( rSource );
392 // Do not copy chains
393 pDest->ResetFmtAttr( RES_CHAIN );
395 if( bFly )
397 // Duplicate the content.
398 const SwNode& rCSttNd = rSource.GetCntnt().GetCntntIdx()->GetNode();
399 SwNodeRange aRg( rCSttNd, 1, *rCSttNd.EndOfSectionNode() );
401 SwNodeIndex aIdx( GetNodes().GetEndOfAutotext() );
402 SwStartNode* pSttNd = GetNodes().MakeEmptySection( aIdx, SwFlyStartNode );
404 // Set the Anchor/CntntIndex first.
405 // Within the copying part, we can access the values (DrawFmt in Headers and Footers)
406 aIdx = *pSttNd;
407 SwFmtCntnt aAttr( rSource.GetCntnt() );
408 aAttr.SetNewCntntIdx( &aIdx );
409 pDest->SetFmtAttr( aAttr );
410 pDest->SetFmtAttr( rNewAnchor );
412 if( !mbCopyIsMove || this != pSrcDoc )
414 if( mbInReading )
415 pDest->SetName( aEmptyStr );
416 else
418 // Test first if the name is already taken, if so generate a new one.
419 sal_Int8 nNdTyp = aRg.aStart.GetNode().GetNodeType();
421 String sOld( pDest->GetName() );
422 pDest->SetName( aEmptyStr );
423 if( FindFlyByName( sOld, nNdTyp ) ) // found one
424 switch( nNdTyp )
426 case ND_GRFNODE: sOld = GetUniqueGrfName(); break;
427 case ND_OLENODE: sOld = GetUniqueOLEName(); break;
428 default: sOld = GetUniqueFrameName(); break;
431 pDest->SetName( sOld );
435 if (GetIDocumentUndoRedo().DoesUndo())
437 GetIDocumentUndoRedo().AppendUndo(new SwUndoInsLayFmt(pDest,0,0));
440 // Make sure that FlyFrames in FlyFrames are copied
441 aIdx = *pSttNd->EndOfSectionNode();
443 //fdo#36631 disable (scoped) any undo operations associated with the
444 //contact object itself. They should be managed by SwUndoInsLayFmt.
445 const ::sw::DrawUndoGuard drawUndoGuard(GetIDocumentUndoRedo());
447 pSrcDoc->CopyWithFlyInFly( aRg, 0, aIdx, sal_False, sal_True, sal_True );
449 else
451 OSL_ENSURE( RES_DRAWFRMFMT == rSource.Which(), "Neither Fly nor Draw." );
452 // #i52780# - Note: moving object to visible layer not needed.
453 SwDrawContact* pSourceContact = (SwDrawContact *)rSource.FindContactObj();
455 SwDrawContact* pContact = new SwDrawContact( (SwDrawFrmFmt*)pDest,
456 CloneSdrObj( *pSourceContact->GetMaster(),
457 mbCopyIsMove && this == pSrcDoc ) );
458 // #i49730# - notify draw frame format that position attributes are
459 // already set, if the position attributes are already set at the
460 // source draw frame format.
461 if ( pDest->ISA(SwDrawFrmFmt) &&
462 rSource.ISA(SwDrawFrmFmt) &&
463 static_cast<const SwDrawFrmFmt&>(rSource).IsPosAttrSet() )
465 static_cast<SwDrawFrmFmt*>(pDest)->PosAttrSet();
468 if( pDest->GetAnchor() == rNewAnchor )
470 // Do *not* connect to layout, if a <MakeFrms> will not be called.
471 if ( bMakeFrms )
473 pContact->ConnectToLayout( &rNewAnchor );
476 else
477 pDest->SetFmtAttr( rNewAnchor );
479 if (GetIDocumentUndoRedo().DoesUndo())
481 GetIDocumentUndoRedo().AppendUndo(new SwUndoInsLayFmt(pDest,0,0));
485 if (bSetTxtFlyAtt && (FLY_AS_CHAR == rNewAnchor.GetAnchorId()))
487 const SwPosition* pPos = rNewAnchor.GetCntntAnchor();
488 SwFmtFlyCnt aFmt( pDest );
489 pPos->nNode.GetNode().GetTxtNode()->InsertItem(
490 aFmt, pPos->nContent.GetIndex(), 0 );
493 if( bMakeFrms )
494 pDest->MakeFrms();
496 return pDest;
499 SdrObject* SwDoc::CloneSdrObj( const SdrObject& rObj, bool bMoveWithinDoc,
500 bool bInsInPage )
502 // #i52858# - method name changed
503 SdrPage *pPg = GetOrCreateDrawModel()->GetPage( 0 );
504 if( !pPg )
506 pPg = GetDrawModel()->AllocPage( sal_False );
507 GetDrawModel()->InsertPage( pPg );
510 SdrObject *pObj = rObj.Clone();
511 if( bMoveWithinDoc && FmFormInventor == pObj->GetObjInventor() )
513 // We need to preserve the Name for Controls
514 uno::Reference< awt::XControlModel > xModel = ((SdrUnoObj*)pObj)->GetUnoControlModel();
515 uno::Any aVal;
516 uno::Reference< beans::XPropertySet > xSet(xModel, uno::UNO_QUERY);
517 OUString sName("Name");
518 if( xSet.is() )
519 aVal = xSet->getPropertyValue( sName );
520 if( bInsInPage )
521 pPg->InsertObject( pObj );
522 if( xSet.is() )
523 xSet->setPropertyValue( sName, aVal );
525 else if( bInsInPage )
526 pPg->InsertObject( pObj );
528 // For drawing objects: set layer of cloned object to invisible layer
529 SdrLayerID nLayerIdForClone = rObj.GetLayer();
530 if ( !pObj->ISA(SwFlyDrawObj) &&
531 !pObj->ISA(SwVirtFlyDrawObj) &&
532 !IS_TYPE(SdrObject,pObj) )
534 if ( IsVisibleLayerId( nLayerIdForClone ) )
536 nLayerIdForClone = GetInvisibleLayerIdByVisibleOne( nLayerIdForClone );
539 pObj->SetLayer( nLayerIdForClone );
542 return pObj;
545 SwFlyFrmFmt* SwDoc::_MakeFlySection( const SwPosition& rAnchPos,
546 const SwCntntNode& rNode,
547 RndStdIds eRequestId,
548 const SfxItemSet* pFlySet,
549 SwFrmFmt* pFrmFmt )
551 if( !pFrmFmt )
552 pFrmFmt = GetFrmFmtFromPool( RES_POOLFRM_FRAME );
554 String sName;
555 if( !mbInReading )
556 switch( rNode.GetNodeType() )
558 case ND_GRFNODE: sName = GetUniqueGrfName(); break;
559 case ND_OLENODE: sName = GetUniqueOLEName(); break;
560 default: sName = GetUniqueFrameName(); break;
562 SwFlyFrmFmt* pFmt = MakeFlyFrmFmt( sName, pFrmFmt );
564 // Create content and connect to the format.
565 // Create CntntNode and put it into the autotext selection.
566 SwNodeRange aRange( GetNodes().GetEndOfAutotext(), -1,
567 GetNodes().GetEndOfAutotext() );
568 GetNodes().SectionDown( &aRange, SwFlyStartNode );
570 pFmt->SetFmtAttr( SwFmtCntnt( rNode.StartOfSectionNode() ));
573 const SwFmtAnchor* pAnchor = 0;
574 if( pFlySet )
576 pFlySet->GetItemState( RES_ANCHOR, sal_False,
577 (const SfxPoolItem**)&pAnchor );
578 if( SFX_ITEM_SET == pFlySet->GetItemState( RES_CNTNT, sal_False ))
580 SfxItemSet aTmpSet( *pFlySet );
581 aTmpSet.ClearItem( RES_CNTNT );
582 pFmt->SetFmtAttr( aTmpSet );
584 else
585 pFmt->SetFmtAttr( *pFlySet );
588 // Anchor not yet set?
589 RndStdIds eAnchorId = pAnchor ? pAnchor->GetAnchorId()
590 : pFmt->GetAnchor().GetAnchorId();
591 // #i107811# Assure that at-page anchored fly frames have a page num or a
592 // content anchor set.
593 if ( !pAnchor ||
594 ( FLY_AT_PAGE != pAnchor->GetAnchorId() &&
595 !pAnchor->GetCntntAnchor() ) ||
596 ( FLY_AT_PAGE == pAnchor->GetAnchorId() &&
597 !pAnchor->GetCntntAnchor() &&
598 pAnchor->GetPageNum() == 0 ) )
600 // set it again, needed for Undo
601 SwFmtAnchor aAnch( pFmt->GetAnchor() );
602 if (pAnchor && (FLY_AT_FLY == pAnchor->GetAnchorId()))
604 SwPosition aPos( *rAnchPos.nNode.GetNode().FindFlyStartNode() );
605 aAnch.SetAnchor( &aPos );
606 eAnchorId = FLY_AT_FLY;
608 else
610 if( eRequestId != aAnch.GetAnchorId() &&
611 SFX_ITEM_SET != pFmt->GetItemState( RES_ANCHOR, sal_True ) )
613 aAnch.SetType( eRequestId );
616 eAnchorId = aAnch.GetAnchorId();
617 if ( FLY_AT_PAGE != eAnchorId ||
618 ( FLY_AT_PAGE == eAnchorId &&
619 ( !pAnchor ||
620 aAnch.GetPageNum() == 0 ) ) )
622 aAnch.SetAnchor( &rAnchPos );
625 pFmt->SetFmtAttr( aAnch );
627 else
628 eAnchorId = pFmt->GetAnchor().GetAnchorId();
630 if ( FLY_AS_CHAR == eAnchorId )
632 xub_StrLen nStt = rAnchPos.nContent.GetIndex();
633 SwTxtNode * pTxtNode = rAnchPos.nNode.GetNode().GetTxtNode();
635 OSL_ENSURE(pTxtNode!= 0, "There should be a SwTxtNode!");
637 if (pTxtNode != NULL)
639 SwFmtFlyCnt aFmt( pFmt );
640 bool const bSuccess( pTxtNode->InsertItem(aFmt, nStt, nStt) );
641 if (!bSuccess) // may fail if there's no space left or header/ftr
642 { // pFmt is dead now
643 return 0;
648 if( SFX_ITEM_SET != pFmt->GetAttrSet().GetItemState( RES_FRM_SIZE ))
650 SwFmtFrmSize aFmtSize( ATT_VAR_SIZE, 0, DEF_FLY_WIDTH );
651 const SwNoTxtNode* pNoTxtNode = rNode.GetNoTxtNode();
652 if( pNoTxtNode )
654 // Set size
655 Size aSize( pNoTxtNode->GetTwipSize() );
656 if( MINFLY > aSize.Width() )
657 aSize.Width() = DEF_FLY_WIDTH;
658 aFmtSize.SetWidth( aSize.Width() );
659 if( aSize.Height() )
661 aFmtSize.SetHeight( aSize.Height() );
662 aFmtSize.SetHeightSizeType( ATT_FIX_SIZE );
665 pFmt->SetFmtAttr( aFmtSize );
668 // Set up frames
669 if( GetCurrentViewShell() )
670 pFmt->MakeFrms(); // ??? //swmod 071108//swmod 071225
672 if (GetIDocumentUndoRedo().DoesUndo())
674 sal_uLong nNodeIdx = rAnchPos.nNode.GetIndex();
675 xub_StrLen nCntIdx = rAnchPos.nContent.GetIndex();
676 GetIDocumentUndoRedo().AppendUndo(
677 new SwUndoInsLayFmt( pFmt, nNodeIdx, nCntIdx ));
680 SetModified();
681 return pFmt;
684 SwFlyFrmFmt* SwDoc::MakeFlySection( RndStdIds eAnchorType,
685 const SwPosition* pAnchorPos,
686 const SfxItemSet* pFlySet,
687 SwFrmFmt* pFrmFmt, bool bCalledFromShell )
689 SwFlyFrmFmt* pFmt = 0;
690 bool bCallMake = true;
691 if ( !pAnchorPos && (FLY_AT_PAGE != eAnchorType) )
693 const SwFmtAnchor* pAnch;
694 if( (pFlySet && SFX_ITEM_SET == pFlySet->GetItemState(
695 RES_ANCHOR, sal_False, (const SfxPoolItem**)&pAnch )) ||
696 ( pFrmFmt && SFX_ITEM_SET == pFrmFmt->GetItemState(
697 RES_ANCHOR, sal_True, (const SfxPoolItem**)&pAnch )) )
699 if ( (FLY_AT_PAGE != pAnch->GetAnchorId()) )
701 pAnchorPos = pAnch->GetCntntAnchor();
702 if (pAnchorPos)
704 bCallMake = false;
710 if( bCallMake )
712 if( !pFrmFmt )
713 pFrmFmt = GetFrmFmtFromPool( RES_POOLFRM_FRAME );
715 sal_uInt16 nCollId = static_cast<sal_uInt16>(
716 get(IDocumentSettingAccess::HTML_MODE) ? RES_POOLCOLL_TEXT : RES_POOLCOLL_FRAME );
718 /* If there is no adjust item in the paragraph style for the content node of the new fly section
719 propagate an existing adjust item at the anchor to the new content node. */
720 SwCntntNode * pNewTxtNd = GetNodes().MakeTxtNode
721 (SwNodeIndex( GetNodes().GetEndOfAutotext()),
722 GetTxtCollFromPool( nCollId ));
723 SwCntntNode * pAnchorNode = pAnchorPos->nNode.GetNode().GetCntntNode();
725 const SfxPoolItem * pItem = NULL;
727 if (bCalledFromShell && !lcl_IsItemSet(*pNewTxtNd, RES_PARATR_ADJUST) &&
728 SFX_ITEM_SET == pAnchorNode->GetSwAttrSet().
729 GetItemState(RES_PARATR_ADJUST, sal_True, &pItem))
731 static_cast<SwCntntNode *>(pNewTxtNd)->SetAttr(*pItem);
734 pFmt = _MakeFlySection( *pAnchorPos, *pNewTxtNd,
735 eAnchorType, pFlySet, pFrmFmt );
737 return pFmt;
740 SwFlyFrmFmt* SwDoc::MakeFlyAndMove( const SwPaM& rPam, const SfxItemSet& rSet,
741 const SwSelBoxes* pSelBoxes,
742 SwFrmFmt *pParent )
744 SwFmtAnchor& rAnch = (SwFmtAnchor&)rSet.Get( RES_ANCHOR );
746 GetIDocumentUndoRedo().StartUndo( UNDO_INSLAYFMT, NULL );
748 SwFlyFrmFmt* pFmt = MakeFlySection( rAnch.GetAnchorId(), rPam.GetPoint(),
749 &rSet, pParent );
751 // If content is selected, it becomes the new frame's content.
752 // Namely, it is moved into the NodeArray's appropriate section.
754 if( pFmt )
756 do { // middle check loop
757 const SwFmtCntnt &rCntnt = pFmt->GetCntnt();
758 OSL_ENSURE( rCntnt.GetCntntIdx(), "No content prepared." );
759 SwNodeIndex aIndex( *(rCntnt.GetCntntIdx()), 1 );
760 SwCntntNode *pNode = aIndex.GetNode().GetCntntNode();
762 // Attention: Do not create an index on the stack, or we
763 // cannot delete CntntNode in the end!
764 SwPosition aPos( aIndex );
765 aPos.nContent.Assign( pNode, 0 );
767 if( pSelBoxes && !pSelBoxes->empty() )
769 // Table selection
770 // Copy parts of a table: create a table with the same width as the
771 // original one and move (copy and delete) the selected boxes.
772 // The size is corrected on a percentage basis.
774 SwTableNode* pTblNd = (SwTableNode*)(*pSelBoxes)[0]->
775 GetSttNd()->FindTableNode();
776 if( !pTblNd )
777 break;
779 SwTable& rTbl = pTblNd->GetTable();
781 // Did we select the whole table?
782 if( pSelBoxes->size() == rTbl.GetTabSortBoxes().size() )
784 // move the whole table
785 SwNodeRange aRg( *pTblNd, 0, *pTblNd->EndOfSectionNode(), 1 );
787 // If we move the whole table and it is located within a
788 // FlyFrame, the we create a TextNode after it.
789 // So that this FlyFrame is preserved.
790 if( aRg.aEnd.GetNode().IsEndNode() )
791 GetNodes().MakeTxtNode( aRg.aStart,
792 (SwTxtFmtColl*)GetDfltTxtFmtColl() );
794 MoveNodeRange( aRg, aPos.nNode, DOC_MOVEDEFAULT );
796 else
798 rTbl.MakeCopy( this, aPos, *pSelBoxes );
799 // Don't delete a part of a table with row span!!
800 // You could delete the content instead -> ToDo
801 //rTbl.DeleteSel( this, *pSelBoxes, 0, 0, true, true );
804 // If the table is within the frame, then copy without the following TextNode
805 aIndex = rCntnt.GetCntntIdx()->GetNode().EndOfSectionIndex() - 1;
806 OSL_ENSURE( aIndex.GetNode().GetTxtNode(),
807 "a TextNode should be here" );
808 aPos.nContent.Assign( 0, 0 ); // Deregister index!
809 GetNodes().Delete( aIndex, 1 );
811 // This is a hack: whilst FlyFrames/Headers/Footers are not undoable we delete all Undo objects
812 if( GetIDocumentUndoRedo().DoesUndo() )
814 GetIDocumentUndoRedo().DelAllUndoObj();
817 else
819 // copy all Pams and then delete all
820 SwPaM* pTmp = (SwPaM*)&rPam;
821 bool bOldFlag = mbCopyIsMove;
822 bool const bOldUndo = GetIDocumentUndoRedo().DoesUndo();
823 bool const bOldRedlineMove(IsRedlineMove());
824 mbCopyIsMove = true;
825 GetIDocumentUndoRedo().DoUndo(false);
826 SetRedlineMove(true);
827 do {
828 if( pTmp->HasMark() &&
829 *pTmp->GetPoint() != *pTmp->GetMark() )
831 CopyRange( *pTmp, aPos, false );
833 pTmp = static_cast<SwPaM*>(pTmp->GetNext());
834 } while ( &rPam != pTmp );
835 SetRedlineMove(bOldRedlineMove);
836 mbCopyIsMove = bOldFlag;
837 GetIDocumentUndoRedo().DoUndo(bOldUndo);
839 pTmp = (SwPaM*)&rPam;
840 do {
841 if( pTmp->HasMark() &&
842 *pTmp->GetPoint() != *pTmp->GetMark() )
844 DeleteAndJoin( *pTmp );
846 pTmp = static_cast<SwPaM*>(pTmp->GetNext());
847 } while ( &rPam != pTmp );
849 } while( false );
852 SetModified();
854 GetIDocumentUndoRedo().EndUndo( UNDO_INSLAYFMT, NULL );
856 return pFmt;
859 /// Insert a DrawObject.
860 /// The Object has to be already registered in the DrawModel.
861 SwDrawFrmFmt* SwDoc::Insert( const SwPaM &rRg,
862 SdrObject& rDrawObj,
863 const SfxItemSet* pFlyAttrSet,
864 SwFrmFmt* pDefFmt )
866 SwDrawFrmFmt *pFmt = MakeDrawFrmFmt( aEmptyStr,
867 pDefFmt ? pDefFmt : GetDfltFrmFmt() );
869 const SwFmtAnchor* pAnchor = 0;
870 if( pFlyAttrSet )
872 pFlyAttrSet->GetItemState( RES_ANCHOR, sal_False,
873 (const SfxPoolItem**)&pAnchor );
874 pFmt->SetFmtAttr( *pFlyAttrSet );
877 RndStdIds eAnchorId = pAnchor ? pAnchor->GetAnchorId()
878 : pFmt->GetAnchor().GetAnchorId();
880 // Didn't set the Anchor yet?
881 // DrawObjecte must never end up in the Header/Footer!
882 const bool bIsAtCntnt = (FLY_AT_PAGE != eAnchorId);
884 const SwNodeIndex* pChkIdx = 0;
885 if( !pAnchor )
887 pChkIdx = &rRg.GetPoint()->nNode;
889 else if( bIsAtCntnt )
891 pChkIdx = pAnchor->GetCntntAnchor()
892 ? &pAnchor->GetCntntAnchor()->nNode
893 : &rRg.GetPoint()->nNode;
896 // Allow drawing objects in header/footer, but control objects aren't
897 // allowed in header/footer.
898 if( pChkIdx &&
899 ::CheckControlLayer( &rDrawObj ) &&
900 IsInHeaderFooter( *pChkIdx ) )
902 pFmt->SetFmtAttr( SwFmtAnchor( eAnchorId = FLY_AT_PAGE ) );
904 else if( !pAnchor || (bIsAtCntnt && !pAnchor->GetCntntAnchor() ))
906 // then set it, we need this in the Undo
907 SwFmtAnchor aAnch( pAnchor ? *pAnchor : pFmt->GetAnchor() );
908 eAnchorId = aAnch.GetAnchorId();
909 if( FLY_AT_FLY == eAnchorId )
911 SwPosition aPos( *rRg.GetNode()->FindFlyStartNode() );
912 aAnch.SetAnchor( &aPos );
914 else
916 aAnch.SetAnchor( rRg.GetPoint() );
917 if ( FLY_AT_PAGE == eAnchorId )
919 eAnchorId = rDrawObj.ISA( SdrUnoObj )
920 ? FLY_AS_CHAR : FLY_AT_PARA;
921 aAnch.SetType( eAnchorId );
924 pFmt->SetFmtAttr( aAnch );
927 // For Draws anchored as character we set the attribute in the paragraph
928 if ( FLY_AS_CHAR == eAnchorId )
930 xub_StrLen nStt = rRg.GetPoint()->nContent.GetIndex();
931 SwFmtFlyCnt aFmt( pFmt );
932 bool const bSuccess( // may fail if there's no space left
933 rRg.GetPoint()->nNode.GetNode().GetTxtNode()->InsertItem(
934 aFmt, nStt, nStt));
935 if (!bSuccess)
936 { // pFmt is dead now
937 return 0;
941 SwDrawContact* pContact = new SwDrawContact( pFmt, &rDrawObj );
943 // Create Frames if necessary
944 if( GetCurrentViewShell() )
946 pFmt->MakeFrms();
947 // #i42319# - follow-up of #i35635#
948 // move object to visible layer
949 // #i79391#
950 if ( pContact->GetAnchorFrm() )
952 pContact->MoveObjToVisibleLayer( &rDrawObj );
956 if (GetIDocumentUndoRedo().DoesUndo())
958 GetIDocumentUndoRedo().AppendUndo( new SwUndoInsLayFmt(pFmt, 0, 0) );
961 SetModified();
962 return pFmt;
965 /* ---------------------------------------------------------------------------
966 paragraph frames - o.k. if the PaM includes the paragraph from the beginning
967 to the beginning of the next paragraph at least
968 frames at character - o.k. if the PaM starts at least at the same position
969 as the frame
970 ---------------------------------------------------------------------------*/
971 static bool lcl_TstFlyRange( const SwPaM* pPam, const SwPosition* pFlyPos,
972 RndStdIds nAnchorId )
974 bool bOk = false;
975 const SwPaM* pTmp = pPam;
976 do {
977 const sal_uInt32 nFlyIndex = pFlyPos->nNode.GetIndex();
978 const SwPosition* pPaMStart = pTmp->Start();
979 const SwPosition* pPaMEnd = pTmp->End();
980 const sal_uInt32 nPamStartIndex = pPaMStart->nNode.GetIndex();
981 const sal_uInt32 nPamEndIndex = pPaMEnd->nNode.GetIndex();
982 if (FLY_AT_PARA == nAnchorId)
983 bOk = (nPamStartIndex < nFlyIndex && nPamEndIndex > nFlyIndex) ||
984 (((nPamStartIndex == nFlyIndex) && (pPaMStart->nContent.GetIndex() == 0)) &&
985 (nPamEndIndex > nFlyIndex));
986 else
988 xub_StrLen nFlyContentIndex = pFlyPos->nContent.GetIndex();
989 xub_StrLen nPamEndContentIndex = pPaMEnd->nContent.GetIndex();
990 bOk = (nPamStartIndex < nFlyIndex &&
991 (( nPamEndIndex > nFlyIndex )||
992 ((nPamEndIndex == nFlyIndex) &&
993 (nPamEndContentIndex > nFlyContentIndex))) )
995 (((nPamStartIndex == nFlyIndex) &&
996 (pPaMStart->nContent.GetIndex() <= nFlyContentIndex)) &&
997 ((nPamEndIndex > nFlyIndex) ||
998 (nPamEndContentIndex > nFlyContentIndex )));
1001 } while( !bOk && pPam != ( pTmp = (const SwPaM*)pTmp->GetNext() ));
1002 return bOk;
1005 SwPosFlyFrms SwDoc::GetAllFlyFmts( const SwPaM* pCmpRange, bool bDrawAlso,
1006 bool bAsCharAlso ) const
1008 SwPosFlyFrms aRetval;
1009 SwFrmFmt *pFly;
1011 // collect all anchored somehow to paragraphs
1012 for( sal_uInt16 n = 0; n < GetSpzFrmFmts()->size(); ++n )
1014 pFly = (*GetSpzFrmFmts())[ n ];
1015 bool bDrawFmt = bDrawAlso ? RES_DRAWFRMFMT == pFly->Which() : false;
1016 bool bFlyFmt = RES_FLYFRMFMT == pFly->Which();
1017 if( bFlyFmt || bDrawFmt )
1019 const SwFmtAnchor& rAnchor = pFly->GetAnchor();
1020 SwPosition const*const pAPos = rAnchor.GetCntntAnchor();
1021 if (pAPos &&
1022 ((FLY_AT_PARA == rAnchor.GetAnchorId()) ||
1023 (FLY_AT_FLY == rAnchor.GetAnchorId()) ||
1024 (FLY_AT_CHAR == rAnchor.GetAnchorId()) ||
1025 ((FLY_AS_CHAR == rAnchor.GetAnchorId()) && bAsCharAlso)))
1027 if( pCmpRange &&
1028 !lcl_TstFlyRange( pCmpRange, pAPos, rAnchor.GetAnchorId() ))
1029 continue; // not a valid FlyFrame
1030 aRetval.insert(SwPosFlyFrmPtr(new SwPosFlyFrm(pAPos->nNode, pFly, aRetval.size())));
1035 // If we don't have a layout we can't get page anchored FlyFrames.
1036 // Also, page anchored FlyFrames are only returned if no range is specified.
1037 if( !GetCurrentViewShell() || pCmpRange ) //swmod 071108//swmod 071225
1039 return aRetval;
1042 SwPageFrm *pPage = (SwPageFrm*)GetCurrentLayout()->GetLower(); //swmod 080218
1043 while( pPage )
1045 if( pPage->GetSortedObjs() )
1047 SwSortedObjs &rObjs = *pPage->GetSortedObjs();
1048 for( sal_uInt16 i = 0; i < rObjs.Count(); ++i)
1050 SwAnchoredObject* pAnchoredObj = rObjs[i];
1051 if ( pAnchoredObj->ISA(SwFlyFrm) )
1052 pFly = &(pAnchoredObj->GetFrmFmt());
1053 else if ( bDrawAlso )
1054 pFly = &(pAnchoredObj->GetFrmFmt());
1055 else
1056 continue;
1058 const SwFmtAnchor& rAnchor = pFly->GetAnchor();
1059 if ((FLY_AT_PARA != rAnchor.GetAnchorId()) &&
1060 (FLY_AT_FLY != rAnchor.GetAnchorId()) &&
1061 (FLY_AT_CHAR != rAnchor.GetAnchorId()))
1063 const SwCntntFrm * pCntntFrm = pPage->FindFirstBodyCntnt();
1064 if ( !pCntntFrm )
1066 // Oops! An empty page.
1067 // In order not to loose the whole frame (RTF) we
1068 // look for the last Cntnt before the page.
1069 SwPageFrm *pPrv = (SwPageFrm*)pPage->GetPrev();
1070 while ( !pCntntFrm && pPrv )
1072 pCntntFrm = pPrv->FindFirstBodyCntnt();
1073 pPrv = (SwPageFrm*)pPrv->GetPrev();
1076 if ( pCntntFrm )
1078 SwNodeIndex aIdx( *pCntntFrm->GetNode() );
1079 aRetval.insert(SwPosFlyFrmPtr(new SwPosFlyFrm(aIdx, pFly, aRetval.size())));
1084 pPage = (SwPageFrm*)pPage->GetNext();
1087 return aRetval;
1090 /* #i6447# changed behaviour if lcl_CpyAttr:
1092 If the old item set contains the item to set (no inheritance) copy the item
1093 into the new set.
1095 If the old item set contains the item by inheritance and the new set
1096 contains the item, too:
1097 If the two items differ copy the item from the old set to the new set.
1099 Otherwise the new set will not be changed.
1101 static void lcl_CpyAttr( SfxItemSet &rNewSet, const SfxItemSet &rOldSet, sal_uInt16 nWhich )
1103 const SfxPoolItem *pOldItem = NULL, *pNewItem = NULL;
1105 rOldSet.GetItemState( nWhich, sal_False, &pOldItem);
1106 if (pOldItem != NULL)
1107 rNewSet.Put( *pOldItem );
1108 else
1110 pOldItem = rOldSet.GetItem( nWhich, sal_True);
1111 if (pOldItem != NULL)
1113 pNewItem = rNewSet.GetItem( nWhich, sal_True);
1114 if (pNewItem != NULL)
1116 if (*pOldItem != *pNewItem)
1117 rNewSet.Put( *pOldItem );
1119 else {
1120 OSL_FAIL("What am I doing here?");
1123 else {
1124 OSL_FAIL("What am I doing here?");
1130 static SwFlyFrmFmt *
1131 lcl_InsertLabel(SwDoc & rDoc, SwTxtFmtColls *const pTxtFmtCollTbl,
1132 SwUndoInsertLabel *const pUndo,
1133 SwLabelType const eType, String const& rTxt, String const& rSeparator,
1134 const String& rNumberingSeparator,
1135 const sal_Bool bBefore, const sal_uInt16 nId, const sal_uLong nNdIdx,
1136 const String& rCharacterStyle,
1137 const sal_Bool bCpyBrd )
1139 ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
1141 bool bTable = false; // To save some code.
1143 // Get the field first, beause we retrieve the TxtColl via the field's name
1144 OSL_ENSURE( nId == USHRT_MAX || nId < rDoc.GetFldTypes()->size(),
1145 "FldType index out of bounds." );
1146 SwFieldType *pType = (nId != USHRT_MAX) ? (*rDoc.GetFldTypes())[nId] : NULL;
1147 OSL_ENSURE(!pType || pType->Which() == RES_SETEXPFLD, "wrong Id for Label");
1149 SwTxtFmtColl * pColl = NULL;
1150 if( pType )
1152 for( sal_uInt16 i = pTxtFmtCollTbl->size(); i; )
1154 if( (*pTxtFmtCollTbl)[ --i ]->GetName().Equals(pType->GetName()) )
1156 pColl = (*pTxtFmtCollTbl)[i];
1157 break;
1160 OSL_ENSURE( pColl, "no text collection found" );
1163 if( !pColl )
1165 pColl = rDoc.GetTxtCollFromPool( RES_POOLCOLL_LABEL );
1168 SwTxtNode *pNew = NULL;
1169 SwFlyFrmFmt* pNewFmt = NULL;
1171 switch ( eType )
1173 case LTYPE_TABLE:
1174 bTable = true;
1175 // no break here
1176 case LTYPE_FLY:
1177 // At the FlySection's Beginning/End insert the corresponding Node with it's Field.
1178 // The Frame is created automatically.
1180 SwStartNode *pSttNd = rDoc.GetNodes()[nNdIdx]->GetStartNode();
1181 OSL_ENSURE( pSttNd, "No StartNode in InsertLabel." );
1182 sal_uLong nNode;
1183 if( bBefore )
1185 nNode = pSttNd->GetIndex();
1186 if( !bTable )
1187 ++nNode;
1189 else
1191 nNode = pSttNd->EndOfSectionIndex();
1192 if( bTable )
1193 ++nNode;
1196 if( pUndo )
1197 pUndo->SetNodePos( nNode );
1199 // Create Node for labeling paragraph.
1200 SwNodeIndex aIdx( rDoc.GetNodes(), nNode );
1201 pNew = rDoc.GetNodes().MakeTxtNode( aIdx, pColl );
1203 break;
1205 case LTYPE_OBJECT:
1207 // Destroy Frame,
1208 // insert new Frame,
1209 // insert the corresponding Node with Field into the new Frame,
1210 // insert the old Frame with the Object (Picture/OLE) paragraph-bound into the new Frame,
1211 // create Frames.
1213 // Get the FlyFrame's Format and decouple the Layout.
1214 SwFrmFmt *pOldFmt = rDoc.GetNodes()[nNdIdx]->GetFlyFmt();
1215 OSL_ENSURE( pOldFmt, "Couldn't find the Fly's Format." );
1216 // #i115719#
1217 // <title> and <description> attributes are lost when calling <DelFrms()>.
1218 // Thus, keep them and restore them after the calling <MakeFrms()>
1219 const bool bIsSwFlyFrmFmtInstance( dynamic_cast<SwFlyFrmFmt*>(pOldFmt) != 0 );
1220 const String sTitle( bIsSwFlyFrmFmtInstance
1221 ? static_cast<SwFlyFrmFmt*>(pOldFmt)->GetObjTitle()
1222 : String() );
1223 const String sDescription( bIsSwFlyFrmFmtInstance
1224 ? static_cast<SwFlyFrmFmt*>(pOldFmt)->GetObjDescription()
1225 : String() );
1226 pOldFmt->DelFrms();
1228 pNewFmt = rDoc.MakeFlyFrmFmt( rDoc.GetUniqueFrameName(),
1229 rDoc.GetFrmFmtFromPool(RES_POOLFRM_FRAME) );
1231 /* #i6447#: Only the selected items are copied from the old
1232 format. */
1233 SfxItemSet* pNewSet = pNewFmt->GetAttrSet().Clone( sal_True );
1236 // Copy only the set attributes.
1237 // The others should apply from the Templates.
1238 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_PRINT );
1239 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_OPAQUE );
1240 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_PROTECT );
1241 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_SURROUND );
1242 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_VERT_ORIENT );
1243 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_HORI_ORIENT );
1244 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_LR_SPACE );
1245 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_UL_SPACE );
1246 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_BACKGROUND );
1247 if( bCpyBrd )
1249 // If there's no BoxItem at graphic, but the new Format has one, then set the
1250 // default item in the new Set. Because the graphic's size has never changed!
1251 const SfxPoolItem *pItem;
1252 if( SFX_ITEM_SET == pOldFmt->GetAttrSet().
1253 GetItemState( RES_BOX, sal_True, &pItem ))
1254 pNewSet->Put( *pItem );
1255 else if( SFX_ITEM_SET == pNewFmt->GetAttrSet().
1256 GetItemState( RES_BOX, sal_True ))
1257 pNewSet->Put( *GetDfltAttr( RES_BOX ) );
1259 if( SFX_ITEM_SET == pOldFmt->GetAttrSet().
1260 GetItemState( RES_SHADOW, sal_True, &pItem ))
1261 pNewSet->Put( *pItem );
1262 else if( SFX_ITEM_SET == pNewFmt->GetAttrSet().
1263 GetItemState( RES_SHADOW, sal_True ))
1264 pNewSet->Put( *GetDfltAttr( RES_SHADOW ) );
1266 else
1268 // Hard-set the attributes, because they could come from the Template
1269 // and then size calculations could not be correct anymore.
1270 pNewSet->Put( SvxBoxItem(RES_BOX) );
1271 pNewSet->Put( SvxShadowItem(RES_SHADOW) );
1275 // Always transfer the anchor, which is a hard attribute anyways.
1276 pNewSet->Put( pOldFmt->GetAnchor() );
1278 // The new one should be changeable in it's height.
1279 SwFmtFrmSize aFrmSize( pOldFmt->GetFrmSize() );
1280 aFrmSize.SetHeightSizeType( ATT_MIN_SIZE );
1281 pNewSet->Put( aFrmSize );
1283 SwStartNode* pSttNd = rDoc.GetNodes().MakeTextSection(
1284 SwNodeIndex( rDoc.GetNodes().GetEndOfAutotext() ),
1285 SwFlyStartNode, pColl );
1286 pNewSet->Put( SwFmtCntnt( pSttNd ));
1288 pNewFmt->SetFmtAttr( *pNewSet );
1290 // InCntnts need to be treated in a special way:
1291 // The TxtAttribute needs to be destroyed.
1292 // Unfortunately, this also destroys the Format next to the Frames.
1293 // To avoid this, we disconnect the attribute from the Format.
1295 const SwFmtAnchor& rAnchor = pNewFmt->GetAnchor();
1296 if ( FLY_AS_CHAR == rAnchor.GetAnchorId() )
1298 const SwPosition *pPos = rAnchor.GetCntntAnchor();
1299 SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
1300 OSL_ENSURE( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
1301 const xub_StrLen nIdx = pPos->nContent.GetIndex();
1302 SwTxtAttr * const pHnt =
1303 pTxtNode->GetTxtAttrForCharAt(nIdx, RES_TXTATR_FLYCNT);
1305 OSL_ENSURE( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
1306 "Missing FlyInCnt-Hint." );
1307 OSL_ENSURE( pHnt && pHnt->GetFlyCnt().GetFrmFmt() == pOldFmt,
1308 "Wrong TxtFlyCnt-Hint." );
1310 const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt(
1311 pNewFmt );
1315 // The old one should not have a flow and it should be adjusted to above and
1316 // middle.
1317 // Also, the width should be 100% and it should also adjust the hight, if changed.
1318 pNewSet->ClearItem();
1320 pNewSet->Put( SwFmtSurround( SURROUND_NONE ) );
1321 pNewSet->Put( SvxOpaqueItem( RES_OPAQUE, sal_True ) );
1323 sal_Int16 eVert = bBefore ? text::VertOrientation::BOTTOM : text::VertOrientation::TOP;
1324 pNewSet->Put( SwFmtVertOrient( 0, eVert ) );
1325 pNewSet->Put( SwFmtHoriOrient( 0, text::HoriOrientation::CENTER ) );
1327 aFrmSize = pOldFmt->GetFrmSize();
1328 aFrmSize.SetWidthPercent( 100 );
1329 aFrmSize.SetHeightPercent( 255 );
1330 pNewSet->Put( aFrmSize );
1332 // Hard-set the attributes, because they could come from the Template
1333 // and then size calculations could not be correct anymore.
1334 if( bCpyBrd )
1336 pNewSet->Put( SvxBoxItem(RES_BOX) );
1337 pNewSet->Put( SvxShadowItem(RES_SHADOW) );
1339 pNewSet->Put( SvxLRSpaceItem(RES_LR_SPACE) );
1340 pNewSet->Put( SvxULSpaceItem(RES_UL_SPACE) );
1342 // The old one is paragraph-bound to the paragraph in the new one.
1343 SwFmtAnchor aAnch( FLY_AT_PARA );
1344 SwNodeIndex aAnchIdx( *pNewFmt->GetCntnt().GetCntntIdx(), 1 );
1345 pNew = aAnchIdx.GetNode().GetTxtNode();
1346 SwPosition aPos( aAnchIdx );
1347 aAnch.SetAnchor( &aPos );
1348 pNewSet->Put( aAnch );
1350 if( pUndo )
1351 pUndo->SetFlys( *pOldFmt, *pNewSet, *pNewFmt );
1352 else
1353 pOldFmt->SetFmtAttr( *pNewSet );
1355 delete pNewSet;
1357 // Have only the FlyFrames created.
1358 // We leave this to established methods (especially for InCntFlys).
1359 pNewFmt->MakeFrms();
1360 // #i115719#
1361 if ( bIsSwFlyFrmFmtInstance )
1363 static_cast<SwFlyFrmFmt*>(pOldFmt)->SetObjTitle( sTitle );
1364 static_cast<SwFlyFrmFmt*>(pOldFmt)->SetObjDescription( sDescription );
1367 break;
1369 default:
1370 OSL_ENSURE(false, "unknown LabelType?");
1372 OSL_ENSURE( pNew, "No Label inserted" );
1373 if( pNew )
1375 // #i61007# order of captions
1376 sal_Bool bOrderNumberingFirst = SW_MOD()->GetModuleConfig()->IsCaptionOrderNumberingFirst();
1377 // Work up string
1378 String aTxt;
1379 if( bOrderNumberingFirst )
1381 aTxt = rNumberingSeparator;
1383 if( pType)
1385 aTxt += pType->GetName();
1386 if( !bOrderNumberingFirst )
1387 aTxt += ' ';
1389 xub_StrLen nIdx = aTxt.Len();
1390 if( rTxt.Len() > 0 )
1392 aTxt += rSeparator;
1394 xub_StrLen nSepIdx = aTxt.Len();
1395 aTxt += rTxt;
1397 // Insert string
1398 SwIndex aIdx( pNew, 0 );
1399 pNew->InsertText( aTxt, aIdx );
1401 // Insert field
1402 if(pType)
1404 SwSetExpField aFld( (SwSetExpFieldType*)pType, aEmptyStr, SVX_NUM_ARABIC);
1405 if( bOrderNumberingFirst )
1406 nIdx = 0;
1407 SwFmtFld aFmt( aFld );
1408 pNew->InsertItem( aFmt, nIdx, nIdx );
1409 if(rCharacterStyle.Len())
1411 SwCharFmt* pCharFmt = rDoc.FindCharFmtByName(rCharacterStyle);
1412 if( !pCharFmt )
1414 const sal_uInt16 nMyId = SwStyleNameMapper::GetPoolIdFromUIName(rCharacterStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT);
1415 pCharFmt = rDoc.GetCharFmtFromPool( nMyId );
1417 if (pCharFmt)
1419 SwFmtCharFmt aCharFmt( pCharFmt );
1420 pNew->InsertItem( aCharFmt, 0,
1421 nSepIdx + 1, nsSetAttrMode::SETATTR_DONTEXPAND );
1426 if ( bTable )
1428 if ( bBefore )
1430 if ( !pNew->GetSwAttrSet().GetKeep().GetValue() )
1431 pNew->SetAttr( SvxFmtKeepItem( sal_True, RES_KEEP ) );
1433 else
1435 SwTableNode *const pNd =
1436 rDoc.GetNodes()[nNdIdx]->GetStartNode()->GetTableNode();
1437 SwTable &rTbl = pNd->GetTable();
1438 if ( !rTbl.GetFrmFmt()->GetKeep().GetValue() )
1439 rTbl.GetFrmFmt()->SetFmtAttr( SvxFmtKeepItem( sal_True, RES_KEEP ) );
1440 if ( pUndo )
1441 pUndo->SetUndoKeep();
1444 rDoc.SetModified();
1447 return pNewFmt;
1450 SwFlyFrmFmt *
1451 SwDoc::InsertLabel(
1452 SwLabelType const eType, String const& rTxt, String const& rSeparator,
1453 String const& rNumberingSeparator,
1454 sal_Bool const bBefore, sal_uInt16 const nId, sal_uLong const nNdIdx,
1455 String const& rCharacterStyle,
1456 sal_Bool const bCpyBrd )
1458 SwUndoInsertLabel * pUndo(0);
1459 if (GetIDocumentUndoRedo().DoesUndo())
1461 pUndo = new SwUndoInsertLabel(
1462 eType, rTxt, rSeparator, rNumberingSeparator,
1463 bBefore, nId, rCharacterStyle, bCpyBrd );
1466 SwFlyFrmFmt *const pNewFmt = lcl_InsertLabel(*this, mpTxtFmtCollTbl, pUndo,
1467 eType, rTxt, rSeparator, rNumberingSeparator, bBefore,
1468 nId, nNdIdx, rCharacterStyle, bCpyBrd);
1470 if (pUndo)
1472 GetIDocumentUndoRedo().AppendUndo(pUndo);
1474 else
1476 GetIDocumentUndoRedo().DelAllUndoObj();
1479 return pNewFmt;
1482 static SwFlyFrmFmt *
1483 lcl_InsertDrawLabel( SwDoc & rDoc, SwTxtFmtColls *const pTxtFmtCollTbl,
1484 SwUndoInsertLabel *const pUndo, SwDrawFrmFmt *const pOldFmt,
1485 String const& rTxt,
1486 const String& rSeparator,
1487 const String& rNumberSeparator,
1488 const sal_uInt16 nId,
1489 const String& rCharacterStyle,
1490 SdrObject& rSdrObj )
1492 ::sw::UndoGuard const undoGuard(rDoc.GetIDocumentUndoRedo());
1493 ::sw::DrawUndoGuard const drawUndoGuard(rDoc.GetIDocumentUndoRedo());
1495 // Because we get by the TxtColl's name, we need to create the field first.
1496 OSL_ENSURE( nId == USHRT_MAX || nId < rDoc.GetFldTypes()->size(),
1497 "FldType index out of bounds" );
1498 SwFieldType *pType = nId != USHRT_MAX ? (*rDoc.GetFldTypes())[nId] : 0;
1499 OSL_ENSURE( !pType || pType->Which() == RES_SETEXPFLD, "Wrong label id" );
1501 SwTxtFmtColl *pColl = NULL;
1502 if( pType )
1504 for( sal_uInt16 i = pTxtFmtCollTbl->size(); i; )
1506 if( (*pTxtFmtCollTbl)[ --i ]->GetName().Equals(pType->GetName()) )
1508 pColl = (*pTxtFmtCollTbl)[i];
1509 break;
1512 OSL_ENSURE( pColl, "no text collection found" );
1515 if( !pColl )
1517 pColl = rDoc.GetTxtCollFromPool( RES_POOLCOLL_LABEL );
1520 SwTxtNode* pNew = NULL;
1521 SwFlyFrmFmt* pNewFmt = NULL;
1523 // Destroy Frame,
1524 // insert new Frame,
1525 // insert the corresponding Node with Field into the new Frame,
1526 // insert the old Frame with the Object (Picture/OLE) paragraph-bound into the new Frame,
1527 // create Frames.
1529 // Keep layer ID of drawing object before removing
1530 // its frames.
1531 // Note: The layer ID is passed to the undo and have to be the correct value.
1532 // Removing the frames of the drawing object changes its layer.
1533 const SdrLayerID nLayerId = rSdrObj.GetLayer();
1535 pOldFmt->DelFrms();
1537 // InCntnts need to be treated in a special way:
1538 // The TxtAttribute needs to be destroyed.
1539 // Unfortunately, this also destroys the Format next to the Frames.
1540 // To avoid this, we disconnect the attribute from the Format.
1541 SfxItemSet* pNewSet = pOldFmt->GetAttrSet().Clone( sal_False );
1543 // Protect the Frame's size and position
1544 if ( rSdrObj.IsMoveProtect() || rSdrObj.IsResizeProtect() )
1546 SvxProtectItem aProtect(RES_PROTECT);
1547 aProtect.SetCntntProtect( sal_False );
1548 aProtect.SetPosProtect( rSdrObj.IsMoveProtect() );
1549 aProtect.SetSizeProtect( rSdrObj.IsResizeProtect() );
1550 pNewSet->Put( aProtect );
1553 // Take over the text wrap
1554 lcl_CpyAttr( *pNewSet, pOldFmt->GetAttrSet(), RES_SURROUND );
1556 // Send the frame to the back, if needed.
1557 // Consider the 'invisible' hell layer.
1558 if ( rDoc.GetHellId() != nLayerId &&
1559 rDoc.GetInvisibleHellId() != nLayerId )
1561 SvxOpaqueItem aOpaque( RES_OPAQUE );
1562 aOpaque.SetValue( sal_True );
1563 pNewSet->Put( aOpaque );
1566 // Take over position
1567 // #i26791# - use directly drawing object's positioning attributes
1568 pNewSet->Put( pOldFmt->GetHoriOrient() );
1569 pNewSet->Put( pOldFmt->GetVertOrient() );
1571 pNewSet->Put( pOldFmt->GetAnchor() );
1573 // The new one should be variable in it's height!
1574 Size aSz( rSdrObj.GetCurrentBoundRect().GetSize() );
1575 SwFmtFrmSize aFrmSize( ATT_MIN_SIZE, aSz.Width(), aSz.Height() );
1576 pNewSet->Put( aFrmSize );
1578 // Apply the margin to the new Frame.
1579 // Don't set a border, use the one from the Template.
1580 pNewSet->Put( pOldFmt->GetLRSpace() );
1581 pNewSet->Put( pOldFmt->GetULSpace() );
1583 SwStartNode* pSttNd =
1584 rDoc.GetNodes().MakeTextSection(
1585 SwNodeIndex( rDoc.GetNodes().GetEndOfAutotext() ),
1586 SwFlyStartNode, pColl );
1588 pNewFmt = rDoc.MakeFlyFrmFmt( rDoc.GetUniqueFrameName(),
1589 rDoc.GetFrmFmtFromPool( RES_POOLFRM_FRAME ) );
1591 // Set border and shadow to default if the template contains any.
1592 if( SFX_ITEM_SET == pNewFmt->GetAttrSet().GetItemState( RES_BOX, sal_True ))
1593 pNewSet->Put( *GetDfltAttr( RES_BOX ) );
1595 if( SFX_ITEM_SET == pNewFmt->GetAttrSet().GetItemState(RES_SHADOW,sal_True))
1596 pNewSet->Put( *GetDfltAttr( RES_SHADOW ) );
1598 pNewFmt->SetFmtAttr( SwFmtCntnt( pSttNd ));
1599 pNewFmt->SetFmtAttr( *pNewSet );
1601 const SwFmtAnchor& rAnchor = pNewFmt->GetAnchor();
1602 if ( FLY_AS_CHAR == rAnchor.GetAnchorId() )
1604 const SwPosition *pPos = rAnchor.GetCntntAnchor();
1605 SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
1606 OSL_ENSURE( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
1607 const xub_StrLen nIdx = pPos->nContent.GetIndex();
1608 SwTxtAttr * const pHnt =
1609 pTxtNode->GetTxtAttrForCharAt( nIdx, RES_TXTATR_FLYCNT );
1611 #if OSL_DEBUG_LEVEL > 0
1612 OSL_ENSURE( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
1613 "Missing FlyInCnt-Hint." );
1614 OSL_ENSURE( pHnt && ((SwFmtFlyCnt&)pHnt->GetFlyCnt()).
1615 GetFrmFmt() == (SwFrmFmt*)pOldFmt,
1616 "Wrong TxtFlyCnt-Hint." );
1617 #endif
1618 const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt( pNewFmt );
1622 // The old one should not have a flow
1623 // and it should be adjusted to above and middle.
1624 pNewSet->ClearItem();
1626 pNewSet->Put( SwFmtSurround( SURROUND_NONE ) );
1627 if (nLayerId == rDoc.GetHellId())
1629 // Consider drawing objects in the 'invisible' hell layer
1630 rSdrObj.SetLayer( rDoc.GetHeavenId() );
1632 else if (nLayerId == rDoc.GetInvisibleHellId())
1634 rSdrObj.SetLayer( rDoc.GetInvisibleHeavenId() );
1636 pNewSet->Put( SvxLRSpaceItem( RES_LR_SPACE ) );
1637 pNewSet->Put( SvxULSpaceItem( RES_UL_SPACE ) );
1639 // #i26791# - set position of the drawing object, which is labeled.
1640 pNewSet->Put( SwFmtVertOrient( 0, text::VertOrientation::TOP, text::RelOrientation::FRAME ) );
1641 pNewSet->Put( SwFmtHoriOrient( 0, text::HoriOrientation::CENTER, text::RelOrientation::FRAME ) );
1643 // The old one is paragraph-bound to the new one's paragraph.
1644 SwFmtAnchor aAnch( FLY_AT_PARA );
1645 SwNodeIndex aAnchIdx( *pNewFmt->GetCntnt().GetCntntIdx(), 1 );
1646 pNew = aAnchIdx.GetNode().GetTxtNode();
1647 SwPosition aPos( aAnchIdx );
1648 aAnch.SetAnchor( &aPos );
1649 pNewSet->Put( aAnch );
1651 if( pUndo )
1653 pUndo->SetFlys( *pOldFmt, *pNewSet, *pNewFmt );
1654 // #i26791# - position no longer needed
1655 pUndo->SetDrawObj( nLayerId );
1657 else
1658 pOldFmt->SetFmtAttr( *pNewSet );
1660 delete pNewSet;
1662 // Have only the FlyFrames created.
1663 // We leave this to established methods (especially for InCntFlys).
1664 pNewFmt->MakeFrms();
1666 OSL_ENSURE( pNew, "No Label inserted" );
1668 if( pNew )
1670 //#i61007# order of captions
1671 sal_Bool bOrderNumberingFirst = SW_MOD()->GetModuleConfig()->IsCaptionOrderNumberingFirst();
1673 // prepare string
1674 String aTxt;
1675 if( bOrderNumberingFirst )
1677 aTxt = rNumberSeparator;
1679 if ( pType )
1681 aTxt += pType->GetName();
1682 if( !bOrderNumberingFirst )
1683 aTxt += ' ';
1685 xub_StrLen nIdx = aTxt.Len();
1686 aTxt += rSeparator;
1687 xub_StrLen nSepIdx = aTxt.Len();
1688 aTxt += rTxt;
1690 // insert text
1691 SwIndex aIdx( pNew, 0 );
1692 pNew->InsertText( aTxt, aIdx );
1694 // insert field
1695 if ( pType )
1697 SwSetExpField aFld( (SwSetExpFieldType*)pType, aEmptyStr, SVX_NUM_ARABIC );
1698 if( bOrderNumberingFirst )
1699 nIdx = 0;
1700 SwFmtFld aFmt( aFld );
1701 pNew->InsertItem( aFmt, nIdx, nIdx );
1702 if ( rCharacterStyle.Len() )
1704 SwCharFmt * pCharFmt = rDoc.FindCharFmtByName(rCharacterStyle);
1705 if ( !pCharFmt )
1707 const sal_uInt16 nMyId = SwStyleNameMapper::GetPoolIdFromUIName( rCharacterStyle, nsSwGetPoolIdFromName::GET_POOLID_CHRFMT );
1708 pCharFmt = rDoc.GetCharFmtFromPool( nMyId );
1710 if ( pCharFmt )
1712 SwFmtCharFmt aCharFmt( pCharFmt );
1713 pNew->InsertItem( aCharFmt, 0, nSepIdx + 1,
1714 nsSetAttrMode::SETATTR_DONTEXPAND );
1720 return pNewFmt;
1723 SwFlyFrmFmt* SwDoc::InsertDrawLabel(
1724 String const& rTxt,
1725 String const& rSeparator,
1726 String const& rNumberSeparator,
1727 sal_uInt16 const nId,
1728 String const& rCharacterStyle,
1729 SdrObject& rSdrObj )
1731 SwDrawContact *const pContact =
1732 static_cast<SwDrawContact*>(GetUserCall( &rSdrObj ));
1733 OSL_ENSURE( RES_DRAWFRMFMT == pContact->GetFmt()->Which(),
1734 "InsertDrawLabel(): not a DrawFrmFmt" );
1735 if (!pContact)
1736 return 0;
1738 SwDrawFrmFmt* pOldFmt = (SwDrawFrmFmt *)pContact->GetFmt();
1739 if (!pOldFmt)
1740 return 0;
1742 SwUndoInsertLabel * pUndo = 0;
1743 if (GetIDocumentUndoRedo().DoesUndo())
1745 GetIDocumentUndoRedo().ClearRedo();
1746 pUndo = new SwUndoInsertLabel(
1747 LTYPE_DRAW, rTxt, rSeparator, rNumberSeparator, sal_False,
1748 nId, rCharacterStyle, sal_False );
1751 SwFlyFrmFmt *const pNewFmt = lcl_InsertDrawLabel(
1752 *this, mpTxtFmtCollTbl, pUndo, pOldFmt,
1753 rTxt, rSeparator, rNumberSeparator, nId, rCharacterStyle, rSdrObj);
1755 if (pUndo)
1757 GetIDocumentUndoRedo().AppendUndo( pUndo );
1759 else
1761 GetIDocumentUndoRedo().DelAllUndoObj();
1764 return pNewFmt;
1767 // IDocumentTimerAccess methods ------------------------------------------
1769 void SwDoc::StartIdling()
1771 mbStartIdleTimer = true;
1772 if( !mIdleBlockCount )
1773 maIdleTimer.Start();
1776 void SwDoc::StopIdling()
1778 mbStartIdleTimer = false;
1779 maIdleTimer.Stop();
1782 void SwDoc::BlockIdling()
1784 maIdleTimer.Stop();
1785 ++mIdleBlockCount;
1788 void SwDoc::UnblockIdling()
1790 --mIdleBlockCount;
1791 if( !mIdleBlockCount && mbStartIdleTimer && !maIdleTimer.IsActive() )
1792 maIdleTimer.Start();
1795 void SwDoc::StartBackgroundJobs() {
1796 // Trigger DoIdleJobs(), asynchronously.
1797 maIdleTimer.Start();
1800 IMPL_LINK( SwDoc, DoIdleJobs, Timer *, pTimer )
1802 #ifdef TIMELOG
1803 static ::rtl::Logfile* pModLogFile = 0;
1804 if( !pModLogFile )
1805 pModLogFile = new ::rtl::Logfile( "First DoIdleJobs" );
1806 #endif
1808 SwRootFrm* pTmpRoot = GetCurrentLayout();//swmod 080219
1809 if( pTmpRoot &&
1810 !SfxProgress::GetActiveProgress( mpDocShell ) )
1812 ViewShell *pSh, *pStartSh;
1813 pSh = pStartSh = GetCurrentViewShell();
1814 do {
1815 if( pSh->ActionPend() )
1817 pTimer->Start();
1818 return 0;
1820 pSh = (ViewShell*)pSh->GetNext();
1821 } while( pSh != pStartSh );
1823 if( pTmpRoot->IsNeedGrammarCheck() )
1825 sal_Bool bIsOnlineSpell = pSh->GetViewOptions()->IsOnlineSpell();
1826 sal_Bool bIsAutoGrammar = sal_False;
1827 SvtLinguConfig().GetProperty( OUString(
1828 UPN_IS_GRAMMAR_AUTO ) ) >>= bIsAutoGrammar;
1830 if (bIsOnlineSpell && bIsAutoGrammar)
1831 StartGrammarChecking( *this );
1833 std::set<SwRootFrm*> aAllLayouts = GetAllLayouts();//swmod 080320
1834 std::set<SwRootFrm*>::iterator pLayIter = aAllLayouts.begin();
1835 for ( ;pLayIter != aAllLayouts.end();++pLayIter )
1837 if ((*pLayIter)->IsIdleFormat())
1839 (*pLayIter)->GetCurrShell()->LayoutIdle();
1841 // Defer the remaining work.
1842 pTimer->Start();
1843 return 0;
1847 SwFldUpdateFlags nFldUpdFlag = getFieldUpdateFlags(true);
1848 if( ( AUTOUPD_FIELD_ONLY == nFldUpdFlag
1849 || AUTOUPD_FIELD_AND_CHARTS == nFldUpdFlag ) &&
1850 GetUpdtFlds().IsFieldsDirty()
1851 // If we switch the field name the Fields are not updated.
1852 // So the "backgorund update" should always be carried out
1853 /* && !pStartSh->GetViewOptions()->IsFldName()*/ )
1855 if ( GetUpdtFlds().IsInUpdateFlds() ||
1856 IsExpFldsLocked() )
1858 pTimer->Start();
1859 return 0;
1862 // Action brackets!
1863 GetUpdtFlds().SetInUpdateFlds( true );
1865 pTmpRoot->StartAllAction();
1867 // no jump on update of fields #i85168#
1868 const sal_Bool bOldLockView = pStartSh->IsViewLocked();
1869 pStartSh->LockView( sal_True );
1871 GetSysFldType( RES_CHAPTERFLD )->ModifyNotification( 0, 0 ); // ChapterField
1872 UpdateExpFlds( 0, sal_False ); // Updates ExpressionFields
1873 UpdateTblFlds(NULL); // Tables
1874 UpdateRefFlds(NULL); // References
1876 pTmpRoot->EndAllAction();
1878 pStartSh->LockView( bOldLockView );
1880 GetUpdtFlds().SetInUpdateFlds( false );
1881 GetUpdtFlds().SetFieldsDirty( false );
1883 } //swmod 080219
1884 #ifdef TIMELOG
1885 if( pModLogFile && 1 != (long)pModLogFile )
1886 delete pModLogFile, ((long&)pModLogFile) = 1;
1887 #endif
1888 return 0;
1891 IMPL_STATIC_LINK( SwDoc, BackgroundDone, SvxBrushItem*, EMPTYARG )
1893 ViewShell *pSh, *pStartSh;
1894 pSh = pStartSh = pThis->GetCurrentViewShell(); //swmod 071108//swmod 071225
1895 if( pStartSh )
1896 do {
1897 if( pSh->GetWin() )
1899 // Make sure to repaint with virtual device
1900 pSh->LockPaint();
1901 pSh->UnlockPaint( sal_True );
1903 pSh = (ViewShell*)pSh->GetNext();
1904 } while( pSh != pStartSh );
1905 return 0;
1908 static String lcl_GetUniqueFlyName( const SwDoc* pDoc, sal_uInt16 nDefStrId )
1910 ResId aId( nDefStrId, *pSwResMgr );
1911 String aName( aId );
1912 xub_StrLen nNmLen = aName.Len();
1914 const SwFrmFmts& rFmts = *pDoc->GetSpzFrmFmts();
1916 sal_uInt16 nNum, nTmp, nFlagSize = ( rFmts.size() / 8 ) +2;
1917 sal_uInt8* pSetFlags = new sal_uInt8[ nFlagSize ];
1918 sal_uInt16 n;
1920 memset( pSetFlags, 0, nFlagSize );
1922 for( n = 0; n < rFmts.size(); ++n )
1924 const SwFrmFmt* pFlyFmt = rFmts[ n ];
1925 if( RES_FLYFRMFMT == pFlyFmt->Which() &&
1926 pFlyFmt->GetName().Match( aName ) == nNmLen )
1928 // Only get and set the Flag
1929 nNum = static_cast< sal_uInt16 >( pFlyFmt->GetName().Copy( nNmLen ).ToInt32() );
1930 if( nNum-- && nNum < rFmts.size() )
1931 pSetFlags[ nNum / 8 ] |= (0x01 << ( nNum & 0x07 ));
1935 // All numbers are flagged accordingly, so determine the right one
1936 nNum = rFmts.size();
1937 for( n = 0; n < nFlagSize; ++n )
1938 if( 0xff != ( nTmp = pSetFlags[ n ] ))
1940 // so determine the number
1941 nNum = n * 8;
1942 while( nTmp & 1 )
1943 ++nNum, nTmp >>= 1;
1944 break;
1947 delete [] pSetFlags;
1948 return aName += OUString::number( ++nNum );
1951 String SwDoc::GetUniqueGrfName() const
1953 return lcl_GetUniqueFlyName( this, STR_GRAPHIC_DEFNAME );
1956 String SwDoc::GetUniqueOLEName() const
1958 return lcl_GetUniqueFlyName( this, STR_OBJECT_DEFNAME );
1961 String SwDoc::GetUniqueFrameName() const
1963 return lcl_GetUniqueFlyName( this, STR_FRAME_DEFNAME );
1966 const SwFlyFrmFmt* SwDoc::FindFlyByName( const String& rName, sal_Int8 nNdTyp ) const
1968 const SwFrmFmts& rFmts = *GetSpzFrmFmts();
1969 for( sal_uInt16 n = rFmts.size(); n; )
1971 const SwFrmFmt* pFlyFmt = rFmts[ --n ];
1972 const SwNodeIndex* pIdx;
1973 if( RES_FLYFRMFMT == pFlyFmt->Which() && pFlyFmt->GetName() == rName &&
1974 0 != ( pIdx = pFlyFmt->GetCntnt().GetCntntIdx() ) &&
1975 pIdx->GetNode().GetNodes().IsDocNodes() )
1977 if( nNdTyp )
1979 // query for the right NodeType
1980 const SwNode* pNd = GetNodes()[ pIdx->GetIndex()+1 ];
1981 if( nNdTyp == ND_TEXTNODE
1982 ? !pNd->IsNoTxtNode()
1983 : nNdTyp == pNd->GetNodeType() )
1984 return (SwFlyFrmFmt*)pFlyFmt;
1986 else
1987 return (SwFlyFrmFmt*)pFlyFmt;
1990 return 0;
1993 void SwDoc::SetFlyName( SwFlyFrmFmt& rFmt, const String& rName )
1995 String sName( rName );
1996 if( !rName.Len() || FindFlyByName( rName ) )
1998 sal_uInt16 nTyp = STR_FRAME_DEFNAME;
1999 const SwNodeIndex* pIdx = rFmt.GetCntnt().GetCntntIdx();
2000 if( pIdx && pIdx->GetNode().GetNodes().IsDocNodes() )
2001 switch( GetNodes()[ pIdx->GetIndex() + 1 ]->GetNodeType() )
2003 case ND_GRFNODE: nTyp = STR_GRAPHIC_DEFNAME; break;
2004 case ND_OLENODE: nTyp = STR_OBJECT_DEFNAME; break;
2006 sName = lcl_GetUniqueFlyName( this, nTyp );
2008 rFmt.SetName( sName, sal_True );
2009 SetModified();
2012 void SwDoc::SetAllUniqueFlyNames()
2014 sal_uInt16 n, nFlyNum = 0, nGrfNum = 0, nOLENum = 0;
2016 ResId nFrmId( STR_FRAME_DEFNAME, *pSwResMgr ),
2017 nGrfId( STR_GRAPHIC_DEFNAME, *pSwResMgr ),
2018 nOLEId( STR_OBJECT_DEFNAME, *pSwResMgr );
2019 String sFlyNm( nFrmId );
2020 String sGrfNm( nGrfId );
2021 String sOLENm( nOLEId );
2023 if( 255 < ( n = GetSpzFrmFmts()->size() ))
2024 n = 255;
2025 SwFrmFmts aArr;
2026 aArr.reserve( n );
2027 SwFrmFmt* pFlyFmt;
2028 bool bContainsAtPageObjWithContentAnchor = false;
2030 for( n = GetSpzFrmFmts()->size(); n; )
2032 if( RES_FLYFRMFMT == (pFlyFmt = (*GetSpzFrmFmts())[ --n ])->Which() )
2034 sal_uInt16 *pNum = 0;
2035 xub_StrLen nLen;
2036 const String& rNm = pFlyFmt->GetName();
2037 if( rNm.Len() )
2039 if( rNm.Match( sGrfNm ) == ( nLen = sGrfNm.Len() ))
2040 pNum = &nGrfNum;
2041 else if( rNm.Match( sFlyNm ) == ( nLen = sFlyNm.Len() ))
2042 pNum = &nFlyNum;
2043 else if( rNm.Match( sOLENm ) == ( nLen = sOLENm.Len() ))
2044 pNum = &nOLENum;
2046 if ( pNum && *pNum < ( nLen = static_cast< xub_StrLen >( rNm.Copy( nLen ).ToInt32() ) ) )
2047 *pNum = nLen;
2049 else
2050 // we want to set that afterwards
2051 aArr.push_back( pFlyFmt );
2054 if ( !bContainsAtPageObjWithContentAnchor )
2056 const SwFmtAnchor& rAnchor = pFlyFmt->GetAnchor();
2057 if ( (FLY_AT_PAGE == rAnchor.GetAnchorId()) &&
2058 rAnchor.GetCntntAnchor() )
2060 bContainsAtPageObjWithContentAnchor = true;
2064 SetContainsAtPageObjWithContentAnchor( bContainsAtPageObjWithContentAnchor );
2066 const SwNodeIndex* pIdx;
2068 for( n = aArr.size(); n; )
2069 if( 0 != ( pIdx = ( pFlyFmt = aArr[ --n ])->GetCntnt().GetCntntIdx() )
2070 && pIdx->GetNode().GetNodes().IsDocNodes() )
2072 sal_uInt16 nNum;
2073 String sNm;
2074 switch( GetNodes()[ pIdx->GetIndex() + 1 ]->GetNodeType() )
2076 case ND_GRFNODE:
2077 sNm = sGrfNm;
2078 nNum = ++nGrfNum;
2079 break;
2080 case ND_OLENODE:
2081 sNm = sOLENm;
2082 nNum = ++nOLENum;
2083 break;
2084 default:
2085 sNm = sFlyNm;
2086 nNum = ++nFlyNum;
2087 break;
2089 pFlyFmt->SetName( sNm += OUString::number( nNum ));
2091 aArr.clear();
2093 if( !GetFtnIdxs().empty() )
2095 SwTxtFtn::SetUniqueSeqRefNo( *this );
2096 // #i52775# Chapter footnotes did not get updated correctly.
2097 // Calling UpdateAllFtn() instead of UpdateFtn() solves this problem,
2098 // but I do not dare to call UpdateAllFtn() in all cases: Safety first.
2099 if ( FTNNUM_CHAPTER == GetFtnInfo().eNum )
2101 GetFtnIdxs().UpdateAllFtn();
2103 else
2105 SwNodeIndex aTmp( GetNodes() );
2106 GetFtnIdxs().UpdateFtn( aTmp );
2111 bool SwDoc::IsInHeaderFooter( const SwNodeIndex& rIdx ) const
2113 // If there's a Layout, use it!
2114 // That can also be a Fly in a Fly in the Header.
2115 // Is also used by sw3io, to determine if a Redline object is
2116 // in the Header or Footer.
2117 // Because Redlines are also attached to Start and EndNoden,
2118 // the Index must not necessarily be from a ContentNode.
2119 SwNode* pNd = &rIdx.GetNode();
2120 if( pNd->IsCntntNode() && mpCurrentView )//swmod 071029//swmod 071225
2122 const SwFrm *pFrm = pNd->GetCntntNode()->getLayoutFrm( GetCurrentLayout() );
2123 if( pFrm )
2125 const SwFrm *pUp = pFrm->GetUpper();
2126 while ( pUp && !pUp->IsHeaderFrm() && !pUp->IsFooterFrm() )
2128 if ( pUp->IsFlyFrm() )
2129 pUp = ((SwFlyFrm*)pUp)->GetAnchorFrm();
2130 pUp = pUp->GetUpper();
2132 if ( pUp )
2133 return true;
2135 return false;
2140 const SwNode* pFlyNd = pNd->FindFlyStartNode();
2141 while( pFlyNd )
2143 // get up by using the Anchor
2144 sal_uInt16 n;
2145 for( n = 0; n < GetSpzFrmFmts()->size(); ++n )
2147 const SwFrmFmt* pFmt = (*GetSpzFrmFmts())[ n ];
2148 const SwNodeIndex* pIdx = pFmt->GetCntnt().GetCntntIdx();
2149 if( pIdx && pFlyNd == &pIdx->GetNode() )
2151 const SwFmtAnchor& rAnchor = pFmt->GetAnchor();
2152 if ((FLY_AT_PAGE == rAnchor.GetAnchorId()) ||
2153 !rAnchor.GetCntntAnchor() )
2155 return false;
2158 pNd = &rAnchor.GetCntntAnchor()->nNode.GetNode();
2159 pFlyNd = pNd->FindFlyStartNode();
2160 break;
2163 if( n >= GetSpzFrmFmts()->size() )
2165 OSL_ENSURE( mbInReading, "Found a FlySection but not a Format!" );
2166 return false;
2170 return 0 != pNd->FindHeaderStartNode() ||
2171 0 != pNd->FindFooterStartNode();
2174 short SwDoc::GetTextDirection( const SwPosition& rPos,
2175 const Point* pPt ) const
2177 short nRet = -1;
2179 SwCntntNode *pNd = rPos.nNode.GetNode().GetCntntNode();
2181 // #i42921# - use new method <SwCntntNode::GetTextDirection(..)>
2182 if ( pNd )
2184 nRet = pNd->GetTextDirection( rPos, pPt );
2186 if ( nRet == -1 )
2188 const SvxFrameDirectionItem* pItem = 0;
2189 if( pNd )
2191 // Are we in a FlyFrame? Then look at that for the correct attribute
2192 const SwFrmFmt* pFlyFmt = pNd->GetFlyFmt();
2193 while( pFlyFmt )
2195 pItem = &pFlyFmt->GetFrmDir();
2196 if( FRMDIR_ENVIRONMENT == pItem->GetValue() )
2198 pItem = 0;
2199 const SwFmtAnchor* pAnchor = &pFlyFmt->GetAnchor();
2200 if ((FLY_AT_PAGE != pAnchor->GetAnchorId()) &&
2201 pAnchor->GetCntntAnchor())
2203 pFlyFmt = pAnchor->GetCntntAnchor()->nNode.
2204 GetNode().GetFlyFmt();
2206 else
2207 pFlyFmt = 0;
2209 else
2210 pFlyFmt = 0;
2213 if( !pItem )
2215 const SwPageDesc* pPgDsc = pNd->FindPageDesc( sal_False );
2216 if( pPgDsc )
2217 pItem = &pPgDsc->GetMaster().GetFrmDir();
2220 if( !pItem )
2221 pItem = (SvxFrameDirectionItem*)&GetAttrPool().GetDefaultItem(
2222 RES_FRAMEDIR );
2223 nRet = pItem->GetValue();
2225 return nRet;
2228 bool SwDoc::IsInVerticalText( const SwPosition& rPos, const Point* pPt ) const
2230 const short nDir = GetTextDirection( rPos, pPt );
2231 return FRMDIR_VERT_TOP_RIGHT == nDir || FRMDIR_VERT_TOP_LEFT == nDir;
2234 void SwDoc::SetCurrentViewShell( ViewShell* pNew )
2236 mpCurrentView = pNew;
2239 SwLayouter* SwDoc::GetLayouter()
2241 return mpLayouter;
2244 const SwLayouter* SwDoc::GetLayouter() const
2246 return mpLayouter;
2249 void SwDoc::SetLayouter( SwLayouter* pNew )
2251 mpLayouter = pNew;
2254 const ViewShell *SwDoc::GetCurrentViewShell() const
2256 return mpCurrentView;
2259 ViewShell *SwDoc::GetCurrentViewShell()
2261 return mpCurrentView;
2264 //swmod 080219
2265 // It must be able to communicate to a ViewShell. This is going to be removed later.
2266 const SwRootFrm *SwDoc::GetCurrentLayout() const
2268 if(GetCurrentViewShell())
2269 return GetCurrentViewShell()->GetLayout();
2270 return 0;
2273 SwRootFrm *SwDoc::GetCurrentLayout()
2275 if(GetCurrentViewShell())
2276 return GetCurrentViewShell()->GetLayout();
2277 return 0;
2280 bool SwDoc::HasLayout() const
2282 // if there is a view, there is always a layout
2283 return (mpCurrentView != 0);
2286 std::set<SwRootFrm*> SwDoc::GetAllLayouts()
2288 std::set<SwRootFrm*> aAllLayouts;
2289 ViewShell *pStart = GetCurrentViewShell();
2290 ViewShell *pTemp = pStart;
2291 if ( pTemp )
2295 if (pTemp->GetLayout())
2297 aAllLayouts.insert(pTemp->GetLayout());
2298 pTemp = (ViewShell*)pTemp->GetNext();
2300 } while(pTemp!=pStart);
2303 return aAllLayouts;
2304 } //swmod 070825
2306 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */