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 1
69 : #define SCTRANS_TYPE_EDIT_RTF 2
70 : #define SCTRANS_TYPE_EDIT_BIN 3
71 : #define SCTRANS_TYPE_EMBOBJ 4
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 22 : 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 22 : 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 22 : pDoc->GetClipStart( nCol1, nRow1 );
133 22 : pDoc->GetClipArea( nCol2, nRow2, true ); // real source area - include filtered rows
134 22 : nCol2 = sal::static_int_cast<SCCOL>( nCol2 + nCol1 );
135 22 : nRow2 = sal::static_int_cast<SCROW>( nRow2 + nRow1 );
136 :
137 : SCCOL nDummy;
138 22 : pDoc->GetClipArea( nDummy, nNonFiltered, false );
139 22 : bHasFiltered = (nNonFiltered < (nRow2 - nRow1));
140 22 : ++nNonFiltered; // to get count instead of diff
141 :
142 22 : SCTAB nTab1=0;
143 22 : SCTAB nTab2=0;
144 22 : bool bFirst = true;
145 44 : for (SCTAB i=0; i< pDoc->GetTableCount(); i++)
146 22 : if (pDoc->HasTable(i))
147 : {
148 22 : if (bFirst)
149 22 : nTab1 = i;
150 22 : nTab2 = i;
151 22 : 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 22 : 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 22 : aBlock = ScRange( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 );
169 22 : nVisibleTab = nTab1; // valid table as default
170 :
171 22 : Rectangle aMMRect = pDoc->GetMMRect( nCol1,nRow1, nCol2,nRow2, nTab1 );
172 22 : aObjDesc.maSize = aMMRect.GetSize();
173 22 : PrepareOLE( aObjDesc );
174 22 : }
175 :
176 66 : ScTransferObj::~ScTransferObj()
177 : {
178 22 : SolarMutexGuard aSolarGuard;
179 :
180 22 : ScModule* pScMod = SC_MOD();
181 22 : if ( pScMod->GetClipData().pCellClipboard == this )
182 : {
183 : OSL_FAIL("ScTransferObj wasn't released");
184 22 : pScMod->SetClipObject( NULL, NULL );
185 : }
186 22 : if ( pScMod->GetDragData().pCellTransfer == this )
187 : {
188 : OSL_FAIL("ScTransferObj wasn't released");
189 0 : pScMod->ResetDragObject();
190 : }
191 :
192 22 : delete pDoc; // ScTransferObj is owner of clipboard document
193 :
194 22 : aDocShellRef.Clear(); // before releasing the mutex
195 :
196 22 : aDrawPersistRef.Clear(); // after the model
197 :
198 44 : }
199 :
200 2542 : ScTransferObj* ScTransferObj::GetOwnClipboard( vcl::Window* pUIWin )
201 : {
202 2542 : ScTransferObj* pObj = SC_MOD()->GetClipData().pCellClipboard;
203 2542 : 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( SOT_FORMATSTR_ID_DIF ) )
213 : {
214 : // OSL_FAIL("ScTransferObj wasn't released");
215 0 : pObj = NULL;
216 0 : }
217 : }
218 2542 : return pObj;
219 : }
220 :
221 0 : void ScTransferObj::AddSupportedFormats()
222 : {
223 0 : AddFormat( SOT_FORMATSTR_ID_EMBED_SOURCE );
224 0 : AddFormat( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR );
225 0 : AddFormat( SOT_FORMAT_GDIMETAFILE );
226 0 : AddFormat( SOT_FORMATSTR_ID_PNG );
227 0 : AddFormat( SOT_FORMAT_BITMAP );
228 :
229 : // ScImportExport formats
230 0 : AddFormat( SOT_FORMATSTR_ID_HTML );
231 0 : AddFormat( SOT_FORMATSTR_ID_SYLK );
232 0 : AddFormat( SOT_FORMATSTR_ID_LINK );
233 0 : AddFormat( SOT_FORMATSTR_ID_DIF );
234 0 : AddFormat( SOT_FORMAT_STRING );
235 :
236 0 : AddFormat( SOT_FORMAT_RTF );
237 0 : if ( aBlock.aStart == aBlock.aEnd )
238 0 : AddFormat( SOT_FORMATSTR_ID_EDITENGINE );
239 0 : }
240 :
241 0 : bool ScTransferObj::GetData( const datatransfer::DataFlavor& rFlavor, const OUString& /*rDestDoc*/ )
242 : {
243 0 : sal_uInt32 nFormat = SotExchange::GetFormat( rFlavor );
244 0 : bool bOK = false;
245 :
246 0 : if( HasFormat( nFormat ) )
247 : {
248 0 : if ( nFormat == SOT_FORMATSTR_ID_LINKSRCDESCRIPTOR || nFormat == SOT_FORMATSTR_ID_OBJECTDESCRIPTOR )
249 : {
250 0 : bOK = SetTransferableObjectDescriptor( aObjDesc, rFlavor );
251 : }
252 0 : else if ( ( nFormat == SOT_FORMAT_RTF || nFormat == SOT_FORMATSTR_ID_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 == FORMAT_RTF) ? SCTRANS_TYPE_EDIT_RTF : SCTRANS_TYPE_EDIT_BIN,
279 0 : rFlavor );
280 : }
281 0 : else if ( ScImportExport::IsFormatSupported( nFormat ) || nFormat == SOT_FORMAT_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 == SOT_FORMATSTR_ID_LINK )
286 0 : bUsedForLink = true;
287 :
288 0 : bool bIncludeFiltered = pDoc->IsCutMode() || bUsedForLink;
289 :
290 0 : ScRange aReducedBlock = aBlock;
291 0 : if ( nFormat == SOT_FORMATSTR_ID_HTML && (aBlock.aEnd.Col() == MAXCOL || aBlock.aEnd.Row() == MAXROW) && aBlock.aStart.Tab() == aBlock.aEnd.Tab() )
292 : {
293 0 : bool bShrunk = false;
294 : //shrink the area to allow pasting to external applications
295 0 : SCCOL aStartCol = aReducedBlock.aStart.Col();
296 0 : SCROW aStartRow = aReducedBlock.aStart.Row();
297 0 : SCCOL aEndCol = aReducedBlock.aEnd.Col();
298 0 : SCROW aEndRow = aReducedBlock.aEnd.Row();
299 0 : pDoc->ShrinkToUsedDataArea( bShrunk, aReducedBlock.aStart.Tab(), aStartCol, aStartRow, aEndCol, aEndRow, false);
300 0 : aReducedBlock = ScRange(aStartCol, aStartRow, aReducedBlock.aStart.Tab(), aEndCol, aEndRow, aReducedBlock.aEnd.Tab());
301 : }
302 :
303 0 : ScImportExport aObj( pDoc, aReducedBlock );
304 0 : ScExportTextOptions aTextOptions(ScExportTextOptions::None, 0, true);
305 0 : if ( bUsedForLink )
306 : {
307 : // For a DDE link, convert line breaks and separators to space.
308 0 : aTextOptions.meNewlineConversion = ScExportTextOptions::ToSpace;
309 0 : aTextOptions.mcSeparatorConvertTo = ' ';
310 0 : aTextOptions.mbAddQuotes = false;
311 : }
312 0 : aObj.SetExportTextOptions(aTextOptions);
313 0 : aObj.SetFormulas( pDoc->GetViewOptions().GetOption( VOPT_FORMULAS ) );
314 0 : aObj.SetIncludeFiltered( bIncludeFiltered );
315 :
316 : // DataType depends on format type:
317 :
318 0 : if ( rFlavor.DataType.equals( ::cppu::UnoType<OUString>::get() ) )
319 : {
320 0 : OUString aString;
321 0 : if ( aObj.ExportString( aString, nFormat ) )
322 0 : bOK = SetString( aString, rFlavor );
323 : }
324 0 : else if ( rFlavor.DataType.equals( ::getCppuType( (const uno::Sequence< sal_Int8 >*) 0 ) ) )
325 : {
326 : // SetObject converts a stream into a Int8-Sequence
327 0 : bOK = SetObject( &aObj, SCTRANS_TYPE_IMPEX, rFlavor );
328 : }
329 : else
330 : {
331 : OSL_FAIL("unknown DataType");
332 0 : }
333 : }
334 0 : else if ( nFormat == SOT_FORMAT_BITMAP || nFormat == SOT_FORMATSTR_ID_PNG )
335 : {
336 0 : Rectangle aMMRect = pDoc->GetMMRect( aBlock.aStart.Col(), aBlock.aStart.Row(),
337 0 : aBlock.aEnd.Col(), aBlock.aEnd.Row(),
338 0 : aBlock.aStart.Tab() );
339 0 : VirtualDevice aVirtDev;
340 0 : aVirtDev.SetOutputSizePixel( aVirtDev.LogicToPixel( aMMRect.GetSize(), MAP_100TH_MM ) );
341 :
342 0 : PaintToDev( &aVirtDev, pDoc, 1.0, aBlock, false );
343 :
344 0 : aVirtDev.SetMapMode( MapMode( MAP_PIXEL ) );
345 0 : Bitmap aBmp = aVirtDev.GetBitmap( Point(), aVirtDev.GetOutputSize() );
346 0 : bOK = SetBitmapEx( aBmp, rFlavor );
347 : }
348 0 : else if ( nFormat == SOT_FORMAT_GDIMETAFILE )
349 : {
350 : // #i123405# 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 0 : InitDocShell(false);
355 :
356 0 : SfxObjectShell* pEmbObj = aDocShellRef;
357 :
358 : // like SvEmbeddedTransfer::GetData:
359 0 : GDIMetaFile aMtf;
360 0 : VirtualDevice aVDev;
361 0 : MapMode aMapMode( pEmbObj->GetMapUnit() );
362 0 : Rectangle aVisArea( pEmbObj->GetVisArea( ASPECT_CONTENT ) );
363 :
364 0 : aVDev.EnableOutput( false );
365 0 : aVDev.SetMapMode( aMapMode );
366 0 : aMtf.SetPrefSize( aVisArea.GetSize() );
367 0 : aMtf.SetPrefMapMode( aMapMode );
368 0 : aMtf.Record( &aVDev );
369 :
370 0 : pEmbObj->DoDraw( &aVDev, Point(), aVisArea.GetSize(), JobSetup(), ASPECT_CONTENT );
371 :
372 0 : aMtf.Stop();
373 0 : aMtf.WindStart();
374 :
375 0 : bOK = SetGDIMetaFile( aMtf, rFlavor );
376 : }
377 0 : else if ( nFormat == SOT_FORMATSTR_ID_EMBED_SOURCE )
378 : {
379 : //TODO/LATER: differentiate between formats?!
380 : // #i123405# Do limit visual size calculation to PageSize
381 0 : InitDocShell(true); // set aDocShellRef
382 :
383 0 : SfxObjectShell* pEmbObj = aDocShellRef;
384 0 : bOK = SetObject( pEmbObj, SCTRANS_TYPE_EMBOBJ, rFlavor );
385 : }
386 : }
387 0 : return bOK;
388 : }
389 :
390 0 : 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 0 : bool bRet = false;
396 0 : switch (nUserObjectId)
397 : {
398 : case SCTRANS_TYPE_IMPEX:
399 : {
400 0 : ScImportExport* pImpEx = (ScImportExport*)pUserObject;
401 :
402 0 : sal_uInt32 nFormat = SotExchange::GetFormat( rFlavor );
403 : // mba: no BaseURL for data exchange
404 0 : if ( pImpEx->ExportStream( *rxOStm, OUString(), nFormat ) )
405 0 : bRet = ( rxOStm->GetError() == ERRCODE_NONE );
406 : }
407 0 : break;
408 :
409 : case SCTRANS_TYPE_EDIT_RTF:
410 : case SCTRANS_TYPE_EDIT_BIN:
411 : {
412 0 : ScTabEditEngine* pEngine = (ScTabEditEngine*)pUserObject;
413 0 : if ( nUserObjectId == SCTRANS_TYPE_EDIT_RTF )
414 : {
415 0 : pEngine->Write( *rxOStm, EE_FORMAT_RTF );
416 0 : bRet = ( rxOStm->GetError() == ERRCODE_NONE );
417 : }
418 : else
419 : {
420 : // 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 0 : sal_Int32 nParCnt = pEngine->GetParagraphCount();
425 0 : if ( nParCnt == 0 )
426 0 : nParCnt = 1;
427 0 : ESelection aSel( 0, 0, nParCnt-1, pEngine->GetTextLen(nParCnt-1) );
428 :
429 0 : uno::Reference<datatransfer::XTransferable> xEditTrans = pEngine->CreateTransferable( aSel );
430 0 : TransferableDataHelper aEditHelper( xEditTrans );
431 :
432 0 : bRet = aEditHelper.GetSotStorageStream( rFlavor, rxOStm );
433 : }
434 : }
435 0 : break;
436 :
437 : case SCTRANS_TYPE_EMBOBJ:
438 : {
439 : // TODO/MBA: testing
440 0 : SfxObjectShell* pEmbObj = (SfxObjectShell*) pUserObject;
441 0 : ::utl::TempFile aTempFile;
442 0 : aTempFile.EnableKillingFile();
443 : uno::Reference< embed::XStorage > xWorkStore =
444 0 : ::comphelper::OStorageHelper::GetStorageFromURL( aTempFile.GetURL(), embed::ElementModes::READWRITE );
445 :
446 : // write document storage
447 0 : pEmbObj->SetupStorage( xWorkStore, SOFFICE_FILEFORMAT_CURRENT, false, false );
448 :
449 : // mba: no relative URLs for clipboard!
450 0 : SfxMedium aMedium( xWorkStore, OUString() );
451 0 : bRet = pEmbObj->DoSaveObjectAs( aMedium, false );
452 0 : pEmbObj->DoSaveCompleted();
453 :
454 0 : uno::Reference< embed::XTransactedObject > xTransact( xWorkStore, uno::UNO_QUERY );
455 0 : if ( xTransact.is() )
456 0 : xTransact->commit();
457 :
458 0 : SvStream* pSrcStm = ::utl::UcbStreamHelper::CreateStream( aTempFile.GetURL(), STREAM_READ );
459 0 : if( pSrcStm )
460 : {
461 0 : rxOStm->SetBufferSize( 0xff00 );
462 0 : rxOStm->WriteStream( *pSrcStm );
463 0 : delete pSrcStm;
464 : }
465 :
466 0 : bRet = true;
467 :
468 0 : xWorkStore->dispose();
469 0 : xWorkStore = uno::Reference < embed::XStorage >();
470 0 : rxOStm->Commit();
471 : }
472 0 : break;
473 :
474 : default:
475 : OSL_FAIL("unknown object id");
476 : }
477 0 : return bRet;
478 : }
479 :
480 0 : void ScTransferObj::ObjectReleased()
481 : {
482 0 : ScModule* pScMod = SC_MOD();
483 0 : if ( pScMod->GetClipData().pCellClipboard == this )
484 0 : pScMod->SetClipObject( NULL, NULL );
485 :
486 0 : TransferableHelper::ObjectReleased();
487 0 : }
488 :
489 0 : void ScTransferObj::DragFinished( sal_Int8 nDropAction )
490 : {
491 0 : if ( nDropAction == DND_ACTION_MOVE && !bDragWasInternal && !(nDragSourceFlags & SC_DROP_NAVIGATOR) )
492 : {
493 : // move: delete source data
494 0 : ScDocShell* pSourceSh = GetSourceDocShell();
495 0 : if (pSourceSh)
496 : {
497 0 : ScMarkData aMarkData = GetSourceMarkData();
498 : // external drag&drop doesn't copy objects, so they also aren't deleted:
499 : // bApi=TRUE, don't show error messages from drag&drop
500 0 : pSourceSh->GetDocFunc().DeleteContents( aMarkData, IDF_ALL & ~IDF_OBJECTS, true, true );
501 : }
502 : }
503 :
504 0 : ScModule* pScMod = SC_MOD();
505 0 : if ( pScMod->GetDragData().pCellTransfer == this )
506 0 : pScMod->ResetDragObject();
507 :
508 0 : xDragSourceRanges = NULL; // don't keep source after dropping
509 :
510 0 : TransferableHelper::DragFinished( nDropAction );
511 0 : }
512 :
513 0 : void ScTransferObj::SetDragHandlePos( SCCOL nX, SCROW nY )
514 : {
515 0 : nDragHandleX = nX;
516 0 : nDragHandleY = nY;
517 0 : }
518 :
519 0 : void ScTransferObj::SetVisibleTab( SCTAB nNew )
520 : {
521 0 : nVisibleTab = nNew;
522 0 : }
523 :
524 0 : void ScTransferObj::SetDrawPersist( const SfxObjectShellRef& rRef )
525 : {
526 0 : aDrawPersistRef = rRef;
527 0 : }
528 :
529 0 : void ScTransferObj::SetDragSource( ScDocShell* pSourceShell, const ScMarkData& rMark )
530 : {
531 0 : ScRangeList aRanges;
532 0 : rMark.FillRangeListWithMarks( &aRanges, false );
533 0 : xDragSourceRanges = new ScCellRangesObj( pSourceShell, aRanges );
534 0 : }
535 :
536 0 : void ScTransferObj::SetDragSourceFlags( sal_uInt16 nFlags )
537 : {
538 0 : nDragSourceFlags = nFlags;
539 0 : }
540 :
541 0 : void ScTransferObj::SetDragWasInternal()
542 : {
543 0 : bDragWasInternal = true;
544 0 : }
545 :
546 0 : void ScTransferObj::SetUseInApi( bool bSet )
547 : {
548 0 : bUseInApi = bSet;
549 0 : }
550 :
551 0 : ScDocument* ScTransferObj::GetSourceDocument()
552 : {
553 0 : ScDocShell* pSourceDocSh = GetSourceDocShell();
554 0 : if (pSourceDocSh)
555 0 : return &pSourceDocSh->GetDocument();
556 0 : return NULL;
557 : }
558 :
559 0 : ScDocShell* ScTransferObj::GetSourceDocShell()
560 : {
561 0 : ScCellRangesBase* pRangesObj = ScCellRangesBase::getImplementation( xDragSourceRanges );
562 0 : if (pRangesObj)
563 0 : return pRangesObj->GetDocShell();
564 :
565 0 : return NULL; // none set
566 : }
567 :
568 0 : ScMarkData ScTransferObj::GetSourceMarkData()
569 : {
570 0 : ScMarkData aMarkData;
571 0 : ScCellRangesBase* pRangesObj = ScCellRangesBase::getImplementation( xDragSourceRanges );
572 0 : if (pRangesObj)
573 : {
574 0 : const ScRangeList& rRanges = pRangesObj->GetRangeList();
575 0 : aMarkData.MarkFromRangeList( rRanges, false );
576 : }
577 0 : return aMarkData;
578 : }
579 :
580 : // initialize aDocShellRef with a live document from the ClipDoc
581 :
582 : // #i123405# added parameter to allow size calculation without limitation
583 : // to PageSize, e.g. used for Metafile creation for clipboard.
584 :
585 0 : void ScTransferObj::InitDocShell(bool bLimitToPageSize)
586 : {
587 0 : if ( !aDocShellRef.Is() )
588 : {
589 0 : ScDocShell* pDocSh = new ScDocShell;
590 0 : aDocShellRef = pDocSh; // ref must be there before InitNew
591 :
592 0 : pDocSh->DoInitNew(NULL);
593 :
594 0 : ScDocument& rDestDoc = pDocSh->GetDocument();
595 0 : ScMarkData aDestMark;
596 0 : aDestMark.SelectTable( 0, true );
597 :
598 0 : rDestDoc.SetDocOptions( pDoc->GetDocOptions() ); // #i42666#
599 :
600 0 : OUString aTabName;
601 0 : pDoc->GetName( aBlock.aStart.Tab(), aTabName );
602 0 : rDestDoc.RenameTab( 0, aTabName, false ); // no UpdateRef (empty)
603 :
604 0 : rDestDoc.CopyStdStylesFrom( pDoc );
605 :
606 0 : SCCOL nStartX = aBlock.aStart.Col();
607 0 : SCROW nStartY = aBlock.aStart.Row();
608 0 : SCCOL nEndX = aBlock.aEnd.Col();
609 0 : SCROW nEndY = aBlock.aEnd.Row();
610 :
611 : // widths / heights
612 : // (must be copied before CopyFromClip, for drawing objects)
613 :
614 : SCCOL nCol;
615 0 : SCTAB nSrcTab = aBlock.aStart.Tab();
616 0 : rDestDoc.SetLayoutRTL(0, pDoc->IsLayoutRTL(nSrcTab));
617 0 : for (nCol=nStartX; nCol<=nEndX; nCol++)
618 0 : if ( pDoc->ColHidden(nCol, nSrcTab) )
619 0 : rDestDoc.ShowCol( nCol, 0, false );
620 : else
621 0 : rDestDoc.SetColWidth( nCol, 0, pDoc->GetColWidth( nCol, nSrcTab ) );
622 :
623 0 : for (SCROW nRow = nStartY; nRow <= nEndY; ++nRow)
624 : {
625 0 : if ( pDoc->RowHidden(nRow, nSrcTab) )
626 0 : rDestDoc.ShowRow( nRow, 0, false );
627 : else
628 : {
629 0 : rDestDoc.SetRowHeight( nRow, 0, pDoc->GetOriginalHeight( nRow, nSrcTab ) );
630 :
631 : // if height was set manually, that flag has to be copied, too
632 0 : bool bManual = pDoc->IsManualRowHeight(nRow, nSrcTab);
633 0 : rDestDoc.SetManualHeight(nRow, nRow, 0, bManual);
634 : }
635 : }
636 :
637 0 : if (pDoc->GetDrawLayer() || pDoc->HasNotes())
638 0 : pDocSh->MakeDrawLayer();
639 :
640 : // cell range is copied to the original position, but on the first sheet
641 : // -> bCutMode must be set
642 : // pDoc is always a Clipboard-document
643 :
644 0 : ScRange aDestRange( nStartX,nStartY,0, nEndX,nEndY,0 );
645 0 : bool bWasCut = pDoc->IsCutMode();
646 0 : if (!bWasCut)
647 0 : pDoc->SetClipArea( aDestRange, true ); // Cut
648 0 : rDestDoc.CopyFromClip( aDestRange, aDestMark, IDF_ALL, NULL, pDoc, false );
649 0 : pDoc->SetClipArea( aDestRange, bWasCut );
650 :
651 0 : StripRefs( pDoc, nStartX,nStartY, nEndX,nEndY, &rDestDoc, 0,0 );
652 :
653 0 : ScRange aMergeRange = aDestRange;
654 0 : rDestDoc.ExtendMerge( aMergeRange, true );
655 :
656 0 : pDoc->CopyDdeLinks( &rDestDoc ); // copy values of DDE Links
657 :
658 : // page format (grid etc) and page size (maximum size for ole object)
659 :
660 0 : Size aPaperSize = SvxPaperInfo::GetPaperSize( PAPER_A4 ); // Twips
661 0 : ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool();
662 0 : OUString aStyleName = pDoc->GetPageStyle( aBlock.aStart.Tab() );
663 0 : SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SFX_STYLE_FAMILY_PAGE );
664 0 : if (pStyleSheet)
665 : {
666 0 : const SfxItemSet& rSourceSet = pStyleSheet->GetItemSet();
667 0 : aPaperSize = static_cast<const SvxSizeItem&>( rSourceSet.Get(ATTR_PAGE_SIZE)).GetSize();
668 :
669 : // CopyStyleFrom kopiert SetItems mit richtigem Pool
670 0 : ScStyleSheetPool* pDestPool = rDestDoc.GetStyleSheetPool();
671 0 : pDestPool->CopyStyleFrom( pStylePool, aStyleName, SFX_STYLE_FAMILY_PAGE );
672 : }
673 :
674 0 : ScViewData aViewData( pDocSh, NULL );
675 0 : aViewData.SetScreen( nStartX,nStartY, nEndX,nEndY );
676 0 : aViewData.SetCurX( nStartX );
677 0 : aViewData.SetCurY( nStartY );
678 :
679 0 : rDestDoc.SetViewOptions( pDoc->GetViewOptions() );
680 :
681 : // Size
682 : //! get while copying sizes
683 :
684 0 : long nPosX = 0;
685 0 : long nPosY = 0;
686 :
687 0 : for (nCol=0; nCol<nStartX; nCol++)
688 0 : nPosX += rDestDoc.GetColWidth( nCol, 0 );
689 0 : nPosY += rDestDoc.GetRowHeight( 0, nStartY-1, 0 );
690 0 : nPosX = (long) ( nPosX * HMM_PER_TWIPS );
691 0 : nPosY = (long) ( nPosY * HMM_PER_TWIPS );
692 :
693 0 : aPaperSize.Width() *= 2; // limit OLE object to double of page size
694 0 : aPaperSize.Height() *= 2;
695 :
696 0 : long nSizeX = 0;
697 0 : long nSizeY = 0;
698 0 : for (nCol=nStartX; nCol<=nEndX; nCol++)
699 : {
700 0 : long nAdd = rDestDoc.GetColWidth( nCol, 0 );
701 0 : if ( bLimitToPageSize && nSizeX+nAdd > aPaperSize.Width() && nSizeX ) // above limit?
702 0 : break;
703 0 : nSizeX += nAdd;
704 : }
705 0 : for (SCROW nRow=nStartY; nRow<=nEndY; nRow++)
706 : {
707 0 : long nAdd = rDestDoc.GetRowHeight( nRow, 0 );
708 0 : if ( bLimitToPageSize && nSizeY+nAdd > aPaperSize.Height() && nSizeY ) // above limit?
709 0 : break;
710 0 : nSizeY += nAdd;
711 : }
712 0 : nSizeX = (long) ( nSizeX * HMM_PER_TWIPS );
713 0 : nSizeY = (long) ( nSizeY * HMM_PER_TWIPS );
714 :
715 : // pDocSh->SetVisAreaSize( Size(nSizeX,nSizeY) );
716 :
717 0 : Rectangle aNewArea( Point(nPosX,nPosY), Size(nSizeX,nSizeY) );
718 : //TODO/LATER: why twice?!
719 : //pDocSh->SvInPlaceObject::SetVisArea( aNewArea );
720 0 : pDocSh->SetVisArea( aNewArea );
721 :
722 0 : pDocSh->UpdateOle(&aViewData, true);
723 :
724 : //! SetDocumentModified?
725 0 : if ( rDestDoc.IsChartListenerCollectionNeedsUpdate() )
726 0 : rDestDoc.UpdateChartListenerCollection();
727 : }
728 0 : }
729 :
730 22 : SfxObjectShell* ScTransferObj::SetDrawClipDoc( bool bAnyOle )
731 : {
732 : // update ScGlobal::pDrawClipDocShellRef
733 :
734 22 : delete ScGlobal::pDrawClipDocShellRef;
735 22 : if (bAnyOle)
736 : {
737 : ScGlobal::pDrawClipDocShellRef =
738 0 : new ScDocShellRef(new ScDocShell(SFX_CREATE_MODE_INTERNAL)); // there must be a ref
739 0 : (*ScGlobal::pDrawClipDocShellRef)->DoInitNew(NULL);
740 0 : return *ScGlobal::pDrawClipDocShellRef;
741 : }
742 : else
743 : {
744 22 : ScGlobal::pDrawClipDocShellRef = NULL;
745 22 : return NULL;
746 : }
747 : }
748 :
749 0 : void ScTransferObj::StripRefs( ScDocument* pDoc,
750 : SCCOL nStartX, SCROW nStartY, SCCOL nEndX, SCROW nEndY,
751 : ScDocument* pDestDoc, SCCOL nSubX, SCROW nSubY )
752 : {
753 0 : if (!pDestDoc)
754 : {
755 0 : pDestDoc = pDoc;
756 : OSL_ENSURE(nSubX==0&&nSubY==0, "can't move within the document");
757 : }
758 :
759 : // In a clipboard doc the data don't have to be on the first sheet
760 :
761 0 : SCTAB nSrcTab = 0;
762 0 : while (nSrcTab<pDoc->GetTableCount() && !pDoc->HasTable(nSrcTab))
763 0 : ++nSrcTab;
764 0 : SCTAB nDestTab = 0;
765 0 : while (nDestTab<pDestDoc->GetTableCount() && !pDestDoc->HasTable(nDestTab))
766 0 : ++nDestTab;
767 :
768 0 : if (!pDoc->HasTable(nSrcTab) || !pDestDoc->HasTable(nDestTab))
769 : {
770 : OSL_FAIL("Sheet not found in ScTransferObj::StripRefs");
771 0 : return;
772 : }
773 :
774 0 : ScRange aRef;
775 :
776 0 : ScCellIterator aIter( pDoc, ScRange(nStartX, nStartY, nSrcTab, nEndX, nEndY, nSrcTab) );
777 0 : for (bool bHas = aIter.first(); bHas; bHas = aIter.next())
778 : {
779 0 : if (aIter.getType() != CELLTYPE_FORMULA)
780 0 : continue;
781 :
782 0 : ScFormulaCell* pFCell = aIter.getFormulaCell();
783 0 : bool bOut = false;
784 0 : ScDetectiveRefIter aRefIter( pFCell );
785 0 : while ( !bOut && aRefIter.GetNextRef( aRef ) )
786 : {
787 0 : if ( aRef.aStart.Tab() != nSrcTab || aRef.aEnd.Tab() != nSrcTab ||
788 0 : aRef.aStart.Col() < nStartX || aRef.aEnd.Col() > nEndX ||
789 0 : aRef.aStart.Row() < nStartY || aRef.aEnd.Row() > nEndY )
790 0 : bOut = true;
791 : }
792 0 : if (bOut)
793 : {
794 0 : SCCOL nCol = aIter.GetPos().Col() - nSubX;
795 0 : SCROW nRow = aIter.GetPos().Row() - nSubY;
796 :
797 0 : sal_uInt16 nErrCode = pFCell->GetErrCode();
798 0 : ScAddress aPos(nCol, nRow, nDestTab);
799 0 : if (nErrCode)
800 : {
801 0 : if ( static_cast<const SvxHorJustifyItem*>(pDestDoc->GetAttr(
802 0 : nCol,nRow,nDestTab, ATTR_HOR_JUSTIFY))->GetValue() ==
803 : SVX_HOR_JUSTIFY_STANDARD )
804 : pDestDoc->ApplyAttr( nCol,nRow,nDestTab,
805 0 : SvxHorJustifyItem(SVX_HOR_JUSTIFY_RIGHT, ATTR_HOR_JUSTIFY) );
806 :
807 0 : ScSetStringParam aParam;
808 0 : aParam.setTextInput();
809 0 : pDestDoc->SetString(aPos, ScGlobal::GetErrorString(nErrCode), &aParam);
810 : }
811 0 : else if (pFCell->IsValue())
812 : {
813 0 : pDestDoc->SetValue(aPos, pFCell->GetValue());
814 : }
815 : else
816 : {
817 0 : OUString aStr = pFCell->GetString().getString();
818 0 : if ( pFCell->IsMultilineResult() )
819 : {
820 0 : ScFieldEditEngine& rEngine = pDestDoc->GetEditEngine();
821 0 : rEngine.SetText(aStr);
822 0 : pDestDoc->SetEditText(ScAddress(nCol,nRow,nDestTab), rEngine.CreateTextObject());
823 : }
824 : else
825 : {
826 0 : ScSetStringParam aParam;
827 0 : aParam.setTextInput();
828 0 : pDestDoc->SetString(aPos, aStr, &aParam);
829 0 : }
830 : }
831 : }
832 0 : }
833 : }
834 :
835 : namespace
836 : {
837 : class theScTransferUnoTunnelId : public rtl::Static< UnoTunnelIdInit, theScTransferUnoTunnelId> {};
838 : }
839 :
840 0 : const com::sun::star::uno::Sequence< sal_Int8 >& ScTransferObj::getUnoTunnelId()
841 : {
842 0 : return theScTransferUnoTunnelId::get().getSeq();
843 : }
844 :
845 0 : sal_Int64 SAL_CALL ScTransferObj::getSomething( const com::sun::star::uno::Sequence< sal_Int8 >& rId ) throw( com::sun::star::uno::RuntimeException, std::exception )
846 : {
847 : sal_Int64 nRet;
848 0 : if( ( rId.getLength() == 16 ) &&
849 0 : ( 0 == memcmp( getUnoTunnelId().getConstArray(), rId.getConstArray(), 16 ) ) )
850 : {
851 0 : nRet = reinterpret_cast< sal_Int64 >( this );
852 : }
853 : else
854 0 : nRet = TransferableHelper::getSomething(rId);
855 0 : return nRet;
856 228 : }
857 :
858 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|