xref: /trunk/main/sc/source/ui/app/transobj.cxx (revision 8a25ac931fc787de81e5f3df2b9fd16cf4ddb14c)
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 
27 // INCLUDE ---------------------------------------------------------------
28 
29 
30 
31 #include "scitems.hxx"
32 #include <editeng/eeitem.hxx>
33 
34 
35 #include <com/sun/star/uno/Sequence.hxx>
36 #include <com/sun/star/embed/XTransactedObject.hpp>
37 
38 #include <unotools/tempfile.hxx>
39 #include <unotools/ucbstreamhelper.hxx>
40 #include <comphelper/storagehelper.hxx>
41 #include <sot/storage.hxx>
42 #include <vcl/svapp.hxx>
43 #include <vcl/virdev.hxx>
44 #include <vos/mutex.hxx>
45 #include <sfx2/app.hxx>
46 #include <sfx2/docfile.hxx>
47 
48 #include "transobj.hxx"
49 #include "document.hxx"
50 #include "viewopti.hxx"
51 #include "editutil.hxx"
52 #include "impex.hxx"
53 #include "cell.hxx"
54 #include "printfun.hxx"
55 #include "docfunc.hxx"
56 #include "scmod.hxx"
57 
58 // for InitDocShell
59 #include <editeng/paperinf.hxx>
60 #include <editeng/sizeitem.hxx>
61 #include <svx/algitem.hxx>
62 #include <svl/intitem.hxx>
63 #include <svl/zforlist.hxx>
64 #include "docsh.hxx"
65 #include "markdata.hxx"
66 #include "stlpool.hxx"
67 #include "viewdata.hxx"
68 #include "dociter.hxx"
69 #include "cellsuno.hxx"
70 
71 using namespace com::sun::star;
72 
73 // -----------------------------------------------------------------------
74 
75 #define SCTRANS_TYPE_IMPEX          1
76 #define SCTRANS_TYPE_EDIT_RTF       2
77 #define SCTRANS_TYPE_EDIT_BIN       3
78 #define SCTRANS_TYPE_EMBOBJ         4
79 
80 // -----------------------------------------------------------------------
81 
82 // static
83 void ScTransferObj::GetAreaSize( ScDocument* pDoc, SCTAB nTab1, SCTAB nTab2, SCROW& nRow, SCCOL& nCol )
84 {
85     SCCOL nMaxCol = 0;
86     SCROW nMaxRow = 0;
87     for( SCTAB nTab = nTab1; nTab <= nTab2; nTab++ )
88     {
89         SCCOL nLastCol = 0;
90         SCROW nLastRow = 0;
91         // GetPrintArea instead of GetCellArea - include drawing objects
92         if( pDoc->GetPrintArea( nTab, nLastCol, nLastRow ) )
93         {
94             if( nLastCol > nMaxCol )
95                 nMaxCol = nLastCol;
96             if( nLastRow > nMaxRow  )
97                 nMaxRow = nLastRow;
98         }
99     }
100     nRow = nMaxRow;
101     nCol = nMaxCol;
102 }
103 
104 // static
105 void ScTransferObj::PaintToDev( OutputDevice* pDev, ScDocument* pDoc, double nPrintFactor,
106                                 const ScRange& rBlock, sal_Bool bMetaFile )
107 {
108     if (!pDoc)
109         return;
110 
111     Point aPoint;
112     Rectangle aBound( aPoint, pDev->GetOutputSize() );      //! use size from clip area?
113 
114     ScViewData aViewData(NULL,NULL);
115     aViewData.InitData( pDoc );
116 
117     aViewData.SetTabNo( rBlock.aEnd.Tab() );
118     aViewData.SetScreen( rBlock.aStart.Col(), rBlock.aStart.Row(),
119                             rBlock.aEnd.Col(), rBlock.aEnd.Row() );
120 
121     ScPrintFunc::DrawToDev( pDoc, pDev, nPrintFactor, aBound, &aViewData, bMetaFile );
122 }
123 
124 // -----------------------------------------------------------------------
125 
126 ScTransferObj::ScTransferObj( ScDocument* pClipDoc, const TransferableObjectDescriptor& rDesc ) :
127     pDoc( pClipDoc ),
128     aObjDesc( rDesc ),
129     nDragHandleX( 0 ),
130     nDragHandleY( 0 ),
131     nDragSourceFlags( 0 ),
132     bDragWasInternal( sal_False ),
133     bUsedForLink( sal_False ),
134     bUseInApi( false )
135 {
136     DBG_ASSERT(pDoc->IsClipboard(), "wrong document");
137 
138     //
139     // get aBlock from clipboard doc
140     //
141 
142     SCCOL nCol1;
143     SCROW nRow1;
144     SCCOL nCol2;
145     SCROW nRow2;
146     pDoc->GetClipStart( nCol1, nRow1 );
147     pDoc->GetClipArea( nCol2, nRow2, sal_True );    // real source area - include filtered rows
148     nCol2 = sal::static_int_cast<SCCOL>( nCol2 + nCol1 );
149     nRow2 = sal::static_int_cast<SCROW>( nRow2 + nRow1 );
150 
151     SCCOL nDummy;
152     pDoc->GetClipArea( nDummy, nNonFiltered, sal_False );
153     bHasFiltered = (nNonFiltered < (nRow2 - nRow1));
154     ++nNonFiltered;     // to get count instead of diff
155 
156     SCTAB nTab1=0;
157     SCTAB nTab2=0;
158     sal_Bool bFirst = sal_True;
159     for (SCTAB i=0; i<=MAXTAB; i++)
160         if (pDoc->HasTable(i))
161         {
162             if (bFirst)
163                 nTab1 = i;
164             nTab2 = i;
165             bFirst = sal_False;
166         }
167     DBG_ASSERT(!bFirst, "no sheet selected");
168 
169     //  only limit to used cells if whole sheet was marked
170     //  (so empty cell areas can be copied)
171     if ( nCol2>=MAXCOL && nRow2>=MAXROW )
172     {
173         SCROW nMaxRow;
174         SCCOL nMaxCol;
175         GetAreaSize( pDoc, nTab1, nTab2, nMaxRow, nMaxCol );
176         if( nMaxRow < nRow2 )
177             nRow2 = nMaxRow;
178         if( nMaxCol < nCol2 )
179             nCol2 = nMaxCol;
180     }
181 
182     aBlock = ScRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
183     nVisibleTab = nTab1;    // valid table as default
184 
185     Rectangle aMMRect = pDoc->GetMMRect( nCol1,nRow1, nCol2,nRow2, nTab1 );
186     aObjDesc.maSize = aMMRect.GetSize();
187     PrepareOLE( aObjDesc );
188 }
189 
190 ScTransferObj::~ScTransferObj()
191 {
192     Application::GetSolarMutex().acquire();
193 
194     ScModule* pScMod = SC_MOD();
195     if ( pScMod->GetClipData().pCellClipboard == this )
196     {
197         DBG_ERROR("ScTransferObj wasn't released");
198         pScMod->SetClipObject( NULL, NULL );
199     }
200     if ( pScMod->GetDragData().pCellTransfer == this )
201     {
202         DBG_ERROR("ScTransferObj wasn't released");
203         pScMod->ResetDragObject();
204     }
205 
206     delete pDoc;        // ScTransferObj is owner of clipboard document
207 
208     aDocShellRef.Clear();   // before releasing the mutex
209 
210     aDrawPersistRef.Clear();                    // after the model
211 
212     Application::GetSolarMutex().release();
213 }
214 
215 // static
216 ScTransferObj* ScTransferObj::GetOwnClipboard( Window* pUIWin )
217 {
218     ScTransferObj* pObj = SC_MOD()->GetClipData().pCellClipboard;
219     if ( pObj && pUIWin )
220     {
221         //  check formats to see if pObj is really in the system clipboard
222 
223         //  pUIWin is NULL when called from core (IsClipboardSource),
224         //  in that case don't access the system clipboard, because the call
225         //  may be from other clipboard operations (like flushing, #86059#)
226 
227         TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pUIWin ) );
228         if ( !aDataHelper.HasFormat( SOT_FORMATSTR_ID_DIF ) )
229         {
230 //          DBG_ERROR("ScTransferObj wasn't released");
231             pObj = NULL;
232         }
233     }
234     return pObj;
235 }
236 
237 void ScTransferObj::AddSupportedFormats()
238 {
239     AddFormat( SOT_FORMATSTR_ID_EMBED_SOURCE );
240     AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR );
241     AddFormat( SOT_FORMAT_GDIMETAFILE );
242     AddFormat( SOT_FORMAT_BITMAP );
243 
244     // ScImportExport formats
245     AddFormat( SOT_FORMATSTR_ID_HTML );
246     AddFormat( SOT_FORMATSTR_ID_SYLK );
247     AddFormat( SOT_FORMATSTR_ID_LINK );
248     AddFormat( SOT_FORMATSTR_ID_DIF );
249     AddFormat( SOT_FORMAT_STRING );
250 
251     AddFormat( SOT_FORMAT_RTF );
252     if ( aBlock.aStart == aBlock.aEnd )
253         AddFormat( SOT_FORMATSTR_ID_EDITENGINE );
254 }
255 
256 sal_Bool ScTransferObj::GetData( const datatransfer::DataFlavor& rFlavor )
257 {
258     sal_uInt32  nFormat = SotExchange::GetFormat( rFlavor );
259     sal_Bool    bOK = sal_False;
260 
261     if( HasFormat( nFormat ) )
262     {
263         if ( nFormat == SOT_FORMATSTR_ID_LINKSRCDESCRIPTOR || nFormat == SOT_FORMATSTR_ID_OBJECTDESCRIPTOR )
264         {
265             bOK = SetTransferableObjectDescriptor( aObjDesc, rFlavor );
266         }
267         else if ( ( nFormat == SOT_FORMAT_RTF || nFormat == SOT_FORMATSTR_ID_EDITENGINE ) &&
268                         aBlock.aStart == aBlock.aEnd )
269         {
270             //  RTF from a single cell is handled by EditEngine
271 
272             SCCOL nCol = aBlock.aStart.Col();
273             SCROW nRow = aBlock.aStart.Row();
274             SCTAB nTab = aBlock.aStart.Tab();
275 
276             const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
277             ScTabEditEngine aEngine( *pPattern, pDoc->GetEditPool() );
278             ScBaseCell* pCell = NULL;
279             pDoc->GetCell( nCol, nRow, nTab, pCell );
280             if (pCell)
281             {
282                 if (pCell->GetCellType() == CELLTYPE_EDIT)
283                 {
284                     const EditTextObject* pObj;
285                     ((ScEditCell*)pCell)->GetData(pObj);
286                     aEngine.SetText( *pObj );
287                 }
288                 else
289                 {
290                     String aText;
291                     pDoc->GetString( nCol, nRow, nTab, aText );
292                     aEngine.SetText(aText);
293                 }
294             }
295 
296             bOK = SetObject( &aEngine,
297                             (nFormat == FORMAT_RTF) ? SCTRANS_TYPE_EDIT_RTF : SCTRANS_TYPE_EDIT_BIN,
298                             rFlavor );
299         }
300         else if ( ScImportExport::IsFormatSupported( nFormat ) || nFormat == SOT_FORMAT_RTF )
301         {
302             //  if this transfer object was used to create a DDE link, filtered rows
303             //  have to be included for subsequent calls (to be consistent with link data)
304             if ( nFormat == SOT_FORMATSTR_ID_LINK )
305                 bUsedForLink = sal_True;
306 
307             sal_Bool bIncludeFiltered = pDoc->IsCutMode() || bUsedForLink;
308 
309             ScImportExport aObj( pDoc, aBlock );
310             if ( bUsedForLink )
311                 aObj.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::ToSpace, ' ', false ) );
312             aObj.SetFormulas( pDoc->GetViewOptions().GetOption( VOPT_FORMULAS ) );
313             aObj.SetIncludeFiltered( bIncludeFiltered );
314 
315             //  DataType depends on format type:
316 
317             if ( rFlavor.DataType.equals( ::getCppuType( (const ::rtl::OUString*) 0 ) ) )
318             {
319                 rtl::OUString aString;
320                 if ( aObj.ExportString( aString, nFormat ) )
321                     bOK = SetString( aString, rFlavor );
322             }
323             else if ( rFlavor.DataType.equals( ::getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) ) )
324             {
325                 //  SetObject converts a stream into a Int8-Sequence
326                 bOK = SetObject( &aObj, SCTRANS_TYPE_IMPEX, rFlavor );
327             }
328             else
329             {
330                 DBG_ERROR("unknown DataType");
331             }
332         }
333         else if ( nFormat == SOT_FORMAT_BITMAP )
334         {
335             Rectangle aMMRect = pDoc->GetMMRect( aBlock.aStart.Col(), aBlock.aStart.Row(),
336                                                  aBlock.aEnd.Col(), aBlock.aEnd.Row(),
337                                                  aBlock.aStart.Tab() );
338             VirtualDevice aVirtDev;
339             aVirtDev.SetOutputSizePixel( aVirtDev.LogicToPixel( aMMRect.GetSize(), MAP_100TH_MM ) );
340 
341             PaintToDev( &aVirtDev, pDoc, 1.0, aBlock, sal_False );
342 
343             aVirtDev.SetMapMode( MapMode( MAP_PIXEL ) );
344             Bitmap aBmp = aVirtDev.GetBitmap( Point(), aVirtDev.GetOutputSize() );
345             bOK = SetBitmapEx( aBmp, rFlavor );
346         }
347         else if ( nFormat == SOT_FORMAT_GDIMETAFILE )
348         {
349             // #123405# Do not limit visual size calculation for metafile creation.
350             // It seems unlikely that removing the limitation causes problems since
351             // metafile creation means that no real pixel device in the needed size is
352             // created.
353             InitDocShell(false);
354 
355             SfxObjectShell* pEmbObj = aDocShellRef;
356 
357             // like SvEmbeddedTransfer::GetData:
358             GDIMetaFile     aMtf;
359             VirtualDevice   aVDev;
360             MapMode         aMapMode( pEmbObj->GetMapUnit() );
361             Rectangle       aVisArea( pEmbObj->GetVisArea( ASPECT_CONTENT ) );
362 
363             aVDev.EnableOutput( sal_False );
364             aVDev.SetMapMode( aMapMode );
365             aMtf.SetPrefSize( aVisArea.GetSize() );
366             aMtf.SetPrefMapMode( aMapMode );
367             aMtf.Record( &aVDev );
368 
369             pEmbObj->DoDraw( &aVDev, Point(), aVisArea.GetSize(), JobSetup(), ASPECT_CONTENT );
370 
371             aMtf.Stop();
372             aMtf.WindStart();
373 
374             bOK = SetGDIMetaFile( aMtf, rFlavor );
375         }
376         else if ( nFormat == SOT_FORMATSTR_ID_EMBED_SOURCE )
377         {
378             //TODO/LATER: differentiate between formats?!
379             // #123405# Do limit visual size calculation to PageSize
380             InitDocShell(true);         // set aDocShellRef
381 
382             SfxObjectShell* pEmbObj = aDocShellRef;
383             bOK = SetObject( pEmbObj, SCTRANS_TYPE_EMBOBJ, rFlavor );
384         }
385     }
386     return bOK;
387 }
388 
389 sal_Bool ScTransferObj::WriteObject( SotStorageStreamRef& rxOStm, void* pUserObject, sal_uInt32 nUserObjectId,
390                                         const datatransfer::DataFlavor& rFlavor )
391 {
392     // called from SetObject, put data into stream
393 
394     sal_Bool bRet = sal_False;
395     switch (nUserObjectId)
396     {
397         case SCTRANS_TYPE_IMPEX:
398             {
399                 ScImportExport* pImpEx = (ScImportExport*)pUserObject;
400 
401                 sal_uInt32 nFormat = SotExchange::GetFormat( rFlavor );
402                 // mba: no BaseURL for data exchange
403                 if ( pImpEx->ExportStream( *rxOStm, String(), nFormat ) )
404                     bRet = ( rxOStm->GetError() == ERRCODE_NONE );
405             }
406             break;
407 
408         case SCTRANS_TYPE_EDIT_RTF:
409         case SCTRANS_TYPE_EDIT_BIN:
410             {
411                 ScTabEditEngine* pEngine = (ScTabEditEngine*)pUserObject;
412                 if ( nUserObjectId == SCTRANS_TYPE_EDIT_RTF )
413                 {
414                     pEngine->Write( *rxOStm, EE_FORMAT_RTF );
415                     bRet = ( rxOStm->GetError() == ERRCODE_NONE );
416                 }
417                 else
418                 {
419                     //  #107722# can't use Write for EditEngine format because that would
420                     //  write old format without support for unicode characters.
421                     //  Get the data from the EditEngine's transferable instead.
422 
423                     sal_uInt16 nParCnt = pEngine->GetParagraphCount();
424                     if ( nParCnt == 0 )
425                         nParCnt = 1;
426                     ESelection aSel( 0, 0, nParCnt-1, pEngine->GetTextLen(nParCnt-1) );
427 
428                     uno::Reference<datatransfer::XTransferable> xEditTrans = pEngine->CreateTransferable( aSel );
429                     TransferableDataHelper aEditHelper( xEditTrans );
430 
431                     bRet = aEditHelper.GetSotStorageStream( rFlavor, rxOStm );
432                 }
433             }
434             break;
435 
436         case SCTRANS_TYPE_EMBOBJ:
437             {
438                 // TODO/MBA: testing
439                 SfxObjectShell*   pEmbObj = (SfxObjectShell*) pUserObject;
440                 ::utl::TempFile     aTempFile;
441                 aTempFile.EnableKillingFile();
442                 uno::Reference< embed::XStorage > xWorkStore =
443                     ::comphelper::OStorageHelper::GetStorageFromURL( aTempFile.GetURL(), embed::ElementModes::READWRITE );
444 
445                 // write document storage
446                 pEmbObj->SetupStorage( xWorkStore, SOFFICE_FILEFORMAT_CURRENT, sal_False );
447 
448                 // mba: no relative ULRs for clipboard!
449                 SfxMedium aMedium( xWorkStore, String() );
450                 bRet = pEmbObj->DoSaveObjectAs( aMedium, sal_False );
451                 pEmbObj->DoSaveCompleted();
452 
453                 uno::Reference< embed::XTransactedObject > xTransact( xWorkStore, uno::UNO_QUERY );
454                 if ( xTransact.is() )
455                     xTransact->commit();
456 
457                 SvStream* pSrcStm = ::utl::UcbStreamHelper::CreateStream( aTempFile.GetURL(), STREAM_READ );
458                 if( pSrcStm )
459                 {
460                     rxOStm->SetBufferSize( 0xff00 );
461                     *rxOStm << *pSrcStm;
462                     delete pSrcStm;
463                 }
464 
465                 bRet = sal_True;
466 
467                 xWorkStore->dispose();
468                 xWorkStore = uno::Reference < embed::XStorage >();
469                 rxOStm->Commit();
470             }
471             break;
472 
473         default:
474             DBG_ERROR("unknown object id");
475     }
476     return bRet;
477 }
478 
479 void ScTransferObj::ObjectReleased()
480 {
481     ScModule* pScMod = SC_MOD();
482     if ( pScMod->GetClipData().pCellClipboard == this )
483         pScMod->SetClipObject( NULL, NULL );
484 
485     TransferableHelper::ObjectReleased();
486 }
487 
488 void ScTransferObj::DragFinished( sal_Int8 nDropAction )
489 {
490     if ( nDropAction == DND_ACTION_MOVE && !bDragWasInternal && !(nDragSourceFlags & SC_DROP_NAVIGATOR) )
491     {
492         //  move: delete source data
493         ScDocShell* pSourceSh = GetSourceDocShell();
494         if (pSourceSh)
495         {
496             ScMarkData aMarkData = GetSourceMarkData();
497             //  external drag&drop doesn't copy objects, so they also aren't deleted:
498             //  #105703# bApi=sal_True, don't show error messages from drag&drop
499             pSourceSh->GetDocFunc().DeleteContents( aMarkData, IDF_ALL & ~IDF_OBJECTS, sal_True, sal_True );
500         }
501     }
502 
503     ScModule* pScMod = SC_MOD();
504     if ( pScMod->GetDragData().pCellTransfer == this )
505         pScMod->ResetDragObject();
506 
507     xDragSourceRanges = NULL;       // don't keep source after dropping
508 
509     TransferableHelper::DragFinished( nDropAction );
510 }
511 
512 void ScTransferObj::SetDragHandlePos( SCCOL nX, SCROW nY )
513 {
514     nDragHandleX = nX;
515     nDragHandleY = nY;
516 }
517 
518 void ScTransferObj::SetVisibleTab( SCTAB nNew )
519 {
520     nVisibleTab = nNew;
521 }
522 
523 void ScTransferObj::SetDrawPersist( const SfxObjectShellRef& rRef )
524 {
525     aDrawPersistRef = rRef;
526 }
527 
528 void ScTransferObj::SetDragSource( ScDocShell* pSourceShell, const ScMarkData& rMark )
529 {
530     ScRangeList aRanges;
531     rMark.FillRangeListWithMarks( &aRanges, sal_False );
532     xDragSourceRanges = new ScCellRangesObj( pSourceShell, aRanges );
533 }
534 
535 void ScTransferObj::SetDragSourceFlags( sal_uInt16 nFlags )
536 {
537     nDragSourceFlags = nFlags;
538 }
539 
540 void ScTransferObj::SetDragWasInternal()
541 {
542     bDragWasInternal = sal_True;
543 }
544 
545 void ScTransferObj::SetUseInApi( bool bSet )
546 {
547     bUseInApi = bSet;
548 }
549 
550 ScDocument* ScTransferObj::GetSourceDocument()
551 {
552     ScDocShell* pSourceDocSh = GetSourceDocShell();
553     if (pSourceDocSh)
554         return pSourceDocSh->GetDocument();
555     return NULL;
556 }
557 
558 ScDocShell* ScTransferObj::GetSourceDocShell()
559 {
560     ScCellRangesBase* pRangesObj = ScCellRangesBase::getImplementation( xDragSourceRanges );
561     if (pRangesObj)
562         return pRangesObj->GetDocShell();
563 
564     return NULL;    // none set
565 }
566 
567 ScMarkData ScTransferObj::GetSourceMarkData()
568 {
569     ScMarkData aMarkData;
570     ScCellRangesBase* pRangesObj = ScCellRangesBase::getImplementation( xDragSourceRanges );
571     if (pRangesObj)
572     {
573         const ScRangeList& rRanges = pRangesObj->GetRangeList();
574         aMarkData.MarkFromRangeList( rRanges, sal_False );
575     }
576     return aMarkData;
577 }
578 
579 //
580 //  initialize aDocShellRef with a live document from the ClipDoc
581 //
582 // #123405# added parameter to allow size calculation without limitation
583 // to PageSize, e.g. used for Metafile creation for clipboard.
584 
585 void ScTransferObj::InitDocShell(bool bLimitToPageSize)
586 {
587     if ( !aDocShellRef.Is() )
588     {
589         ScDocShell* pDocSh = new ScDocShell;
590         aDocShellRef = pDocSh;      // ref must be there before InitNew
591 
592         pDocSh->DoInitNew(NULL);
593 
594         ScDocument* pDestDoc = pDocSh->GetDocument();
595         ScMarkData aDestMark;
596         aDestMark.SelectTable( 0, sal_True );
597 
598         pDestDoc->SetDocOptions( pDoc->GetDocOptions() );   // #i42666#
599 
600         String aTabName;
601         pDoc->GetName( aBlock.aStart.Tab(), aTabName );
602         pDestDoc->RenameTab( 0, aTabName, sal_False );          // no UpdateRef (empty)
603 
604         pDestDoc->CopyStdStylesFrom( pDoc );
605 
606         SCCOL nStartX = aBlock.aStart.Col();
607         SCROW nStartY = aBlock.aStart.Row();
608         SCCOL nEndX = aBlock.aEnd.Col();
609         SCROW nEndY = aBlock.aEnd.Row();
610 
611         //  widths / heights
612         //  (must be copied before CopyFromClip, for drawing objects)
613 
614         SCCOL nCol, nLastCol;
615         SCTAB nSrcTab = aBlock.aStart.Tab();
616         pDestDoc->SetLayoutRTL(0, pDoc->IsLayoutRTL(nSrcTab));
617         for (nCol=nStartX; nCol<=nEndX; nCol++)
618             if ( pDoc->ColHidden(nCol, nSrcTab, nLastCol) )
619                 pDestDoc->ShowCol( nCol, 0, sal_False );
620             else
621                 pDestDoc->SetColWidth( nCol, 0, pDoc->GetColWidth( nCol, nSrcTab ) );
622 
623         ScBitMaskCompressedArray< SCROW, sal_uInt8> & rDestRowFlags =
624             pDestDoc->GetRowFlagsArrayModifiable(0);
625 
626         for (SCROW nRow = nStartY; nRow <= nEndY; ++nRow)
627         {
628             sal_uInt8 nSourceFlags = pDoc->GetRowFlags(nRow, nSrcTab);
629             SCROW nLastRow = -1;
630             if ( pDoc->RowHidden(nRow, nSrcTab, nLastRow) )
631                 pDestDoc->ShowRow( nRow, 0, sal_False );
632             else
633             {
634                 pDestDoc->SetRowHeight( nRow, 0, pDoc->GetOriginalHeight( nRow, nSrcTab ) );
635 
636                 //  if height was set manually, that flag has to be copied, too
637                 if ( nSourceFlags & CR_MANUALSIZE )
638                     rDestRowFlags.OrValue( nRow, CR_MANUALSIZE);
639             }
640         }
641 
642         if ( pDoc->GetDrawLayer() )
643             pDocSh->MakeDrawLayer();
644 
645         //  cell range is copied to the original position, but on the first sheet
646         //  -> bCutMode must be set
647         //  pDoc is always a Clipboard-document
648 
649         ScRange aDestRange( nStartX,nStartY,0, nEndX,nEndY,0 );
650         sal_Bool bWasCut = pDoc->IsCutMode();
651         if (!bWasCut)
652             pDoc->SetClipArea( aDestRange, sal_True );          // Cut
653         pDestDoc->CopyFromClip( aDestRange, aDestMark, IDF_ALL, NULL, pDoc, sal_False );
654         pDoc->SetClipArea( aDestRange, bWasCut );
655 
656         StripRefs( pDoc, nStartX,nStartY, nEndX,nEndY, pDestDoc, 0,0 );
657 
658         ScRange aMergeRange = aDestRange;
659         pDestDoc->ExtendMerge( aMergeRange, sal_True );
660 
661         pDoc->CopyDdeLinks( pDestDoc );         // copy values of DDE Links
662 
663         //  page format (grid etc) and page size (maximum size for ole object)
664 
665         Size aPaperSize = SvxPaperInfo::GetPaperSize( PAPER_A4 );       // Twips
666         ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool();
667         String aStyleName = pDoc->GetPageStyle( aBlock.aStart.Tab() );
668         SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SFX_STYLE_FAMILY_PAGE );
669         if (pStyleSheet)
670         {
671             const SfxItemSet& rSourceSet = pStyleSheet->GetItemSet();
672             aPaperSize = ((const SvxSizeItem&) rSourceSet.Get(ATTR_PAGE_SIZE)).GetSize();
673 
674             //  CopyStyleFrom kopiert SetItems mit richtigem Pool
675             ScStyleSheetPool* pDestPool = pDestDoc->GetStyleSheetPool();
676             pDestPool->CopyStyleFrom( pStylePool, aStyleName, SFX_STYLE_FAMILY_PAGE );
677         }
678 
679         ScViewData aViewData( pDocSh, NULL );
680         aViewData.SetScreen( nStartX,nStartY, nEndX,nEndY );
681         aViewData.SetCurX( nStartX );
682         aViewData.SetCurY( nStartY );
683 
684         pDestDoc->SetViewOptions( pDoc->GetViewOptions() );
685 
686         //      Size
687         //! get while copying sizes
688 
689         long nPosX = 0;
690         long nPosY = 0;
691 
692         for (nCol=0; nCol<nStartX; nCol++)
693             nPosX += pDestDoc->GetColWidth( nCol, 0 );
694         nPosY += pDestDoc->GetRowHeight( 0, nStartY-1, 0 );
695         nPosX = (long) ( nPosX * HMM_PER_TWIPS );
696         nPosY = (long) ( nPosY * HMM_PER_TWIPS );
697 
698 
699         aPaperSize.Width()  *= 2;       // limit OLE object to double of page size
700         aPaperSize.Height() *= 2;
701 
702         long nSizeX = 0;
703         long nSizeY = 0;
704         for (nCol=nStartX; nCol<=nEndX; nCol++)
705         {
706             long nAdd = pDestDoc->GetColWidth( nCol, 0 );
707             if ( bLimitToPageSize && nSizeX+nAdd > aPaperSize.Width() && nSizeX )   // above limit?
708                 break;
709             nSizeX += nAdd;
710         }
711         for (SCROW nRow=nStartY; nRow<=nEndY; nRow++)
712         {
713             long nAdd = pDestDoc->GetRowHeight( nRow, 0 );
714             if ( bLimitToPageSize && nSizeY+nAdd > aPaperSize.Height() && nSizeY )  // above limit?
715                 break;
716             nSizeY += nAdd;
717         }
718         nSizeX = (long) ( nSizeX * HMM_PER_TWIPS );
719         nSizeY = (long) ( nSizeY * HMM_PER_TWIPS );
720 
721 //      pDocSh->SetVisAreaSize( Size(nSizeX,nSizeY) );
722 
723         Rectangle aNewArea( Point(nPosX,nPosY), Size(nSizeX,nSizeY) );
724         //TODO/LATER: why twice?!
725         //pDocSh->SvInPlaceObject::SetVisArea( aNewArea );
726         pDocSh->SetVisArea( aNewArea );
727 
728         pDocSh->UpdateOle(&aViewData, sal_True);
729 
730         //! SetDocumentModified?
731         if ( pDestDoc->IsChartListenerCollectionNeedsUpdate() )
732             pDestDoc->UpdateChartListenerCollection();
733     }
734 }
735 
736 //  static
737 SfxObjectShell* ScTransferObj::SetDrawClipDoc( sal_Bool bAnyOle )
738 {
739     // update ScGlobal::pDrawClipDocShellRef
740 
741     delete ScGlobal::pDrawClipDocShellRef;
742     if (bAnyOle)
743     {
744         ScGlobal::pDrawClipDocShellRef =
745                         new ScDocShellRef(new ScDocShell(SFX_CREATE_MODE_INTERNAL));      // there must be a ref
746         (*ScGlobal::pDrawClipDocShellRef)->DoInitNew(NULL);
747         return *ScGlobal::pDrawClipDocShellRef;
748     }
749     else
750     {
751         ScGlobal::pDrawClipDocShellRef = NULL;
752         return NULL;
753     }
754 }
755 
756 //  static
757 void ScTransferObj::StripRefs( ScDocument* pDoc,
758                     SCCOL nStartX, SCROW nStartY, SCCOL nEndX, SCROW nEndY,
759                     ScDocument* pDestDoc, SCCOL nSubX, SCROW nSubY )
760 {
761     if (!pDestDoc)
762     {
763         pDestDoc = pDoc;
764         DBG_ASSERT(nSubX==0&&nSubY==0, "can't move within the document");
765     }
766 
767     //  In a clipboard doc the data don't have to be on the first sheet
768 
769     SCTAB nSrcTab = 0;
770     while (nSrcTab<MAXTAB && !pDoc->HasTable(nSrcTab))
771         ++nSrcTab;
772     SCTAB nDestTab = 0;
773     while (nDestTab<MAXTAB && !pDestDoc->HasTable(nDestTab))
774         ++nDestTab;
775 
776     if (!pDoc->HasTable(nSrcTab) || !pDestDoc->HasTable(nDestTab))
777     {
778         DBG_ERROR("Sheet not found in ScTransferObj::StripRefs");
779         return;
780     }
781 
782     SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
783     ScRange aRef;
784 
785     ScCellIterator aIter( pDoc, nStartX, nStartY, nSrcTab, nEndX, nEndY, nSrcTab );
786     ScBaseCell* pCell = aIter.GetFirst();
787     while (pCell)
788     {
789         if (pCell->GetCellType() == CELLTYPE_FORMULA)
790         {
791             ScFormulaCell* pFCell = (ScFormulaCell*) pCell;
792             sal_Bool bOut = sal_False;
793             ScDetectiveRefIter aRefIter( pFCell );
794             while ( !bOut && aRefIter.GetNextRef( aRef ) )
795             {
796                 if ( aRef.aStart.Tab() != nSrcTab || aRef.aEnd.Tab() != nSrcTab ||
797                         aRef.aStart.Col() < nStartX || aRef.aEnd.Col() > nEndX ||
798                         aRef.aStart.Row() < nStartY || aRef.aEnd.Row() > nEndY )
799                     bOut = sal_True;
800             }
801             if (bOut)
802             {
803                 SCCOL nCol = aIter.GetCol() - nSubX;
804                 SCROW nRow = aIter.GetRow() - nSubY;
805 
806                 ScBaseCell* pNew = 0;
807                 sal_uInt16 nErrCode = pFCell->GetErrCode();
808                 if (nErrCode)
809                 {
810                     pNew = new ScStringCell( ScGlobal::GetErrorString(nErrCode) );
811                     if ( ((const SvxHorJustifyItem*) pDestDoc->GetAttr(
812                             nCol,nRow,nDestTab, ATTR_HOR_JUSTIFY))->GetValue() ==
813                             SVX_HOR_JUSTIFY_STANDARD )
814                         pDestDoc->ApplyAttr( nCol,nRow,nDestTab,
815                                 SvxHorJustifyItem(SVX_HOR_JUSTIFY_RIGHT, ATTR_HOR_JUSTIFY) );
816                 }
817                 else if (pFCell->IsValue())
818                 {
819                     double fVal = pFCell->GetValue();
820                     pNew = new ScValueCell( fVal );
821                 }
822                 else
823                 {
824                     String aStr;
825                     pFCell->GetString(aStr);
826                     if ( pFCell->IsMultilineResult() )
827                         pNew = new ScEditCell( aStr, pDestDoc );
828                     else
829                         pNew = new ScStringCell( aStr );
830                 }
831                 pDestDoc->PutCell( nCol,nRow,nDestTab, pNew );
832 
833                 //  number formats
834 
835                 sal_uLong nOldFormat = ((const SfxUInt32Item*)
836                                 pDestDoc->GetAttr(nCol,nRow,nDestTab, ATTR_VALUE_FORMAT))->GetValue();
837                 if ( (nOldFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
838                 {
839                     sal_uLong nNewFormat = pFCell->GetStandardFormat( *pFormatter,
840                         nOldFormat );
841                     pDestDoc->ApplyAttr( nCol,nRow,nDestTab,
842                                 SfxUInt32Item(ATTR_VALUE_FORMAT, nNewFormat) );
843                 }
844             }
845         }
846         pCell = aIter.GetNext();
847     }
848 }
849 
850 const com::sun::star::uno::Sequence< sal_Int8 >& ScTransferObj::getUnoTunnelId()
851 {
852     static com::sun::star::uno::Sequence< sal_Int8 > aSeq;
853     if( !aSeq.getLength() )
854     {
855         static osl::Mutex           aCreateMutex;
856         osl::Guard< osl::Mutex >    aGuard( aCreateMutex );
857         aSeq.realloc( 16 );
858         rtl_createUuid( reinterpret_cast< sal_uInt8* >( aSeq.getArray() ), 0, sal_True );
859     }
860     return aSeq;
861 }
862 
863 sal_Int64 SAL_CALL ScTransferObj::getSomething( const com::sun::star::uno::Sequence< sal_Int8 >& rId ) throw( com::sun::star::uno::RuntimeException )
864 {
865     sal_Int64 nRet;
866     if( ( rId.getLength() == 16 ) &&
867         ( 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) )
868     {
869         nRet = reinterpret_cast< sal_Int64 >( this );
870     }
871     else
872         nRet = TransferableHelper::getSomething(rId);
873     return nRet;
874 }
875 
876 
877