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
GetAreaSize(ScDocument * pDoc,SCTAB nTab1,SCTAB nTab2,SCROW & nRow,SCCOL & nCol)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
PaintToDev(OutputDevice * pDev,ScDocument * pDoc,double nPrintFactor,const ScRange & rBlock,sal_Bool bMetaFile)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
ScTransferObj(ScDocument * pClipDoc,const TransferableObjectDescriptor & rDesc)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
~ScTransferObj()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
GetOwnClipboard(Window * pUIWin)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
AddSupportedFormats()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_FORMATSTR_ID_PNG );
243 AddFormat( SOT_FORMAT_BITMAP );
244
245 // ScImportExport formats
246 AddFormat( SOT_FORMATSTR_ID_HTML );
247 AddFormat( SOT_FORMATSTR_ID_SYLK );
248 AddFormat( SOT_FORMATSTR_ID_LINK );
249 AddFormat( SOT_FORMATSTR_ID_DIF );
250 AddFormat( SOT_FORMAT_STRING );
251
252 AddFormat( SOT_FORMAT_RTF );
253 if ( aBlock.aStart == aBlock.aEnd )
254 AddFormat( SOT_FORMATSTR_ID_EDITENGINE );
255 }
256
GetData(const datatransfer::DataFlavor & rFlavor)257 sal_Bool ScTransferObj::GetData( const datatransfer::DataFlavor& rFlavor )
258 {
259 sal_uInt32 nFormat = SotExchange::GetFormat( rFlavor );
260 sal_Bool bOK = sal_False;
261
262 if( HasFormat( nFormat ) )
263 {
264 if ( nFormat == SOT_FORMATSTR_ID_LINKSRCDESCRIPTOR || nFormat == SOT_FORMATSTR_ID_OBJECTDESCRIPTOR )
265 {
266 bOK = SetTransferableObjectDescriptor( aObjDesc, rFlavor );
267 }
268 else if ( ( nFormat == SOT_FORMAT_RTF || nFormat == SOT_FORMATSTR_ID_EDITENGINE ) &&
269 aBlock.aStart == aBlock.aEnd )
270 {
271 // RTF from a single cell is handled by EditEngine
272
273 SCCOL nCol = aBlock.aStart.Col();
274 SCROW nRow = aBlock.aStart.Row();
275 SCTAB nTab = aBlock.aStart.Tab();
276
277 const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
278 ScTabEditEngine aEngine( *pPattern, pDoc->GetEditPool() );
279 ScBaseCell* pCell = NULL;
280 pDoc->GetCell( nCol, nRow, nTab, pCell );
281 if (pCell)
282 {
283 if (pCell->GetCellType() == CELLTYPE_EDIT)
284 {
285 const EditTextObject* pObj;
286 ((ScEditCell*)pCell)->GetData(pObj);
287 aEngine.SetText( *pObj );
288 }
289 else
290 {
291 String aText;
292 pDoc->GetString( nCol, nRow, nTab, aText );
293 aEngine.SetText(aText);
294 }
295 }
296
297 bOK = SetObject( &aEngine,
298 (nFormat == FORMAT_RTF) ? SCTRANS_TYPE_EDIT_RTF : SCTRANS_TYPE_EDIT_BIN,
299 rFlavor );
300 }
301 else if ( ScImportExport::IsFormatSupported( nFormat ) || nFormat == SOT_FORMAT_RTF )
302 {
303 // if this transfer object was used to create a DDE link, filtered rows
304 // have to be included for subsequent calls (to be consistent with link data)
305 if ( nFormat == SOT_FORMATSTR_ID_LINK )
306 bUsedForLink = sal_True;
307
308 sal_Bool bIncludeFiltered = pDoc->IsCutMode() || bUsedForLink;
309
310 ScImportExport aObj( pDoc, aBlock );
311 if ( bUsedForLink )
312 aObj.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::ToSpace, ' ', false ) );
313 aObj.SetFormulas( pDoc->GetViewOptions().GetOption( VOPT_FORMULAS ) );
314 aObj.SetIncludeFiltered( bIncludeFiltered );
315
316 // DataType depends on format type:
317
318 if ( rFlavor.DataType.equals( ::getCppuType( (const ::rtl::OUString*) 0 ) ) )
319 {
320 rtl::OUString aString;
321 if ( aObj.ExportString( aString, nFormat ) )
322 bOK = SetString( aString, rFlavor );
323 }
324 else if ( rFlavor.DataType.equals( ::getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) ) )
325 {
326 // SetObject converts a stream into a Int8-Sequence
327 bOK = SetObject( &aObj, SCTRANS_TYPE_IMPEX, rFlavor );
328 }
329 else
330 {
331 DBG_ERROR("unknown DataType");
332 }
333 }
334 else if ( nFormat == SOT_FORMAT_BITMAP || nFormat == SOT_FORMATSTR_ID_PNG )
335 {
336 Rectangle aMMRect = pDoc->GetMMRect( aBlock.aStart.Col(), aBlock.aStart.Row(),
337 aBlock.aEnd.Col(), aBlock.aEnd.Row(),
338 aBlock.aStart.Tab() );
339 VirtualDevice aVirtDev;
340 aVirtDev.SetOutputSizePixel( aVirtDev.LogicToPixel( aMMRect.GetSize(), MAP_100TH_MM ) );
341
342 PaintToDev( &aVirtDev, pDoc, 1.0, aBlock, sal_False );
343
344 aVirtDev.SetMapMode( MapMode( MAP_PIXEL ) );
345 Bitmap aBmp = aVirtDev.GetBitmap( Point(), aVirtDev.GetOutputSize() );
346 bOK = SetBitmapEx( aBmp, rFlavor );
347 }
348 else if ( nFormat == SOT_FORMAT_GDIMETAFILE )
349 {
350 // #123405# Do not limit visual size calculation for metafile creation.
351 // It seems unlikely that removing the limitation causes problems since
352 // metafile creation means that no real pixel device in the needed size is
353 // created.
354 InitDocShell(false);
355
356 SfxObjectShell* pEmbObj = aDocShellRef;
357
358 // like SvEmbeddedTransfer::GetData:
359 GDIMetaFile aMtf;
360 VirtualDevice aVDev;
361 MapMode aMapMode( pEmbObj->GetMapUnit() );
362 Rectangle aVisArea( pEmbObj->GetVisArea( ASPECT_CONTENT ) );
363
364 aVDev.EnableOutput( sal_False );
365 aVDev.SetMapMode( aMapMode );
366 aMtf.SetPrefSize( aVisArea.GetSize() );
367 aMtf.SetPrefMapMode( aMapMode );
368 aMtf.Record( &aVDev );
369
370 pEmbObj->DoDraw( &aVDev, Point(), aVisArea.GetSize(), JobSetup(), ASPECT_CONTENT );
371
372 aMtf.Stop();
373 aMtf.WindStart();
374
375 bOK = SetGDIMetaFile( aMtf, rFlavor );
376 }
377 else if ( nFormat == SOT_FORMATSTR_ID_EMBED_SOURCE )
378 {
379 //TODO/LATER: differentiate between formats?!
380 // #123405# Do limit visual size calculation to PageSize
381 InitDocShell(true); // set aDocShellRef
382
383 SfxObjectShell* pEmbObj = aDocShellRef;
384 bOK = SetObject( pEmbObj, SCTRANS_TYPE_EMBOBJ, rFlavor );
385 }
386 }
387 return bOK;
388 }
389
WriteObject(SotStorageStreamRef & rxOStm,void * pUserObject,sal_uInt32 nUserObjectId,const datatransfer::DataFlavor & rFlavor)390 sal_Bool ScTransferObj::WriteObject( SotStorageStreamRef& rxOStm, void* pUserObject, sal_uInt32 nUserObjectId,
391 const datatransfer::DataFlavor& rFlavor )
392 {
393 // called from SetObject, put data into stream
394
395 sal_Bool bRet = sal_False;
396 switch (nUserObjectId)
397 {
398 case SCTRANS_TYPE_IMPEX:
399 {
400 ScImportExport* pImpEx = (ScImportExport*)pUserObject;
401
402 sal_uInt32 nFormat = SotExchange::GetFormat( rFlavor );
403 // mba: no BaseURL for data exchange
404 if ( pImpEx->ExportStream( *rxOStm, String(), nFormat ) )
405 bRet = ( rxOStm->GetError() == ERRCODE_NONE );
406 }
407 break;
408
409 case SCTRANS_TYPE_EDIT_RTF:
410 case SCTRANS_TYPE_EDIT_BIN:
411 {
412 ScTabEditEngine* pEngine = (ScTabEditEngine*)pUserObject;
413 if ( nUserObjectId == SCTRANS_TYPE_EDIT_RTF )
414 {
415 pEngine->Write( *rxOStm, EE_FORMAT_RTF );
416 bRet = ( rxOStm->GetError() == ERRCODE_NONE );
417 }
418 else
419 {
420 // #107722# can't use Write for EditEngine format because that would
421 // write old format without support for unicode characters.
422 // Get the data from the EditEngine's transferable instead.
423
424 sal_uInt32 nParCnt = pEngine->GetParagraphCount();
425 if ( nParCnt == 0 )
426 nParCnt = 1;
427 ESelection aSel( 0, 0, nParCnt-1, pEngine->GetTextLen(nParCnt-1) );
428
429 uno::Reference<datatransfer::XTransferable> xEditTrans = pEngine->CreateTransferable( aSel );
430 TransferableDataHelper aEditHelper( xEditTrans );
431
432 bRet = aEditHelper.GetSotStorageStream( rFlavor, rxOStm );
433 }
434 }
435 break;
436
437 case SCTRANS_TYPE_EMBOBJ:
438 {
439 // TODO/MBA: testing
440 SfxObjectShell* pEmbObj = (SfxObjectShell*) pUserObject;
441 ::utl::TempFile aTempFile;
442 aTempFile.EnableKillingFile();
443 uno::Reference< embed::XStorage > xWorkStore =
444 ::comphelper::OStorageHelper::GetStorageFromURL( aTempFile.GetURL(), embed::ElementModes::READWRITE );
445
446 // write document storage
447 pEmbObj->SetupStorage( xWorkStore, SOFFICE_FILEFORMAT_CURRENT, sal_False );
448
449 // mba: no relative ULRs for clipboard!
450 SfxMedium aMedium( xWorkStore, String() );
451 bRet = pEmbObj->DoSaveObjectAs( aMedium, sal_False );
452 pEmbObj->DoSaveCompleted();
453
454 uno::Reference< embed::XTransactedObject > xTransact( xWorkStore, uno::UNO_QUERY );
455 if ( xTransact.is() )
456 xTransact->commit();
457
458 SvStream* pSrcStm = ::utl::UcbStreamHelper::CreateStream( aTempFile.GetURL(), STREAM_READ );
459 if( pSrcStm )
460 {
461 rxOStm->SetBufferSize( 0xff00 );
462 *rxOStm << *pSrcStm;
463 delete pSrcStm;
464 }
465
466 bRet = sal_True;
467
468 xWorkStore->dispose();
469 xWorkStore = uno::Reference < embed::XStorage >();
470 rxOStm->Commit();
471 }
472 break;
473
474 default:
475 DBG_ERROR("unknown object id");
476 }
477 return bRet;
478 }
479
ObjectReleased()480 void ScTransferObj::ObjectReleased()
481 {
482 ScModule* pScMod = SC_MOD();
483 if ( pScMod->GetClipData().pCellClipboard == this )
484 pScMod->SetClipObject( NULL, NULL );
485
486 TransferableHelper::ObjectReleased();
487 }
488
DragFinished(sal_Int8 nDropAction)489 void ScTransferObj::DragFinished( sal_Int8 nDropAction )
490 {
491 if ( nDropAction == DND_ACTION_MOVE && !bDragWasInternal && !(nDragSourceFlags & SC_DROP_NAVIGATOR) )
492 {
493 // move: delete source data
494 ScDocShell* pSourceSh = GetSourceDocShell();
495 if (pSourceSh)
496 {
497 ScMarkData aMarkData = GetSourceMarkData();
498 // external drag&drop doesn't copy objects, so they also aren't deleted:
499 // #105703# bApi=sal_True, don't show error messages from drag&drop
500 pSourceSh->GetDocFunc().DeleteContents( aMarkData, IDF_ALL & ~IDF_OBJECTS, sal_True, sal_True );
501 }
502 }
503
504 ScModule* pScMod = SC_MOD();
505 if ( pScMod->GetDragData().pCellTransfer == this )
506 pScMod->ResetDragObject();
507
508 xDragSourceRanges = NULL; // don't keep source after dropping
509
510 TransferableHelper::DragFinished( nDropAction );
511 }
512
SetDragHandlePos(SCCOL nX,SCROW nY)513 void ScTransferObj::SetDragHandlePos( SCCOL nX, SCROW nY )
514 {
515 nDragHandleX = nX;
516 nDragHandleY = nY;
517 }
518
SetVisibleTab(SCTAB nNew)519 void ScTransferObj::SetVisibleTab( SCTAB nNew )
520 {
521 nVisibleTab = nNew;
522 }
523
SetDrawPersist(const SfxObjectShellRef & rRef)524 void ScTransferObj::SetDrawPersist( const SfxObjectShellRef& rRef )
525 {
526 aDrawPersistRef = rRef;
527 }
528
SetDragSource(ScDocShell * pSourceShell,const ScMarkData & rMark)529 void ScTransferObj::SetDragSource( ScDocShell* pSourceShell, const ScMarkData& rMark )
530 {
531 ScRangeList aRanges;
532 rMark.FillRangeListWithMarks( &aRanges, sal_False );
533 xDragSourceRanges = new ScCellRangesObj( pSourceShell, aRanges );
534 }
535
SetDragSourceFlags(sal_uInt16 nFlags)536 void ScTransferObj::SetDragSourceFlags( sal_uInt16 nFlags )
537 {
538 nDragSourceFlags = nFlags;
539 }
540
SetDragWasInternal()541 void ScTransferObj::SetDragWasInternal()
542 {
543 bDragWasInternal = sal_True;
544 }
545
SetUseInApi(bool bSet)546 void ScTransferObj::SetUseInApi( bool bSet )
547 {
548 bUseInApi = bSet;
549 }
550
GetSourceDocument()551 ScDocument* ScTransferObj::GetSourceDocument()
552 {
553 ScDocShell* pSourceDocSh = GetSourceDocShell();
554 if (pSourceDocSh)
555 return pSourceDocSh->GetDocument();
556 return NULL;
557 }
558
GetSourceDocShell()559 ScDocShell* ScTransferObj::GetSourceDocShell()
560 {
561 ScCellRangesBase* pRangesObj = ScCellRangesBase::getImplementation( xDragSourceRanges );
562 if (pRangesObj)
563 return pRangesObj->GetDocShell();
564
565 return NULL; // none set
566 }
567
GetSourceMarkData()568 ScMarkData ScTransferObj::GetSourceMarkData()
569 {
570 ScMarkData aMarkData;
571 ScCellRangesBase* pRangesObj = ScCellRangesBase::getImplementation( xDragSourceRanges );
572 if (pRangesObj)
573 {
574 const ScRangeList& rRanges = pRangesObj->GetRangeList();
575 aMarkData.MarkFromRangeList( rRanges, sal_False );
576 }
577 return aMarkData;
578 }
579
580 //
581 // initialize aDocShellRef with a live document from the ClipDoc
582 //
583 // #123405# added parameter to allow size calculation without limitation
584 // to PageSize, e.g. used for Metafile creation for clipboard.
585
InitDocShell(bool bLimitToPageSize)586 void ScTransferObj::InitDocShell(bool bLimitToPageSize)
587 {
588 if ( !aDocShellRef.Is() )
589 {
590 ScDocShell* pDocSh = new ScDocShell;
591 aDocShellRef = pDocSh; // ref must be there before InitNew
592
593 pDocSh->DoInitNew(NULL);
594
595 ScDocument* pDestDoc = pDocSh->GetDocument();
596 ScMarkData aDestMark;
597 aDestMark.SelectTable( 0, sal_True );
598
599 pDestDoc->SetDocOptions( pDoc->GetDocOptions() ); // #i42666#
600
601 String aTabName;
602 pDoc->GetName( aBlock.aStart.Tab(), aTabName );
603 pDestDoc->RenameTab( 0, aTabName, sal_False ); // no UpdateRef (empty)
604
605 pDestDoc->CopyStdStylesFrom( pDoc );
606
607 SCCOL nStartX = aBlock.aStart.Col();
608 SCROW nStartY = aBlock.aStart.Row();
609 SCCOL nEndX = aBlock.aEnd.Col();
610 SCROW nEndY = aBlock.aEnd.Row();
611
612 // widths / heights
613 // (must be copied before CopyFromClip, for drawing objects)
614
615 SCCOL nCol, nLastCol;
616 SCTAB nSrcTab = aBlock.aStart.Tab();
617 pDestDoc->SetLayoutRTL(0, pDoc->IsLayoutRTL(nSrcTab));
618 for (nCol=nStartX; nCol<=nEndX; nCol++)
619 if ( pDoc->ColHidden(nCol, nSrcTab, nLastCol) )
620 pDestDoc->ShowCol( nCol, 0, sal_False );
621 else
622 pDestDoc->SetColWidth( nCol, 0, pDoc->GetColWidth( nCol, nSrcTab ) );
623
624 ScBitMaskCompressedArray< SCROW, sal_uInt8> & rDestRowFlags =
625 pDestDoc->GetRowFlagsArrayModifiable(0);
626
627 for (SCROW nRow = nStartY; nRow <= nEndY; ++nRow)
628 {
629 sal_uInt8 nSourceFlags = pDoc->GetRowFlags(nRow, nSrcTab);
630 SCROW nLastRow = -1;
631 if ( pDoc->RowHidden(nRow, nSrcTab, nLastRow) )
632 pDestDoc->ShowRow( nRow, 0, sal_False );
633 else
634 {
635 pDestDoc->SetRowHeight( nRow, 0, pDoc->GetOriginalHeight( nRow, nSrcTab ) );
636
637 // if height was set manually, that flag has to be copied, too
638 if ( nSourceFlags & CR_MANUALSIZE )
639 rDestRowFlags.OrValue( nRow, CR_MANUALSIZE);
640 }
641 }
642
643 if ( pDoc->GetDrawLayer() )
644 pDocSh->MakeDrawLayer();
645
646 // cell range is copied to the original position, but on the first sheet
647 // -> bCutMode must be set
648 // pDoc is always a Clipboard-document
649
650 ScRange aDestRange( nStartX,nStartY,0, nEndX,nEndY,0 );
651 sal_Bool bWasCut = pDoc->IsCutMode();
652 if (!bWasCut)
653 pDoc->SetClipArea( aDestRange, sal_True ); // Cut
654 pDestDoc->CopyFromClip( aDestRange, aDestMark, IDF_ALL, NULL, pDoc, sal_False );
655 pDoc->SetClipArea( aDestRange, bWasCut );
656
657 StripRefs( pDoc, nStartX,nStartY, nEndX,nEndY, pDestDoc, 0,0 );
658
659 ScRange aMergeRange = aDestRange;
660 pDestDoc->ExtendMerge( aMergeRange, sal_True );
661
662 pDoc->CopyDdeLinks( pDestDoc ); // copy values of DDE Links
663
664 // page format (grid etc) and page size (maximum size for ole object)
665
666 Size aPaperSize = SvxPaperInfo::GetPaperSize( PAPER_A4 ); // Twips
667 ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool();
668 String aStyleName = pDoc->GetPageStyle( aBlock.aStart.Tab() );
669 SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SFX_STYLE_FAMILY_PAGE );
670 if (pStyleSheet)
671 {
672 const SfxItemSet& rSourceSet = pStyleSheet->GetItemSet();
673 aPaperSize = ((const SvxSizeItem&) rSourceSet.Get(ATTR_PAGE_SIZE)).GetSize();
674
675 // CopyStyleFrom kopiert SetItems mit richtigem Pool
676 ScStyleSheetPool* pDestPool = pDestDoc->GetStyleSheetPool();
677 pDestPool->CopyStyleFrom( pStylePool, aStyleName, SFX_STYLE_FAMILY_PAGE );
678 }
679
680 ScViewData aViewData( pDocSh, NULL );
681 aViewData.SetScreen( nStartX,nStartY, nEndX,nEndY );
682 aViewData.SetCurX( nStartX );
683 aViewData.SetCurY( nStartY );
684
685 pDestDoc->SetViewOptions( pDoc->GetViewOptions() );
686
687 // Size
688 //! get while copying sizes
689
690 long nPosX = 0;
691 long nPosY = 0;
692
693 for (nCol=0; nCol<nStartX; nCol++)
694 nPosX += pDestDoc->GetColWidth( nCol, 0 );
695 nPosY += pDestDoc->GetRowHeight( 0, nStartY-1, 0 );
696 nPosX = (long) ( nPosX * HMM_PER_TWIPS );
697 nPosY = (long) ( nPosY * HMM_PER_TWIPS );
698
699
700 aPaperSize.Width() *= 2; // limit OLE object to double of page size
701 aPaperSize.Height() *= 2;
702
703 long nSizeX = 0;
704 long nSizeY = 0;
705 for (nCol=nStartX; nCol<=nEndX; nCol++)
706 {
707 long nAdd = pDestDoc->GetColWidth( nCol, 0 );
708 if ( bLimitToPageSize && nSizeX+nAdd > aPaperSize.Width() && nSizeX ) // above limit?
709 break;
710 nSizeX += nAdd;
711 }
712 for (SCROW nRow=nStartY; nRow<=nEndY; nRow++)
713 {
714 long nAdd = pDestDoc->GetRowHeight( nRow, 0 );
715 if ( bLimitToPageSize && nSizeY+nAdd > aPaperSize.Height() && nSizeY ) // above limit?
716 break;
717 nSizeY += nAdd;
718 }
719 nSizeX = (long) ( nSizeX * HMM_PER_TWIPS );
720 nSizeY = (long) ( nSizeY * HMM_PER_TWIPS );
721
722 // pDocSh->SetVisAreaSize( Size(nSizeX,nSizeY) );
723
724 Rectangle aNewArea( Point(nPosX,nPosY), Size(nSizeX,nSizeY) );
725 //TODO/LATER: why twice?!
726 //pDocSh->SvInPlaceObject::SetVisArea( aNewArea );
727 pDocSh->SetVisArea( aNewArea );
728
729 pDocSh->UpdateOle(&aViewData, sal_True);
730
731 //! SetDocumentModified?
732 if ( pDestDoc->IsChartListenerCollectionNeedsUpdate() )
733 pDestDoc->UpdateChartListenerCollection();
734 }
735 }
736
737 // static
SetDrawClipDoc(sal_Bool bAnyOle)738 SfxObjectShell* ScTransferObj::SetDrawClipDoc( sal_Bool bAnyOle )
739 {
740 // update ScGlobal::pDrawClipDocShellRef
741
742 delete ScGlobal::pDrawClipDocShellRef;
743 if (bAnyOle)
744 {
745 ScGlobal::pDrawClipDocShellRef =
746 new ScDocShellRef(new ScDocShell(SFX_CREATE_MODE_INTERNAL)); // there must be a ref
747 (*ScGlobal::pDrawClipDocShellRef)->DoInitNew(NULL);
748 return *ScGlobal::pDrawClipDocShellRef;
749 }
750 else
751 {
752 ScGlobal::pDrawClipDocShellRef = NULL;
753 return NULL;
754 }
755 }
756
757 // static
StripRefs(ScDocument * pDoc,SCCOL nStartX,SCROW nStartY,SCCOL nEndX,SCROW nEndY,ScDocument * pDestDoc,SCCOL nSubX,SCROW nSubY)758 void ScTransferObj::StripRefs( ScDocument* pDoc,
759 SCCOL nStartX, SCROW nStartY, SCCOL nEndX, SCROW nEndY,
760 ScDocument* pDestDoc, SCCOL nSubX, SCROW nSubY )
761 {
762 if (!pDestDoc)
763 {
764 pDestDoc = pDoc;
765 DBG_ASSERT(nSubX==0&&nSubY==0, "can't move within the document");
766 }
767
768 // In a clipboard doc the data don't have to be on the first sheet
769
770 SCTAB nSrcTab = 0;
771 while (nSrcTab<MAXTAB && !pDoc->HasTable(nSrcTab))
772 ++nSrcTab;
773 SCTAB nDestTab = 0;
774 while (nDestTab<MAXTAB && !pDestDoc->HasTable(nDestTab))
775 ++nDestTab;
776
777 if (!pDoc->HasTable(nSrcTab) || !pDestDoc->HasTable(nDestTab))
778 {
779 DBG_ERROR("Sheet not found in ScTransferObj::StripRefs");
780 return;
781 }
782
783 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
784 ScRange aRef;
785
786 ScCellIterator aIter( pDoc, nStartX, nStartY, nSrcTab, nEndX, nEndY, nSrcTab );
787 ScBaseCell* pCell = aIter.GetFirst();
788 while (pCell)
789 {
790 if (pCell->GetCellType() == CELLTYPE_FORMULA)
791 {
792 ScFormulaCell* pFCell = (ScFormulaCell*) pCell;
793 sal_Bool bOut = sal_False;
794 ScDetectiveRefIter aRefIter( pFCell );
795 while ( !bOut && aRefIter.GetNextRef( aRef ) )
796 {
797 if ( aRef.aStart.Tab() != nSrcTab || aRef.aEnd.Tab() != nSrcTab ||
798 aRef.aStart.Col() < nStartX || aRef.aEnd.Col() > nEndX ||
799 aRef.aStart.Row() < nStartY || aRef.aEnd.Row() > nEndY )
800 bOut = sal_True;
801 }
802 if (bOut)
803 {
804 SCCOL nCol = aIter.GetCol() - nSubX;
805 SCROW nRow = aIter.GetRow() - nSubY;
806
807 ScBaseCell* pNew = 0;
808 sal_uInt16 nErrCode = pFCell->GetErrCode();
809 if (nErrCode)
810 {
811 pNew = new ScStringCell( ScGlobal::GetErrorString(nErrCode) );
812 if ( ((const SvxHorJustifyItem*) pDestDoc->GetAttr(
813 nCol,nRow,nDestTab, ATTR_HOR_JUSTIFY))->GetValue() ==
814 SVX_HOR_JUSTIFY_STANDARD )
815 pDestDoc->ApplyAttr( nCol,nRow,nDestTab,
816 SvxHorJustifyItem(SVX_HOR_JUSTIFY_RIGHT, ATTR_HOR_JUSTIFY) );
817 }
818 else if (pFCell->IsValue())
819 {
820 double fVal = pFCell->GetValue();
821 pNew = new ScValueCell( fVal );
822 }
823 else
824 {
825 String aStr;
826 pFCell->GetString(aStr);
827 if ( pFCell->IsMultilineResult() )
828 pNew = new ScEditCell( aStr, pDestDoc );
829 else
830 pNew = new ScStringCell( aStr );
831 }
832 pDestDoc->PutCell( nCol,nRow,nDestTab, pNew );
833
834 // number formats
835
836 sal_uLong nOldFormat = ((const SfxUInt32Item*)
837 pDestDoc->GetAttr(nCol,nRow,nDestTab, ATTR_VALUE_FORMAT))->GetValue();
838 if ( (nOldFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 )
839 {
840 sal_uLong nNewFormat = pFCell->GetStandardFormat( *pFormatter,
841 nOldFormat );
842 pDestDoc->ApplyAttr( nCol,nRow,nDestTab,
843 SfxUInt32Item(ATTR_VALUE_FORMAT, nNewFormat) );
844 }
845 }
846 }
847 pCell = aIter.GetNext();
848 }
849 }
850
getUnoTunnelId()851 const com::sun::star::uno::Sequence< sal_Int8 >& ScTransferObj::getUnoTunnelId()
852 {
853 static com::sun::star::uno::Sequence< sal_Int8 > aSeq;
854 if( !aSeq.getLength() )
855 {
856 static osl::Mutex aCreateMutex;
857 osl::Guard< osl::Mutex > aGuard( aCreateMutex );
858 aSeq.realloc( 16 );
859 rtl_createUuid( reinterpret_cast< sal_uInt8* >( aSeq.getArray() ), 0, sal_True );
860 }
861 return aSeq;
862 }
863
getSomething(const com::sun::star::uno::Sequence<sal_Int8> & rId)864 sal_Int64 SAL_CALL ScTransferObj::getSomething( const com::sun::star::uno::Sequence< sal_Int8 >& rId ) throw( com::sun::star::uno::RuntimeException )
865 {
866 sal_Int64 nRet;
867 if( ( rId.getLength() == 16 ) &&
868 ( 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) )
869 {
870 nRet = reinterpret_cast< sal_Int64 >( this );
871 }
872 else
873 nRet = TransferableHelper::getSomething(rId);
874 return nRet;
875 }
876
877
878