xref: /AOO41X/main/sc/source/core/data/drwlayer.cxx (revision 15be5a03f01e8235a28bf01d4c07e0eb463981d7)
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_sc.hxx"
26 #include <com/sun/star/uno/Reference.hxx>
27 #include <com/sun/star/chart/XChartDocument.hpp>
28 #include <com/sun/star/embed/XEmbeddedObject.hpp>
29 #include <com/sun/star/embed/XVisualObject.hpp>
30 #include <com/sun/star/embed/XClassifiedObject.hpp>
31 #include <com/sun/star/embed/XComponentSupplier.hpp>
32 #include <com/sun/star/embed/EmbedStates.hpp>
33 #include <com/sun/star/embed/ElementModes.hpp>
34 #include <com/sun/star/embed/NoVisualAreaSizeException.hpp>
35 #include <com/sun/star/datatransfer/XTransferable.hpp>
36 
37 // INCLUDE ---------------------------------------------------------------
38 
39 #include "scitems.hxx"
40 #include <editeng/eeitem.hxx>
41 #include <editeng/frmdiritem.hxx>
42 #include <sot/exchange.hxx>
43 #include <svx/objfac3d.hxx>
44 #include <svx/xtable.hxx>
45 #include <svx/svdoutl.hxx>
46 #include <svx/svditer.hxx>
47 #include <svx/svdocapt.hxx>
48 #include <svx/svdocirc.hxx>
49 #include <svx/svdoedge.hxx>
50 #include <svx/svdograf.hxx>
51 #include <svx/svdoole2.hxx>
52 #include <svx/svdundo.hxx>
53 #include <editeng/unolingu.hxx>
54 #include <svx/drawitem.hxx>
55 #include <editeng/fhgtitem.hxx>
56 #include <editeng/scriptspaceitem.hxx>
57 #include <svx/shapepropertynotifier.hxx>
58 #include <sfx2/viewsh.hxx>
59 #include <sfx2/docfile.hxx>
60 #include <sot/storage.hxx>
61 #include <unotools/pathoptions.hxx>
62 #include <svl/itempool.hxx>
63 #include <vcl/virdev.hxx>
64 #include <vcl/svapp.hxx>
65 #include <unotools/ucbstreamhelper.hxx>
66 
67 #include "drwlayer.hxx"
68 #include "drawpage.hxx"
69 #include "global.hxx"
70 #include "document.hxx"
71 #include "rechead.hxx"
72 #include "userdat.hxx"
73 #include "markdata.hxx"
74 #include "globstr.hrc"
75 #include "scmod.hxx"
76 #include "chartarr.hxx"
77 #include "postit.hxx"
78 #include "attrib.hxx"
79 #include "charthelper.hxx"
80 
81 #define DET_ARROW_OFFSET    1000
82 
83 //  Abstand zur naechsten Zelle beim Loeschen (bShrink), damit der Anker
84 //  immer an der richtigen Zelle angezeigt wird
85 //#define SHRINK_DIST       3
86 //  und noch etwas mehr, damit das Objekt auch sichtbar in der Zelle liegt
87 #define SHRINK_DIST     25
88 
89 #define SHRINK_DIST_TWIPS   15
90 
91 using namespace ::com::sun::star;
92 
93 // STATIC DATA -----------------------------------------------------------
94 
95 TYPEINIT1(ScTabDeletedHint, SfxHint);
96 TYPEINIT1(ScTabSizeChangedHint, SfxHint);
97 
98 static ScDrawObjFactory* pFac = NULL;
99 static E3dObjFactory* pF3d = NULL;
100 static sal_uInt16 nInst = 0;
101 
102 SfxObjectShell* ScDrawLayer::pGlobalDrawPersist = NULL;
103 //REMOVE    SvPersist* ScDrawLayer::pGlobalDrawPersist = NULL;
104 
105 sal_Bool bDrawIsInUndo = sal_False;         //! Member
106 
107 // -----------------------------------------------------------------------
108 
ScUndoObjData(SdrObject * pObjP,const ScAddress & rOS,const ScAddress & rOE,const ScAddress & rNS,const ScAddress & rNE)109 ScUndoObjData::ScUndoObjData( SdrObject* pObjP, const ScAddress& rOS, const ScAddress& rOE,
110                                                const ScAddress& rNS, const ScAddress& rNE ) :
111     SdrUndoObj( *pObjP ),
112     aOldStt( rOS ),
113     aOldEnd( rOE ),
114     aNewStt( rNS ),
115     aNewEnd( rNE )
116 {
117 }
118 
~ScUndoObjData()119 __EXPORT ScUndoObjData::~ScUndoObjData()
120 {
121 }
122 
Undo()123 void ScUndoObjData::Undo()
124 {
125     ScDrawObjData* pData = ScDrawLayer::GetObjData( pObj );
126     DBG_ASSERT(pData,"ScUndoObjData: Daten nicht da");
127     if (pData)
128     {
129         pData->maStart = aOldStt;
130         pData->maEnd = aOldEnd;
131     }
132 }
133 
Redo()134 void __EXPORT ScUndoObjData::Redo()
135 {
136     ScDrawObjData* pData = ScDrawLayer::GetObjData( pObj );
137     DBG_ASSERT(pData,"ScUndoObjData: Daten nicht da");
138     if (pData)
139     {
140         pData->maStart = aNewStt;
141         pData->maEnd = aNewEnd;
142     }
143 }
144 
145 // -----------------------------------------------------------------------
146 
ScTabDeletedHint(SCTAB nTabNo)147 ScTabDeletedHint::ScTabDeletedHint( SCTAB nTabNo ) :
148     nTab( nTabNo )
149 {
150 }
151 
~ScTabDeletedHint()152 __EXPORT ScTabDeletedHint::~ScTabDeletedHint()
153 {
154 }
155 
ScTabSizeChangedHint(SCTAB nTabNo)156 ScTabSizeChangedHint::ScTabSizeChangedHint( SCTAB nTabNo ) :
157     nTab( nTabNo )
158 {
159 }
160 
~ScTabSizeChangedHint()161 __EXPORT ScTabSizeChangedHint::~ScTabSizeChangedHint()
162 {
163 }
164 
165 // -----------------------------------------------------------------------
166 
167 #define MAXMM   10000000
168 
TwipsToMM(long & nVal)169 inline void TwipsToMM( long& nVal )
170 {
171     nVal = (long) ( nVal * HMM_PER_TWIPS );
172 }
173 
ReverseTwipsToMM(long & nVal)174 inline void ReverseTwipsToMM( long& nVal )
175 {
176     //  reverse the effect of TwipsToMM - round up here (add 1)
177 
178     nVal = ((long) ( nVal / HMM_PER_TWIPS )) + 1;
179 }
180 
lcl_TwipsToMM(Point & rPoint)181 void lcl_TwipsToMM( Point& rPoint )
182 {
183     TwipsToMM( rPoint.X() );
184     TwipsToMM( rPoint.Y() );
185 }
186 
lcl_ReverseTwipsToMM(Point & rPoint)187 void lcl_ReverseTwipsToMM( Point& rPoint )
188 {
189     ReverseTwipsToMM( rPoint.X() );
190     ReverseTwipsToMM( rPoint.Y() );
191 }
192 
lcl_ReverseTwipsToMM(Rectangle & rRect)193 void lcl_ReverseTwipsToMM( Rectangle& rRect )
194 {
195     ReverseTwipsToMM( rRect.Left() );
196     ReverseTwipsToMM( rRect.Right() );
197     ReverseTwipsToMM( rRect.Top() );
198     ReverseTwipsToMM( rRect.Bottom() );
199 }
200 
201 // -----------------------------------------------------------------------
202 
203 
ScDrawLayer(ScDocument * pDocument,const String & rName)204 ScDrawLayer::ScDrawLayer( ScDocument* pDocument, const String& rName ) :
205     FmFormModel( SvtPathOptions().GetPalettePath(),
206                  NULL,                          // SfxItemPool* Pool
207                  pGlobalDrawPersist ?
208                     pGlobalDrawPersist :
209                     ( pDocument ? pDocument->GetDocumentShell() : NULL )),
210     aName( rName ),
211     pDoc( pDocument ),
212     pUndoGroup( NULL ),
213     bRecording( sal_False ),
214     bAdjustEnabled( sal_True ),
215     bHyphenatorSet( sal_False ),
216         mbUndoAllowed( sal_True )
217 {
218     pGlobalDrawPersist = NULL;          // nur einmal benutzen
219 
220     SfxObjectShell* pObjSh = pDocument ? pDocument->GetDocumentShell() : NULL;
221     if ( pObjSh )
222     {
223         SetObjectShell( pObjSh );
224 
225         // set color table
226         const SvxColorTableItem* pColItem = static_cast< const SvxColorTableItem* >(pObjSh->GetItem( SID_COLOR_TABLE ));
227         XColorListSharedPtr aXCol = pColItem ? pColItem->GetColorTable() : XColorList::GetStdColorList();
228         SetColorTableAtSdrModel( aXCol );
229     }
230     else
231         SetColorTableAtSdrModel( XColorList::GetStdColorList() );
232 
233     SetSwapGraphics(sal_True);
234 //  SetSwapAsynchron(sal_True);     // an der View
235 
236     SetScaleUnit(MAP_100TH_MM);
237     SfxItemPool& rPool = GetItemPool();
238     rPool.SetDefaultMetric(SFX_MAPUNIT_100TH_MM);
239     SvxFrameDirectionItem aModeItem( FRMDIR_ENVIRONMENT, EE_PARA_WRITINGDIR );
240     rPool.SetPoolDefaultItem( aModeItem );
241 
242     // #i33700#
243     // Set shadow distance defaults as PoolDefaultItems. Details see bug.
244     rPool.SetPoolDefaultItem(SdrShadowXDistItem(300));
245     rPool.SetPoolDefaultItem(SdrShadowYDistItem(300));
246 
247     // #111216# default for script spacing depends on locale, see SdDrawDocument ctor in sd
248     LanguageType eOfficeLanguage = Application::GetSettings().GetLanguage();
249     if ( eOfficeLanguage == LANGUAGE_KOREAN || eOfficeLanguage == LANGUAGE_KOREAN_JOHAB ||
250          eOfficeLanguage == LANGUAGE_JAPANESE )
251     {
252         // secondary is edit engine pool
253         rPool.GetSecondaryPool()->SetPoolDefaultItem( SvxScriptSpaceItem( sal_False, EE_PARA_ASIANCJKSPACING ) );
254     }
255 
256     rPool.FreezeIdRanges();                         // the pool is also used directly
257 
258     SdrLayerAdmin& rAdmin = GetLayerAdmin();
259     rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("vorne")),    SC_LAYER_FRONT);
260     rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("hinten")),   SC_LAYER_BACK);
261     rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("intern")),   SC_LAYER_INTERN);
262     rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Controls")), SC_LAYER_CONTROLS);
263     rAdmin.NewLayer(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("hidden")),   SC_LAYER_HIDDEN);
264     // "Controls" is new - must also be created when loading
265 
266     //  Link fuer URL-Fields setzen
267     ScModule* pScMod = SC_MOD();
268     Outliner& rOutliner = GetDrawOutliner();
269     rOutliner.SetCalcFieldValueHdl( LINK( pScMod, ScModule, CalcFieldValueHdl ) );
270 
271     Outliner& rHitOutliner = GetHitTestOutliner();
272     rHitOutliner.SetCalcFieldValueHdl( LINK( pScMod, ScModule, CalcFieldValueHdl ) );
273 
274     // #95129# SJ: set FontHeight pool defaults without changing static SdrEngineDefaults
275     SfxItemPool* pOutlinerPool = rOutliner.GetEditTextObjectPool();
276     if ( pOutlinerPool )
277     {
278         pItemPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT ));           // 12Pt
279         pItemPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT_CJK ));           // 12Pt
280     }
281     SfxItemPool* pHitOutlinerPool = rHitOutliner.GetEditTextObjectPool();
282     if ( pHitOutlinerPool )
283     {
284         pHitOutlinerPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT ));    // 12Pt
285         pHitOutlinerPool->SetPoolDefaultItem(SvxFontHeightItem( 423, 100, EE_CHAR_FONTHEIGHT_CJK ));    // 12Pt
286     }
287 
288     // initial undo mode as in Calc document
289     if( pDoc )
290         EnableUndo( pDoc->IsUndoEnabled() );
291 
292     //  URL-Buttons haben keinen Handler mehr, machen alles selber
293 
294     if( !nInst++ )
295     {
296         pFac = new ScDrawObjFactory;
297         pF3d = new E3dObjFactory;
298     }
299 }
300 
~ScDrawLayer()301 __EXPORT ScDrawLayer::~ScDrawLayer()
302 {
303     Broadcast(SdrHint(HINT_MODELCLEARED));
304 
305     // #116168#
306     //Clear();
307     ClearModel(sal_True);
308 
309     delete pUndoGroup;
310     if( !--nInst )
311     {
312         delete pFac, pFac = NULL;
313         delete pF3d, pF3d = NULL;
314     }
315 }
316 
UseHyphenator()317 void ScDrawLayer::UseHyphenator()
318 {
319     if (!bHyphenatorSet)
320     {
321         com::sun::star::uno::Reference< com::sun::star::linguistic2::XHyphenator >
322                                     xHyphenator = LinguMgr::GetHyphenator();
323 
324         GetDrawOutliner().SetHyphenator( xHyphenator );
325         GetHitTestOutliner().SetHyphenator( xHyphenator );
326 
327         bHyphenatorSet = sal_True;
328     }
329 }
330 
AllocPage(FASTBOOL bMasterPage)331 SdrPage* __EXPORT ScDrawLayer::AllocPage(FASTBOOL bMasterPage)
332 {
333     //  don't create basic until it is needed
334     StarBASIC* pBasic = NULL;
335     ScDrawPage* pPage = new ScDrawPage( *this, pBasic, sal::static_int_cast<sal_Bool>(bMasterPage) );
336     return pPage;
337 }
338 
HasObjects() const339 sal_Bool ScDrawLayer::HasObjects() const
340 {
341     sal_Bool bFound = sal_False;
342 
343     sal_uInt16 nCount = GetPageCount();
344     for (sal_uInt16 i=0; i<nCount && !bFound; i++)
345         if (GetPage(i)->GetObjCount())
346             bFound = sal_True;
347 
348     return bFound;
349 }
350 
UpdateBasic()351 void ScDrawLayer::UpdateBasic()
352 {
353     //  don't create basic until it is needed
354     //! remove this method?
355 }
356 
AllocModel() const357 SdrModel* __EXPORT ScDrawLayer::AllocModel() const
358 {
359     //  #103849# Allocated model (for clipboard etc) must not have a pointer
360     //  to the original model's document, pass NULL as document:
361 
362     return new ScDrawLayer( NULL, aName );
363 }
364 
GetCurDocViewWin()365 Window* __EXPORT ScDrawLayer::GetCurDocViewWin()
366 {
367     DBG_ASSERT( pDoc, "ScDrawLayer::GetCurDocViewWin without document" );
368     if ( !pDoc )
369         return NULL;
370 
371     SfxViewShell* pViewSh = SfxViewShell::Current();
372     SfxObjectShell* pObjSh = pDoc->GetDocumentShell();
373 
374     if (pViewSh && pViewSh->GetObjectShell() == pObjSh)
375         return pViewSh->GetWindow();
376 
377     return NULL;
378 }
379 
ScAddPage(SCTAB nTab)380 sal_Bool ScDrawLayer::ScAddPage( SCTAB nTab )
381 {
382     if (bDrawIsInUndo)
383         return sal_False;   // not inserted
384 
385     ScDrawPage* pPage = (ScDrawPage*)AllocPage( sal_False );
386     InsertPage(pPage, static_cast<sal_uInt16>(nTab));
387     if (bRecording)
388             AddCalcUndo< SdrUndoNewPage >(*pPage);
389 
390     return sal_True;        // inserted
391 }
392 
ScRemovePage(SCTAB nTab)393 void ScDrawLayer::ScRemovePage( SCTAB nTab )
394 {
395     if (bDrawIsInUndo)
396         return;
397 
398     Broadcast( ScTabDeletedHint( nTab ) );
399     if (bRecording)
400     {
401         SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
402         AddCalcUndo< SdrUndoDelPage >(*pPage);      // Undo-Action wird Owner der Page
403         RemovePage( static_cast<sal_uInt16>(nTab) );                            // nur austragen, nicht loeschen
404     }
405     else
406         DeletePage( static_cast<sal_uInt16>(nTab) );                            // einfach weg damit
407 }
408 
ScRenamePage(SCTAB nTab,const String & rNewName)409 void ScDrawLayer::ScRenamePage( SCTAB nTab, const String& rNewName )
410 {
411     ScDrawPage* pPage = (ScDrawPage*) GetPage(static_cast<sal_uInt16>(nTab));
412     if (pPage)
413         pPage->SetName(rNewName);
414 }
415 
ScMovePage(sal_uInt16 nOldPos,sal_uInt16 nNewPos)416 void ScDrawLayer::ScMovePage( sal_uInt16 nOldPos, sal_uInt16 nNewPos )
417 {
418     MovePage( nOldPos, nNewPos );
419 }
420 
ScCopyPage(sal_uInt16 nOldPos,sal_uInt16 nNewPos,sal_Bool bAlloc)421 void ScDrawLayer::ScCopyPage( sal_uInt16 nOldPos, sal_uInt16 nNewPos, sal_Bool bAlloc )
422 {
423     //! remove argument bAlloc (always sal_False)
424 
425     if (bDrawIsInUndo)
426         return;
427 
428     SdrPage* pOldPage = GetPage(nOldPos);
429     SdrPage* pNewPage = bAlloc ? AllocPage(sal_False) : GetPage(nNewPos);
430 
431     // kopieren
432 
433     if (pOldPage && pNewPage)
434     {
435         SdrObjListIter aIter( *pOldPage, IM_FLAT );
436         SdrObject* pOldObject = aIter.Next();
437         while (pOldObject)
438         {
439             // #i112034# do not copy internal objects (detective) and note captions
440             if ( pOldObject->GetLayer() != SC_LAYER_INTERN && !IsNoteCaption( pOldObject ) )
441             {
442                 // #116235#
443                 SdrObject* pNewObject = pOldObject->Clone();
444                 //SdrObject* pNewObject = pOldObject->Clone( pNewPage, this );
445                 pNewObject->SetModel(this);
446                 pNewObject->SetPage(pNewPage);
447 
448                 pNewObject->NbcMove(Size(0,0));
449                 pNewPage->InsertObject( pNewObject );
450                 if (bRecording)
451                     AddCalcUndo< SdrUndoInsertObj >( *pNewObject );
452             }
453 
454             pOldObject = aIter.Next();
455         }
456     }
457 
458     if (bAlloc)
459         InsertPage(pNewPage, nNewPos);
460 }
461 
IsInBlock(const ScAddress & rPos,SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2)462 inline sal_Bool IsInBlock( const ScAddress& rPos, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SCROW nRow2 )
463 {
464     return rPos.Col() >= nCol1 && rPos.Col() <= nCol2 &&
465            rPos.Row() >= nRow1 && rPos.Row() <= nRow2;
466 }
467 
MoveCells(SCTAB nTab,SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,SCsCOL nDx,SCsROW nDy,bool bUpdateNoteCaptionPos)468 void ScDrawLayer::MoveCells( SCTAB nTab, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SCROW nRow2,
469                                 SCsCOL nDx,SCsROW nDy, bool bUpdateNoteCaptionPos )
470 {
471     SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
472     DBG_ASSERT(pPage,"Page nicht gefunden");
473     if (!pPage)
474         return;
475 
476     sal_Bool bNegativePage = pDoc && pDoc->IsNegativePage( nTab );
477 
478     sal_uLong nCount = pPage->GetObjCount();
479     for ( sal_uLong i = 0; i < nCount; i++ )
480     {
481         SdrObject* pObj = pPage->GetObj( i );
482         ScDrawObjData* pData = GetObjDataTab( pObj, nTab );
483         if( pData )
484         {
485             const ScAddress aOldStt = pData->maStart;
486             const ScAddress aOldEnd = pData->maEnd;
487             sal_Bool bChange = sal_False;
488             if ( aOldStt.IsValid() && IsInBlock( aOldStt, nCol1,nRow1, nCol2,nRow2 ) )
489             {
490                 pData->maStart.IncCol( nDx );
491                 pData->maStart.IncRow( nDy );
492                 bChange = sal_True;
493             }
494             if ( aOldEnd.IsValid() && IsInBlock( aOldEnd, nCol1,nRow1, nCol2,nRow2 ) )
495             {
496                 pData->maEnd.IncCol( nDx );
497                 pData->maEnd.IncRow( nDy );
498                 bChange = sal_True;
499             }
500             if (bChange)
501             {
502                 if ( pObj->ISA( SdrRectObj ) && pData->maStart.IsValid() && pData->maEnd.IsValid() )
503                     pData->maStart.PutInOrder( pData->maEnd );
504                 AddCalcUndo< ScUndoObjData >( pObj, aOldStt, aOldEnd, pData->maStart, pData->maEnd );
505                 RecalcPos( pObj, *pData, bNegativePage, bUpdateNoteCaptionPos );
506             }
507         }
508     }
509 }
510 
SetPageSize(sal_uInt16 nPageNo,const Size & rSize,bool bUpdateNoteCaptionPos)511 void ScDrawLayer::SetPageSize( sal_uInt16 nPageNo, const Size& rSize, bool bUpdateNoteCaptionPos )
512 {
513     SdrPage* pPage = GetPage(nPageNo);
514     if (pPage)
515     {
516         if ( rSize != pPage->GetSize() )
517         {
518             pPage->SetSize( rSize );
519             Broadcast( ScTabSizeChangedHint( static_cast<SCTAB>(nPageNo) ) );   // SetWorkArea() an den Views
520         }
521 
522         // Detektivlinien umsetzen (an neue Hoehen/Breiten anpassen)
523         //  auch wenn Groesse gleich geblieben ist
524         //  (einzelne Zeilen/Spalten koennen geaendert sein)
525 
526         sal_Bool bNegativePage = pDoc && pDoc->IsNegativePage( static_cast<SCTAB>(nPageNo) );
527 
528         sal_uLong nCount = pPage->GetObjCount();
529         for ( sal_uLong i = 0; i < nCount; i++ )
530         {
531             SdrObject* pObj = pPage->GetObj( i );
532             ScDrawObjData* pData = GetObjDataTab( pObj, static_cast<SCTAB>(nPageNo) );
533             if( pData )
534                 RecalcPos( pObj, *pData, bNegativePage, bUpdateNoteCaptionPos );
535         }
536     }
537 }
538 
RecalcPos(SdrObject * pObj,const ScDrawObjData & rData,bool bNegativePage,bool bUpdateNoteCaptionPos)539 void ScDrawLayer::RecalcPos( SdrObject* pObj, const ScDrawObjData& rData, bool bNegativePage, bool bUpdateNoteCaptionPos )
540 {
541     DBG_ASSERT( pDoc, "ScDrawLayer::RecalcPos - missing document" );
542     if( !pDoc )
543         return;
544 
545     if( rData.mbNote )
546     {
547         DBG_ASSERT( rData.maStart.IsValid(), "ScDrawLayer::RecalcPos - invalid position for cell note" );
548         /*  #i109372# On insert/remove rows/columns/cells: Updating the caption
549             position must not be done, if the cell containing the note has not
550             been moved yet in the document. The calling code now passes an
551             additional boolean stating if the cells are already moved. */
552         if( bUpdateNoteCaptionPos )
553             /*  When inside an undo action, there may be pending note captions
554                 where cell note is already deleted (thus document cannot find
555                 the note object anymore). The caption will be deleted later
556                 with drawing undo. */
557             if( ScPostIt* pNote = pDoc->GetNote( rData.maStart ) )
558                 pNote->UpdateCaptionPos( rData.maStart );
559         return;
560     }
561 
562     bool bValid1 = rData.maStart.IsValid();
563     SCCOL nCol1 = rData.maStart.Col();
564     SCROW nRow1 = rData.maStart.Row();
565     SCTAB nTab1 = rData.maStart.Tab();
566     bool bValid2 = rData.maEnd.IsValid();
567     SCCOL nCol2 = rData.maEnd.Col();
568     SCROW nRow2 = rData.maEnd.Row();
569     SCTAB nTab2 = rData.maEnd.Tab();
570 
571     // validation circle
572     bool bCircle = pObj->ISA( SdrCircObj );
573     // detective arrow
574     bool bArrow = pObj->IsPolyObj() && (pObj->GetPointCount() == 2);
575 
576     if( bCircle )
577     {
578         Point aPos( pDoc->GetColOffset( nCol1, nTab1 ), pDoc->GetRowOffset( nRow1, nTab1 ) );
579         TwipsToMM( aPos.X() );
580         TwipsToMM( aPos.Y() );
581 
582         //  Berechnung und Werte wie in detfunc.cxx
583 
584         Size aSize( (long)(pDoc->GetColWidth( nCol1, nTab1 ) * HMM_PER_TWIPS),
585                     (long)(pDoc->GetRowHeight( nRow1, nTab1 ) * HMM_PER_TWIPS) );
586         Rectangle aRect( aPos, aSize );
587         aRect.Left()    -= 250;
588         aRect.Right()   += 250;
589         aRect.Top()     -= 70;
590         aRect.Bottom()  += 70;
591         if ( bNegativePage )
592             MirrorRectRTL( aRect );
593 
594         if ( pObj->GetLogicRect() != aRect )
595         {
596             if (bRecording)
597                         AddCalcUndo<SdrUndoGeoObj>( *pObj );
598             pObj->SetLogicRect(aRect);
599         }
600     }
601     else if( bArrow )
602     {
603         //! nicht mehrere Undos fuer ein Objekt erzeugen (hinteres kann dann weggelassen werden)
604 
605         SCCOL nLastCol;
606         SCROW nLastRow;
607         if( bValid1 )
608         {
609             Point aPos( pDoc->GetColOffset( nCol1, nTab1 ), pDoc->GetRowOffset( nRow1, nTab1 ) );
610             if (!pDoc->ColHidden(nCol1, nTab1, nLastCol))
611                 aPos.X() += pDoc->GetColWidth( nCol1, nTab1 ) / 4;
612             if (!pDoc->RowHidden(nRow1, nTab1, nLastRow))
613                 aPos.Y() += pDoc->GetRowHeight( nRow1, nTab1 ) / 2;
614             TwipsToMM( aPos.X() );
615             TwipsToMM( aPos.Y() );
616             Point aStartPos = aPos;
617             if ( bNegativePage )
618                 aStartPos.X() = -aStartPos.X();     // don't modify aPos - used below
619             if ( pObj->GetPoint( 0 ) != aStartPos )
620             {
621                 if (bRecording)
622                             AddCalcUndo< SdrUndoGeoObj> ( *pObj );
623                 pObj->SetPoint( aStartPos, 0 );
624             }
625 
626             if( !bValid2 )
627             {
628                 Point aEndPos( aPos.X() + DET_ARROW_OFFSET, aPos.Y() - DET_ARROW_OFFSET );
629                 if (aEndPos.Y() < 0)
630                     aEndPos.Y() += (2 * DET_ARROW_OFFSET);
631                 if ( bNegativePage )
632                     aEndPos.X() = -aEndPos.X();
633                 if ( pObj->GetPoint( 1 ) != aEndPos )
634                 {
635                     if (bRecording)
636                                 AddCalcUndo< SdrUndoGeoObj >( *pObj );
637                     pObj->SetPoint( aEndPos, 1 );
638                 }
639             }
640         }
641         if( bValid2 )
642         {
643             Point aPos( pDoc->GetColOffset( nCol2, nTab2 ), pDoc->GetRowOffset( nRow2, nTab2 ) );
644             if (!pDoc->ColHidden(nCol2, nTab2, nLastCol))
645                 aPos.X() += pDoc->GetColWidth( nCol2, nTab2 ) / 4;
646             if (!pDoc->RowHidden(nRow2, nTab2, nLastRow))
647                 aPos.Y() += pDoc->GetRowHeight( nRow2, nTab2 ) / 2;
648             TwipsToMM( aPos.X() );
649             TwipsToMM( aPos.Y() );
650             Point aEndPos = aPos;
651             if ( bNegativePage )
652                 aEndPos.X() = -aEndPos.X();         // don't modify aPos - used below
653             if ( pObj->GetPoint( 1 ) != aEndPos )
654             {
655                 if (bRecording)
656                             AddCalcUndo< SdrUndoGeoObj> ( *pObj  );
657                 pObj->SetPoint( aEndPos, 1 );
658             }
659 
660             if( !bValid1 )
661             {
662                 Point aStartPos( aPos.X() - DET_ARROW_OFFSET, aPos.Y() - DET_ARROW_OFFSET );
663                 if (aStartPos.X() < 0)
664                     aStartPos.X() += (2 * DET_ARROW_OFFSET);
665                 if (aStartPos.Y() < 0)
666                     aStartPos.Y() += (2 * DET_ARROW_OFFSET);
667                 if ( bNegativePage )
668                     aStartPos.X() = -aStartPos.X();
669                 if ( pObj->GetPoint( 0 ) != aStartPos )
670                 {
671                     if (bRecording)
672                                     AddCalcUndo< SdrUndoGeoObj >( *pObj );
673                     pObj->SetPoint( aStartPos, 0 );
674                 }
675             }
676         }
677     }
678     else                                // Referenz-Rahmen
679     {
680         DBG_ASSERT( bValid1, "ScDrawLayer::RecalcPos - invalid start position" );
681         Point aPos( pDoc->GetColOffset( nCol1, nTab1 ), pDoc->GetRowOffset( nRow1, nTab1 ) );
682         TwipsToMM( aPos.X() );
683         TwipsToMM( aPos.Y() );
684 
685         if( bValid2 )
686         {
687             Point aEnd( pDoc->GetColOffset( nCol2 + 1, nTab2 ), pDoc->GetRowOffset( nRow2 + 1, nTab2 ) );
688             TwipsToMM( aEnd.X() );
689             TwipsToMM( aEnd.Y() );
690 
691             Rectangle aNew( aPos, aEnd );
692             if ( bNegativePage )
693                 MirrorRectRTL( aNew );
694             if ( pObj->GetLogicRect() != aNew )
695             {
696                 if (bRecording)
697                             AddCalcUndo< SdrUndoGeoObj >( *pObj );
698                 pObj->SetLogicRect(aNew);
699             }
700         }
701         else
702         {
703             if ( bNegativePage )
704                 aPos.X() = -aPos.X();
705             if ( pObj->GetRelativePos() != aPos )
706             {
707                 if (bRecording)
708                             AddCalcUndo< SdrUndoGeoObj >( *pObj );
709                 pObj->SetRelativePos( aPos );
710             }
711         }
712     }
713 }
714 
GetPrintArea(ScRange & rRange,sal_Bool bSetHor,sal_Bool bSetVer) const715 sal_Bool ScDrawLayer::GetPrintArea( ScRange& rRange, sal_Bool bSetHor, sal_Bool bSetVer ) const
716 {
717     DBG_ASSERT( pDoc, "ScDrawLayer::GetPrintArea without document" );
718     if ( !pDoc )
719         return sal_False;
720 
721     SCTAB nTab = rRange.aStart.Tab();
722     DBG_ASSERT( rRange.aEnd.Tab() == nTab, "GetPrintArea: Tab unterschiedlich" );
723 
724     sal_Bool bNegativePage = pDoc->IsNegativePage( nTab );
725 
726     sal_Bool bAny = sal_False;
727     long nEndX = 0;
728     long nEndY = 0;
729     long nStartX = LONG_MAX;
730     long nStartY = LONG_MAX;
731 
732     // Grenzen ausrechnen
733 
734     if (!bSetHor)
735     {
736         nStartX = 0;
737         SCCOL nStartCol = rRange.aStart.Col();
738             SCCOL i;
739         for (i=0; i<nStartCol; i++)
740             nStartX +=pDoc->GetColWidth(i,nTab);
741         nEndX = nStartX;
742         SCCOL nEndCol = rRange.aEnd.Col();
743         for (i=nStartCol; i<=nEndCol; i++)
744             nEndX += pDoc->GetColWidth(i,nTab);
745         nStartX = (long)(nStartX * HMM_PER_TWIPS);
746         nEndX   = (long)(nEndX   * HMM_PER_TWIPS);
747     }
748     if (!bSetVer)
749     {
750         nStartY = pDoc->GetRowHeight( 0, rRange.aStart.Row()-1, nTab);
751         nEndY = nStartY + pDoc->GetRowHeight( rRange.aStart.Row(),
752                 rRange.aEnd.Row(), nTab);
753         nStartY = (long)(nStartY * HMM_PER_TWIPS);
754         nEndY   = (long)(nEndY   * HMM_PER_TWIPS);
755     }
756 
757     if ( bNegativePage )
758     {
759         nStartX = -nStartX;     // positions are negative, swap start/end so the same comparisons work
760         nEndX   = -nEndX;
761         ::std::swap( nStartX, nEndX );
762     }
763 
764     const SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
765     DBG_ASSERT(pPage,"Page nicht gefunden");
766     if (pPage)
767     {
768         SdrObjListIter aIter( *pPage, IM_FLAT );
769         SdrObject* pObject = aIter.Next();
770         while (pObject)
771         {
772                             //! Flags (ausgeblendet?) testen
773 
774             Rectangle aObjRect = pObject->GetCurrentBoundRect();
775             sal_Bool bFit = sal_True;
776             if ( !bSetHor && ( aObjRect.Right() < nStartX || aObjRect.Left() > nEndX ) )
777                 bFit = sal_False;
778             if ( !bSetVer && ( aObjRect.Bottom() < nStartY || aObjRect.Top() > nEndY ) )
779                 bFit = sal_False;
780             // #i104716# don't include hidden note objects
781             if ( bFit && pObject->GetLayer() != SC_LAYER_HIDDEN )
782             {
783                 if (bSetHor)
784                 {
785                     if (aObjRect.Left() < nStartX) nStartX = aObjRect.Left();
786                     if (aObjRect.Right()  > nEndX) nEndX = aObjRect.Right();
787                 }
788                 if (bSetVer)
789                 {
790                     if (aObjRect.Top()  < nStartY) nStartY = aObjRect.Top();
791                     if (aObjRect.Bottom() > nEndY) nEndY = aObjRect.Bottom();
792                 }
793                 bAny = sal_True;
794             }
795 
796             pObject = aIter.Next();
797         }
798     }
799 
800     if ( bNegativePage )
801     {
802         nStartX = -nStartX;     // reverse transformation, so the same cell address calculation works
803         nEndX   = -nEndX;
804         ::std::swap( nStartX, nEndX );
805     }
806 
807     if (bAny)
808     {
809         DBG_ASSERT( nStartX<=nEndX && nStartY<=nEndY, "Start/End falsch in ScDrawLayer::GetPrintArea" );
810 
811         if (bSetHor)
812         {
813             nStartX = (long) (nStartX / HMM_PER_TWIPS);
814             nEndX = (long) (nEndX / HMM_PER_TWIPS);
815             long nWidth;
816             SCCOL i;
817 
818             nWidth = 0;
819             for (i=0; i<=MAXCOL && nWidth<=nStartX; i++)
820                 nWidth += pDoc->GetColWidth(i,nTab);
821             rRange.aStart.SetCol( i>0 ? (i-1) : 0 );
822 
823             nWidth = 0;
824             for (i=0; i<=MAXCOL && nWidth<=nEndX; i++)          //! bei Start anfangen
825                 nWidth += pDoc->GetColWidth(i,nTab);
826             rRange.aEnd.SetCol( i>0 ? (i-1) : 0 );
827         }
828 
829         if (bSetVer)
830         {
831             nStartY = (long) (nStartY / HMM_PER_TWIPS);
832             nEndY = (long) (nEndY / HMM_PER_TWIPS);
833             SCROW nRow = pDoc->GetRowForHeight( nTab, nStartY);
834             rRange.aStart.SetRow( nRow>0 ? (nRow-1) : 0);
835             nRow = pDoc->GetRowForHeight( nTab, nEndY);
836             rRange.aEnd.SetRow( nRow == MAXROW ? MAXROW :
837                     (nRow>0 ? (nRow-1) : 0));
838         }
839     }
840     else
841     {
842         if (bSetHor)
843         {
844             rRange.aStart.SetCol(0);
845             rRange.aEnd.SetCol(0);
846         }
847         if (bSetVer)
848         {
849             rRange.aStart.SetRow(0);
850             rRange.aEnd.SetRow(0);
851         }
852     }
853     return bAny;
854 }
855 
AddCalcUndo(SdrUndoAction * pUndo)856 void ScDrawLayer::AddCalcUndo( SdrUndoAction* pUndo )
857 {
858     if (bRecording)
859     {
860         if (!pUndoGroup)
861             pUndoGroup = new SdrUndoGroup(*this);
862 
863         pUndoGroup->AddAction( pUndo );
864     }
865     else
866         delete pUndo;
867 }
868 
BeginCalcUndo(bool bDisableTextEditUsesCommonUndoManager)869 void ScDrawLayer::BeginCalcUndo(bool bDisableTextEditUsesCommonUndoManager)
870 {
871 //! DBG_ASSERT( !bRecording, "BeginCalcUndo ohne GetCalcUndo" );
872     SetDisableTextEditUsesCommonUndoManager(bDisableTextEditUsesCommonUndoManager);
873     DELETEZ(pUndoGroup);
874     bRecording = sal_True;
875 }
876 
GetCalcUndo()877 SdrUndoGroup* ScDrawLayer::GetCalcUndo()
878 {
879 //! DBG_ASSERT( bRecording, "GetCalcUndo ohne BeginCalcUndo" );
880 
881     SdrUndoGroup* pRet = pUndoGroup;
882     pUndoGroup = NULL;
883     bRecording = sal_False;
884     SetDisableTextEditUsesCommonUndoManager(false);
885     return pRet;
886 }
887 
888 //  MoveAreaTwips: all measures are kept in twips
MoveAreaTwips(SCTAB nTab,const Rectangle & rArea,const Point & rMove,const Point & rTopLeft)889 void ScDrawLayer::MoveAreaTwips( SCTAB nTab, const Rectangle& rArea,
890         const Point& rMove, const Point& rTopLeft )
891 {
892     if (!rMove.X() && !rMove.Y())
893         return;                                     // nix
894 
895     SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
896     DBG_ASSERT(pPage,"Page nicht gefunden");
897     if (!pPage)
898         return;
899 
900     sal_Bool bNegativePage = pDoc && pDoc->IsNegativePage( nTab );
901 
902     // fuer Shrinking!
903     Rectangle aNew( rArea );
904     sal_Bool bShrink = sal_False;
905     if ( rMove.X() < 0 || rMove.Y() < 0 )       // verkleinern
906     {
907         if ( rTopLeft != rArea.TopLeft() )      // sind gleich beim Verschieben von Zellen
908         {
909             bShrink = sal_True;
910             aNew.Left() = rTopLeft.X();
911             aNew.Top() = rTopLeft.Y();
912         }
913     }
914     SdrObjListIter aIter( *pPage, IM_FLAT );
915     SdrObject* pObject = aIter.Next();
916     while (pObject)
917     {
918         if( GetAnchor( pObject ) == SCA_CELL )
919         {
920             if ( GetObjData( pObject ) )                    // Detektiv-Pfeil ?
921             {
922                 // hier nichts
923             }
924             else if ( pObject->ISA( SdrEdgeObj ) )          // Verbinder?
925             {
926                 //  hier auch nichts
927                 //! nicht verbundene Enden wie bei Linien (s.u.) behandeln?
928             }
929             else if ( pObject->IsPolyObj() && pObject->GetPointCount()==2 )
930             {
931                 for (sal_uInt16 i=0; i<2; i++)
932                 {
933                     sal_Bool bMoved = sal_False;
934                     Point aPoint = pObject->GetPoint(i);
935                     lcl_ReverseTwipsToMM( aPoint );
936                     if (rArea.IsInside(aPoint))
937                     {
938                         aPoint += rMove; bMoved = sal_True;
939                     }
940                     else if (bShrink && aNew.IsInside(aPoint))
941                     {
942                         //  Punkt ist in betroffener Zelle - Test auf geloeschten Bereich
943                         if ( rMove.X() && aPoint.X() >= rArea.Left() + rMove.X() )
944                         {
945                             aPoint.X() = rArea.Left() + rMove.X() - SHRINK_DIST_TWIPS;
946                             if ( aPoint.X() < 0 ) aPoint.X() = 0;
947                             bMoved = sal_True;
948                         }
949                         if ( rMove.Y() && aPoint.Y() >= rArea.Top() + rMove.Y() )
950                         {
951                             aPoint.Y() = rArea.Top() + rMove.Y() - SHRINK_DIST_TWIPS;
952                             if ( aPoint.Y() < 0 ) aPoint.Y() = 0;
953                             bMoved = sal_True;
954                         }
955                     }
956                     if( bMoved )
957                     {
958                                     AddCalcUndo< SdrUndoGeoObj >( *pObject );
959                         lcl_TwipsToMM( aPoint );
960                         pObject->SetPoint( aPoint, i );
961                     }
962                 }
963             }
964             else
965             {
966                 Rectangle aObjRect = pObject->GetLogicRect();
967                 // aOldMMPos: not converted, millimeters
968                 Point aOldMMPos = bNegativePage ? aObjRect.TopRight() : aObjRect.TopLeft();
969                 lcl_ReverseTwipsToMM( aObjRect );
970                 Point aTopLeft = bNegativePage ? aObjRect.TopRight() : aObjRect.TopLeft();  // logical left
971                 Size aMoveSize;
972                 sal_Bool bDoMove = sal_False;
973                 if (rArea.IsInside(aTopLeft))
974                 {
975                     aMoveSize = Size(rMove.X(),rMove.Y());
976                     bDoMove = sal_True;
977                 }
978                 else if (bShrink && aNew.IsInside(aTopLeft))
979                 {
980                     //  Position ist in betroffener Zelle - Test auf geloeschten Bereich
981                     if ( rMove.X() && aTopLeft.X() >= rArea.Left() + rMove.X() )
982                     {
983                         aMoveSize.Width() = rArea.Left() + rMove.X() - SHRINK_DIST - aTopLeft.X();
984                         bDoMove = sal_True;
985                     }
986                     if ( rMove.Y() && aTopLeft.Y() >= rArea.Top() + rMove.Y() )
987                     {
988                         aMoveSize.Height() = rArea.Top() + rMove.Y() - SHRINK_DIST - aTopLeft.Y();
989                         bDoMove = sal_True;
990                     }
991                 }
992                 if ( bDoMove )
993                 {
994                     if ( bNegativePage )
995                     {
996                         if ( aTopLeft.X() + aMoveSize.Width() > 0 )
997                             aMoveSize.Width() = -aTopLeft.X();
998                     }
999                     else
1000                     {
1001                         if ( aTopLeft.X() + aMoveSize.Width() < 0 )
1002                             aMoveSize.Width() = -aTopLeft.X();
1003                     }
1004                     if ( aTopLeft.Y() + aMoveSize.Height() < 0 )
1005                         aMoveSize.Height() = -aTopLeft.Y();
1006 
1007                     //  get corresponding move size in millimeters:
1008                     Point aNewPos( aTopLeft.X() + aMoveSize.Width(), aTopLeft.Y() + aMoveSize.Height() );
1009                     lcl_TwipsToMM( aNewPos );
1010                     aMoveSize = Size( aNewPos.X() - aOldMMPos.X(), aNewPos.Y() - aOldMMPos.Y() );   // millimeters
1011 
1012                                 AddCalcUndo< SdrUndoMoveObj >( *pObject, aMoveSize );
1013                     pObject->Move( aMoveSize );
1014                 }
1015                 else if ( rArea.IsInside( bNegativePage ? aObjRect.BottomLeft() : aObjRect.BottomRight() ) &&
1016                             !pObject->IsResizeProtect() )
1017                 {
1018                     //  geschuetzte Groessen werden nicht veraendert
1019                     //  (Positionen schon, weil sie ja an der Zelle "verankert" sind)
1020                             AddCalcUndo< SdrUndoGeoObj >( *pObject );
1021                     long nOldSizeX = aObjRect.Right() - aObjRect.Left() + 1;
1022                     long nOldSizeY = aObjRect.Bottom() - aObjRect.Top() + 1;
1023                     long nLogMoveX = rMove.X() * ( bNegativePage ? -1 : 1 );    // logical direction
1024                     pObject->Resize( aOldMMPos, Fraction( nOldSizeX+nLogMoveX, nOldSizeX ),
1025                                                 Fraction( nOldSizeY+rMove.Y(), nOldSizeY ) );
1026                 }
1027             }
1028         }
1029         pObject = aIter.Next();
1030     }
1031 }
1032 
MoveArea(SCTAB nTab,SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2,SCsCOL nDx,SCsROW nDy,sal_Bool bInsDel,bool bUpdateNoteCaptionPos)1033 void ScDrawLayer::MoveArea( SCTAB nTab, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SCROW nRow2,
1034                             SCsCOL nDx,SCsROW nDy, sal_Bool bInsDel, bool bUpdateNoteCaptionPos )
1035 {
1036     DBG_ASSERT( pDoc, "ScDrawLayer::MoveArea without document" );
1037     if ( !pDoc )
1038         return;
1039 
1040     if (!bAdjustEnabled)
1041         return;
1042 
1043     sal_Bool bNegativePage = pDoc->IsNegativePage( nTab );
1044 
1045     Rectangle aRect = pDoc->GetMMRect( nCol1, nRow1, nCol2, nRow2, nTab );
1046     lcl_ReverseTwipsToMM( aRect );
1047     //! use twips directly?
1048 
1049     Point aMove;
1050 
1051     if (nDx > 0)
1052         for (SCsCOL s=0; s<nDx; s++)
1053             aMove.X() += pDoc->GetColWidth(s+(SCsCOL)nCol1,nTab);
1054     else
1055         for (SCsCOL s=-1; s>=nDx; s--)
1056             aMove.X() -= pDoc->GetColWidth(s+(SCsCOL)nCol1,nTab);
1057     if (nDy > 0)
1058         aMove.Y() += pDoc->GetRowHeight( nRow1, nRow1+nDy-1, nTab);
1059     else
1060         aMove.Y() -= pDoc->GetRowHeight( nRow1+nDy, nRow1-1, nTab);
1061 
1062     if ( bNegativePage )
1063         aMove.X() = -aMove.X();
1064 
1065     Point aTopLeft = aRect.TopLeft();       // Anfang beim Verkleinern
1066     if (bInsDel)
1067     {
1068         if ( aMove.X() != 0 && nDx < 0 )    // nDx counts cells, sign is independent of RTL
1069             aTopLeft.X() += aMove.X();
1070         if ( aMove.Y() < 0 )
1071             aTopLeft.Y() += aMove.Y();
1072     }
1073 
1074     //  drawing objects are now directly included in cut&paste
1075     //  -> only update references when inserting/deleting (or changing widths or heights)
1076     if ( bInsDel )
1077         MoveAreaTwips( nTab, aRect, aMove, aTopLeft );
1078 
1079         //
1080         //      Detektiv-Pfeile: Zellpositionen anpassen
1081         //
1082 
1083     MoveCells( nTab, nCol1,nRow1, nCol2,nRow2, nDx,nDy, bUpdateNoteCaptionPos );
1084 }
1085 
WidthChanged(SCTAB nTab,SCCOL nCol,long nDifTwips)1086 void ScDrawLayer::WidthChanged( SCTAB nTab, SCCOL nCol, long nDifTwips )
1087 {
1088     DBG_ASSERT( pDoc, "ScDrawLayer::WidthChanged without document" );
1089     if ( !pDoc )
1090         return;
1091 
1092     if (!bAdjustEnabled)
1093         return;
1094 
1095     Rectangle aRect;
1096     Point aTopLeft;
1097 
1098     for (SCCOL i=0; i<nCol; i++)
1099         aRect.Left() += pDoc->GetColWidth(i,nTab);
1100     aTopLeft.X() = aRect.Left();
1101     aRect.Left() += pDoc->GetColWidth(nCol,nTab);
1102 
1103     aRect.Right() = MAXMM;
1104     aRect.Top() = 0;
1105     aRect.Bottom() = MAXMM;
1106 
1107     //! aTopLeft ist falsch, wenn mehrere Spalten auf einmal ausgeblendet werden
1108 
1109     sal_Bool bNegativePage = pDoc->IsNegativePage( nTab );
1110     if ( bNegativePage )
1111     {
1112         MirrorRectRTL( aRect );
1113         aTopLeft.X() = -aTopLeft.X();
1114         nDifTwips = -nDifTwips;
1115     }
1116 
1117     MoveAreaTwips( nTab, aRect, Point( nDifTwips,0 ), aTopLeft );
1118 }
1119 
HeightChanged(SCTAB nTab,SCROW nRow,long nDifTwips)1120 void ScDrawLayer::HeightChanged( SCTAB nTab, SCROW nRow, long nDifTwips )
1121 {
1122     DBG_ASSERT( pDoc, "ScDrawLayer::HeightChanged without document" );
1123     if ( !pDoc )
1124         return;
1125 
1126     if (!bAdjustEnabled)
1127         return;
1128 
1129     SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
1130     DBG_ASSERT(pPage,"Page not found");
1131     if (!pPage)
1132         return;
1133 
1134     // for an empty page, there's no need to calculate the row heights
1135     if (!pPage->GetObjCount())
1136         return;
1137 
1138     Rectangle aRect;
1139     Point aTopLeft;
1140 
1141     aRect.Top() += pDoc->GetRowHeight( 0, nRow-1, nTab);
1142     aTopLeft.Y() = aRect.Top();
1143     aRect.Top() += pDoc->GetRowHeight(nRow, nTab);
1144 
1145     aRect.Bottom() = MAXMM;
1146     aRect.Left() = 0;
1147     aRect.Right() = MAXMM;
1148 
1149     //! aTopLeft ist falsch, wenn mehrere Zeilen auf einmal ausgeblendet werden
1150 
1151     sal_Bool bNegativePage = pDoc->IsNegativePage( nTab );
1152     if ( bNegativePage )
1153     {
1154         MirrorRectRTL( aRect );
1155         aTopLeft.X() = -aTopLeft.X();
1156     }
1157 
1158     MoveAreaTwips( nTab, aRect, Point( 0,nDifTwips ), aTopLeft );
1159 }
1160 
HasObjectsInRows(SCTAB nTab,SCROW nStartRow,SCROW nEndRow,bool bIncludeNotes)1161 sal_Bool ScDrawLayer::HasObjectsInRows( SCTAB nTab, SCROW nStartRow, SCROW nEndRow, bool bIncludeNotes )
1162 {
1163     DBG_ASSERT( pDoc, "ScDrawLayer::HasObjectsInRows without document" );
1164     if ( !pDoc )
1165         return sal_False;
1166 
1167     SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
1168     DBG_ASSERT(pPage,"Page not found");
1169     if (!pPage)
1170         return sal_False;
1171 
1172     // for an empty page, there's no need to calculate the row heights
1173     if (!pPage->GetObjCount())
1174         return sal_False;
1175 
1176     Rectangle aTestRect;
1177 
1178     aTestRect.Top() += pDoc->GetRowHeight( 0, nStartRow-1, nTab);
1179 
1180     if (nEndRow==MAXROW)
1181         aTestRect.Bottom() = MAXMM;
1182     else
1183     {
1184         aTestRect.Bottom() = aTestRect.Top();
1185         aTestRect.Bottom() += pDoc->GetRowHeight( nStartRow, nEndRow, nTab);
1186         TwipsToMM( aTestRect.Bottom() );
1187     }
1188 
1189     TwipsToMM( aTestRect.Top() );
1190 
1191     aTestRect.Left()  = 0;
1192     aTestRect.Right() = MAXMM;
1193 
1194     sal_Bool bNegativePage = pDoc->IsNegativePage( nTab );
1195     if ( bNegativePage )
1196         MirrorRectRTL( aTestRect );
1197 
1198     sal_Bool bFound = sal_False;
1199 
1200     Rectangle aObjRect;
1201     SdrObjListIter aIter( *pPage );
1202     SdrObject* pObject = aIter.Next();
1203     while ( pObject && !bFound )
1204     {
1205         aObjRect = pObject->GetSnapRect();  //! GetLogicRect ?
1206         // #i116164# note captions are handled separately, don't have to be included for each single row height change
1207         if ( (aTestRect.IsInside(aObjRect.TopLeft()) || aTestRect.IsInside(aObjRect.BottomLeft())) &&
1208              (bIncludeNotes || !IsNoteCaption(pObject)) )
1209             bFound = sal_True;
1210 
1211         pObject = aIter.Next();
1212     }
1213 
1214     return bFound;
1215 }
1216 
1217 #if 0
1218 void ScDrawLayer::DeleteObjects( SCTAB nTab )
1219 {
1220     SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
1221     DBG_ASSERT(pPage,"Page ?");
1222     if (!pPage)
1223         return;
1224 
1225     pPage->RecalcObjOrdNums();
1226 
1227     long    nDelCount = 0;
1228     sal_uLong   nObjCount = pPage->GetObjCount();
1229     if (nObjCount)
1230     {
1231         SdrObject** ppObj = new SdrObject*[nObjCount];
1232 
1233         SdrObjListIter aIter( *pPage, IM_FLAT );
1234         SdrObject* pObject = aIter.Next();
1235         while (pObject)
1236         {
1237             //  alle loeschen
1238             ppObj[nDelCount++] = pObject;
1239             pObject = aIter.Next();
1240         }
1241 
1242         long i;
1243         if (bRecording)
1244             for (i=1; i<=nDelCount; i++)
1245                         AddCalcUndo< SdrUndoRemoveObj >( *ppObj[nDelCount-i] );
1246 
1247         for (i=1; i<=nDelCount; i++)
1248             pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() );
1249 
1250         delete[] ppObj;
1251     }
1252 }
1253 #endif
1254 
DeleteObjectsInArea(SCTAB nTab,SCCOL nCol1,SCROW nRow1,SCCOL nCol2,SCROW nRow2)1255 void ScDrawLayer::DeleteObjectsInArea( SCTAB nTab, SCCOL nCol1,SCROW nRow1,
1256                                             SCCOL nCol2,SCROW nRow2 )
1257 {
1258     DBG_ASSERT( pDoc, "ScDrawLayer::DeleteObjectsInArea without document" );
1259     if ( !pDoc )
1260         return;
1261 
1262     SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
1263     DBG_ASSERT(pPage,"Page ?");
1264     if (!pPage)
1265         return;
1266 
1267     pPage->RecalcObjOrdNums();
1268 
1269     long    nDelCount = 0;
1270     sal_uLong   nObjCount = pPage->GetObjCount();
1271     if (nObjCount)
1272     {
1273         Rectangle aDelRect = pDoc->GetMMRect( nCol1, nRow1, nCol2, nRow2, nTab );
1274 
1275         SdrObject** ppObj = new SdrObject*[nObjCount];
1276 
1277         SdrObjListIter aIter( *pPage, IM_FLAT );
1278         SdrObject* pObject = aIter.Next();
1279         while (pObject)
1280         {
1281             // do not delete note caption, they are always handled by the cell note
1282             // TODO: detective objects are still deleted, is this desired?
1283             if (!IsNoteCaption( pObject ))
1284             {
1285                 Rectangle aObjRect = pObject->GetCurrentBoundRect();
1286                 if ( aDelRect.IsInside( aObjRect ) )
1287                     ppObj[nDelCount++] = pObject;
1288             }
1289 
1290             pObject = aIter.Next();
1291         }
1292 
1293         long i;
1294         if (bRecording)
1295             for (i=1; i<=nDelCount; i++)
1296                         AddCalcUndo< SdrUndoRemoveObj >( *ppObj[nDelCount-i] );
1297 
1298         for (i=1; i<=nDelCount; i++)
1299             pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() );
1300 
1301         delete[] ppObj;
1302     }
1303 }
1304 
DeleteObjectsInSelection(const ScMarkData & rMark)1305 void ScDrawLayer::DeleteObjectsInSelection( const ScMarkData& rMark )
1306 {
1307     DBG_ASSERT( pDoc, "ScDrawLayer::DeleteObjectsInSelection without document" );
1308     if ( !pDoc )
1309         return;
1310 
1311     if ( !rMark.IsMultiMarked() )
1312         return;
1313 
1314     ScRange aMarkRange;
1315     rMark.GetMultiMarkArea( aMarkRange );
1316 
1317     SCTAB nTabCount = pDoc->GetTableCount();
1318     for (SCTAB nTab=0; nTab<=nTabCount; nTab++)
1319         if ( rMark.GetTableSelect( nTab ) )
1320         {
1321             SdrPage* pPage = GetPage(static_cast<sal_uInt16>(nTab));
1322             if (pPage)
1323             {
1324                 pPage->RecalcObjOrdNums();
1325                 long    nDelCount = 0;
1326                 sal_uLong   nObjCount = pPage->GetObjCount();
1327                 if (nObjCount)
1328                 {
1329                     //  Rechteck um die ganze Selektion
1330                     Rectangle aMarkBound = pDoc->GetMMRect(
1331                                 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
1332                                 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), nTab );
1333 
1334                     SdrObject** ppObj = new SdrObject*[nObjCount];
1335 
1336                     SdrObjListIter aIter( *pPage, IM_FLAT );
1337                     SdrObject* pObject = aIter.Next();
1338                     while (pObject)
1339                     {
1340                         // do not delete note caption, they are always handled by the cell note
1341                         // TODO: detective objects are still deleted, is this desired?
1342                         if (!IsNoteCaption( pObject ))
1343                         {
1344                             Rectangle aObjRect = pObject->GetCurrentBoundRect();
1345                             if ( aMarkBound.IsInside( aObjRect ) )
1346                             {
1347                                 ScRange aRange = pDoc->GetRange( nTab, aObjRect );
1348                                 if (rMark.IsAllMarked(aRange))
1349                                     ppObj[nDelCount++] = pObject;
1350                             }
1351                         }
1352 
1353                         pObject = aIter.Next();
1354                     }
1355 
1356                     //  Objekte loeschen (rueckwaerts)
1357 
1358                     long i;
1359                     if (bRecording)
1360                         for (i=1; i<=nDelCount; i++)
1361                                         AddCalcUndo< SdrUndoRemoveObj >( *ppObj[nDelCount-i] );
1362 
1363                     for (i=1; i<=nDelCount; i++)
1364                         pPage->RemoveObject( ppObj[nDelCount-i]->GetOrdNum() );
1365 
1366                     delete[] ppObj;
1367                 }
1368             }
1369             else
1370             {
1371                 DBG_ERROR("pPage?");
1372             }
1373         }
1374 }
1375 
CopyToClip(ScDocument * pClipDoc,SCTAB nTab,const Rectangle & rRange)1376 void ScDrawLayer::CopyToClip( ScDocument* pClipDoc, SCTAB nTab, const Rectangle& rRange )
1377 {
1378     //  copy everything in the specified range into the same page (sheet) in the clipboard doc
1379 
1380     SdrPage* pSrcPage = GetPage(static_cast<sal_uInt16>(nTab));
1381     if (pSrcPage)
1382     {
1383         ScDrawLayer* pDestModel = NULL;
1384         SdrPage* pDestPage = NULL;
1385 
1386         SdrObjListIter aIter( *pSrcPage, IM_FLAT );
1387         SdrObject* pOldObject = aIter.Next();
1388         while (pOldObject)
1389         {
1390             Rectangle aObjRect = pOldObject->GetCurrentBoundRect();
1391             // do not copy internal objects (detective) and note captions
1392             if ( rRange.IsInside( aObjRect ) && (pOldObject->GetLayer() != SC_LAYER_INTERN) && !IsNoteCaption( pOldObject ) )
1393             {
1394                 if ( !pDestModel )
1395                 {
1396                     pDestModel = pClipDoc->GetDrawLayer();      // does the document already have a drawing layer?
1397                     if ( !pDestModel )
1398                     {
1399                         //  allocate drawing layer in clipboard document only if there are objects to copy
1400 
1401                         pClipDoc->InitDrawLayer();                  //! create contiguous pages
1402                         pDestModel = pClipDoc->GetDrawLayer();
1403                     }
1404                     if (pDestModel)
1405                         pDestPage = pDestModel->GetPage( static_cast<sal_uInt16>(nTab) );
1406                 }
1407 
1408                 DBG_ASSERT( pDestPage, "no page" );
1409                 if (pDestPage)
1410                 {
1411                     // #116235#
1412                     SdrObject* pNewObject = pOldObject->Clone();
1413                     //SdrObject* pNewObject = pOldObject->Clone( pDestPage, pDestModel );
1414                     pNewObject->SetModel(pDestModel);
1415                     pNewObject->SetPage(pDestPage);
1416 
1417                     uno::Reference< chart2::XChartDocument > xOldChart( ScChartHelper::GetChartFromSdrObject( pOldObject ) );
1418                     if(!xOldChart.is())//#i110034# do not move charts as they loose all their data references otherwise
1419                         pNewObject->NbcMove(Size(0,0));
1420                     pDestPage->InsertObject( pNewObject );
1421 
1422                     //  no undo needed in clipboard document
1423                     //  charts are not updated
1424                 }
1425             }
1426 
1427             pOldObject = aIter.Next();
1428         }
1429     }
1430 }
1431 
lcl_IsAllInRange(const::std::vector<ScRangeList> & rRangesVector,const ScRange & rClipRange)1432 sal_Bool lcl_IsAllInRange( const ::std::vector< ScRangeList >& rRangesVector, const ScRange& rClipRange )
1433 {
1434     //  check if every range of rRangesVector is completely in rClipRange
1435 
1436     ::std::vector< ScRangeList >::const_iterator aIt = rRangesVector.begin();
1437     for( ;aIt!=rRangesVector.end(); ++aIt )
1438     {
1439         const ScRangeList& rRanges = *aIt;
1440         sal_uLong nCount = rRanges.Count();
1441         for (sal_uLong i=0; i<nCount; i++)
1442         {
1443             ScRange aRange = *rRanges.GetObject(i);
1444             if ( !rClipRange.In( aRange ) )
1445             {
1446                 return sal_False;   // at least one range is not valid
1447             }
1448         }
1449     }
1450 
1451     return sal_True;            // everything is fine
1452 }
1453 
lcl_MoveRanges(::std::vector<ScRangeList> & rRangesVector,const ScRange & rSourceRange,const ScAddress & rDestPos)1454 sal_Bool lcl_MoveRanges( ::std::vector< ScRangeList >& rRangesVector, const ScRange& rSourceRange, const ScAddress& rDestPos )
1455 {
1456     sal_Bool bChanged = sal_False;
1457 
1458     ::std::vector< ScRangeList >::iterator aIt = rRangesVector.begin();
1459     for( ;aIt!=rRangesVector.end(); ++aIt )
1460     {
1461         ScRangeList& rRanges = *aIt;
1462         sal_uLong nCount = rRanges.Count();
1463         for (sal_uLong i=0; i<nCount; i++)
1464         {
1465             ScRange* pRange = rRanges.GetObject(i);
1466             if ( rSourceRange.In( *pRange ) )
1467             {
1468                 SCsCOL nDiffX = rDestPos.Col() - (SCsCOL)rSourceRange.aStart.Col();
1469                 SCsROW nDiffY = rDestPos.Row() - (SCsROW)rSourceRange.aStart.Row();
1470                 SCsTAB nDiffZ = rDestPos.Tab() - (SCsTAB)rSourceRange.aStart.Tab();
1471                 pRange->Move( nDiffX, nDiffY, nDiffZ );
1472                 bChanged = sal_True;
1473             }
1474         }
1475     }
1476 
1477     return bChanged;
1478 }
1479 
CopyFromClip(ScDrawLayer * pClipModel,SCTAB nSourceTab,const Rectangle & rSourceRange,const ScAddress & rDestPos,const Rectangle & rDestRange)1480 void ScDrawLayer::CopyFromClip( ScDrawLayer* pClipModel, SCTAB nSourceTab, const Rectangle& rSourceRange,
1481                                     const ScAddress& rDestPos, const Rectangle& rDestRange )
1482 {
1483     DBG_ASSERT( pDoc, "ScDrawLayer::CopyFromClip without document" );
1484     if ( !pDoc )
1485         return;
1486 
1487     if (!pClipModel)
1488         return;
1489 
1490     if (bDrawIsInUndo)      //! can this happen?
1491     {
1492         DBG_ERROR("CopyFromClip, bDrawIsInUndo");
1493         return;
1494     }
1495 
1496     sal_Bool bMirrorObj = ( rSourceRange.Left() < 0 && rSourceRange.Right() < 0 &&
1497                         rDestRange.Left()   > 0 && rDestRange.Right()   > 0 ) ||
1498                       ( rSourceRange.Left() > 0 && rSourceRange.Right() > 0 &&
1499                         rDestRange.Left()   < 0 && rDestRange.Right()   < 0 );
1500     Rectangle aMirroredSource = rSourceRange;
1501     if ( bMirrorObj )
1502         MirrorRectRTL( aMirroredSource );
1503 
1504     SCTAB nDestTab = rDestPos.Tab();
1505 
1506     SdrPage* pSrcPage = pClipModel->GetPage(static_cast<sal_uInt16>(nSourceTab));
1507     SdrPage* pDestPage = GetPage(static_cast<sal_uInt16>(nDestTab));
1508     DBG_ASSERT( pSrcPage && pDestPage, "draw page missing" );
1509     if ( !pSrcPage || !pDestPage )
1510         return;
1511 
1512     SdrObjListIter aIter( *pSrcPage, IM_FLAT );
1513     SdrObject* pOldObject = aIter.Next();
1514 
1515     ScDocument* pClipDoc = pClipModel->GetDocument();
1516     //  a clipboard document and its source share the same document item pool,
1517     //  so the pointers can be compared to see if this is copy&paste within
1518     //  the same document
1519     sal_Bool bSameDoc = pDoc && pClipDoc && pDoc->GetPool() == pClipDoc->GetPool();
1520     sal_Bool bDestClip = pDoc && pDoc->IsClipboard();
1521 
1522     //#i110034# charts need correct sheet names for xml range conversion during load
1523     //so the target sheet name is temporarily renamed (if we have any SdrObjects)
1524     String aDestTabName;
1525     sal_Bool bRestoreDestTabName = sal_False;
1526     if( pOldObject && !bSameDoc && !bDestClip )
1527     {
1528         if( pDoc && pClipDoc )
1529         {
1530             String aSourceTabName;
1531             if( pClipDoc->GetName( nSourceTab, aSourceTabName )
1532                 && pDoc->GetName( nDestTab, aDestTabName ) )
1533             {
1534                 if( !(aSourceTabName==aDestTabName) &&
1535                     pDoc->ValidNewTabName(aSourceTabName) )
1536                 {
1537                     bRestoreDestTabName = pDoc->RenameTab( nDestTab, aSourceTabName ); //sal_Bool bUpdateRef = sal_True, sal_Bool bExternalDocument = sal_False
1538                 }
1539             }
1540         }
1541     }
1542 
1543     // first mirror, then move
1544     Size aMove( rDestRange.Left() - aMirroredSource.Left(), rDestRange.Top() - aMirroredSource.Top() );
1545 
1546     long nDestWidth = rDestRange.GetWidth();
1547     long nDestHeight = rDestRange.GetHeight();
1548     long nSourceWidth = rSourceRange.GetWidth();
1549     long nSourceHeight = rSourceRange.GetHeight();
1550 
1551     long nWidthDiff = nDestWidth - nSourceWidth;
1552     long nHeightDiff = nDestHeight - nSourceHeight;
1553 
1554     Fraction aHorFract(1,1);
1555     Fraction aVerFract(1,1);
1556     sal_Bool bResize = sal_False;
1557     // sizes can differ by 1 from twips->1/100mm conversion for equal cell sizes,
1558     // don't resize to empty size when pasting into hidden columns or rows
1559     if ( Abs(nWidthDiff) > 1 && nDestWidth > 1 && nSourceWidth > 1 )
1560     {
1561         aHorFract = Fraction( nDestWidth, nSourceWidth );
1562         bResize = sal_True;
1563     }
1564     if ( Abs(nHeightDiff) > 1 && nDestHeight > 1 && nSourceHeight > 1 )
1565     {
1566         aVerFract = Fraction( nDestHeight, nSourceHeight );
1567         bResize = sal_True;
1568     }
1569     Point aRefPos = rDestRange.TopLeft();       // for resizing (after moving)
1570 
1571     while (pOldObject)
1572     {
1573         Rectangle aObjRect = pOldObject->GetCurrentBoundRect();
1574         // do not copy internal objects (detective) and note captions
1575         if ( rSourceRange.IsInside( aObjRect ) && (pOldObject->GetLayer() != SC_LAYER_INTERN) && !IsNoteCaption( pOldObject ) )
1576         {
1577             // #116235#
1578             SdrObject* pNewObject = pOldObject->Clone();
1579             //SdrObject* pNewObject = pOldObject->Clone( pDestPage, this );
1580             pNewObject->SetModel(this);
1581             pNewObject->SetPage(pDestPage);
1582 
1583             if ( bMirrorObj )
1584                 MirrorRTL( pNewObject );        // first mirror, then move
1585 
1586             pNewObject->NbcMove( aMove );
1587             if ( bResize )
1588                 pNewObject->NbcResize( aRefPos, aHorFract, aVerFract );
1589 
1590             pDestPage->InsertObject( pNewObject );
1591             if (bRecording)
1592                         AddCalcUndo< SdrUndoInsertObj >( *pNewObject );
1593 
1594             //#i110034# handle chart data references (after InsertObject)
1595 
1596             if ( pNewObject->GetObjIdentifier() == OBJ_OLE2 )
1597             {
1598                 uno::Reference< embed::XEmbeddedObject > xIPObj = ((SdrOle2Obj*)pNewObject)->GetObjRef();
1599                 uno::Reference< embed::XClassifiedObject > xClassified( xIPObj, uno::UNO_QUERY );
1600                 SvGlobalName aObjectClassName;
1601                 if ( xClassified.is() )
1602                 {
1603                     try {
1604                         aObjectClassName = SvGlobalName( xClassified->getClassID() );
1605                     } catch( uno::Exception& )
1606                     {
1607                         // TODO: handle error?
1608                     }
1609                 }
1610 
1611                 if ( xIPObj.is() && SotExchange::IsChart( aObjectClassName ) )
1612                 {
1613                     uno::Reference< chart2::XChartDocument > xNewChart( ScChartHelper::GetChartFromSdrObject( pNewObject ) );
1614                     if( xNewChart.is() && !xNewChart->hasInternalDataProvider() )
1615                     {
1616                         String aChartName = ((SdrOle2Obj*)pNewObject)->GetPersistName();
1617                         ::std::vector< ScRangeList > aRangesVector;
1618                         pDoc->GetChartRanges( aChartName, aRangesVector, pDoc );
1619                         if( !aRangesVector.empty() )
1620                         {
1621                             sal_Bool bInSourceRange = sal_False;
1622                             ScRange aClipRange;
1623                             if ( pClipDoc )
1624                             {
1625                                 SCCOL nClipStartX;
1626                                 SCROW nClipStartY;
1627                                 SCCOL nClipEndX;
1628                                 SCROW nClipEndY;
1629                                 pClipDoc->GetClipStart( nClipStartX, nClipStartY );
1630                                 pClipDoc->GetClipArea( nClipEndX, nClipEndY, sal_True );
1631                                 nClipEndX = nClipEndX + nClipStartX;
1632                                 nClipEndY += nClipStartY;   // GetClipArea returns the difference
1633 
1634                                 SCTAB nClipTab = bRestoreDestTabName ? nDestTab : nSourceTab;
1635                                 aClipRange = ScRange( nClipStartX, nClipStartY, nClipTab,
1636                                                         nClipEndX, nClipEndY, nClipTab );
1637 
1638                                 bInSourceRange = lcl_IsAllInRange( aRangesVector, aClipRange );
1639                             }
1640 
1641                             // always lose references when pasting into a clipboard document (transpose)
1642                             if ( ( bInSourceRange || bSameDoc ) && !bDestClip )
1643                             {
1644                                 if ( bInSourceRange )
1645                                 {
1646                                     if ( rDestPos != aClipRange.aStart )
1647                                     {
1648                                         //  update the data ranges to the new (copied) position
1649                                         if ( lcl_MoveRanges( aRangesVector, aClipRange, rDestPos ) )
1650                                             pDoc->SetChartRanges( aChartName, aRangesVector );
1651                                     }
1652                                 }
1653                                 else
1654                                 {
1655                                     //  leave the ranges unchanged
1656                                 }
1657                             }
1658                             else
1659                             {
1660                                 //  pasting into a new document without the complete source data
1661                                 //  -> break connection to source data and switch to own data
1662 
1663                                 uno::Reference< chart::XChartDocument > xOldChartDoc( ScChartHelper::GetChartFromSdrObject( pOldObject ), uno::UNO_QUERY );
1664                                 uno::Reference< chart::XChartDocument > xNewChartDoc( xNewChart, uno::UNO_QUERY );
1665                                 if( xOldChartDoc.is() && xNewChartDoc.is() )
1666                                     xNewChartDoc->attachData( xOldChartDoc->getData() );
1667 
1668                                 //  (see ScDocument::UpdateChartListenerCollection, PastingDrawFromOtherDoc)
1669                             }
1670                         }
1671                     }
1672                 }
1673             }
1674         }
1675 
1676         pOldObject = aIter.Next();
1677     }
1678 
1679     if( bRestoreDestTabName )
1680         pDoc->RenameTab( nDestTab, aDestTabName );
1681 }
1682 
MirrorRTL(SdrObject * pObj)1683 void ScDrawLayer::MirrorRTL( SdrObject* pObj )
1684 {
1685     sal_uInt16 nIdent = pObj->GetObjIdentifier();
1686 
1687     //  don't mirror OLE or graphics, otherwise ask the object
1688     //  if it can be mirrored
1689     sal_Bool bCanMirror = ( nIdent != OBJ_GRAF && nIdent != OBJ_OLE2 );
1690     if (bCanMirror)
1691     {
1692         SdrObjTransformInfoRec aInfo;
1693         pObj->TakeObjInfo( aInfo );
1694         bCanMirror = aInfo.bMirror90Allowed;
1695     }
1696 
1697     if (bCanMirror)
1698     {
1699         Point aRef1( 0, 0 );
1700         Point aRef2( 0, 1 );
1701         if (bRecording)
1702                     AddCalcUndo< SdrUndoGeoObj >( *pObj );
1703         pObj->Mirror( aRef1, aRef2 );
1704     }
1705     else
1706     {
1707         //  Move instead of mirroring:
1708         //  New start position is negative of old end position
1709         //  -> move by sum of start and end position
1710         Rectangle aObjRect = pObj->GetLogicRect();
1711         Size aMoveSize( -(aObjRect.Left() + aObjRect.Right()), 0 );
1712         if (bRecording)
1713                     AddCalcUndo< SdrUndoMoveObj >( *pObj, aMoveSize );
1714         pObj->Move( aMoveSize );
1715     }
1716 }
1717 
1718 // static
MirrorRectRTL(Rectangle & rRect)1719 void ScDrawLayer::MirrorRectRTL( Rectangle& rRect )
1720 {
1721     //  mirror and swap left/right
1722     long nTemp = rRect.Left();
1723     rRect.Left() = -rRect.Right();
1724     rRect.Right() = -nTemp;
1725 }
1726 
GetCellRect(ScDocument & rDoc,const ScAddress & rPos,bool bMergedCell)1727 Rectangle ScDrawLayer::GetCellRect( ScDocument& rDoc, const ScAddress& rPos, bool bMergedCell )
1728 {
1729     Rectangle aCellRect;
1730     DBG_ASSERT( ValidColRowTab( rPos.Col(), rPos.Row(), rPos.Tab() ), "ScDrawLayer::GetCellRect - invalid cell address" );
1731     if( ValidColRowTab( rPos.Col(), rPos.Row(), rPos.Tab() ) )
1732     {
1733         // find top left position of passed cell address
1734         Point aTopLeft;
1735         for( SCCOL nCol = 0; nCol < rPos.Col(); ++nCol )
1736             aTopLeft.X() += rDoc.GetColWidth( nCol, rPos.Tab() );
1737         if( rPos.Row() > 0 )
1738             aTopLeft.Y() += rDoc.GetRowHeight( 0, rPos.Row() - 1, rPos.Tab() );
1739 
1740         // find bottom-right position of passed cell address
1741         ScAddress aEndPos = rPos;
1742         if( bMergedCell )
1743         {
1744             const ScMergeAttr* pMerge = static_cast< const ScMergeAttr* >( rDoc.GetAttr( rPos.Col(), rPos.Row(), rPos.Tab(), ATTR_MERGE ) );
1745             if( pMerge->GetColMerge() > 1 )
1746                 aEndPos.IncCol( pMerge->GetColMerge() - 1 );
1747             if( pMerge->GetRowMerge() > 1 )
1748                 aEndPos.IncRow( pMerge->GetRowMerge() - 1 );
1749         }
1750         Point aBotRight = aTopLeft;
1751         for( SCCOL nCol = rPos.Col(); nCol <= aEndPos.Col(); ++nCol )
1752             aBotRight.X() += rDoc.GetColWidth( nCol, rPos.Tab() );
1753         aBotRight.Y() += rDoc.GetRowHeight( rPos.Row(), aEndPos.Row(), rPos.Tab() );
1754 
1755         // twips -> 1/100 mm
1756         aTopLeft.X() = static_cast< long >( aTopLeft.X() * HMM_PER_TWIPS );
1757         aTopLeft.Y() = static_cast< long >( aTopLeft.Y() * HMM_PER_TWIPS );
1758         aBotRight.X() = static_cast< long >( aBotRight.X() * HMM_PER_TWIPS );
1759         aBotRight.Y() = static_cast< long >( aBotRight.Y() * HMM_PER_TWIPS );
1760 
1761         aCellRect = Rectangle( aTopLeft, aBotRight );
1762         if( rDoc.IsNegativePage( rPos.Tab() ) )
1763             MirrorRectRTL( aCellRect );
1764     }
1765     return aCellRect;
1766 }
1767 
1768 // static
GetVisibleName(SdrObject * pObj)1769 String ScDrawLayer::GetVisibleName( SdrObject* pObj )
1770 {
1771     String aName = pObj->GetName();
1772     if ( pObj->GetObjIdentifier() == OBJ_OLE2 )
1773     {
1774         //  #95575# For OLE, the user defined name (GetName) is used
1775         //  if it's not empty (accepting possibly duplicate names),
1776         //  otherwise the persist name is used so every object appears
1777         //  in the Navigator at all.
1778 
1779         if ( !aName.Len() )
1780             aName = static_cast<SdrOle2Obj*>(pObj)->GetPersistName();
1781     }
1782     return aName;
1783 }
1784 
IsNamedObject(SdrObject * pObj,const String & rName)1785 inline sal_Bool IsNamedObject( SdrObject* pObj, const String& rName )
1786 {
1787     //  sal_True if rName is the object's Name or PersistName
1788     //  (used to find a named object)
1789 
1790     return ( pObj->GetName() == rName ||
1791             ( pObj->GetObjIdentifier() == OBJ_OLE2 &&
1792               static_cast<SdrOle2Obj*>(pObj)->GetPersistName() == rName ) );
1793 }
1794 
GetNamedObject(const String & rName,sal_uInt16 nId,SCTAB & rFoundTab) const1795 SdrObject* ScDrawLayer::GetNamedObject( const String& rName, sal_uInt16 nId, SCTAB& rFoundTab ) const
1796 {
1797     sal_uInt16 nTabCount = GetPageCount();
1798     for (sal_uInt16 nTab=0; nTab<nTabCount; nTab++)
1799     {
1800         const SdrPage* pPage = GetPage(nTab);
1801         DBG_ASSERT(pPage,"Page ?");
1802         if (pPage)
1803         {
1804             SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS );
1805             SdrObject* pObject = aIter.Next();
1806             while (pObject)
1807             {
1808                 if ( nId == 0 || pObject->GetObjIdentifier() == nId )
1809                     if ( IsNamedObject( pObject, rName ) )
1810                     {
1811                         rFoundTab = static_cast<SCTAB>(nTab);
1812                         return pObject;
1813                     }
1814 
1815                 pObject = aIter.Next();
1816             }
1817         }
1818     }
1819 
1820     return NULL;
1821 }
1822 
GetNewGraphicName(long * pnCounter) const1823 String ScDrawLayer::GetNewGraphicName( long* pnCounter ) const
1824 {
1825     String aBase = ScGlobal::GetRscString(STR_GRAPHICNAME);
1826     aBase += ' ';
1827 
1828     sal_Bool bThere = sal_True;
1829     String aGraphicName;
1830     SCTAB nDummy;
1831     long nId = pnCounter ? *pnCounter : 0;
1832     while (bThere)
1833     {
1834         ++nId;
1835         aGraphicName = aBase;
1836         aGraphicName += String::CreateFromInt32( nId );
1837         bThere = ( GetNamedObject( aGraphicName, 0, nDummy ) != NULL );
1838     }
1839 
1840     if ( pnCounter )
1841         *pnCounter = nId;
1842 
1843     return aGraphicName;
1844 }
1845 
EnsureGraphicNames()1846 void ScDrawLayer::EnsureGraphicNames()
1847 {
1848     //  make sure all graphic objects have names (after Excel import etc.)
1849 
1850     sal_uInt16 nTabCount = GetPageCount();
1851     for (sal_uInt16 nTab=0; nTab<nTabCount; nTab++)
1852     {
1853         SdrPage* pPage = GetPage(nTab);
1854         DBG_ASSERT(pPage,"Page ?");
1855         if (pPage)
1856         {
1857             SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS );
1858             SdrObject* pObject = aIter.Next();
1859 
1860             /* #101799# The index passed to GetNewGraphicName() will be set to
1861                 the used index in each call. This prevents the repeated search
1862                 for all names from 1 to current index. */
1863             long nCounter = 0;
1864 
1865             while (pObject)
1866             {
1867                 if ( pObject->GetObjIdentifier() == OBJ_GRAF && pObject->GetName().Len() == 0 )
1868                     pObject->SetName( GetNewGraphicName( &nCounter ) );
1869 
1870                 pObject = aIter.Next();
1871             }
1872         }
1873     }
1874 }
1875 
SetAnchor(SdrObject * pObj,ScAnchorType eType)1876 void ScDrawLayer::SetAnchor( SdrObject* pObj, ScAnchorType eType )
1877 {
1878     ScAnchorType eOldAnchorType = GetAnchor( pObj );
1879 
1880     // Ein an der Seite verankertes Objekt zeichnet sich durch eine Anker-Pos
1881     // von (0,1) aus. Das ist ein shabby Trick, der aber funktioniert!
1882     Point aAnchor( 0, eType == SCA_PAGE ? 1 : 0 );
1883     pObj->SetAnchorPos( aAnchor );
1884 
1885     if ( eOldAnchorType != eType )
1886         pObj->notifyShapePropertyChange( ::svx::eSpreadsheetAnchor );
1887 }
1888 
GetAnchor(const SdrObject * pObj)1889 ScAnchorType ScDrawLayer::GetAnchor( const SdrObject* pObj )
1890 {
1891     Point aAnchor( pObj->GetAnchorPos() );
1892     return ( aAnchor.Y() != 0 ) ? SCA_PAGE : SCA_CELL;
1893 }
1894 
GetObjData(SdrObject * pObj,sal_Bool bCreate)1895 ScDrawObjData* ScDrawLayer::GetObjData( SdrObject* pObj, sal_Bool bCreate )     // static
1896 {
1897     sal_uInt16 nCount = pObj ? pObj->GetUserDataCount() : 0;
1898     for( sal_uInt16 i = 0; i < nCount; i++ )
1899     {
1900         SdrObjUserData* pData = pObj->GetUserData( i );
1901         if( pData && pData->GetInventor() == SC_DRAWLAYER
1902                     && pData->GetId() == SC_UD_OBJDATA )
1903             return (ScDrawObjData*) pData;
1904     }
1905     if( pObj && bCreate )
1906     {
1907         ScDrawObjData* pData = new ScDrawObjData;
1908         pObj->InsertUserData( pData, 0 );
1909         return pData;
1910     }
1911     return 0;
1912 }
1913 
GetObjDataTab(SdrObject * pObj,SCTAB nTab)1914 ScDrawObjData* ScDrawLayer::GetObjDataTab( SdrObject* pObj, SCTAB nTab )    // static
1915 {
1916     ScDrawObjData* pData = GetObjData( pObj );
1917     if ( pData )
1918     {
1919         if ( pData->maStart.IsValid() )
1920             pData->maStart.SetTab( nTab );
1921         if ( pData->maEnd.IsValid() )
1922             pData->maEnd.SetTab( nTab );
1923     }
1924     return pData;
1925 }
1926 
IsNoteCaption(SdrObject * pObj)1927 bool ScDrawLayer::IsNoteCaption( SdrObject* pObj )
1928 {
1929     ScDrawObjData* pData = pObj ? GetObjData( pObj ) : 0;
1930     return pData && pData->mbNote;
1931 }
1932 
GetNoteCaptionData(SdrObject * pObj,SCTAB nTab)1933 ScDrawObjData* ScDrawLayer::GetNoteCaptionData( SdrObject* pObj, SCTAB nTab )
1934 {
1935     ScDrawObjData* pData = pObj ? GetObjDataTab( pObj, nTab ) : 0;
1936     return (pData && pData->mbNote) ? pData : 0;
1937 }
1938 
GetIMapInfo(SdrObject * pObj)1939 ScIMapInfo* ScDrawLayer::GetIMapInfo( SdrObject* pObj )             // static
1940 {
1941     sal_uInt16 nCount = pObj->GetUserDataCount();
1942     for( sal_uInt16 i = 0; i < nCount; i++ )
1943     {
1944         SdrObjUserData* pData = pObj->GetUserData( i );
1945         if( pData && pData->GetInventor() == SC_DRAWLAYER
1946                     && pData->GetId() == SC_UD_IMAPDATA )
1947             return (ScIMapInfo*) pData;
1948     }
1949     return NULL;
1950 }
1951 
1952 // static:
GetHitIMapObject(SdrObject * pObj,const Point & rWinPoint,const Window & rCmpWnd)1953 IMapObject* ScDrawLayer::GetHitIMapObject( SdrObject* pObj,
1954                                           const Point& rWinPoint, const Window& rCmpWnd )
1955 {
1956     const MapMode       aMap100( MAP_100TH_MM );
1957     MapMode             aWndMode = rCmpWnd.GetMapMode();
1958     Point               aRelPoint( rCmpWnd.LogicToLogic( rWinPoint, &aWndMode, &aMap100 ) );
1959     Rectangle           aLogRect = rCmpWnd.LogicToLogic( pObj->GetLogicRect(), &aWndMode, &aMap100 );
1960     ScIMapInfo*         pIMapInfo = GetIMapInfo( pObj );
1961     IMapObject*         pIMapObj = NULL;
1962 
1963     if ( pIMapInfo )
1964     {
1965         Size        aGraphSize;
1966         ImageMap&   rImageMap = (ImageMap&) pIMapInfo->GetImageMap();
1967         Graphic     aGraphic;
1968         sal_Bool        bObjSupported = sal_False;
1969 
1970         if ( pObj->ISA( SdrGrafObj )  ) // einfaches Grafik-Objekt
1971         {
1972             const SdrGrafObj*   pGrafObj = (const SdrGrafObj*) pObj;
1973             const GeoStat&      rGeo = pGrafObj->GetGeoStat();
1974             const Graphic&      rGraphic = pGrafObj->GetGraphic();
1975 
1976             // Drehung rueckgaengig
1977             if ( rGeo.nDrehWink )
1978                 RotatePoint( aRelPoint, aLogRect.TopLeft(), -rGeo.nSin, rGeo.nCos );
1979 
1980             // Spiegelung rueckgaengig
1981             if ( ( (const SdrGrafObjGeoData*) pGrafObj->GetGeoData() )->bMirrored )
1982                 aRelPoint.X() = aLogRect.Right() + aLogRect.Left() - aRelPoint.X();
1983 
1984             // ggf. Unshear:
1985             if ( rGeo.nShearWink )
1986                 ShearPoint( aRelPoint, aLogRect.TopLeft(), -rGeo.nTan );
1987 
1988 
1989             if ( rGraphic.GetPrefMapMode().GetMapUnit() == MAP_PIXEL )
1990                 aGraphSize = rCmpWnd.PixelToLogic( rGraphic.GetPrefSize(),
1991                                                          aMap100 );
1992             else
1993                 aGraphSize = OutputDevice::LogicToLogic( rGraphic.GetPrefSize(),
1994                                                          rGraphic.GetPrefMapMode(),
1995                                                          aMap100 );
1996 
1997             bObjSupported = sal_True;
1998         }
1999         else if ( pObj->ISA( SdrOle2Obj ) ) // OLE-Objekt
2000         {
2001             // TODO/LEAN: working with visual area needs running state
2002             aGraphSize = ((SdrOle2Obj*)pObj)->GetOrigObjSize();
2003             bObjSupported = sal_True;
2004         }
2005 
2006         // hat alles geklappt, dann HitTest ausfuehren
2007         if ( bObjSupported )
2008         {
2009             // relativen Mauspunkt berechnen
2010             aRelPoint -= aLogRect.TopLeft();
2011             pIMapObj = rImageMap.GetHitIMapObject( aGraphSize, aLogRect.GetSize(), aRelPoint );
2012         }
2013     }
2014 
2015     return pIMapObj;
2016 }
2017 
GetMacroInfo(SdrObject * pObj,sal_Bool bCreate)2018 ScMacroInfo* ScDrawLayer::GetMacroInfo( SdrObject* pObj, sal_Bool bCreate )             // static
2019 {
2020     sal_uInt16 nCount = pObj->GetUserDataCount();
2021     for( sal_uInt16 i = 0; i < nCount; i++ )
2022     {
2023         SdrObjUserData* pData = pObj->GetUserData( i );
2024         if( pData && pData->GetInventor() == SC_DRAWLAYER
2025                     && pData->GetId() == SC_UD_MACRODATA )
2026             return (ScMacroInfo*) pData;
2027     }
2028     if ( bCreate )
2029     {
2030         ScMacroInfo* pData = new ScMacroInfo;
2031         pObj->InsertUserData( pData, 0 );
2032         return pData;
2033     }
2034     return 0;
2035 }
GetImageMapForObject(SdrObject * pObj)2036 ImageMap* ScDrawLayer::GetImageMapForObject(SdrObject* pObj)
2037 {
2038     ScIMapInfo* pIMapInfo = const_cast<ScIMapInfo*>( GetIMapInfo( pObj ) );
2039     if ( pIMapInfo )
2040     {
2041         return const_cast<ImageMap*>( &(pIMapInfo->GetImageMap()) );
2042     }
2043     return NULL;
2044 }
2045 
GetHyperlinkCount(SdrObject * pObj)2046 sal_Int32 ScDrawLayer::GetHyperlinkCount(SdrObject* pObj)
2047 {
2048     sal_Int32 nHLCount = 0;
2049     ScMacroInfo* pMacroInfo = GetMacroInfo(pObj, sal_False);
2050     if (pMacroInfo)
2051         // MT IA2: GetHlink*( doesn|t exist in DEV300 anymore...
2052         nHLCount = 0; // pMacroInfo->GetHlink().getLength() > 0 ? 1 : 0;
2053     return nHLCount;
2054 }
SetGlobalDrawPersist(SfxObjectShell * pPersist)2055 void ScDrawLayer::SetGlobalDrawPersist(SfxObjectShell* pPersist)            // static
2056 {
2057     DBG_ASSERT(!pGlobalDrawPersist,"SetGlobalDrawPersist mehrfach");
2058     pGlobalDrawPersist = pPersist;
2059 }
2060 
SetChanged(sal_Bool bFlg)2061 void __EXPORT ScDrawLayer::SetChanged( sal_Bool bFlg /* = sal_True */ )
2062 {
2063     if ( bFlg && pDoc )
2064         pDoc->SetChartListenerCollectionNeedsUpdate( sal_True );
2065     FmFormModel::SetChanged( bFlg );
2066 }
2067 
GetDocumentStream(SdrDocumentStreamInfo & rStreamInfo) const2068 SvStream* __EXPORT ScDrawLayer::GetDocumentStream(SdrDocumentStreamInfo& rStreamInfo) const
2069 {
2070     DBG_ASSERT( pDoc, "ScDrawLayer::GetDocumentStream without document" );
2071     if ( !pDoc )
2072         return NULL;
2073 
2074     uno::Reference< embed::XStorage > xStorage = pDoc->GetDocumentShell() ?
2075                                                         pDoc->GetDocumentShell()->GetStorage() :
2076                                                         NULL;
2077     SvStream*   pRet = NULL;
2078 
2079     if( xStorage.is() )
2080     {
2081         if( rStreamInfo.maUserData.Len() &&
2082             ( rStreamInfo.maUserData.GetToken( 0, ':' ) ==
2083               String( RTL_CONSTASCII_USTRINGPARAM( "vnd.sun.star.Package" ) ) ) )
2084         {
2085             const String aPicturePath( rStreamInfo.maUserData.GetToken( 1, ':' ) );
2086 
2087             // graphic from picture stream in picture storage in XML package
2088             if( aPicturePath.GetTokenCount( '/' ) == 2 )
2089             {
2090                 const String aPictureStreamName( aPicturePath.GetToken( 1, '/' ) );
2091                 const String aPictureStorageName( aPicturePath.GetToken( 0, '/' ) );
2092 
2093                 try {
2094                     if ( xStorage->isStorageElement( aPictureStorageName ) )
2095                     {
2096                         uno::Reference< embed::XStorage > xPictureStorage =
2097                                     xStorage->openStorageElement( aPictureStorageName, embed::ElementModes::READ );
2098 
2099                         if( xPictureStorage.is() &&
2100                             xPictureStorage->isStreamElement( aPictureStreamName ) )
2101                         {
2102                             uno::Reference< io::XStream > xStream =
2103                                 xPictureStorage->openStreamElement( aPictureStreamName, embed::ElementModes::READ );
2104                             if ( xStream.is() )
2105                                 pRet = ::utl::UcbStreamHelper::CreateStream( xStream );
2106                         }
2107                     }
2108                 }
2109                 catch( uno::Exception& )
2110                 {
2111                     // TODO: error handling
2112                 }
2113             }
2114         }
2115         // the following code seems to be related to binary format
2116 //REMOVE            else
2117 //REMOVE            {
2118 //REMOVE                pRet = pStor->OpenStream( String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM(STRING_SCSTREAM)),
2119 //REMOVE                                          STREAM_READ | STREAM_WRITE | STREAM_TRUNC );
2120 //REMOVE
2121 //REMOVE                if( pRet )
2122 //REMOVE                {
2123 //REMOVE                    pRet->SetVersion( pStor->GetVersion() );
2124 //REMOVE                    pRet->SetKey( pStor->GetKey() );
2125 //REMOVE                }
2126 //REMOVE            }
2127 
2128         rStreamInfo.mbDeleteAfterUse = ( pRet != NULL );
2129     }
2130 
2131     return pRet;
2132 }
2133 
2134 //REMOVE    void ScDrawLayer::ReleasePictureStorage()
2135 //REMOVE    {
2136 //REMOVE        xPictureStorage.Clear();
2137 //REMOVE    }
2138 
GetControlExportLayerId(const SdrObject &) const2139 SdrLayerID __EXPORT ScDrawLayer::GetControlExportLayerId( const SdrObject & ) const
2140 {
2141     //  Layer fuer Export von Form-Controls in Versionen vor 5.0 - immer SC_LAYER_FRONT
2142     return SC_LAYER_FRONT;
2143 }
2144 
createUnoModel()2145 ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > ScDrawLayer::createUnoModel()
2146 {
2147     ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface > xRet;
2148     if( pDoc && pDoc->GetDocumentShell() )
2149         xRet = pDoc->GetDocumentShell()->GetModel();
2150 
2151     return xRet;
2152 }
2153