xref: /AOO41X/main/sw/source/core/draw/dview.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sw.hxx"
30 
31 #include "hintids.hxx"
32 #include <editeng/protitem.hxx>
33 #include <svx/svdpagv.hxx>
34 #include <svx/fmmodel.hxx>
35 #include <sot/exchange.hxx>
36 
37 #include "swtypes.hxx"
38 #include "pagefrm.hxx"
39 #include "rootfrm.hxx"
40 #include "cntfrm.hxx"
41 #include "flyfrm.hxx"
42 #include "frmfmt.hxx"
43 #include "dflyobj.hxx"
44 #include "dcontact.hxx"
45 #include "frmatr.hxx"
46 #include "viewsh.hxx"
47 #include "viewimp.hxx"
48 #include "dview.hxx"
49 #include "dpage.hxx"
50 #include "doc.hxx"
51 #include "mdiexp.hxx"
52 #include <ndole.hxx>
53 #include <fmtanchr.hxx>
54 #include "shellres.hxx"
55 #include <IDocumentUndoRedo.hxx>
56 
57 // #i7672#
58 #include <editeng/outliner.hxx>
59 
60 #include <com/sun/star/embed/EmbedMisc.hpp>
61 
62 // OD 18.06.2003 #108784#
63 //#ifndef _SVDVMARK_HXX //autogen
64 //#include <svx/svdvmark.hxx>
65 //#endif
66 #include <vector>
67 // --> OD 2004-06-24 #i28701#
68 #include <sortedobjs.hxx>
69 #include <flyfrms.hxx>
70 // <--
71 
72 
73 using namespace com::sun::star;
74 
75 
76 class SwSdrHdl : public SdrHdl
77 {
78 public:
79     SwSdrHdl(const Point& rPnt, bool bTopRight ) :
80         SdrHdl( rPnt, bTopRight ? HDL_ANCHOR_TR : HDL_ANCHOR ) {}
81     virtual sal_Bool IsFocusHdl() const;
82 };
83 
84 sal_Bool SwSdrHdl::IsFocusHdl() const
85 {
86     if( HDL_ANCHOR == eKind || HDL_ANCHOR_TR == eKind )
87         return sal_True;
88     return SdrHdl::IsFocusHdl();
89 }
90 
91 const SwFrm *lcl_FindAnchor( const SdrObject *pObj, sal_Bool bAll )
92 {
93 	const SwVirtFlyDrawObj *pVirt = pObj->ISA(SwVirtFlyDrawObj) ?
94 											(SwVirtFlyDrawObj*)pObj : 0;
95 	if ( pVirt )
96 	{
97 		if ( bAll || !pVirt->GetFlyFrm()->IsFlyInCntFrm() )
98             return pVirt->GetFlyFrm()->GetAnchorFrm();
99 	}
100 	else
101 	{
102         const SwDrawContact *pCont = (const SwDrawContact*)GetUserCall(pObj);
103 		if ( pCont )
104             return pCont->GetAnchorFrm( pObj );
105 	}
106 	return 0;
107 }
108 
109 /*************************************************************************
110 |*
111 |*	SwDrawView::Ctor
112 |*
113 |*	Ersterstellung		OK 18.11.94
114 |*	Letzte Aenderung	MA 22. Jul. 96
115 |*
116 *************************************************************************/
117 
118 
119 
120 SwDrawView::SwDrawView( SwViewImp &rI, SdrModel *pMd, OutputDevice *pOutDev) :
121 	FmFormView( (FmFormModel*)pMd, pOutDev ),
122 	rImp( rI )
123 {
124 	SetPageVisible( sal_False );
125 	SetBordVisible( sal_False );
126 	SetGridVisible( sal_False );
127 	SetHlplVisible( sal_False );
128 	SetGlueVisible( sal_False );
129 	SetFrameDragSingles( sal_True );
130 	SetVirtualObjectBundling( sal_True );
131 	SetSwapAsynchron( sal_True );
132 
133 	EnableExtendedKeyInputDispatcher( sal_False );
134 	EnableExtendedMouseEventDispatcher( sal_False );
135 	EnableExtendedCommandEventDispatcher( sal_False );
136 
137 	SetHitTolerancePixel( GetMarkHdlSizePixel()/2 );
138 
139 	SetPrintPreview( rI.GetShell()->IsPreView() );
140 
141 	// #i73602# Use default from the configuration
142 	SetBufferedOverlayAllowed(getOptionsDrawinglayer().IsOverlayBuffer_Writer());
143 
144 	// #i74769#, #i75172# Use default from the configuration
145 	SetBufferedOutputAllowed(getOptionsDrawinglayer().IsPaintBuffer_Writer());
146 }
147 
148 // --> OD 2009-03-05 #i99665#
149 sal_Bool SwDrawView::IsAntiAliasing() const
150 {
151     return getOptionsDrawinglayer().IsAntiAliasing();
152 }
153 // <--
154 
155 //////////////////////////////////////////////////////////////////////////////
156 
157 SdrObject* impLocalHitCorrection(SdrObject* pRetval, const Point& rPnt, sal_uInt16 nTol, const SdrMarkList &rMrkList)
158 {
159     if(!nTol)
160     {
161         // the old method forced back to outer bounds test when nTol == 0, so
162         // do not try to correct when nTol is not set (used from HelpContent)
163     }
164     else
165     {
166         // rebuild logic from former SwVirtFlyDrawObj::CheckSdrObjectHit. This is needed since
167         // the SdrObject-specific CheckHit implementations are now replaced with primitives and
168         // 'tricks' like in the old implementation (e.g. using a view from a model-data class to
169         // detect if object is selected) are no longer valid.
170         // The standard primitive hit-test for SwVirtFlyDrawObj now is the outer bound. The old
171         // implementation reduced this excluding the inner bound when the object was not selected.
172         SwVirtFlyDrawObj* pSwVirtFlyDrawObj = dynamic_cast< SwVirtFlyDrawObj* >(pRetval);
173 
174         if(pSwVirtFlyDrawObj)
175         {
176             if(pSwVirtFlyDrawObj->GetFlyFrm()->Lower() && pSwVirtFlyDrawObj->GetFlyFrm()->Lower()->IsNoTxtFrm())
177 			{
178                 // the old method used IsNoTxtFrm (should be for SW's own OLE and
179                 // graphic's) to accept hit only based on outer bounds; nothing to do
180             }
181             else
182             {
183                 // check if the object is selected in this view
184                 const sal_uInt32 nMarkCount(rMrkList.GetMarkCount());
185                 bool bSelected(false);
186 
187                 for(sal_uInt32 a(0); !bSelected && a < nMarkCount; a++)
188                 {
189                     if(pSwVirtFlyDrawObj == rMrkList.GetMark(a)->GetMarkedSdrObj())
190                     {
191                         bSelected = true;
192                     }
193                 }
194 
195                 if(!bSelected)
196                 {
197                     // when not selected, the object is not hit when hit position is inside
198                     // inner range. Get and shrink inner range
199                     basegfx::B2DRange aInnerBound(pSwVirtFlyDrawObj->getInnerBound());
200 
201                     aInnerBound.grow(-1.0 * nTol);
202 
203                     if(aInnerBound.isInside(basegfx::B2DPoint(rPnt.X(), rPnt.Y())))
204                     {
205                         // exclude this hit
206                         pRetval = 0;
207                     }
208                 }
209             }
210         }
211     }
212 
213     return pRetval;
214 }
215 
216 SdrObject* SwDrawView::CheckSingleSdrObjectHit(const Point& rPnt, sal_uInt16 nTol, SdrObject* pObj, SdrPageView* pPV, sal_uLong nOptions, const SetOfByte* pMVisLay) const
217 {
218     // call parent
219     SdrObject* pRetval = FmFormView::CheckSingleSdrObjectHit(rPnt, nTol, pObj, pPV, nOptions, pMVisLay);
220 
221     if(pRetval)
222     {
223         // overloaded to allow extra handling when picking SwVirtFlyDrawObj's
224         pRetval = impLocalHitCorrection(pRetval, rPnt, nTol, GetMarkedObjectList());
225     }
226 
227     return pRetval;
228 }
229 
230 /*************************************************************************
231 |*
232 |*	SwDrawView::AddCustomHdl()
233 |*
234 |*  Gets called every time the handles need to be build
235 |*
236 |*	Ersterstellung		AW 06. Sep. 99
237 |*	Letzte Aenderung	AW 06. Sep. 99
238 |*
239 *************************************************************************/
240 
241 void SwDrawView::AddCustomHdl()
242 {
243 	const SdrMarkList &rMrkList = GetMarkedObjectList();
244 
245 	if(rMrkList.GetMarkCount() != 1 || !GetUserCall(rMrkList.GetMark( 0 )->GetMarkedSdrObj()))
246 		return;
247 
248 	SdrObject *pObj = rMrkList.GetMark(0)->GetMarkedSdrObj();
249     // --> OD 2006-11-06 #130889# - make code robust
250 //    const SwFmtAnchor &rAnchor = ::FindFrmFmt(pObj)->GetAnchor();
251     SwFrmFmt* pFrmFmt( ::FindFrmFmt( pObj ) );
252     if ( !pFrmFmt )
253     {
254         ASSERT( false, "<SwDrawView::AddCustomHdl()> - missing frame format!" );
255         return;
256     }
257     const SwFmtAnchor &rAnchor = pFrmFmt->GetAnchor();
258     // <--
259 
260     if (FLY_AS_CHAR == rAnchor.GetAnchorId())
261 		return;
262 
263 	const SwFrm* pAnch;
264 	if(0 == (pAnch = CalcAnchor()))
265 		return;
266 
267     Point aPos(aAnchorPoint);
268 
269     if ( FLY_AT_CHAR == rAnchor.GetAnchorId() )
270 	{
271         // --> OD 2004-06-24 #i28701# - use last character rectangle saved at object
272         // in order to avoid a format of the anchor frame
273         SwAnchoredObject* pAnchoredObj = ::GetUserCall( pObj )->GetAnchoredObj( pObj );
274         SwRect aAutoPos = pAnchoredObj->GetLastCharRect();
275         if ( aAutoPos.Height() )
276         {
277             aPos = aAutoPos.Pos();
278         }
279 	}
280 
281 	// add anchor handle:
282     //Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
283     aHdl.AddHdl( new SwSdrHdl( aPos, ( pAnch->IsVertical() && !pAnch->IsVertLR() ) ||
284                                      pAnch->IsRightToLeft() ) );
285 }
286 
287 /*************************************************************************
288 |*
289 |*	SwDrawView::GetMaxToTopObj(), _GetMaxToTopObj()
290 |*
291 |*	Ersterstellung		MA 13. Jan. 95
292 |*	Letzte Aenderung	MA 18. Mar. 97
293 |*
294 *************************************************************************/
295 
296 
297 SdrObject* SwDrawView::GetMaxToTopObj( SdrObject* pObj ) const
298 {
299 	if ( GetUserCall(pObj) )
300 	{
301 		const SwFrm *pAnch = ::lcl_FindAnchor( pObj, sal_False );
302 		if ( pAnch )
303 		{
304 			//Das oberste Obj innerhalb des Ankers darf nicht ueberholt
305 			//werden.
306 			const SwFlyFrm *pFly = pAnch->FindFlyFrm();
307 			if ( pFly )
308 			{
309 				const SwPageFrm *pPage = pFly->FindPageFrm();
310 				if ( pPage->GetSortedObjs() )
311 				{
312 					sal_uInt32 nOrdNum = 0;
313 					for ( sal_uInt16 i = 0; i < pPage->GetSortedObjs()->Count(); ++i )
314 					{
315                         const SdrObject *pO =
316                                     (*pPage->GetSortedObjs())[i]->GetDrawObj();
317 
318                         if ( pO->GetOrdNumDirect() > nOrdNum )
319 						{
320                             const SwFrm *pTmpAnch = ::lcl_FindAnchor( pO, sal_False );
321                             if ( pFly->IsAnLower( pTmpAnch ) )
322 							{
323 								nOrdNum = pO->GetOrdNumDirect();
324 							}
325 						}
326 					}
327 					if ( nOrdNum )
328 					{
329                         SdrPage *pTmpPage = GetModel()->GetPage( 0 );
330 						++nOrdNum;
331                         if ( nOrdNum < pTmpPage->GetObjCount() )
332 						{
333                             return pTmpPage->GetObj( nOrdNum );
334 						}
335 					}
336 				}
337 			}
338 		}
339 	}
340 	return 0;
341 }
342 
343 /*************************************************************************
344 |*
345 |*	SwDrawView::GetMaxToBtmObj()
346 |*
347 |*	Ersterstellung		MA 13. Jan. 95
348 |*	Letzte Aenderung	MA 05. Sep. 96
349 |*
350 *************************************************************************/
351 
352 
353 SdrObject* SwDrawView::GetMaxToBtmObj(SdrObject* pObj) const
354 {
355 	if ( GetUserCall(pObj) )
356 	{
357 		const SwFrm *pAnch = ::lcl_FindAnchor( pObj, sal_False );
358 		if ( pAnch )
359 		{
360 			//Der Fly des Ankers darf nicht "unterflogen" werden.
361 			const SwFlyFrm *pFly = pAnch->FindFlyFrm();
362 			if ( pFly )
363 			{
364 				SdrObject *pRet = (SdrObject*)pFly->GetVirtDrawObj();
365 				return pRet != pObj ? pRet : 0;
366 			}
367 		}
368 	}
369 	return 0;
370 }
371 
372 /*************************************************************************
373 |*
374 |*	SwDrawView::ObjOrderChanged()
375 |*
376 |*	Ersterstellung		MA 31. Jul. 95
377 |*	Letzte Aenderung	MA 18. Mar. 97
378 |*
379 *************************************************************************/
380 
381 inline sal_Bool lcl_IsChild( SdrObject *pParent, SdrObject *pChild )
382 {
383 	if ( pParent->ISA(SwVirtFlyDrawObj) )
384 	{
385 		const SwFrm *pAnch = lcl_FindAnchor( pChild, sal_False );
386 		if ( pAnch && ((SwVirtFlyDrawObj*)pParent)->GetFlyFrm()->IsAnLower( pAnch ))
387 		{
388 			return sal_True;
389 		}
390 	}
391 	return sal_False;
392 }
393 
394 inline SdrObject *lcl_FindParent( SdrObject *pObj )
395 {
396 	const SwFrm *pAnch = lcl_FindAnchor( pObj, sal_False );
397 	if ( pAnch && pAnch->IsInFly() )
398 		return (SdrObject*)pAnch->FindFlyFrm()->GetVirtDrawObj();
399 	return 0;
400 }
401 
402 /** determine maximal order number for a 'child' object of given 'parent' object
403 
404     OD 2004-08-20 #110810#
405 
406     @author OD
407 */
408 sal_uInt32 SwDrawView::_GetMaxChildOrdNum( const SwFlyFrm& _rParentObj,
409                                            const SdrObject* _pExclChildObj ) const
410 {
411     sal_uInt32 nMaxChildOrdNum = _rParentObj.GetDrawObj()->GetOrdNum();
412 
413     const SdrPage* pDrawPage = _rParentObj.GetDrawObj()->GetPage();
414     ASSERT( pDrawPage,
415             "<SwDrawView::_GetMaxChildOrdNum(..) - missing drawing page at parent object - crash!" );
416 
417     sal_uInt32 nObjCount = pDrawPage->GetObjCount();
418     for ( sal_uInt32 i = nObjCount-1; i > _rParentObj.GetDrawObj()->GetOrdNum() ; --i )
419     {
420         const SdrObject* pObj = pDrawPage->GetObj( i );
421 
422         // Don't consider 'child' object <_pExclChildObj>
423         if ( pObj == _pExclChildObj )
424         {
425             continue;
426         }
427 
428         if ( pObj->GetOrdNum() > nMaxChildOrdNum &&
429              _rParentObj.IsAnLower( lcl_FindAnchor( pObj, sal_True ) ) )
430         {
431             nMaxChildOrdNum = pObj->GetOrdNum();
432             break;
433         }
434     }
435 
436     return nMaxChildOrdNum;
437 }
438 
439 /** method to move 'repeated' objects of the given moved object to the
440     according level
441 
442     OD 2004-08-23 #110810#
443 
444     @author OD
445 */
446 void SwDrawView::_MoveRepeatedObjs( const SwAnchoredObject& _rMovedAnchoredObj,
447                                     const std::vector<SdrObject*>& _rMovedChildObjs ) const
448 {
449     // determine 'repeated' objects of already moved object <_rMovedAnchoredObj>
450     std::list<SwAnchoredObject*> aAnchoredObjs;
451     {
452         const SwContact* pContact = ::GetUserCall( _rMovedAnchoredObj.GetDrawObj() );
453         ASSERT( pContact,
454                 "SwDrawView::_MoveRepeatedObjs(..) - missing contact object -> crash." );
455         pContact->GetAnchoredObjs( aAnchoredObjs );
456     }
457 
458     // check, if 'repeated' objects exists.
459     if ( aAnchoredObjs.size() > 1 )
460     {
461         SdrPage* pDrawPage = GetModel()->GetPage( 0 );
462 
463         // move 'repeated' ones to the same order number as the already moved one.
464         sal_uInt32 nNewPos = _rMovedAnchoredObj.GetDrawObj()->GetOrdNum();
465         while ( !aAnchoredObjs.empty() )
466         {
467             SwAnchoredObject* pAnchoredObj = aAnchoredObjs.back();
468             if ( pAnchoredObj != &_rMovedAnchoredObj )
469             {
470                 pDrawPage->SetObjectOrdNum( pAnchoredObj->GetDrawObj()->GetOrdNum(),
471                                             nNewPos );
472                 pDrawPage->RecalcObjOrdNums();
473                 // adjustments for accessibility API
474                 if ( pAnchoredObj->ISA(SwFlyFrm) )
475                 {
476                     const SwFlyFrm *pTmpFlyFrm = static_cast<SwFlyFrm*>(pAnchoredObj);
477                     rImp.DisposeAccessibleFrm( pTmpFlyFrm );
478                     rImp.AddAccessibleFrm( pTmpFlyFrm );
479                 }
480                 else
481                 {
482                     rImp.DisposeAccessibleObj( pAnchoredObj->GetDrawObj() );
483                     rImp.AddAccessibleObj( pAnchoredObj->GetDrawObj() );
484                 }
485             }
486             aAnchoredObjs.pop_back();
487         }
488 
489         // move 'repeated' ones of 'child' objects
490         for ( std::vector<SdrObject*>::const_iterator aObjIter = _rMovedChildObjs.begin();
491               aObjIter != _rMovedChildObjs.end(); ++aObjIter )
492         {
493             SdrObject* pChildObj = (*aObjIter);
494             {
495                 const SwContact* pContact = ::GetUserCall( pChildObj );
496                 ASSERT( pContact,
497                         "SwDrawView::_MoveRepeatedObjs(..) - missing contact object -> crash." );
498                 pContact->GetAnchoredObjs( aAnchoredObjs );
499             }
500             // move 'repeated' ones to the same order number as the already moved one.
501             const sal_uInt32 nTmpNewPos = pChildObj->GetOrdNum();
502             while ( !aAnchoredObjs.empty() )
503             {
504                 SwAnchoredObject* pAnchoredObj = aAnchoredObjs.back();
505                 if ( pAnchoredObj->GetDrawObj() != pChildObj )
506                 {
507                     pDrawPage->SetObjectOrdNum( pAnchoredObj->GetDrawObj()->GetOrdNum(),
508                                                 nTmpNewPos );
509                     pDrawPage->RecalcObjOrdNums();
510                     // adjustments for accessibility API
511                     if ( pAnchoredObj->ISA(SwFlyFrm) )
512                     {
513                         const SwFlyFrm *pTmpFlyFrm = static_cast<SwFlyFrm*>(pAnchoredObj);
514                         rImp.DisposeAccessibleFrm( pTmpFlyFrm );
515                         rImp.AddAccessibleFrm( pTmpFlyFrm );
516                     }
517                     else
518                     {
519                         rImp.DisposeAccessibleObj( pAnchoredObj->GetDrawObj() );
520                         rImp.AddAccessibleObj( pAnchoredObj->GetDrawObj() );
521                     }
522                 }
523                 aAnchoredObjs.pop_back();
524             }
525         }
526     }
527 }
528 
529 // --> OD 2004-08-20 #110810# - adjustment and re-factoring of method
530 void SwDrawView::ObjOrderChanged( SdrObject* pObj, sal_uLong nOldPos,
531 										  sal_uLong nNewPos )
532 {
533     // --> OD 2004-08-17 #110810# - nothing to do for group members
534     if ( pObj->GetUpGroup() )
535     {
536         return;
537     }
538     // <--
539 
540     // determine drawing page and assure that the order numbers are correct.
541     SdrPage* pDrawPage = GetModel()->GetPage( 0 );
542     if ( pDrawPage->IsObjOrdNumsDirty() )
543         pDrawPage->RecalcObjOrdNums();
544     const sal_uInt32 nObjCount = pDrawPage->GetObjCount();
545 
546     SwAnchoredObject* pMovedAnchoredObj =
547                                 ::GetUserCall( pObj )->GetAnchoredObj( pObj );
548     const SwFlyFrm* pParentAnchoredObj =
549                                 pMovedAnchoredObj->GetAnchorFrm()->FindFlyFrm();
550 
551     const bool bMovedForward = nOldPos < nNewPos;
552 
553     // assure for a 'child' object, that it doesn't exceed the limits of its 'parent'
554     if ( pParentAnchoredObj )
555     {
556         if ( bMovedForward )
557         {
558             sal_uInt32 nMaxChildOrdNumWithoutMoved =
559                     _GetMaxChildOrdNum( *pParentAnchoredObj, pMovedAnchoredObj->GetDrawObj() );
560             if ( nNewPos > nMaxChildOrdNumWithoutMoved+1 )
561             {
562                 // set position to the top of the 'child' object group
563                 pDrawPage->SetObjectOrdNum( nNewPos, nMaxChildOrdNumWithoutMoved+1 );
564                 nNewPos = nMaxChildOrdNumWithoutMoved+1;
565             }
566         }
567         else
568         {
569             const sal_uInt32 nParentOrdNum = pParentAnchoredObj->GetDrawObj()->GetOrdNum();
570             if ( nNewPos < nParentOrdNum )
571             {
572                 // set position to the bottom of the 'child' object group
573                 pDrawPage->SetObjectOrdNum( nNewPos, nParentOrdNum );
574                 nNewPos = nParentOrdNum;
575             }
576         }
577         if ( pDrawPage->IsObjOrdNumsDirty() )
578             pDrawPage->RecalcObjOrdNums();
579     }
580 
581     // Assure, that object isn't positioned between 'repeated' ones
582     if ( ( bMovedForward && nNewPos < nObjCount - 1 ) ||
583          ( !bMovedForward && nNewPos > 0 ) )
584     {
585         const SdrObject* pTmpObj =
586                 pDrawPage->GetObj( bMovedForward ? nNewPos - 1 : nNewPos + 1 );
587         if ( pTmpObj )
588         {
589             sal_uInt32 nTmpNewPos( nNewPos );
590             if ( bMovedForward )
591             {
592                 // move before the top 'repeated' object
593                 const sal_uInt32 nTmpMaxOrdNum =
594                                     ::GetUserCall( pTmpObj )->GetMaxOrdNum();
595                 if ( nTmpMaxOrdNum > nNewPos )
596                     nTmpNewPos = nTmpMaxOrdNum;
597             }
598             else
599             {
600                 // move behind the bottom 'repeated' object
601                 const sal_uInt32 nTmpMinOrdNum =
602                                     ::GetUserCall( pTmpObj )->GetMinOrdNum();
603                 if ( nTmpMinOrdNum < nNewPos )
604                     nTmpNewPos = nTmpMinOrdNum;
605             }
606             if ( nTmpNewPos != nNewPos )
607             {
608                 pDrawPage->SetObjectOrdNum( nNewPos, nTmpNewPos );
609                 nNewPos = nTmpNewPos;
610                 pDrawPage->RecalcObjOrdNums();
611             }
612         }
613     }
614 
615     // On move forward, assure that object is moved before its own childs.
616     // Only Writer fly frames can have childs.
617     if ( pMovedAnchoredObj->ISA(SwFlyFrm) &&
618          bMovedForward && nNewPos < nObjCount - 1 )
619     {
620         sal_uInt32 nMaxChildOrdNum =
621                     _GetMaxChildOrdNum( *(static_cast<const SwFlyFrm*>(pMovedAnchoredObj)) );
622         if ( nNewPos < nMaxChildOrdNum )
623         {
624             // determine position before the object before its top 'child' object
625             const SdrObject* pTmpObj = pDrawPage->GetObj( nMaxChildOrdNum );
626             sal_uInt32 nTmpNewPos = ::GetUserCall( pTmpObj )->GetMaxOrdNum() + 1;
627             if ( nTmpNewPos >= nObjCount )
628             {
629                 --nTmpNewPos;
630             }
631             // assure, that determined position isn't between 'repeated' objects
632             pTmpObj = pDrawPage->GetObj( nTmpNewPos );
633             nTmpNewPos = ::GetUserCall( pTmpObj )->GetMaxOrdNum();
634             // apply new position
635             pDrawPage->SetObjectOrdNum( nNewPos, nTmpNewPos );
636             nNewPos = nTmpNewPos;
637             pDrawPage->RecalcObjOrdNums();
638         }
639     }
640 
641     // Assure, that object isn't positioned between nested objects
642     if ( ( bMovedForward && nNewPos < nObjCount - 1 ) ||
643          ( !bMovedForward && nNewPos > 0 ) )
644     {
645         sal_uInt32 nTmpNewPos( nNewPos );
646         const SwFrmFmt* pParentFrmFmt =
647                 pParentAnchoredObj ? &(pParentAnchoredObj->GetFrmFmt()) : 0L;
648         const SdrObject* pTmpObj = pDrawPage->GetObj( nNewPos + 1 );
649         while ( pTmpObj )
650         {
651             // --> OD 2004-12-07 #i38563# - assure, that anchor frame exists.
652             // If object is anchored inside a invisible part of the document
653             // (e.g. page header, whose page style isn't applied, or hidden
654             // section), no anchor frame exists.
655             const SwFrm* pTmpAnchorFrm = lcl_FindAnchor( pTmpObj, sal_True );
656             const SwFlyFrm* pTmpParentObj = pTmpAnchorFrm
657                                             ? pTmpAnchorFrm->FindFlyFrm() : 0L;
658             // <--
659             if ( pTmpParentObj &&
660                  &(pTmpParentObj->GetFrmFmt()) != pParentFrmFmt )
661             {
662                 if ( bMovedForward )
663                 {
664                     nTmpNewPos = ::GetUserCall( pTmpObj )->GetMaxOrdNum();
665                     pTmpObj = pDrawPage->GetObj( nTmpNewPos + 1 );
666                 }
667                 else
668                 {
669                     nTmpNewPos = ::GetUserCall( pTmpParentObj->GetDrawObj() )
670                                                             ->GetMinOrdNum();
671                     pTmpObj = pTmpParentObj->GetDrawObj();
672                 }
673             }
674             else
675                 break;
676         }
677         if ( nTmpNewPos != nNewPos )
678         {
679             pDrawPage->SetObjectOrdNum( nNewPos, nTmpNewPos );
680             nNewPos = nTmpNewPos;
681             pDrawPage->RecalcObjOrdNums();
682         }
683     }
684 
685     // setup collection of moved 'child' objects to move its 'repeated' objects.
686     std::vector< SdrObject* > aMovedChildObjs;
687 
688     // move 'childs' accordingly
689     if ( pMovedAnchoredObj->ISA(SwFlyFrm) )
690     {
691         const SwFlyFrm* pFlyFrm = static_cast<SwFlyFrm*>(pMovedAnchoredObj);
692 
693         // adjustments for accessibility API
694         rImp.DisposeAccessibleFrm( pFlyFrm );
695         rImp.AddAccessibleFrm( pFlyFrm );
696 
697         const sal_uInt32 nChildNewPos = bMovedForward ? nNewPos : nNewPos+1;
698         sal_uInt32 i = bMovedForward ? nOldPos : nObjCount-1;
699         do
700         {
701             SdrObject* pTmpObj = pDrawPage->GetObj( i );
702             if ( pTmpObj == pObj )
703                 break;
704 
705             // --> OD 2004-12-07 #i38563# - assure, that anchor frame exists.
706             // If object is anchored inside a invisible part of the document
707             // (e.g. page header, whose page style isn't applied, or hidden
708             // section), no anchor frame exists.
709             const SwFrm* pTmpAnchorFrm = lcl_FindAnchor( pTmpObj, sal_True );
710             const SwFlyFrm* pTmpParentObj = pTmpAnchorFrm
711                                             ? pTmpAnchorFrm->FindFlyFrm() : 0L;
712             // <--
713             if ( pTmpParentObj &&
714                  ( ( pTmpParentObj == pFlyFrm ) ||
715                    ( pFlyFrm->IsUpperOf( *pTmpParentObj ) ) ) )
716             {
717                 // move child object.,
718                 pDrawPage->SetObjectOrdNum( i, nChildNewPos );
719                 pDrawPage->RecalcObjOrdNums();
720                 // collect 'child' object
721                 aMovedChildObjs.push_back( pTmpObj );
722                 // adjustments for accessibility API
723                 if ( pTmpObj->ISA(SwVirtFlyDrawObj) )
724                 {
725                     const SwFlyFrm *pTmpFlyFrm =
726                         static_cast<SwVirtFlyDrawObj*>(pTmpObj)->GetFlyFrm();
727                     rImp.DisposeAccessibleFrm( pTmpFlyFrm );
728                     rImp.AddAccessibleFrm( pTmpFlyFrm );
729                 }
730                 else
731                 {
732                     rImp.DisposeAccessibleObj( pTmpObj );
733                     rImp.AddAccessibleObj( pTmpObj );
734                 }
735             }
736             else
737             {
738                 // adjust loop counter
739                 if ( bMovedForward )
740                     ++i;
741                 else if ( !bMovedForward && i > 0 )
742                     --i;
743             }
744 
745         } while ( ( bMovedForward && i < ( nObjCount - aMovedChildObjs.size() ) ) ||
746                   ( !bMovedForward && i > ( nNewPos + aMovedChildObjs.size() ) ) );
747     }
748 	else
749 	{
750         // adjustments for accessibility API
751 		rImp.DisposeAccessibleObj( pObj );
752 		rImp.AddAccessibleObj( pObj );
753 	}
754 
755     _MoveRepeatedObjs( *pMovedAnchoredObj, aMovedChildObjs );
756 }
757 // <--
758 
759 /*************************************************************************
760 |*
761 |*	SwDrawView::TakeDragLimit()
762 |*
763 |*	Ersterstellung		AMA 26. Apr. 96
764 |*	Letzte Aenderung	MA 03. May. 96
765 |*
766 *************************************************************************/
767 
768 
769 sal_Bool SwDrawView::TakeDragLimit( SdrDragMode eMode,
770 											Rectangle& rRect ) const
771 {
772 	const SdrMarkList &rMrkList = GetMarkedObjectList();
773 	sal_Bool bRet = sal_False;
774 	if( 1 == rMrkList.GetMarkCount() )
775 	{
776 		const SdrObject *pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
777 		SwRect aRect;
778 		if( ::CalcClipRect( pObj, aRect, eMode == SDRDRAG_MOVE ) )
779 		{
780 			rRect = aRect.SVRect();
781 		 	bRet = sal_True;
782 		}
783 	}
784 	return bRet;
785 }
786 
787 /*************************************************************************
788 |*
789 |*	SwDrawView::CalcAnchor()
790 |*
791 |*	Ersterstellung		MA 13. Jan. 95
792 |*	Letzte Aenderung	MA 08. Nov. 96
793 |*
794 *************************************************************************/
795 
796 
797 const SwFrm* SwDrawView::CalcAnchor()
798 {
799 	const SdrMarkList &rMrkList = GetMarkedObjectList();
800 	if ( rMrkList.GetMarkCount() != 1 )
801 		return NULL;
802 
803     SdrObject* pObj = rMrkList.GetMark( 0 )->GetMarkedSdrObj();
804 
805 	//Fuer Absatzgebundene Objekte suchen, andernfalls einfach nur
806 	//der aktuelle Anker. Nur suchen wenn wir gerade draggen.
807     const SwFrm* pAnch;
808     Rectangle aMyRect;
809 	const sal_Bool bFly = pObj->ISA(SwVirtFlyDrawObj);
810 	if ( bFly )
811 	{
812         pAnch = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm()->GetAnchorFrm();
813         aMyRect = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm()->Frm().SVRect();
814 	}
815 	else
816 	{
817         SwDrawContact *pC = (SwDrawContact*)GetUserCall(pObj);
818         // OD 17.06.2003 #108784# - determine correct anchor position for
819         // 'virtual' drawing objects.
820         // OD 2004-03-25 #i26791#
821         pAnch = pC->GetAnchorFrm( pObj );
822 		if( !pAnch )
823 		{
824 			pC->ConnectToLayout();
825             // OD 17.06.2003 #108784# - determine correct anchor position for
826             // 'virtual' drawing objects.
827             // OD 2004-03-25 #i26791#
828             pAnch = pC->GetAnchorFrm( pObj );
829 		}
830         aMyRect = pObj->GetSnapRect();
831 	}
832 
833 	//Badaa: 2008-04-18 * Support for Classical Mongolian Script (SCMS) joint with Jiayanmin
834     const sal_Bool bTopRight = pAnch && ( ( pAnch->IsVertical() &&
835     										!pAnch->IsVertLR() ) ||
836                                          	pAnch->IsRightToLeft() );
837     const Point aMyPt = bTopRight ? aMyRect.TopRight() : aMyRect.TopLeft();
838 
839     Point aPt;
840     if ( IsAction() )
841     {
842         if ( !TakeDragObjAnchorPos( aPt, bTopRight ) )
843             return NULL;
844     }
845     else
846     {
847         Rectangle aRect = pObj->GetSnapRect();
848         aPt = bTopRight ? aRect.TopRight() : aRect.TopLeft();
849     }
850 
851     if ( aPt != aMyPt )
852 	{
853 		if ( pAnch->IsCntntFrm() )
854         {
855             // OD 26.06.2003 #108784# - allow drawing objects in header/footer,
856             // but exclude control objects.
857             bool bBodyOnly = CheckControlLayer( pObj );
858             pAnch = ::FindAnchor( (SwCntntFrm*)pAnch, aPt, bBodyOnly );
859         }
860 		else if ( !bFly )
861         {
862             const SwRect aRect( aPt.X(), aPt.Y(), 1, 1 );
863 
864             SwDrawContact* pContact = (SwDrawContact*)GetUserCall(pObj);
865             if ( pContact->GetAnchorFrm( pObj ) &&
866                  pContact->GetAnchorFrm( pObj )->IsPageFrm() )
867                 pAnch = pContact->GetPageFrm();
868 			else
869 				pAnch = pContact->FindPage( aRect );
870 		}
871 	}
872 	if( pAnch && !pAnch->IsProtected() )
873         aAnchorPoint = pAnch->GetFrmAnchorPos( ::HasWrap( pObj ) );
874 	else
875 		pAnch = 0;
876 	return pAnch;
877 }
878 
879 /*************************************************************************
880 |*
881 |*	SwDrawView::ShowDragXor(), HideDragXor()
882 |*
883 |*	Ersterstellung		MA 17. Jan. 95
884 |*	Letzte Aenderung	MA 27. Jan. 95
885 |*
886 *************************************************************************/
887 
888 
889 void SwDrawView::ShowDragAnchor()
890 {
891 	SdrHdl* pHdl = aHdl.GetHdl(HDL_ANCHOR);
892 	if ( ! pHdl )
893 		pHdl = aHdl.GetHdl(HDL_ANCHOR_TR);
894 
895 	if(pHdl)
896 	{
897 		CalcAnchor();
898 		pHdl->SetPos(aAnchorPoint);
899 		//OLMRefreshAllIAOManagers();
900 	}
901 }
902 
903 /*************************************************************************
904 |*
905 |*	SwDrawView::MarkListHasChanged()
906 |*
907 |*	Ersterstellung		OM 02. Feb. 95
908 |*	Letzte Aenderung	OM 07. Jul. 95
909 |*
910 *************************************************************************/
911 
912 
913 void SwDrawView::MarkListHasChanged()
914 {
915     Imp().GetShell()->DrawSelChanged();
916 	FmFormView::MarkListHasChanged();
917 }
918 
919 // #i7672#
920 void SwDrawView::ModelHasChanged()
921 {
922 	// The ModelHasChanged() call in DrawingLayer also updates
923 	// a eventually active text edit view (OutlinerView). This also leads
924 	// to newly setting the background color for that edit view. Thus,
925 	// this method rescues the current background color if a OutlinerView
926 	// exists and re-establishes it then. To be more safe, the OutlinerView
927 	// will be fetched again (maybe textedit has ended).
928 	OutlinerView* pView = GetTextEditOutlinerView();
929 	Color aBackColor;
930 	sal_Bool bColorWasSaved(sal_False);
931 
932 	if(pView)
933 	{
934 		aBackColor = pView->GetBackgroundColor();
935 		bColorWasSaved = sal_True;
936 	}
937 
938 	// call parent
939 	FmFormView::ModelHasChanged();
940 
941 	if(bColorWasSaved)
942 	{
943 		pView = GetTextEditOutlinerView();
944 
945 		if(pView)
946 		{
947 			pView->SetBackgroundColor(aBackColor);
948 		}
949 	}
950 }
951 
952 void SwDrawView::MakeVisible( const Rectangle &rRect, Window & )
953 {
954     ASSERT( rImp.GetShell()->GetWin(), "MakeVisible, unknown Window");
955 	rImp.GetShell()->MakeVisible( SwRect( rRect ) );
956 }
957 
958 void SwDrawView::CheckPossibilities()
959 {
960 	FmFormView::CheckPossibilities();
961 
962 	//Zusaetzlich zu den bestehenden Flags der Objekte selbst, die von der
963 	//DrawingEngine ausgewertet werden, koennen weitere Umstaende zu einem
964 	//Schutz fuehren.
965 	//Objekte, die in Rahmen verankert sind, muessen genau dann geschuetzt
966 	//sein, wenn der Inhalt des Rahmens geschuetzt ist.
967 	//OLE-Objekte konnen selbst einen Resize-Schutz wuenschen (StarMath)
968 
969 	const SdrMarkList &rMrkList = GetMarkedObjectList();
970 	sal_Bool bProtect = sal_False,
971 			 bSzProtect = sal_False;
972 	for ( sal_uInt16 i = 0; !bProtect && i < rMrkList.GetMarkCount(); ++i )
973 	{
974 		const SdrObject *pObj = rMrkList.GetMark( i )->GetMarkedSdrObj();
975 		const SwFrm *pFrm = NULL;
976 		if ( pObj->ISA(SwVirtFlyDrawObj) )
977 		{
978 			const SwFlyFrm *pFly = ((SwVirtFlyDrawObj*)pObj)->GetFlyFrm();
979 			if ( pFly  )
980 			{
981                 pFrm = pFly->GetAnchorFrm();
982 				if ( pFly->Lower() && pFly->Lower()->IsNoTxtFrm() )
983 				{
984 					SwOLENode *pNd = ((SwCntntFrm*)pFly->Lower())->GetNode()->GetOLENode();
985 					if ( pNd )
986 					{
987                         uno::Reference < embed::XEmbeddedObject > xObj = pNd->GetOLEObj().GetOleRef();
988                         if ( xObj.is() )
989 						{
990                             // --> OD 2004-08-16 #110810# - improvement for
991                             // the future, when more than one Writer fly frame
992                             // can be selected.
993 
994                             // TODO/LATER: retrieve Aspect - from where?!
995                             bSzProtect |= ( embed::EmbedMisc::EMBED_NEVERRESIZE & xObj->getStatus( embed::Aspects::MSOLE_CONTENT ) ) ? sal_True : sal_False;
996 
997                             // <--
998 
999                             // #i972: protect position if it is a Math object anchored 'as char' and baseline alignment is activated
1000                         	SwDoc* pDoc = Imp().GetShell()->GetDoc();
1001                             const bool bProtectMathPos = SotExchange::IsMath( xObj->getClassID() )
1002                                     && FLY_AS_CHAR == pFly->GetFmt()->GetAnchor().GetAnchorId()
1003                                     && pDoc->get( IDocumentSettingAccess::MATH_BASELINE_ALIGNMENT );
1004                             if (bProtectMathPos)
1005                                 bMoveProtect = true;
1006                         }
1007 					}
1008 				}
1009 			}
1010 		}
1011 		else
1012 		{
1013 			SwDrawContact *pC = (SwDrawContact*)GetUserCall(pObj);
1014             if ( pC )
1015                 pFrm = pC->GetAnchorFrm( pObj );
1016 		}
1017 		if ( pFrm )
1018 			bProtect = pFrm->IsProtected(); //Rahmen, Bereiche usw.
1019         {
1020             SwFrmFmt* pFrmFmt( ::FindFrmFmt( const_cast<SdrObject*>(pObj) ) );
1021             if ( !pFrmFmt )
1022             {
1023                 ASSERT( false,
1024                         "<SwDrawView::CheckPossibilities()> - missing frame format" );
1025                 bProtect = sal_True;
1026             }
1027             else if ((FLY_AS_CHAR == pFrmFmt->GetAnchor().GetAnchorId()) &&
1028                       rMrkList.GetMarkCount() > 1 )
1029             {
1030                 bProtect = sal_True;
1031             }
1032         }
1033 	}
1034 	bMoveProtect	|= bProtect;
1035 	bResizeProtect	|= bProtect | bSzProtect;
1036 }
1037 
1038 /** replace marked <SwDrawVirtObj>-objects by its reference object for delete
1039     marked objects.
1040 
1041     OD 18.06.2003 #108784#
1042 
1043     @author OD
1044 */
1045 void SwDrawView::ReplaceMarkedDrawVirtObjs( SdrMarkView& _rMarkView )
1046 {
1047     SdrPageView* pDrawPageView = _rMarkView.GetSdrPageView();
1048     const SdrMarkList& rMarkList = _rMarkView.GetMarkedObjectList();
1049 
1050     if( rMarkList.GetMarkCount() )
1051     {
1052         // collect marked objects in a local data structure
1053         std::vector<SdrObject*> aMarkedObjs;
1054         for( sal_uInt32 i = 0; i < rMarkList.GetMarkCount(); ++i )
1055         {
1056             SdrObject* pMarkedObj = rMarkList.GetMark( i )->GetMarkedSdrObj();
1057             aMarkedObjs.push_back( pMarkedObj );
1058         }
1059         // unmark all objects
1060         _rMarkView.UnmarkAllObj();
1061         // re-mark objects, but for marked <SwDrawVirtObj>-objects marked its
1062         // reference object.
1063         while ( !aMarkedObjs.empty() )
1064         {
1065             SdrObject* pMarkObj = aMarkedObjs.back();
1066             if ( pMarkObj->ISA(SwDrawVirtObj) )
1067             {
1068                 SdrObject* pRefObj = &(static_cast<SwDrawVirtObj*>(pMarkObj)->ReferencedObj());
1069                 if ( !_rMarkView.IsObjMarked( pRefObj )  )
1070                 {
1071                     _rMarkView.MarkObj( pRefObj, pDrawPageView );
1072                 }
1073             }
1074             else
1075             {
1076                 _rMarkView.MarkObj( pMarkObj, pDrawPageView );
1077             }
1078 
1079             aMarkedObjs.pop_back();
1080         }
1081         // sort marked list in order to assure consistent state in drawing layer
1082         _rMarkView.SortMarkedObjects();
1083     }
1084 }
1085 
1086 void SwDrawView::DeleteMarked()
1087 {
1088 	SwDoc* pDoc = Imp().GetShell()->GetDoc();
1089 	SwRootFrm *pTmpRoot = pDoc->GetCurrentLayout();//swmod 080317
1090     if ( pTmpRoot )
1091 		pTmpRoot->StartAllAction();
1092     pDoc->GetIDocumentUndoRedo().StartUndo(UNDO_EMPTY, NULL);
1093     // OD 18.06.2003 #108784# - replace marked <SwDrawVirtObj>-objects by its
1094     // reference objects.
1095     {
1096         SdrPageView* pDrawPageView = rImp.GetPageView();
1097         if ( pDrawPageView )
1098         {
1099             SdrMarkView* pMarkView = PTR_CAST( SdrMarkView, &(pDrawPageView->GetView()) );
1100             if ( pMarkView )
1101             {
1102                 ReplaceMarkedDrawVirtObjs( *pMarkView );
1103             }
1104         }
1105     }
1106     if ( pDoc->DeleteSelection( *this ) )
1107 	{
1108 		FmFormView::DeleteMarked();
1109 		::FrameNotify( Imp().GetShell(), FLY_DRAG_END );
1110 	}
1111     pDoc->GetIDocumentUndoRedo().EndUndo(UNDO_EMPTY, NULL);
1112 	if( pTmpRoot )
1113 		pTmpRoot->EndAllAction();	//swmod 080218
1114 }
1115 
1116