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