Update ooo320-m1
[ooovba.git] / sw / source / core / doc / docfly.cxx
blobe0645fcdc1f897ca0a8396f28347e66680a45d21
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: docfly.cxx,v $
10 * $Revision: 1.34 $
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"
35 #include <hintids.hxx>
36 #include <svtools/itemiter.hxx>
37 #include <svx/svdobj.hxx>
38 #include <svx/svdpage.hxx>
39 #include <svx/svdmodel.hxx>
40 #include <svx/svdocapt.hxx>
41 #include <svx/svdmark.hxx>
42 #include <fmtfsize.hxx>
43 #include <fmtornt.hxx>
44 #include <fmtsrnd.hxx>
45 #include <dcontact.hxx>
47 #include <ndgrf.hxx>
48 #include <doc.hxx>
49 #include <ndindex.hxx>
50 #include <docary.hxx>
51 #include <fmtcntnt.hxx>
52 #include <fmtanchr.hxx>
53 #include <txtflcnt.hxx>
54 #include <fmtflcnt.hxx>
55 #include <txtfrm.hxx>
56 #include <pagefrm.hxx>
57 #include <rootfrm.hxx>
58 #include <flyfrms.hxx>
59 #include <frmtool.hxx>
60 #include <frmfmt.hxx>
61 #include <ndtxt.hxx>
62 #include <pam.hxx>
63 #include <tblsel.hxx>
64 #include <swundo.hxx>
65 #include <swtable.hxx>
66 #include <crstate.hxx>
67 #include <undobj.hxx>
68 #include <fmtcnct.hxx>
69 #include <dflyobj.hxx>
71 // --> OD 2009-07-20 #i73249#
72 #include <undoflystrattr.hxx>
73 // <--
75 extern USHORT GetHtmlMode( const SwDocShell* );
78 using namespace ::com::sun::star;
80 /*-----------------17.02.98 08:35-------------------
82 --------------------------------------------------*/
83 USHORT SwDoc::GetFlyCount( FlyCntType eType ) const
85 const SwSpzFrmFmts& rFmts = *GetSpzFrmFmts();
86 USHORT nSize = rFmts.Count();
87 USHORT nCount = 0;
88 const SwNodeIndex* pIdx;
89 for ( USHORT i = 0; i < nSize; i++)
91 const SwFrmFmt* pFlyFmt = rFmts[ i ];
92 if( RES_FLYFRMFMT == pFlyFmt->Which()
93 && 0 != ( pIdx = pFlyFmt->GetCntnt().GetCntntIdx() )
94 && pIdx->GetNodes().IsDocNodes()
97 const SwNode* pNd = GetNodes()[ pIdx->GetIndex() + 1 ];
99 switch( eType )
101 case FLYCNTTYPE_FRM:
102 if(!pNd->IsNoTxtNode())
103 nCount++;
104 break;
106 case FLYCNTTYPE_GRF:
107 if( pNd->IsGrfNode() )
108 nCount++;
109 break;
111 case FLYCNTTYPE_OLE:
112 if(pNd->IsOLENode())
113 nCount++;
114 break;
116 default:
117 nCount++;
121 return nCount;
124 /*-----------------17.02.98 08:35-------------------
126 --------------------------------------------------*/
127 // If you change this, also update SwXFrameEnumeration in unocoll.
128 SwFrmFmt* SwDoc::GetFlyNum( USHORT nIdx, FlyCntType eType )
130 SwSpzFrmFmts& rFmts = *GetSpzFrmFmts();
131 SwFrmFmt* pRetFmt = 0;
132 USHORT nSize = rFmts.Count();
133 const SwNodeIndex* pIdx;
134 USHORT nCount = 0;
135 for( USHORT i = 0; !pRetFmt && i < nSize; ++i )
137 SwFrmFmt* pFlyFmt = rFmts[ i ];
138 if( RES_FLYFRMFMT == pFlyFmt->Which()
139 && 0 != ( pIdx = pFlyFmt->GetCntnt().GetCntntIdx() )
140 && pIdx->GetNodes().IsDocNodes()
143 const SwNode* pNd = GetNodes()[ pIdx->GetIndex() + 1 ];
144 switch( eType )
146 case FLYCNTTYPE_FRM:
147 if( !pNd->IsNoTxtNode() && nIdx == nCount++)
148 pRetFmt = pFlyFmt;
149 break;
150 case FLYCNTTYPE_GRF:
151 if(pNd->IsGrfNode() && nIdx == nCount++ )
152 pRetFmt = pFlyFmt;
153 break;
154 case FLYCNTTYPE_OLE:
155 if(pNd->IsOLENode() && nIdx == nCount++)
156 pRetFmt = pFlyFmt;
157 break;
158 default:
159 if(nIdx == nCount++)
160 pRetFmt = pFlyFmt;
164 return pRetFmt;
167 /* \f */
169 /***********************************************************************
170 #* Class : SwDoc
171 #* Methode : SetFlyFrmAnchor
172 #* Beschreibung: Das Ankerattribut des FlyFrms aendert sich.
173 #* Datum : MA 01. Feb. 94
174 #* Update : JP 09.03.98
175 #***********************************************************************/
177 Point lcl_FindAnchorLayPos( SwDoc& rDoc, const SwFmtAnchor& rAnch,
178 const SwFrmFmt* pFlyFmt )
180 Point aRet;
181 if( rDoc.GetRootFrm() )
182 switch( rAnch.GetAnchorId() )
184 case FLY_IN_CNTNT:
185 if( pFlyFmt && rAnch.GetCntntAnchor() )
187 const SwFrm* pOld = ((SwFlyFrmFmt*)pFlyFmt)->GetFrm( &aRet, FALSE );
188 if( pOld )
189 aRet = pOld->Frm().Pos();
191 break;
193 case FLY_AT_CNTNT:
194 case FLY_AUTO_CNTNT: // LAYER_IMPL
195 if( rAnch.GetCntntAnchor() )
197 const SwPosition *pPos = rAnch.GetCntntAnchor();
198 const SwCntntNode* pNd = pPos->nNode.GetNode().GetCntntNode();
199 const SwFrm* pOld = pNd ? pNd->GetFrm( &aRet, 0, FALSE ) : 0;
200 if( pOld )
201 aRet = pOld->Frm().Pos();
203 break;
205 case FLY_AT_FLY: // LAYER_IMPL
206 if( rAnch.GetCntntAnchor() )
208 const SwFlyFrmFmt* pFmt = (SwFlyFrmFmt*)rAnch.GetCntntAnchor()->
209 nNode.GetNode().GetFlyFmt();
210 const SwFrm* pOld = pFmt ? pFmt->GetFrm( &aRet, FALSE ) : 0;
211 if( pOld )
212 aRet = pOld->Frm().Pos();
214 break;
216 case FLY_PAGE:
218 USHORT nPgNum = rAnch.GetPageNum();
219 const SwPageFrm *pPage = (SwPageFrm*)rDoc.GetRootFrm()->Lower();
220 for( USHORT i = 1; (i <= nPgNum) && pPage; ++i,
221 pPage = (const SwPageFrm*)pPage->GetNext() )
222 if( i == nPgNum )
224 aRet = pPage->Frm().Pos();
225 break;
228 break;
229 default:
230 break;
232 return aRet;
235 #define MAKEFRMS 0
236 #define IGNOREANCHOR 1
237 #define DONTMAKEFRMS 2
239 sal_Int8 SwDoc::SetFlyFrmAnchor( SwFrmFmt& rFmt, SfxItemSet& rSet, BOOL bNewFrms )
241 //Ankerwechsel sind fast immer in alle 'Richtungen' erlaubt.
242 //Ausnahme: Absatz- bzw. Zeichengebundene Rahmen duerfen wenn sie in
243 //Kopf-/Fusszeilen stehen nicht Seitengebunden werden.
244 const SwFmtAnchor &rOldAnch = rFmt.GetAnchor();
245 const RndStdIds nOld = rOldAnch.GetAnchorId();
247 SwFmtAnchor aNewAnch( (SwFmtAnchor&)rSet.Get( RES_ANCHOR ) );
248 RndStdIds nNew = aNewAnch.GetAnchorId();
250 // ist der neue ein gueltiger Anker?
251 if( !aNewAnch.GetCntntAnchor() && (FLY_AT_FLY == nNew ||
252 FLY_AT_CNTNT == nNew || FLY_IN_CNTNT == nNew ||
253 FLY_AUTO_CNTNT == nNew ))
254 return IGNOREANCHOR;
256 if( nOld == nNew )
257 return DONTMAKEFRMS;
260 Point aOldAnchorPos( ::lcl_FindAnchorLayPos( *this, rOldAnch, &rFmt ));
261 Point aNewAnchorPos( ::lcl_FindAnchorLayPos( *this, aNewAnch, 0 ));
263 //Die alten Frms vernichten. Dabei werden die Views implizit gehidet und
264 //doppeltes hiden waere so eine art Show!
265 rFmt.DelFrms();
267 if( FLY_IN_CNTNT == nOld )
269 //Bei InCntnt's wird es spannend: Das TxtAttribut muss vernichtet
270 //werden. Leider reisst dies neben den Frms auch noch das Format mit
271 //in sein Grab. Um dass zu unterbinden loesen wir vorher die
272 //Verbindung zwischen Attribut und Format.
273 const SwPosition *pPos = rOldAnch.GetCntntAnchor();
274 SwTxtNode *pTxtNode = pPos->nNode.GetNode().GetTxtNode();
275 ASSERT( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
276 const xub_StrLen nIdx = pPos->nContent.GetIndex();
277 SwTxtAttr * const pHnt =
278 pTxtNode->GetTxtAttrForCharAt( nIdx, RES_TXTATR_FLYCNT );
279 ASSERT( pHnt && pHnt->Which() == RES_TXTATR_FLYCNT,
280 "Missing FlyInCnt-Hint." );
281 ASSERT( pHnt && pHnt->GetFlyCnt().GetFrmFmt() == &rFmt,
282 "Wrong TxtFlyCnt-Hint." );
283 const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt();
285 //Die Verbindung ist geloest, jetzt muss noch das Attribut vernichtet
286 //werden.
287 pTxtNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIdx, nIdx );
290 //Endlich kann das Attribut gesetzt werden. Es muss das erste Attribut
291 //sein; Undo depends on it!
292 rFmt.SetFmtAttr( aNewAnch );
294 //Positionskorrekturen
295 const SfxPoolItem* pItem;
296 switch( nNew )
298 case FLY_IN_CNTNT:
299 //Wenn keine Positionsattribute hereinkommen, dann muss dafuer
300 //gesorgt werden, das keine unerlaubte automatische Ausrichtung
301 //bleibt.
303 const SwPosition *pPos = aNewAnch.GetCntntAnchor();
304 SwTxtNode *pNd = pPos->nNode.GetNode().GetTxtNode();
305 ASSERT( pNd, "Crsr steht nicht auf TxtNode." );
307 SwFmtFlyCnt aFmt( static_cast<SwFlyFrmFmt*>(&rFmt) );
308 pNd->InsertItem( aFmt, pPos->nContent.GetIndex(), 0 );
311 if( SFX_ITEM_SET != rSet.GetItemState( RES_VERT_ORIENT, FALSE, &pItem ))
313 SwFmtVertOrient aOldV( rFmt.GetVertOrient() );
314 BOOL bSet = TRUE;
315 switch( aOldV.GetVertOrient() )
317 case text::VertOrientation::LINE_TOP: aOldV.SetVertOrient( text::VertOrientation::TOP ); break;
318 case text::VertOrientation::LINE_CENTER: aOldV.SetVertOrient( text::VertOrientation::CENTER); break;
319 case text::VertOrientation::LINE_BOTTOM: aOldV.SetVertOrient( text::VertOrientation::BOTTOM); break;
320 case text::VertOrientation::NONE: aOldV.SetVertOrient( text::VertOrientation::CENTER); break;
321 default:
322 bSet = FALSE;
324 if( bSet )
325 rSet.Put( aOldV );
327 break;
329 case FLY_AT_CNTNT:
330 case FLY_AUTO_CNTNT: // LAYER_IMPL
331 case FLY_AT_FLY: // LAYER_IMPL
332 case FLY_PAGE:
334 //Wenn keine Positionsattribute hereinschneien korrigieren wir
335 //die Position so, dass die Dokumentkoordinaten des Flys erhalten
336 //bleiben.
337 //Chg: Wenn sich in den Positionsattributen lediglich die
338 //Ausrichtung veraendert (text::RelOrientation::FRAME vs. text::RelOrientation::PRTAREA), dann wird die
339 //Position ebenfalls korrigiert.
340 if( SFX_ITEM_SET != rSet.GetItemState( RES_HORI_ORIENT, FALSE, &pItem ))
341 pItem = 0;
343 SwFmtHoriOrient aOldH( rFmt.GetHoriOrient() );
345 if( text::HoriOrientation::NONE == aOldH.GetHoriOrient() && ( !pItem ||
346 aOldH.GetPos() == ((SwFmtHoriOrient*)pItem)->GetPos() ))
348 SwTwips nPos = FLY_IN_CNTNT == nOld ? 0 : aOldH.GetPos();
349 nPos += aOldAnchorPos.X() - aNewAnchorPos.X();
351 if( pItem )
353 SwFmtHoriOrient* pH = (SwFmtHoriOrient*)pItem;
354 aOldH.SetHoriOrient( pH->GetHoriOrient() );
355 aOldH.SetRelationOrient( pH->GetRelationOrient() );
357 aOldH.SetPos( nPos );
358 rSet.Put( aOldH );
361 if( SFX_ITEM_SET != rSet.GetItemState( RES_VERT_ORIENT, FALSE, &pItem ))
362 pItem = 0;
363 SwFmtVertOrient aOldV( rFmt.GetVertOrient() );
365 // OD 2004-05-14 #i28922# - correction: compare <aOldV.GetVertOrient()
366 // with <text::VertOrientation::NONE>
367 if( text::VertOrientation::NONE == aOldV.GetVertOrient() && (!pItem ||
368 aOldV.GetPos() == ((SwFmtVertOrient*)pItem)->GetPos() ) )
370 SwTwips nPos = FLY_IN_CNTNT == nOld ? 0 : aOldV.GetPos();
371 nPos += aOldAnchorPos.Y() - aNewAnchorPos.Y();
372 if( pItem )
374 SwFmtVertOrient* pV = (SwFmtVertOrient*)pItem;
375 aOldV.SetVertOrient( pV->GetVertOrient() );
376 aOldV.SetRelationOrient( pV->GetRelationOrient() );
378 aOldV.SetPos( nPos );
379 rSet.Put( aOldV );
382 break;
383 default:
384 break;
387 if( bNewFrms )
388 rFmt.MakeFrms();
390 return MAKEFRMS;
393 BOOL SwDoc::SetFlyFrmAttr( SwFrmFmt& rFlyFmt, SfxItemSet& rSet )
395 if( !rSet.Count() )
396 return FALSE;
398 ::std::auto_ptr<SwUndoFmtAttrHelper> pSaveUndo;
399 const bool bDoesUndo = DoesUndo();
401 if( DoesUndo() )
403 ClearRedo();
404 pSaveUndo.reset( new SwUndoFmtAttrHelper( rFlyFmt ) );
405 // --> FME 2004-10-13 #i32968#
406 // Inserting columns in the frame causes MakeFrmFmt to put two
407 // objects of type SwUndoFrmFmt on the undo stack. We don't want them.
408 DoUndo( FALSE );
409 // <--
412 //Ist das Ankerattribut dabei? Falls ja ueberlassen wir die Verarbeitung
413 //desselben einer Spezialmethode. Sie Returnt TRUE wenn der Fly neu
414 //erzeugt werden muss (z.B. weil ein Wechsel des FlyTyps vorliegt).
415 sal_Int8 nMakeFrms = SFX_ITEM_SET == rSet.GetItemState( RES_ANCHOR, FALSE )?
416 SetFlyFrmAnchor( rFlyFmt, rSet, FALSE ) : DONTMAKEFRMS;
418 const SfxPoolItem* pItem;
419 SfxItemIter aIter( rSet );
420 SfxItemSet aTmpSet( GetAttrPool(), aFrmFmtSetRange );
421 USHORT nWhich = aIter.GetCurItem()->Which();
422 do {
423 switch( nWhich )
425 case RES_FILL_ORDER:
426 case RES_BREAK:
427 case RES_PAGEDESC:
428 case RES_CNTNT:
429 case RES_FOOTER:
430 ASSERT( !this, ":-) Unbekanntes Attribut fuer Fly." );
431 // kein break;
432 case RES_CHAIN:
433 rSet.ClearItem( nWhich );
434 break;
435 case RES_ANCHOR:
436 if( DONTMAKEFRMS != nMakeFrms )
437 break;
439 default:
440 if( !IsInvalidItem( aIter.GetCurItem() ) && ( SFX_ITEM_SET !=
441 rFlyFmt.GetAttrSet().GetItemState( nWhich, TRUE, &pItem ) ||
442 *pItem != *aIter.GetCurItem() ))
443 aTmpSet.Put( *aIter.GetCurItem() );
444 break;
447 if( aIter.IsAtEnd() )
448 break;
450 } while( 0 != ( nWhich = aIter.NextItem()->Which() ) );
452 if( aTmpSet.Count() )
453 rFlyFmt.SetFmtAttr( aTmpSet );
455 if( MAKEFRMS == nMakeFrms )
456 rFlyFmt.MakeFrms();
458 if ( pSaveUndo.get() )
460 // --> FME 2004-10-13 #i32968#
461 DoUndo( bDoesUndo );
462 // <--
464 if ( pSaveUndo->GetUndo() )
466 AppendUndo( pSaveUndo->ReleaseUndo() );
470 SetModified();
472 return aTmpSet.Count() || MAKEFRMS == nMakeFrms;
475 // --> OD 2009-07-20 #i73249#
476 void SwDoc::SetFlyFrmTitle( SwFlyFrmFmt& rFlyFrmFmt,
477 const String& sNewTitle )
479 if ( rFlyFrmFmt.GetObjTitle() == sNewTitle )
481 return;
484 const bool bFormerIsNoDrawUndoObj( IsNoDrawUndoObj() );
485 SetNoDrawUndoObj( true );
487 if ( DoesUndo() )
489 ClearRedo();
490 AppendUndo( new SwUndoFlyStrAttr( rFlyFrmFmt,
491 UNDO_FLYFRMFMT_TITLE,
492 rFlyFrmFmt.GetObjTitle(),
493 sNewTitle ) );
496 rFlyFrmFmt.SetObjTitle( sNewTitle, true );
498 SetNoDrawUndoObj( bFormerIsNoDrawUndoObj );
500 SetModified();
503 void SwDoc::SetFlyFrmDescription( SwFlyFrmFmt& rFlyFrmFmt,
504 const String& sNewDescription )
506 if ( rFlyFrmFmt.GetObjDescription() == sNewDescription )
508 return;
511 const bool bFormerIsNoDrawUndoObj( IsNoDrawUndoObj() );
512 SetNoDrawUndoObj( true );
514 if ( DoesUndo() )
516 ClearRedo();
517 AppendUndo( new SwUndoFlyStrAttr( rFlyFrmFmt,
518 UNDO_FLYFRMFMT_DESCRIPTION,
519 rFlyFrmFmt.GetObjDescription(),
520 sNewDescription ) );
523 rFlyFrmFmt.SetObjDescription( sNewDescription, true );
525 SetNoDrawUndoObj( bFormerIsNoDrawUndoObj );
527 SetModified();
529 // <--
531 /***************************************************************************
532 * Methode : BOOL SwDoc::SetFrmFmtToFly( SwFlyFrm&, SwFrmFmt& )
533 * Beschreibung:
534 * Erstellt : OK 14.04.94 15:40
535 * Aenderung : JP 23.04.98
536 ***************************************************************************/
538 BOOL SwDoc::SetFrmFmtToFly( SwFrmFmt& rFmt, SwFrmFmt& rNewFmt,
539 SfxItemSet* pSet, BOOL bKeepOrient )
541 BOOL bChgAnchor = FALSE, bFrmSz = FALSE;
543 const SwFmtFrmSize aFrmSz( rFmt.GetFrmSize() );
544 const SwFmtVertOrient aVert( rFmt.GetVertOrient() );
545 const SwFmtHoriOrient aHori( rFmt.GetHoriOrient() );
547 SwUndoSetFlyFmt* pUndo = 0;
548 if( DoesUndo() )
550 ClearRedo();
551 AppendUndo( pUndo = new SwUndoSetFlyFmt( rFmt, rNewFmt ) );
552 // --> FME 2004-10-13 #i32968#
553 // Inserting columns in the section causes MakeFrmFmt to put two
554 // objects of type SwUndoFrmFmt on the undo stack. We don't want them.
555 DoUndo( FALSE );
556 // <--
559 //Erstmal die Spalten setzen, sonst gibts nix als Aerger mit dem
560 //Set/Reset/Abgleich usw.
561 const SfxPoolItem* pItem;
562 if( SFX_ITEM_SET != rNewFmt.GetAttrSet().GetItemState( RES_COL ))
563 rFmt.ResetFmtAttr( RES_COL );
565 if( rFmt.DerivedFrom() != &rNewFmt )
567 rFmt.SetDerivedFrom( &rNewFmt );
569 // 1. wenn nicht automatisch -> ignorieren, sonst -> wech
570 // 2. wech damit, MB!
571 if( SFX_ITEM_SET == rNewFmt.GetAttrSet().GetItemState( RES_FRM_SIZE, FALSE ))
573 rFmt.ResetFmtAttr( RES_FRM_SIZE );
574 bFrmSz = TRUE;
577 const SfxItemSet* pAsk = pSet;
578 if( !pAsk ) pAsk = &rNewFmt.GetAttrSet();
579 if( SFX_ITEM_SET == pAsk->GetItemState( RES_ANCHOR, FALSE, &pItem )
580 && ((SwFmtAnchor*)pItem)->GetAnchorId() !=
581 rFmt.GetAnchor().GetAnchorId() )
583 if( pSet )
584 bChgAnchor = MAKEFRMS == SetFlyFrmAnchor( rFmt, *pSet, FALSE );
585 else
587 //JP 23.04.98: muss den FlyFmt-Range haben, denn im SetFlyFrmAnchor
588 // werden Attribute in diesen gesetzt!
589 SfxItemSet aFlySet( *rNewFmt.GetAttrSet().GetPool(),
590 rNewFmt.GetAttrSet().GetRanges() );
591 aFlySet.Put( *pItem );
592 bChgAnchor = MAKEFRMS == SetFlyFrmAnchor( rFmt, aFlySet, FALSE);
597 //Hori und Vert nur dann resetten, wenn in der Vorlage eine
598 //automatische Ausrichtung eingestellt ist, anderfalls den alten Wert
599 //wieder hineinstopfen.
600 //JP 09.06.98: beim Update der RahmenVorlage sollte der Fly NICHT
601 // seine Orientierng verlieren (diese wird nicht geupdatet!)
602 //OS: #96584# text::HoriOrientation::NONE and text::VertOrientation::NONE are allowed now
603 if (!bKeepOrient)
605 rFmt.ResetFmtAttr(RES_VERT_ORIENT);
606 rFmt.ResetFmtAttr(RES_HORI_ORIENT);
609 rFmt.ResetFmtAttr( RES_PRINT, RES_SURROUND );
610 rFmt.ResetFmtAttr( RES_LR_SPACE, RES_UL_SPACE );
611 rFmt.ResetFmtAttr( RES_BACKGROUND, RES_COL );
612 rFmt.ResetFmtAttr( RES_URL, RES_EDIT_IN_READONLY );
614 if( !bFrmSz )
615 rFmt.SetFmtAttr( aFrmSz );
617 if( bChgAnchor )
618 rFmt.MakeFrms();
620 if( pUndo )
621 rFmt.Remove( pUndo );
623 SetModified();
625 // --> FME 2004-10-13 #i32968#
626 if ( pUndo )
627 DoUndo( TRUE );
628 // <--
630 return bChgAnchor;
633 void SwDoc::GetGrfNms( const SwFlyFrmFmt& rFmt, String* pGrfName,
634 String* pFltName ) const
636 SwNodeIndex aIdx( *rFmt.GetCntnt().GetCntntIdx(), 1 );
637 const SwGrfNode* pGrfNd = aIdx.GetNode().GetGrfNode();
638 if( pGrfNd && pGrfNd->IsLinkedFile() )
639 pGrfNd->GetFileFilterNms( pGrfName, pFltName );
642 /*************************************************************************
644 |* SwDoc::ChgAnchor()
646 |* Ersterstellung MA 10. Jan. 95
647 |* Letzte Aenderung JP 08.07.98
649 *************************************************************************/
651 sal_Bool SwDoc::ChgAnchor( const SdrMarkList& _rMrkList,
652 RndStdIds _eAnchorType,
653 const sal_Bool _bSameOnly,
654 const sal_Bool _bPosCorr )
656 ASSERT( GetRootFrm(), "Ohne Layout geht gar nichts" );
658 if ( !_rMrkList.GetMarkCount() ||
659 _rMrkList.GetMark( 0 )->GetMarkedSdrObj()->GetUpGroup() )
661 return false;
664 StartUndo( UNDO_INSATTR, NULL );
666 BOOL bUnmark = FALSE;
667 for ( USHORT i = 0; i < _rMrkList.GetMarkCount(); ++i )
669 SdrObject* pObj = _rMrkList.GetMark( i )->GetMarkedSdrObj();
670 if ( !pObj->ISA(SwVirtFlyDrawObj) )
672 SwDrawContact* pContact = static_cast<SwDrawContact*>(GetUserCall(pObj));
674 // OD 27.06.2003 #108784# - consider, that drawing object has
675 // no user call. E.g.: a 'virtual' drawing object is disconnected by
676 // the anchor type change of the 'master' drawing object.
677 // Continue with next selected object and assert, if this isn't excepted.
678 if ( !pContact )
680 #ifndef PRODUCT
681 bool bNoUserCallExcepted =
682 pObj->ISA(SwDrawVirtObj) &&
683 !static_cast<SwDrawVirtObj*>(pObj)->IsConnected();
684 ASSERT( bNoUserCallExcepted, "SwDoc::ChgAnchor(..) - no contact at selected drawing object" );
685 #endif
686 continue;
689 // OD 2004-03-29 #i26791#
690 const SwFrm* pOldAnchorFrm = pContact->GetAnchorFrm( pObj );
691 const SwFrm* pNewAnchorFrm = pOldAnchorFrm;
693 // --> OD 2006-03-01 #i54336#
694 // Instead of only keeping the index position for an as-character
695 // anchored object the complete <SwPosition> is kept, because the
696 // anchor index position could be moved, if the object again is
697 // anchored as character.
698 // xub_StrLen nIndx = STRING_NOTFOUND;
699 const SwPosition* pOldAsCharAnchorPos( 0L );
700 const RndStdIds eOldAnchorType = pContact->GetAnchorId();
701 if ( !_bSameOnly && eOldAnchorType == FLY_IN_CNTNT )
703 pOldAsCharAnchorPos = new SwPosition( pContact->GetCntntAnchor() );
705 // <--
707 if ( _bSameOnly )
708 _eAnchorType = eOldAnchorType;
710 SwFmtAnchor aNewAnch( _eAnchorType );
711 Rectangle aObjRect( pContact->GetAnchoredObj( pObj )->GetObjRect().SVRect() );
712 const Point aPt( aObjRect.TopLeft() );
714 switch ( _eAnchorType )
716 case FLY_AT_CNTNT:
717 case FLY_AUTO_CNTNT:
719 const Point aNewPoint = pOldAnchorFrm &&
720 ( pOldAnchorFrm->IsVertical() ||
721 pOldAnchorFrm->IsRightToLeft() )
722 ? aObjRect.TopRight()
723 : aPt;
725 // OD 18.06.2003 #108784# - allow drawing objects in header/footer
726 pNewAnchorFrm = ::FindAnchor( pOldAnchorFrm, aNewPoint, false );
727 if ( pNewAnchorFrm->IsTxtFrm() && ((SwTxtFrm*)pNewAnchorFrm)->IsFollow() )
729 pNewAnchorFrm = ((SwTxtFrm*)pNewAnchorFrm)->FindMaster();
731 if ( pNewAnchorFrm->IsProtected() )
733 pNewAnchorFrm = 0;
735 else
737 SwPosition aPos( *((SwCntntFrm*)pNewAnchorFrm)->GetNode() );
738 aNewAnch.SetType( _eAnchorType );
739 aNewAnch.SetAnchor( &aPos );
742 break;
744 case FLY_AT_FLY: // LAYER_IMPL
746 //Ausgehend von der linken oberen Ecke des Fly den
747 //dichtesten SwFlyFrm suchen.
748 SwFrm *pTxtFrm;
750 SwCrsrMoveState aState( MV_SETONLYTEXT );
751 SwPosition aPos( GetNodes() );
752 Point aPoint( aPt );
753 aPoint.X() -= 1;
754 GetRootFrm()->GetCrsrOfst( &aPos, aPoint, &aState );
755 // OD 20.06.2003 #108784# - consider that drawing objects
756 // can be in header/footer. Thus, <GetFrm()> by left-top-corner
757 pTxtFrm = aPos.nNode.GetNode().
758 GetCntntNode()->GetFrm( &aPt, 0, FALSE );
760 const SwFrm *pTmp = ::FindAnchor( pTxtFrm, aPt );
761 pNewAnchorFrm = pTmp->FindFlyFrm();
762 if( pNewAnchorFrm && !pNewAnchorFrm->IsProtected() )
764 const SwFrmFmt *pTmpFmt = ((SwFlyFrm*)pNewAnchorFrm)->GetFmt();
765 const SwFmtCntnt& rCntnt = pTmpFmt->GetCntnt();
766 SwPosition aPos( *rCntnt.GetCntntIdx() );
767 aNewAnch.SetAnchor( &aPos );
768 break;
771 aNewAnch.SetType( FLY_PAGE );
772 // no break
774 case FLY_PAGE:
776 pNewAnchorFrm = GetRootFrm()->Lower();
777 while ( pNewAnchorFrm && !pNewAnchorFrm->Frm().IsInside( aPt ) )
778 pNewAnchorFrm = pNewAnchorFrm->GetNext();
779 if ( !pNewAnchorFrm )
780 continue;
782 aNewAnch.SetPageNum( ((SwPageFrm*)pNewAnchorFrm)->GetPhyPageNum());
784 break;
785 case FLY_IN_CNTNT:
786 if( _bSameOnly ) // Positions/Groessenaenderung
788 if( !pOldAnchorFrm )
790 pContact->ConnectToLayout();
791 pOldAnchorFrm = pContact->GetAnchorFrm();
793 ((SwTxtFrm*)pOldAnchorFrm)->Prepare();
795 else // Ankerwechsel
797 // OD 18.06.2003 #108784# - allow drawing objects in header/footer
798 pNewAnchorFrm = ::FindAnchor( pOldAnchorFrm, aPt, false );
799 if( pNewAnchorFrm->IsProtected() )
801 pNewAnchorFrm = 0;
802 break;
805 bUnmark = ( 0 != i );
806 Point aPoint( aPt );
807 aPoint.X() -= 1; // nicht im DrawObj landen!!
808 aNewAnch.SetType( FLY_IN_CNTNT );
809 SwPosition aPos( *((SwCntntFrm*)pNewAnchorFrm)->GetNode() );
810 if ( pNewAnchorFrm->Frm().IsInside( aPoint ) )
812 // es muss ein TextNode gefunden werden, denn nur dort
813 // ist ein inhaltsgebundenes DrawObjekt zu verankern
814 SwCrsrMoveState aState( MV_SETONLYTEXT );
815 GetRootFrm()->GetCrsrOfst( &aPos, aPoint, &aState );
817 else
819 SwCntntNode &rCNd = (SwCntntNode&)
820 *((SwCntntFrm*)pNewAnchorFrm)->GetNode();
821 if ( pNewAnchorFrm->Frm().Bottom() < aPt.Y() )
822 rCNd.MakeStartIndex( &aPos.nContent );
823 else
824 rCNd.MakeEndIndex( &aPos.nContent );
826 aNewAnch.SetAnchor( &aPos );
827 SetAttr( aNewAnch, *pContact->GetFmt() );
828 // OD 2004-04-13 #i26791# - adjust vertical positioning to
829 // 'center to baseline'
830 SetAttr( SwFmtVertOrient( 0, text::VertOrientation::CENTER, text::RelOrientation::FRAME ), *pContact->GetFmt() );
831 SwTxtNode *pNd = aPos.nNode.GetNode().GetTxtNode();
832 ASSERT( pNd, "Cursor not positioned at TxtNode." );
834 SwFmtFlyCnt aFmt( pContact->GetFmt() );
835 pNd->InsertItem( aFmt, aPos.nContent.GetIndex(), 0 );
837 break;
838 default:
839 ASSERT( !this, "unexpected AnchorId." );
842 if ( (FLY_IN_CNTNT != _eAnchorType) &&
843 pNewAnchorFrm &&
844 ( !_bSameOnly || pNewAnchorFrm != pOldAnchorFrm ) )
846 // OD 2004-04-06 #i26791# - Direct object positioning no longer
847 // needed. Apply of attributes (method call <SetAttr(..)>) takes
848 // care of the invalidation of the object position.
849 SetAttr( aNewAnch, *pContact->GetFmt() );
850 if ( _bPosCorr )
852 // --> OD 2004-08-24 #i33313# - consider not connected
853 // 'virtual' drawing objects
854 if ( pObj->ISA(SwDrawVirtObj) &&
855 !static_cast<SwDrawVirtObj*>(pObj)->IsConnected() )
857 SwRect aNewObjRect( aObjRect );
858 static_cast<SwAnchoredDrawObject*>(pContact->GetAnchoredObj( 0L ))
859 ->AdjustPositioningAttr( pNewAnchorFrm,
860 &aNewObjRect );
863 else
865 static_cast<SwAnchoredDrawObject*>(pContact->GetAnchoredObj( pObj ))
866 ->AdjustPositioningAttr( pNewAnchorFrm );
871 // --> OD 2006-03-01 #i54336#
872 if ( pNewAnchorFrm && pOldAsCharAnchorPos )
874 //Bei InCntnt's wird es spannend: Das TxtAttribut muss vernichtet
875 //werden. Leider reisst dies neben den Frms auch noch das Format mit
876 //in sein Grab. Um dass zu unterbinden loesen wir vorher die
877 //Verbindung zwischen Attribut und Format.
878 const xub_StrLen nIndx( pOldAsCharAnchorPos->nContent.GetIndex() );
879 SwTxtNode* pTxtNode( pOldAsCharAnchorPos->nNode.GetNode().GetTxtNode() );
880 ASSERT( pTxtNode, "<SwDoc::ChgAnchor(..)> - missing previous anchor text node for as-character anchored object" );
881 ASSERT( pTxtNode->HasHints(), "Missing FlyInCnt-Hint." );
882 SwTxtAttr * const pHnt =
883 pTxtNode->GetTxtAttrForCharAt( nIndx, RES_TXTATR_FLYCNT );
884 const_cast<SwFmtFlyCnt&>(pHnt->GetFlyCnt()).SetFlyFmt();
886 //Die Verbindung ist geloest, jetzt muss noch das Attribut vernichtet
887 //werden.
888 pTxtNode->DeleteAttributes( RES_TXTATR_FLYCNT, nIndx, nIndx );
889 delete pOldAsCharAnchorPos;
891 // <--
895 EndUndo( UNDO_END, NULL );
896 SetModified();
898 return bUnmark;
902 /* -----------------23.07.98 13:56-------------------
904 * --------------------------------------------------*/
905 int SwDoc::Chainable( const SwFrmFmt &rSource, const SwFrmFmt &rDest )
907 //Die Source darf noch keinen Follow haben.
908 const SwFmtChain &rOldChain = rSource.GetChain();
909 if ( rOldChain.GetNext() )
910 return SW_CHAIN_SOURCE_CHAINED;
912 //Ziel darf natuerlich nicht gleich Source sein und es
913 //darf keine geschlossene Kette entstehen.
914 const SwFrmFmt *pFmt = &rDest;
915 do {
916 if( pFmt == &rSource )
917 return SW_CHAIN_SELF;
918 pFmt = pFmt->GetChain().GetNext();
919 } while ( pFmt );
921 //Auch eine Verkettung von Innen nach aussen oder von aussen
922 //nach innen ist nicht zulaessig.
923 if( rDest.IsLowerOf( rSource ) || rSource .IsLowerOf( rDest ) )
924 return SW_CHAIN_SELF;
926 //Das Ziel darf noch keinen Master haben.
927 const SwFmtChain &rChain = rDest.GetChain();
928 if( rChain.GetPrev() )
929 return SW_CHAIN_IS_IN_CHAIN;
931 //Das Ziel muss leer sein.
932 const SwNodeIndex* pCntIdx = rDest.GetCntnt().GetCntntIdx();
933 if( !pCntIdx )
934 return SW_CHAIN_NOT_FOUND;
936 SwNodeIndex aNxtIdx( *pCntIdx, 1 );
937 const SwTxtNode* pTxtNd = aNxtIdx.GetNode().GetTxtNode();
938 if( !pTxtNd )
939 return SW_CHAIN_NOT_FOUND;
941 const ULONG nFlySttNd = pCntIdx->GetIndex();
942 if( 2 != ( pCntIdx->GetNode().EndOfSectionIndex() - nFlySttNd ) ||
943 pTxtNd->GetTxt().Len() )
944 return SW_CHAIN_NOT_EMPTY;
946 USHORT nArrLen = GetSpzFrmFmts()->Count();
947 for( USHORT n = 0; n < nArrLen; ++n )
949 const SwFmtAnchor& rAnchor = (*GetSpzFrmFmts())[ n ]->GetAnchor();
950 ULONG nTstSttNd;
951 // OD 11.12.2003 #i20622# - to-frame anchored objects are allowed.
952 if ( ( rAnchor.GetAnchorId() == FLY_AT_CNTNT ||
953 rAnchor.GetAnchorId() == FLY_AUTO_CNTNT ) &&
954 0 != rAnchor.GetCntntAnchor() &&
955 nFlySttNd <= ( nTstSttNd =
956 rAnchor.GetCntntAnchor()->nNode.GetIndex() ) &&
957 nTstSttNd < nFlySttNd + 2 )
959 return SW_CHAIN_NOT_EMPTY;
963 //Auf die richtige Area muessen wir auch noch einen Blick werfen.
964 //Beide Flys muessen im selben Bereich (Body, Head/Foot, Fly) sitzen
965 //Wenn die Source nicht der selektierte Rahmen ist, so reicht es
966 //Wenn ein passender gefunden wird (Der Wunsch kann z.B. von der API
967 //kommen).
969 // both in the same fly, header, footer or on the page?
970 const SwFmtAnchor &rSrcAnchor = rSource.GetAnchor(),
971 &rDstAnchor = rDest.GetAnchor();
972 ULONG nEndOfExtras = GetNodes().GetEndOfExtras().GetIndex();
973 BOOL bAllowed = FALSE;
974 if( FLY_PAGE == rSrcAnchor.GetAnchorId() )
976 if( FLY_PAGE == rDstAnchor.GetAnchorId() ||
977 ( rDstAnchor.GetCntntAnchor() &&
978 rDstAnchor.GetCntntAnchor()->nNode.GetIndex() > nEndOfExtras ))
979 bAllowed = TRUE;
981 else if( rSrcAnchor.GetCntntAnchor() && rDstAnchor.GetCntntAnchor() )
983 const SwNodeIndex &rSrcIdx = rSrcAnchor.GetCntntAnchor()->nNode,
984 &rDstIdx = rDstAnchor.GetCntntAnchor()->nNode;
985 const SwStartNode* pSttNd = 0;
986 if( rSrcIdx == rDstIdx ||
987 ( !pSttNd &&
988 0 != ( pSttNd = rSrcIdx.GetNode().FindFlyStartNode() ) &&
989 pSttNd == rDstIdx.GetNode().FindFlyStartNode() ) ||
990 ( !pSttNd &&
991 0 != ( pSttNd = rSrcIdx.GetNode().FindFooterStartNode() ) &&
992 pSttNd == rDstIdx.GetNode().FindFooterStartNode() ) ||
993 ( !pSttNd &&
994 0 != ( pSttNd = rSrcIdx.GetNode().FindHeaderStartNode() ) &&
995 pSttNd == rDstIdx.GetNode().FindHeaderStartNode() ) ||
996 ( !pSttNd && rDstIdx.GetIndex() > nEndOfExtras &&
997 rSrcIdx.GetIndex() > nEndOfExtras ))
998 bAllowed = TRUE;
1001 return bAllowed ? SW_CHAIN_OK : SW_CHAIN_WRONG_AREA;
1003 /* -----------------23.07.98 13:56-------------------
1005 * --------------------------------------------------*/
1006 int SwDoc::Chain( SwFrmFmt &rSource, const SwFrmFmt &rDest )
1008 int nErr = Chainable( rSource, rDest );
1009 if ( !nErr )
1011 StartUndo( UNDO_CHAINE, NULL );
1013 SwFlyFrmFmt& rDestFmt = (SwFlyFrmFmt&)rDest;
1015 //Follow an den Master haengen.
1016 SwFmtChain aChain = rDestFmt.GetChain();
1017 aChain.SetPrev( &(SwFlyFrmFmt&)rSource );
1018 SetAttr( aChain, rDestFmt );
1020 SfxItemSet aSet( GetAttrPool(), RES_FRM_SIZE, RES_FRM_SIZE,
1021 RES_CHAIN, RES_CHAIN, 0 );
1023 //Follow an den Master haengen.
1024 aChain.SetPrev( &(SwFlyFrmFmt&)rSource );
1025 SetAttr( aChain, rDestFmt );
1027 //Master an den Follow haengen und dafuer sorgen, dass der Master
1028 //eine fixierte Hoehe hat.
1029 aChain = rSource.GetChain();
1030 aChain.SetNext( &rDestFmt );
1031 aSet.Put( aChain );
1033 SwFmtFrmSize aSize( rSource.GetFrmSize() );
1034 if ( aSize.GetHeightSizeType() != ATT_FIX_SIZE )
1036 SwClientIter aIter( rSource );
1037 SwFlyFrm *pFly = (SwFlyFrm*)aIter.First( TYPE(SwFlyFrm) );
1038 if ( pFly )
1039 aSize.SetHeight( pFly->Frm().Height() );
1040 aSize.SetHeightSizeType( ATT_FIX_SIZE );
1041 aSet.Put( aSize );
1043 SetAttr( aSet, rSource );
1045 EndUndo( UNDO_CHAINE, NULL );
1047 return nErr;
1049 /* -----------------23.07.98 13:56-------------------
1051 * --------------------------------------------------*/
1052 void SwDoc::Unchain( SwFrmFmt &rFmt )
1054 SwFmtChain aChain( rFmt.GetChain() );
1055 if ( aChain.GetNext() )
1057 StartUndo( UNDO_UNCHAIN, NULL );
1058 SwFrmFmt *pFollow = aChain.GetNext();
1059 aChain.SetNext( 0 );
1060 SetAttr( aChain, rFmt );
1061 aChain = pFollow->GetChain();
1062 aChain.SetPrev( 0 );
1063 SetAttr( aChain, *pFollow );
1064 EndUndo( UNDO_UNCHAIN, NULL );