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