xref: /AOO41X/main/sw/source/core/draw/dview.cxx (revision 707fc0d4d52eb4f69d89a98ffec6918ca5de6326)
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