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