Update ooo320-m1
[ooovba.git] / sc / source / ui / view / viewfun3.cxx
blob880ff11db48f54e462a6506fe271b66781b7c988
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: viewfun3.cxx,v $
10 * $Revision: 1.41.126.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
36 //----------------------------------------------------------------------------
38 #define _SV_NOXSOUND
40 #ifdef WIN
41 #define _MENUBTN_HXX
42 #endif
44 #define _BASE_DLGS_HXX
45 #define _BIGINT_HXX
46 #define _CACHESTR_HXX
47 #define _CONFIG_HXX
48 #define _CURSOR_HXX
49 #define _CTRLTOOL_HXX
50 #define _DLGCFG_HXX
51 #define _DYNARR_HXX
52 #define _EXTATTR_HXX
53 #define _FILDLG_HXX
54 #define _FONTDLG_HXX
55 #define _FRM3D_HXX
56 #define _INTRO_HXX
57 #define _ISETBWR_HXX
58 #define _NO_SVRTF_PARSER_HXX
59 #define _MACRODLG_HXX
60 #define _MODALDLG_HXX
61 #define _MOREBUTTON_HXX
62 #define _OUTLINER_HXX
63 //#define _PRNDLG_HXX
64 //#define _POLY_HXX
65 #define _PVRWIN_HXX
66 //#define _QUEUE_HXX
67 #define _RULER_HXX
68 #define _SCRWIN_HXX
69 #define _SETBRW_HXX
70 //#define _STACK_HXX
71 //#define _STATUS_HXX ***
72 #define _STDCTRL_HXX
73 #define _STDMENU_HXX
74 //#define _TAB_HXX
75 #define _TABBAR_HXX
76 #define _TREELIST_HXX
77 #define _VALUESET_HXX
78 #define _VCATTR_HXX
79 #define _VCBRW_HXX
80 #define _VCTRLS_HXX
81 #define _VCSBX_HXX
82 #define _VCONT_HXX
83 #define _VDRWOBJ_HXX
85 //#define _SELENG_HXX
86 //#define _SOUND_HXX
87 //#define _SYSDLG_HXX
92 #define _PASSWD_HXX
94 #define _SFX_DOCFILE_HXX
95 //#define _SFX_DOCFILT_HXX
96 #define _SFX_DOCINF_HXX
97 #define _SFX_DOCSH_HXX
98 //#define _SFXDOCFILT_HXX
99 //#define _SFXDOCINF_HXX
100 //#define _SFXDOCSH_HXX
101 #define _SFX_PRNMON_HXX
102 #define _SFX_RESMGR_HXX
103 #define _SFX_TEMPLDLG_HXX
104 //#define _SFXAPPWIN_HXX
105 #define _SFXBASIC_HXX
106 #define _SFXCTRLITEM
107 #define _SFXDLGCFG_HXX
108 //#define _SFXDISPATCH_HXX
109 #define _SFXFILEDLG_HXX
110 //#define _SFXIMGMGR_HXX
111 #define _SFXIPFRM_HXX
112 #define _SFX_MACRO_HXX
113 #define _SFXMNUITEM_HXX
114 #define _SFXMNUMGR_HXX
115 #define _SFXMULTISEL_HXX
116 //#define _SFXMSG_HXX
117 #define _SFXMSGDESCR_HXX
118 #define _SFXMSGPOOL_HXX
119 #define _SFX_MINFITEM_HXX
120 #define _SFXOBJFACE_HXX
121 #define _SFXOBJFAC_HXX
122 #define _SFX_SAVEOPT_HXX
123 #define _SFXSTBITEM_HXX
124 #define _SFXSTBMGR_HXX
125 #define _SFXTBXCTRL_HXX
126 #define _SFXTBXMGR_HXX
128 #define _SI_HXX
129 //#define _SI_DLL_HXX
130 //#define _SIDLL_HXX
131 //#define _SI_NOITEMS
132 //#define _SI_NOOTHERFORMS
133 //#define _SI_NOSBXCONTROLS
134 //#define _SINOSBXCONTROLS
135 //#define _SI_NODRW
136 //#define _SI_NOCONTROL
138 #define _SVBOXITM_HXX
139 #define _SVCONTNR_HXX //
141 #define _SDR_NOTRANSFORM
143 #define _SVDRAG_HXX
144 #define _SVINCVW_HXX
145 #define _SV_MULTISEL_HXX
146 #define _SVRTV_HXX
147 #define _SVTABBX_HXX
148 #define _SVTREEBOX_HXX
149 #define _SVTREELIST_HXX
151 #define _SVX_DAILDLL_HXX
152 #define _SVX_HYPHEN_HXX
153 #define _SVX_IMPGRF_HXX
154 #define _SVX_LAYCTRL_HXX
155 #define _SVX_OPTITEMS_HXX
156 #define _SVX_OPTGERL_HXX
157 #define _SVX_OPTSAVE_HXX
158 #define _SVX_OPTSPELL_HXX
159 #define _SVX_OPTPATH_HXX
160 #define _SVX_OPTLINGU_HXX
161 #define _SVX_RULER_HXX
162 #define _SVX_RULRITEM_HXX
163 #define _SVX_SELCTRL_HXX
164 #define _SVX_SPLWRAP_HXX
165 #define _SVX_SPLDLG_HXX
166 #define _SVX_STDDLG_HXX
167 #define _SVX_THESDLG_HXX
169 // INCLUDE -------------------------------------------------------------------
171 #include "scitems.hxx"
172 #include <svx/dbexch.hrc>
173 #include <svx/svdetc.hxx>
174 #include <sfx2/dispatch.hxx>
175 #include <sfx2/docfile.hxx>
176 #include <svtools/stritem.hxx>
177 #include <svtools/ptitem.hxx>
178 #include <svtools/urlbmk.hxx>
179 #include <sot/clsids.hxx>
180 #include <sot/formats.hxx>
181 #include <vcl/graph.hxx>
182 #include <vcl/virdev.hxx>
183 #include <vcl/msgbox.hxx>
184 #include <tools/urlobj.hxx>
185 #include <sot/exchange.hxx>
186 #include <memory>
188 #include "attrib.hxx"
189 #include "patattr.hxx"
190 #include "dociter.hxx"
191 #include "viewfunc.hxx"
192 #include "tabvwsh.hxx"
193 #include "docsh.hxx"
194 #include "docfunc.hxx"
195 #include "undoblk.hxx"
196 #include "refundo.hxx"
197 #include "globstr.hrc"
198 #include "global.hxx"
199 #include "transobj.hxx"
200 #include "drwtrans.hxx"
201 #include "rangenam.hxx"
202 #include "dbcolect.hxx"
203 #include "impex.hxx" // Sylk-ID fuer CB
204 #include "chgtrack.hxx"
205 #include "waitoff.hxx"
206 #include "scmod.hxx"
207 #include "sc.hrc"
208 #include "inputopt.hxx"
209 #include "warnbox.hxx"
210 #include "drwlayer.hxx"
211 #include "editable.hxx"
212 #include "transobj.hxx"
213 #include "drwtrans.hxx"
214 #include "docuno.hxx"
215 #include "clipparam.hxx"
216 #include "undodat.hxx" // Amelia Wang
218 using namespace com::sun::star;
220 // STATIC DATA ---------------------------------------------------------------
223 //============================================================================
225 // GlobalName der Writer-DocShell kommt jetzt aus comphelper/classids.hxx
227 //----------------------------------------------------------------------------
228 // C U T
230 void ScViewFunc::CutToClip( ScDocument* pClipDoc, BOOL bIncludeObjects )
232 UpdateInputLine();
234 ScEditableTester aTester( this );
235 if (!aTester.IsEditable()) // selection editable?
237 ErrorMessage( aTester.GetMessageId() );
238 return;
241 ScRange aRange; // zu loeschender Bereich
242 if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
244 ScDocument* pDoc = GetViewData()->GetDocument();
245 ScDocShell* pDocSh = GetViewData()->GetDocShell();
246 ScMarkData& rMark = GetViewData()->GetMarkData();
247 const BOOL bRecord(pDoc->IsUndoEnabled()); // Undo/Redo
249 ScDocShellModificator aModificator( *pDocSh );
251 if ( !rMark.IsMarked() && !rMark.IsMultiMarked() ) // mark the range if not marked yet
253 DoneBlockMode();
254 InitOwnBlockMode();
255 rMark.SetMarkArea( aRange );
256 MarkDataChanged();
259 CopyToClip( pClipDoc, TRUE, FALSE, bIncludeObjects ); // Ab ins Clipboard
261 ScAddress aOldEnd( aRange.aEnd ); // Zusammengefasste Zellen im Bereich?
262 pDoc->ExtendMerge( aRange, TRUE );
264 ScDocument* pUndoDoc = NULL;
265 if ( bRecord )
267 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
268 pUndoDoc->InitUndoSelected( pDoc, rMark );
269 // all sheets - CopyToDocument skips those that don't exist in pUndoDoc
270 ScRange aCopyRange = aRange;
271 aCopyRange.aStart.SetTab(0);
272 aCopyRange.aEnd.SetTab(pDoc->GetTableCount()-1);
273 pDoc->CopyToDocument( aCopyRange, (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS, FALSE, pUndoDoc );
274 pDoc->BeginDrawUndo();
277 USHORT nExtFlags = 0;
278 pDocSh->UpdatePaintExt( nExtFlags, aRange );
280 HideCursor(); // Cursor aendert sich !
282 rMark.MarkToMulti();
283 pDoc->DeleteSelection( IDF_ALL, rMark );
284 if ( bIncludeObjects )
285 pDoc->DeleteObjectsInSelection( rMark );
286 rMark.MarkToSimple();
288 if ( !AdjustRowHeight( aRange.aStart.Row(), aRange.aEnd.Row() ) )
289 pDocSh->PostPaint( aRange, PAINT_GRID, nExtFlags );
291 if ( bRecord ) // erst jetzt ist Draw-Undo verfuegbar
292 pDocSh->GetUndoManager()->AddUndoAction(
293 new ScUndoCut( pDocSh, aRange, aOldEnd, rMark, pUndoDoc ) );
295 aModificator.SetDocumentModified();
296 ShowCursor(); // Cursor aendert sich !
297 pDocSh->UpdateOle(GetViewData());
299 CellContentChanged();
301 else
302 ErrorMessage( STR_NOMULTISELECT );
306 //----------------------------------------------------------------------------
307 // C O P Y
309 BOOL ScViewFunc::CopyToClip( ScDocument* pClipDoc, BOOL bCut, BOOL bApi, BOOL bIncludeObjects, BOOL bStopEdit )
311 BOOL bDone = FALSE;
312 if ( bStopEdit )
313 UpdateInputLine();
315 ScRange aRange;
316 ScMarkType eMarkType = GetViewData()->GetSimpleArea( aRange );
317 ScDocument* pDoc = GetViewData()->GetDocument();
318 ScMarkData& rMark = GetViewData()->GetMarkData();
319 if ( eMarkType == SC_MARK_SIMPLE || eMarkType == SC_MARK_SIMPLE_FILTERED )
321 if ( !pDoc->HasSelectedBlockMatrixFragment(
322 aRange.aStart.Col(), aRange.aStart.Row(),
323 aRange.aEnd.Col(), aRange.aEnd.Row(),
324 rMark ) )
326 BOOL bSysClip = FALSE;
327 if ( !pClipDoc ) // no clip doc specified
329 pClipDoc = new ScDocument( SCDOCMODE_CLIP ); // create one (deleted by ScTransferObj)
330 bSysClip = TRUE; // and copy into system
333 if ( !bCut )
335 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
336 if ( pChangeTrack )
337 pChangeTrack->ResetLastCut(); // kein CutMode mehr
340 if ( bSysClip && bIncludeObjects )
342 BOOL bAnyOle = pDoc->HasOLEObjectsInArea( aRange, &rMark );
343 // update ScGlobal::pDrawClipDocShellRef
344 ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
347 ScClipParam aClipParam(aRange, bCut);
348 pDoc->CopyToClip(aClipParam, pClipDoc, &rMark, false, false, bIncludeObjects);
349 if (bSysClip)
351 ScDrawLayer::SetGlobalDrawPersist(NULL);
353 ScGlobal::SetClipDocName( pDoc->GetDocumentShell()->GetTitle( SFX_TITLE_FULLNAME ) );
355 pClipDoc->ExtendMerge( aRange, TRUE );
357 if (bSysClip)
359 ScDocShell* pDocSh = GetViewData()->GetDocShell();
360 TransferableObjectDescriptor aObjDesc;
361 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
362 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
363 // maSize is set in ScTransferObj ctor
365 ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
366 uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
368 if ( ScGlobal::pDrawClipDocShellRef )
370 SfxObjectShellRef aPersistRef( &(*ScGlobal::pDrawClipDocShellRef) );
371 pTransferObj->SetDrawPersist( aPersistRef ); // keep persist for ole objects alive
374 pTransferObj->CopyToClipboard( GetActiveWin() ); // system clipboard
375 SC_MOD()->SetClipObject( pTransferObj, NULL ); // internal clipboard
378 bDone = TRUE;
380 else
382 if (!bApi)
383 ErrorMessage(STR_MATRIXFRAGMENTERR);
386 else if (eMarkType == SC_MARK_MULTI)
388 bool bSuccess = false;
389 ScClipParam aClipParam;
390 aClipParam.mbCutMode = false;
391 rMark.MarkToSimple();
392 rMark.FillRangeListWithMarks(&aClipParam.maRanges, false);
396 if (bCut)
397 // We con't support cutting of multi-selections.
398 break;
400 if (pClipDoc)
401 // TODO: What's this for?
402 break;
404 ::std::auto_ptr<ScDocument> pDocClip(new ScDocument(SCDOCMODE_CLIP));
406 // Check for geometrical feasibility of the ranges.
407 bool bValidRanges = true;
408 ScRangePtr p = aClipParam.maRanges.First();
409 SCCOL nPrevColDelta = 0;
410 SCROW nPrevRowDelta = 0;
411 SCCOL nPrevCol = p->aStart.Col();
412 SCROW nPrevRow = p->aStart.Row();
413 SCCOL nPrevColSize = p->aEnd.Col() - p->aStart.Col() + 1;
414 SCROW nPrevRowSize = p->aEnd.Row() - p->aStart.Row() + 1;
415 for (p = aClipParam.maRanges.Next(); p; p = aClipParam.maRanges.Next())
417 if (pDoc->HasSelectedBlockMatrixFragment(
418 p->aStart.Col(), p->aStart.Row(), p->aEnd.Col(), p->aEnd.Row(), rMark))
420 if (!bApi)
421 ErrorMessage(STR_MATRIXFRAGMENTERR);
422 return false;
425 SCCOL nColDelta = p->aStart.Col() - nPrevCol;
426 SCROW nRowDelta = p->aStart.Row() - nPrevRow;
428 if ((nColDelta && nRowDelta) || (nPrevColDelta && nRowDelta) || (nPrevRowDelta && nColDelta))
430 bValidRanges = false;
431 break;
434 if (aClipParam.meDirection == ScClipParam::Unspecified)
436 if (nColDelta)
437 aClipParam.meDirection = ScClipParam::Column;
438 if (nRowDelta)
439 aClipParam.meDirection = ScClipParam::Row;
442 SCCOL nColSize = p->aEnd.Col() - p->aStart.Col() + 1;
443 SCROW nRowSize = p->aEnd.Row() - p->aStart.Row() + 1;
445 if (aClipParam.meDirection == ScClipParam::Column && nRowSize != nPrevRowSize)
447 // column-oriented ranges must have identical row size.
448 bValidRanges = false;
449 break;
451 if (aClipParam.meDirection == ScClipParam::Row && nColSize != nPrevColSize)
453 // likewise, row-oriented ranges must have identical
454 // column size.
455 bValidRanges = false;
456 break;
459 nPrevCol = p->aStart.Col();
460 nPrevRow = p->aStart.Row();
461 nPrevColDelta = nColDelta;
462 nPrevRowDelta = nRowDelta;
463 nPrevColSize = nColSize;
464 nPrevRowSize = nRowSize;
466 if (!bValidRanges)
467 break;
469 pDoc->CopyToClip(aClipParam, pDocClip.get(), &rMark, false, false, bIncludeObjects);
471 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
472 if ( pChangeTrack )
473 pChangeTrack->ResetLastCut(); // kein CutMode mehr
476 ScDocShell* pDocSh = GetViewData()->GetDocShell();
477 TransferableObjectDescriptor aObjDesc;
478 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
479 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
480 // maSize is set in ScTransferObj ctor
482 ScTransferObj* pTransferObj = new ScTransferObj( pDocClip.release(), aObjDesc );
483 uno::Reference<datatransfer::XTransferable> xTransferable( pTransferObj );
485 if ( ScGlobal::pDrawClipDocShellRef )
487 SfxObjectShellRef aPersistRef( &(*ScGlobal::pDrawClipDocShellRef) );
488 pTransferObj->SetDrawPersist( aPersistRef ); // keep persist for ole objects alive
491 pTransferObj->CopyToClipboard( GetActiveWin() ); // system clipboard
492 SC_MOD()->SetClipObject( pTransferObj, NULL ); // internal clipboard
495 bSuccess = true;
497 while (false);
499 if (!bSuccess && !bApi)
500 ErrorMessage(STR_NOMULTISELECT);
502 bDone = bSuccess;
504 else
506 if (!bApi)
507 ErrorMessage(STR_NOMULTISELECT);
510 return bDone;
513 ScTransferObj* ScViewFunc::CopyToTransferable()
515 ScRange aRange;
516 if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
518 ScDocument* pDoc = GetViewData()->GetDocument();
519 ScMarkData& rMark = GetViewData()->GetMarkData();
520 if ( !pDoc->HasSelectedBlockMatrixFragment(
521 aRange.aStart.Col(), aRange.aStart.Row(),
522 aRange.aEnd.Col(), aRange.aEnd.Row(),
523 rMark ) )
525 ScDocument *pClipDoc = new ScDocument( SCDOCMODE_CLIP ); // create one (deleted by ScTransferObj)
527 BOOL bAnyOle = pDoc->HasOLEObjectsInArea( aRange, &rMark );
528 ScDrawLayer::SetGlobalDrawPersist( ScTransferObj::SetDrawClipDoc( bAnyOle ) );
530 ScClipParam aClipParam(aRange, false);
531 pDoc->CopyToClip(aClipParam, pClipDoc, &rMark, false, false, true);
533 ScDrawLayer::SetGlobalDrawPersist(NULL);
534 pClipDoc->ExtendMerge( aRange, TRUE );
536 ScDocShell* pDocSh = GetViewData()->GetDocShell();
537 TransferableObjectDescriptor aObjDesc;
538 pDocSh->FillTransferableObjectDescriptor( aObjDesc );
539 aObjDesc.maDisplayName = pDocSh->GetMedium()->GetURLObject().GetURLNoPass();
540 ScTransferObj* pTransferObj = new ScTransferObj( pClipDoc, aObjDesc );
541 return pTransferObj;
545 return NULL;
548 //----------------------------------------------------------------------------
549 // P A S T E
551 void ScViewFunc::PasteDraw()
553 ScViewData* pViewData = GetViewData();
554 SCCOL nPosX = pViewData->GetCurX();
555 SCROW nPosY = pViewData->GetCurY();
556 Window* pWin = GetActiveWin();
557 Point aPos = pWin->PixelToLogic( pViewData->GetScrPos( nPosX, nPosY,
558 pViewData->GetActivePart() ) );
559 ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard( pWin );
560 if (pDrawClip)
561 PasteDraw( aPos, pDrawClip->GetModel(), FALSE,
562 pDrawClip->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() );
565 void ScViewFunc::PasteFromSystem()
567 UpdateInputLine();
569 Window* pWin = GetActiveWin();
570 ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
571 ScDrawTransferObj* pDrawClip = ScDrawTransferObj::GetOwnClipboard( pWin );
573 if (pOwnClip)
575 // #129384# keep a reference in case the clipboard is changed during PasteFromClip
576 uno::Reference<datatransfer::XTransferable> aOwnClipRef( pOwnClip );
577 PasteFromClip( IDF_ALL, pOwnClip->GetDocument(),
578 PASTE_NOFUNC, FALSE, FALSE, FALSE, INS_NONE, IDF_NONE,
579 TRUE ); // allow warning dialog
581 else if (pDrawClip)
582 PasteDraw();
583 else
585 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
587 // if (pClipObj.Is())
589 ULONG nBiff8 = SotExchange::RegisterFormatName(
590 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Biff8")));
591 ULONG nBiff5 = SotExchange::RegisterFormatName(
592 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Biff5")));
594 // als erstes SvDraw-Model, dann Grafik
595 // (Grafik darf nur bei einzelner Grafik drinstehen)
597 if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ))
599 // special case for tables from drawing
600 if( aDataHelper.HasFormat( SOT_FORMAT_RTF ) )
602 PasteFromSystem( FORMAT_RTF );
604 else
606 PasteFromSystem( SOT_FORMATSTR_ID_DRAWING );
609 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ))
610 PasteFromSystem( SOT_FORMATSTR_ID_SVXB );
611 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ))
613 // If it's a Writer object, insert RTF instead of OLE
615 BOOL bDoRtf = FALSE;
616 TransferableObjectDescriptor aObjDesc;
617 if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) )
619 bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
620 aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
621 && aDataHelper.HasFormat( SOT_FORMAT_RTF ) );
623 if ( bDoRtf )
624 PasteFromSystem( FORMAT_RTF );
625 else
626 PasteFromSystem( SOT_FORMATSTR_ID_EMBED_SOURCE );
628 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ))
629 PasteFromSystem( SOT_FORMATSTR_ID_LINK_SOURCE );
630 // the following format can not affect scenario from #89579#
631 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ))
632 PasteFromSystem( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE );
633 // FORMAT_PRIVATE no longer here (can't work if pOwnClip is NULL)
634 else if (aDataHelper.HasFormat(nBiff8)) // before xxx_OLE formats
635 PasteFromSystem(nBiff8);
636 else if (aDataHelper.HasFormat(nBiff5))
637 PasteFromSystem(nBiff5);
638 else if (aDataHelper.HasFormat(FORMAT_RTF))
639 PasteFromSystem(FORMAT_RTF);
640 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML))
641 PasteFromSystem(SOT_FORMATSTR_ID_HTML);
642 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML_SIMPLE))
643 PasteFromSystem(SOT_FORMATSTR_ID_HTML_SIMPLE);
644 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_SYLK))
645 PasteFromSystem(SOT_FORMATSTR_ID_SYLK);
646 else if (aDataHelper.HasFormat(FORMAT_STRING))
647 PasteFromSystem(FORMAT_STRING);
648 else if (aDataHelper.HasFormat(FORMAT_GDIMETAFILE))
649 PasteFromSystem(FORMAT_GDIMETAFILE);
650 else if (aDataHelper.HasFormat(FORMAT_BITMAP))
651 PasteFromSystem(FORMAT_BITMAP);
652 // #89579# xxx_OLE formats come last, like in SotExchange tables
653 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ))
654 PasteFromSystem( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE );
655 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ))
656 PasteFromSystem( SOT_FORMATSTR_ID_LINK_SOURCE_OLE );
657 // else
658 // ErrorMessage(STR_PASTE_ERROR);
660 // else
661 // ErrorMessage(STR_PASTE_ERROR);
664 // keine Fehlermeldung, weil SID_PASTE in der idl das FastCall-Flag hat,
665 // also auch gerufen wird, wenn nichts im Clipboard steht (#42531#)
668 void ScViewFunc::PasteFromTransferable( const uno::Reference<datatransfer::XTransferable>& rxTransferable )
670 ScTransferObj *pOwnClip=0;
671 ScDrawTransferObj *pDrawClip=0;
672 uno::Reference<lang::XUnoTunnel> xTunnel( rxTransferable, uno::UNO_QUERY );
673 if ( xTunnel.is() )
675 sal_Int64 nHandle = xTunnel->getSomething( ScTransferObj::getUnoTunnelId() );
676 if ( nHandle )
677 pOwnClip = (ScTransferObj*) (sal_IntPtr) nHandle;
678 else
680 nHandle = xTunnel->getSomething( ScDrawTransferObj::getUnoTunnelId() );
681 if ( nHandle )
682 pDrawClip = (ScDrawTransferObj*) (sal_IntPtr) nHandle;
686 if (pOwnClip)
688 PasteFromClip( IDF_ALL, pOwnClip->GetDocument(),
689 PASTE_NOFUNC, FALSE, FALSE, FALSE, INS_NONE, IDF_NONE,
690 TRUE ); // allow warning dialog
692 else if (pDrawClip)
694 ScViewData* pViewData = GetViewData();
695 SCCOL nPosX = pViewData->GetCurX();
696 SCROW nPosY = pViewData->GetCurY();
697 Window* pWin = GetActiveWin();
698 Point aPos = pWin->PixelToLogic( pViewData->GetScrPos( nPosX, nPosY, pViewData->GetActivePart() ) );
699 PasteDraw( aPos, pDrawClip->GetModel(), FALSE, pDrawClip->GetSourceDocID() == pViewData->GetDocument()->GetDocumentID() );
701 else
703 TransferableDataHelper aDataHelper( rxTransferable );
705 ULONG nBiff8 = SotExchange::RegisterFormatName(
706 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Biff8")));
707 ULONG nBiff5 = SotExchange::RegisterFormatName(
708 String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("Biff5")));
709 ULONG nFormatId = 0;
710 // als erstes SvDraw-Model, dann Grafik
711 // (Grafik darf nur bei einzelner Grafik drinstehen)
713 if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_DRAWING ))
714 nFormatId = SOT_FORMATSTR_ID_DRAWING;
715 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ))
716 nFormatId = SOT_FORMATSTR_ID_SVXB;
717 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE ))
719 // If it's a Writer object, insert RTF instead of OLE
720 BOOL bDoRtf = FALSE;
721 TransferableObjectDescriptor aObjDesc;
722 if( aDataHelper.GetTransferableObjectDescriptor( SOT_FORMATSTR_ID_OBJECTDESCRIPTOR, aObjDesc ) )
724 bDoRtf = ( ( aObjDesc.maClassName == SvGlobalName( SO3_SW_CLASSID ) ||
725 aObjDesc.maClassName == SvGlobalName( SO3_SWWEB_CLASSID ) )
726 && aDataHelper.HasFormat( SOT_FORMAT_RTF ) );
728 if ( bDoRtf )
729 nFormatId = FORMAT_RTF;
730 else
731 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE;
733 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE ))
734 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE;
735 // the following format can not affect scenario from #89579#
736 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE ))
737 nFormatId = SOT_FORMATSTR_ID_EMBEDDED_OBJ_OLE;
738 // FORMAT_PRIVATE no longer here (can't work if pOwnClip is NULL)
739 else if (aDataHelper.HasFormat(nBiff8)) // before xxx_OLE formats
740 nFormatId = nBiff8;
741 else if (aDataHelper.HasFormat(nBiff5))
742 nFormatId = nBiff5;
743 else if (aDataHelper.HasFormat(FORMAT_RTF))
744 nFormatId = FORMAT_RTF;
745 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML))
746 nFormatId = SOT_FORMATSTR_ID_HTML;
747 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_HTML_SIMPLE))
748 nFormatId = SOT_FORMATSTR_ID_HTML_SIMPLE;
749 else if (aDataHelper.HasFormat(SOT_FORMATSTR_ID_SYLK))
750 nFormatId = SOT_FORMATSTR_ID_SYLK;
751 else if (aDataHelper.HasFormat(FORMAT_STRING))
752 nFormatId = FORMAT_STRING;
753 else if (aDataHelper.HasFormat(FORMAT_GDIMETAFILE))
754 nFormatId = FORMAT_GDIMETAFILE;
755 else if (aDataHelper.HasFormat(FORMAT_BITMAP))
756 nFormatId = FORMAT_BITMAP;
757 // #89579# xxx_OLE formats come last, like in SotExchange tables
758 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_EMBED_SOURCE_OLE ))
759 nFormatId = SOT_FORMATSTR_ID_EMBED_SOURCE_OLE;
760 else if (aDataHelper.HasFormat( SOT_FORMATSTR_ID_LINK_SOURCE_OLE ))
761 nFormatId = SOT_FORMATSTR_ID_LINK_SOURCE_OLE;
762 else
763 return;
765 PasteDataFormat( nFormatId, aDataHelper.GetTransferable(),
766 GetViewData()->GetCurX(), GetViewData()->GetCurY(),
767 NULL, FALSE, FALSE );
772 BOOL ScViewFunc::PasteFromSystem( ULONG nFormatId, BOOL bApi )
774 UpdateInputLine();
776 BOOL bRet = TRUE;
777 Window* pWin = GetActiveWin();
778 ScTransferObj* pOwnClip = ScTransferObj::GetOwnClipboard( pWin );
779 if ( nFormatId == 0 && pOwnClip )
781 // #129384# keep a reference in case the clipboard is changed during PasteFromClip
782 uno::Reference<datatransfer::XTransferable> aOwnClipRef( pOwnClip );
783 PasteFromClip( IDF_ALL, pOwnClip->GetDocument(),
784 PASTE_NOFUNC, FALSE, FALSE, FALSE, INS_NONE, IDF_NONE,
785 !bApi ); // allow warning dialog
787 else
789 TransferableDataHelper aDataHelper( TransferableDataHelper::CreateFromSystemClipboard( pWin ) );
790 if ( !aDataHelper.GetTransferable().is() )
791 return FALSE;
793 bRet = PasteDataFormat( nFormatId, aDataHelper.GetTransferable(),
794 GetViewData()->GetCurX(), GetViewData()->GetCurY(),
795 NULL, FALSE, !bApi ); // allow warning dialog
797 if ( !bRet && !bApi )
798 ErrorMessage(STR_PASTE_ERROR);
800 return bRet;
804 //----------------------------------------------------------------------------
805 // P A S T E
807 BOOL ScViewFunc::PasteOnDrawObject( const uno::Reference<datatransfer::XTransferable>& rxTransferable,
808 SdrObject* pHitObj, BOOL bLink )
810 BOOL bRet = FALSE;
811 if ( bLink )
813 TransferableDataHelper aDataHelper( rxTransferable );
814 if ( aDataHelper.HasFormat( SOT_FORMATSTR_ID_SVXB ) )
816 SotStorageStreamRef xStm;
817 if( aDataHelper.GetSotStorageStream( SOT_FORMATSTR_ID_SVXB, xStm ) )
819 Graphic aGraphic;
820 *xStm >> aGraphic;
821 bRet = ApplyGraphicToObject( pHitObj, aGraphic );
824 else if ( aDataHelper.HasFormat( SOT_FORMAT_GDIMETAFILE ) )
826 GDIMetaFile aMtf;
827 if( aDataHelper.GetGDIMetaFile( FORMAT_GDIMETAFILE, aMtf ) )
828 bRet = ApplyGraphicToObject( pHitObj, Graphic(aMtf) );
830 else if ( aDataHelper.HasFormat( SOT_FORMAT_BITMAP ) )
832 Bitmap aBmp;
833 if( aDataHelper.GetBitmap( FORMAT_BITMAP, aBmp ) )
834 bRet = ApplyGraphicToObject( pHitObj, Graphic(aBmp) );
837 else
839 // ham' wa noch nich
841 return bRet;
844 BOOL lcl_SelHasAttrib( ScDocument* pDoc, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2,
845 const ScMarkData& rTabSelection, USHORT nMask )
847 SCTAB nTabCount = pDoc->GetTableCount();
848 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
849 if ( rTabSelection.GetTableSelect(nTab) && pDoc->HasAttrib( nCol1, nRow1, nTab, nCol2, nRow2, nTab, nMask ) )
850 return TRUE;
851 return FALSE;
855 // Einfuegen auf Tabelle:
858 // internes Paste
860 namespace {
862 class CursorSwitcher
864 public:
865 CursorSwitcher(ScViewFunc* pViewFunc) :
866 mpViewFunc(pViewFunc)
868 mpViewFunc->HideCursor();
871 ~CursorSwitcher()
873 mpViewFunc->ShowCursor();
875 private:
876 ScViewFunc* mpViewFunc;
879 bool lcl_checkDestRangeForOverwrite(const ScRange& rDestRange, const ScDocument* pDoc, const ScMarkData& rMark, Window* pParentWnd)
881 bool bIsEmpty = true;
882 SCTAB nTabCount = pDoc->GetTableCount();
883 for (SCTAB nTab=0; nTab < nTabCount && bIsEmpty; ++nTab)
885 if (!rMark.GetTableSelect(nTab))
886 continue;
888 bIsEmpty = pDoc->IsBlockEmpty(nTab, rDestRange.aStart.Col(), rDestRange.aStart.Row(),
889 rDestRange.aEnd.Col(), rDestRange.aEnd.Row());
892 if (!bIsEmpty)
894 ScReplaceWarnBox aBox(pParentWnd);
895 if (aBox.Execute() != RET_YES)
897 // changing the configuration is within the ScReplaceWarnBox
898 return false;
901 return true;
906 BOOL ScViewFunc::PasteFromClip( USHORT nFlags, ScDocument* pClipDoc,
907 USHORT nFunction, BOOL bSkipEmpty,
908 BOOL bTranspose, BOOL bAsLink,
909 InsCellCmd eMoveMode, USHORT nUndoExtraFlags,
910 BOOL bAllowDialogs )
912 if (!pClipDoc)
914 DBG_ERROR("PasteFromClip: pClipDoc=0 not allowed");
915 return FALSE;
918 // fuer Undo etc. immer alle oder keine Inhalte sichern
919 USHORT nContFlags = IDF_NONE;
920 if (nFlags & IDF_CONTENTS)
921 nContFlags |= IDF_CONTENTS;
922 if (nFlags & IDF_ATTRIB)
923 nContFlags |= IDF_ATTRIB;
924 // evtl. Attribute ins Undo ohne sie vom Clip ins Doc zu kopieren
925 USHORT nUndoFlags = nContFlags;
926 if (nUndoExtraFlags & IDF_ATTRIB)
927 nUndoFlags |= IDF_ATTRIB;
928 // do not copy note captions into undo document
929 nUndoFlags |= IDF_NOCAPTIONS;
931 ScClipParam& rClipParam = pClipDoc->GetClipParam();
932 if (rClipParam.isMultiRange())
933 return PasteMultiRangesFromClip(
934 nFlags, pClipDoc, nFunction, bSkipEmpty, bTranspose, bAsLink, bAllowDialogs,
935 eMoveMode, nContFlags, nUndoFlags);
937 BOOL bCutMode = pClipDoc->IsCutMode(); // if transposing, take from original clipdoc
938 BOOL bIncludeFiltered = bCutMode;
940 // paste drawing: also if IDF_NOTE is set (to create drawing layer for note captions)
941 BOOL bPasteDraw = ( pClipDoc->GetDrawLayer() && ( nFlags & (IDF_OBJECTS|IDF_NOTE) ) );
943 ScDocShellRef aTransShellRef; // for objects in xTransClip - must remain valid as long as xTransClip
944 ScDocument* pOrigClipDoc = NULL;
945 ::std::auto_ptr< ScDocument > xTransClip;
946 if ( bTranspose )
948 SCCOL nX;
949 SCROW nY;
950 // include filtered rows until TransposeClip can skip them
951 bIncludeFiltered = TRUE;
952 pClipDoc->GetClipArea( nX, nY, TRUE );
953 if ( nY > static_cast<sal_Int32>(MAXCOL) ) // zuviele Zeilen zum Transponieren
955 ErrorMessage(STR_PASTE_FULL);
956 return FALSE;
958 pOrigClipDoc = pClipDoc; // fuer Referenzen
960 if ( bPasteDraw )
962 aTransShellRef = new ScDocShell; // DocShell needs a Ref immediately
963 aTransShellRef->DoInitNew(NULL);
965 ScDrawLayer::SetGlobalDrawPersist(aTransShellRef);
967 xTransClip.reset( new ScDocument( SCDOCMODE_CLIP ));
968 pClipDoc->TransposeClip( xTransClip.get(), nFlags, bAsLink );
969 pClipDoc = xTransClip.get();
971 ScDrawLayer::SetGlobalDrawPersist(NULL);
974 SCCOL nStartCol;
975 SCROW nStartRow;
976 SCTAB nStartTab;
977 SCCOL nEndCol;
978 SCROW nEndRow;
979 SCTAB nEndTab;
980 SCCOL nClipSizeX;
981 SCROW nClipSizeY;
982 pClipDoc->GetClipArea( nClipSizeX, nClipSizeY, TRUE ); // size in clipboard doc
984 // size in target doc: include filtered rows only if CutMode is set
985 SCCOL nDestSizeX;
986 SCROW nDestSizeY;
987 pClipDoc->GetClipArea( nDestSizeX, nDestSizeY, bIncludeFiltered );
989 ScDocument* pDoc = GetViewData()->GetDocument();
990 ScDocShell* pDocSh = GetViewData()->GetDocShell();
991 ScMarkData& rMark = GetViewData()->GetMarkData();
992 SfxUndoManager* pUndoMgr = pDocSh->GetUndoManager();
993 const BOOL bRecord(pDoc->IsUndoEnabled());
995 ScDocShellModificator aModificator( *pDocSh );
997 ScRange aMarkRange;
998 ScMarkData aFilteredMark( rMark); // local copy for all modifications
999 ScMarkType eMarkType = GetViewData()->GetSimpleArea( aMarkRange, aFilteredMark);
1000 bool bMarkIsFiltered = (eMarkType == SC_MARK_SIMPLE_FILTERED);
1001 bool bNoPaste = ((eMarkType != SC_MARK_SIMPLE && !bMarkIsFiltered) ||
1002 (bMarkIsFiltered && (eMoveMode != INS_NONE || bAsLink)));
1003 if (!bNoPaste && !rMark.IsMarked())
1005 // Create a selection with clipboard row count and check that for
1006 // filtered.
1007 nStartCol = GetViewData()->GetCurX();
1008 nStartRow = GetViewData()->GetCurY();
1009 nStartTab = GetViewData()->GetTabNo();
1010 nEndCol = nStartCol + nDestSizeX;
1011 nEndRow = nStartRow + nDestSizeY;
1012 nEndTab = nStartTab;
1013 aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
1014 if (ScViewUtil::HasFiltered( aMarkRange, pDoc))
1016 bMarkIsFiltered = true;
1017 // Fit to clipboard's row count unfiltered rows. If there is no
1018 // fit assume that pasting is not possible. Note that nDestSizeY is
1019 // size-1 (difference).
1020 if (!ScViewUtil::FitToUnfilteredRows( aMarkRange, pDoc, nDestSizeY+1))
1021 bNoPaste = true;
1023 aFilteredMark.SetMarkArea( aMarkRange);
1025 if (bNoPaste)
1027 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1028 return FALSE;
1031 SCROW nUnfilteredRows = aMarkRange.aEnd.Row() - aMarkRange.aStart.Row() + 1;
1032 ScRangeList aRangeList;
1033 if (bMarkIsFiltered)
1035 ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc);
1036 aFilteredMark.FillRangeListWithMarks( &aRangeList, FALSE);
1037 nUnfilteredRows = 0;
1038 for (ScRange* p = aRangeList.First(); p; p = aRangeList.Next())
1040 nUnfilteredRows += p->aEnd.Row() - p->aStart.Row() + 1;
1042 #if 0
1043 /* This isn't needed but could be a desired restriction. */
1044 // For filtered, destination rows have to be an exact multiple of
1045 // source rows. Note that nDestSizeY is size-1 (difference), so
1046 // nDestSizeY==0 fits always.
1047 if ((nUnfilteredRows % (nDestSizeY+1)) != 0)
1049 /* FIXME: this should be a more descriptive error message then. */
1050 ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
1051 return FALSE;
1053 #endif
1056 SCCOL nMarkAddX = 0;
1057 SCROW nMarkAddY = 0;
1059 // Also for a filtered selection the area is used, for undo et al.
1060 if ( aFilteredMark.IsMarked() || bMarkIsFiltered )
1062 aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
1063 SCCOL nBlockAddX = nEndCol-nStartCol;
1064 SCROW nBlockAddY = nEndRow-nStartRow;
1066 // #58422# Nachfrage, wenn die Selektion groesser als 1 Zeile/Spalte, aber kleiner
1067 // als das Clipboard ist (dann wird ueber die Selektion hinaus eingefuegt)
1069 // ClipSize is not size, but difference
1070 if ( ( nBlockAddX != 0 && nBlockAddX < nDestSizeX ) ||
1071 ( nBlockAddY != 0 && nBlockAddY < nDestSizeY ) ||
1072 ( bMarkIsFiltered && nUnfilteredRows < nDestSizeY+1 ) )
1074 ScWaitCursorOff aWaitOff( GetFrameWin() );
1075 String aMessage = ScGlobal::GetRscString( STR_PASTE_BIGGER );
1076 QueryBox aBox( GetViewData()->GetDialogParent(),
1077 WinBits(WB_YES_NO | WB_DEF_NO), aMessage );
1078 if ( aBox.Execute() != RET_YES )
1080 return FALSE;
1084 if (nBlockAddX > nDestSizeX)
1085 nMarkAddX = nBlockAddX - nDestSizeX; // fuer Merge-Test
1086 else
1087 nEndCol = nStartCol + nDestSizeX;
1089 if (nBlockAddY > nDestSizeY)
1090 nMarkAddY = nBlockAddY - nDestSizeY; // fuer Merge-Test
1091 else
1093 nEndRow = nStartRow + nDestSizeY;
1094 if (bMarkIsFiltered || nEndRow > aMarkRange.aEnd.Row())
1096 // Same as above if nothing was marked: re-fit selection to
1097 // unfiltered rows. Extending the selection actually may
1098 // introduce filtered rows where there weren't any before, so
1099 // we also need to test for that.
1100 aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
1101 if (bMarkIsFiltered || ScViewUtil::HasFiltered( aMarkRange, pDoc))
1103 bMarkIsFiltered = true;
1104 // Worst case: all rows up to the end of the sheet are filtered.
1105 if (!ScViewUtil::FitToUnfilteredRows( aMarkRange, pDoc, nDestSizeY+1))
1107 ErrorMessage(STR_PASTE_FULL);
1108 return FALSE;
1111 aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab);
1112 aFilteredMark.SetMarkArea( aMarkRange);
1113 if (bMarkIsFiltered)
1115 ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc);
1116 aFilteredMark.FillRangeListWithMarks( &aRangeList, TRUE);
1121 else
1123 nStartCol = GetViewData()->GetCurX();
1124 nStartRow = GetViewData()->GetCurY();
1125 nStartTab = GetViewData()->GetTabNo();
1126 nEndCol = nStartCol + nDestSizeX;
1127 nEndRow = nStartRow + nDestSizeY;
1128 nEndTab = nStartTab;
1131 bool bOffLimits = !ValidCol(nEndCol) || !ValidRow(nEndRow);
1133 // Zielbereich, wie er angezeigt wird:
1134 ScRange aUserRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab );
1136 // Sollen Zellen eingefuegt werden?
1137 // (zu grosse nEndCol/nEndRow werden weiter unten erkannt)
1138 BOOL bInsertCells = ( eMoveMode != INS_NONE && !bOffLimits );
1139 if ( bInsertCells )
1141 // #94115# Instead of EnterListAction, the paste undo action is merged into the
1142 // insert action, so Repeat can insert the right cells
1144 MarkRange( aUserRange ); // wird vor CopyFromClip sowieso gesetzt
1146 // #72930# CutMode is reset on insertion of cols/rows but needed again on cell move
1147 BOOL bCut = pClipDoc->IsCutMode();
1148 if (!InsertCells( eMoveMode, bRecord, TRUE )) // is inserting possible?
1150 return FALSE;
1151 // #i21036# EnterListAction isn't used, and InsertCells doesn't insert
1152 // its undo action on failure, so no undo handling is needed here
1154 if ( bCut )
1155 pClipDoc->SetCutMode( bCut );
1157 else if (!bOffLimits)
1159 BOOL bAskIfNotEmpty = bAllowDialogs &&
1160 ( nFlags & IDF_CONTENTS ) &&
1161 nFunction == PASTE_NOFUNC &&
1162 SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1163 if ( bAskIfNotEmpty )
1165 if (!lcl_checkDestRangeForOverwrite(aUserRange, pDoc, aFilteredMark, GetViewData()->GetDialogParent()))
1166 return false;
1170 SCCOL nClipStartX; // Clipboard-Bereich erweitern
1171 SCROW nClipStartY;
1172 pClipDoc->GetClipStart( nClipStartX, nClipStartY );
1173 SCCOL nUndoEndCol = nClipStartX + nClipSizeX;
1174 SCROW nUndoEndRow = nClipStartY + nClipSizeY; // end of source area in clipboard document
1175 BOOL bClipOver = FALSE;
1176 // #i68690# ExtendMerge for the clip doc must be called with the clipboard's sheet numbers.
1177 // The same end column/row can be used for all calls because the clip doc doesn't contain
1178 // content outside the clip area.
1179 for (SCTAB nClipTab=0; nClipTab<=MAXTAB; nClipTab++)
1180 if ( pClipDoc->HasTable(nClipTab) )
1181 if ( pClipDoc->ExtendMerge( nClipStartX,nClipStartY, nUndoEndCol,nUndoEndRow, nClipTab, FALSE ) )
1182 bClipOver = TRUE;
1183 nUndoEndCol -= nClipStartX + nClipSizeX;
1184 nUndoEndRow -= nClipStartY + nClipSizeY; // now contains only the difference added by ExtendMerge
1185 nUndoEndCol = sal::static_int_cast<SCCOL>( nUndoEndCol + nEndCol );
1186 nUndoEndRow = sal::static_int_cast<SCROW>( nUndoEndRow + nEndRow ); // destination area, expanded for merged cells
1188 // if (nUndoEndCol < nEndCol) nUndoEndCol = nEndCol;
1189 // if (nUndoEndRow < nEndRow) nUndoEndRow = nEndRow;
1191 // nUndoEndCol += nMarkAddX;
1192 // nUndoEndRow += nMarkAddY;
1194 if (nUndoEndCol>MAXCOL || nUndoEndRow>MAXROW)
1196 ErrorMessage(STR_PASTE_FULL);
1197 return FALSE;
1200 pDoc->ExtendMergeSel( nStartCol,nStartRow, nUndoEndCol,nUndoEndRow, aFilteredMark, FALSE );
1202 // Test auf Zellschutz
1204 ScEditableTester aTester( pDoc, nStartTab, nStartCol,nStartRow, nUndoEndCol,nUndoEndRow );
1205 if (!aTester.IsEditable())
1207 ErrorMessage(aTester.GetMessageId());
1208 return FALSE;
1211 //! Test auf Ueberlappung
1212 //! nur wirkliche Schnittmenge testen !!!!!!!
1214 // pDoc->HasCommonAttr( StartCol,nStartRow, nUndoEndCol,nUndoEndRow, nStartTab,
1215 // pClipDoc, nClipStartX, nClipStartY );
1217 ScDocFunc& rDocFunc = pDocSh->GetDocFunc();
1218 if ( bRecord )
1220 String aUndo = ScGlobal::GetRscString( pClipDoc->IsCutMode() ? STR_UNDO_MOVE : STR_UNDO_COPY );
1221 pUndoMgr->EnterListAction( aUndo, aUndo );
1224 if (bClipOver)
1225 if (lcl_SelHasAttrib( pDoc, nStartCol,nStartRow, nUndoEndCol,nUndoEndRow, aFilteredMark, HASATTR_OVERLAPPED ))
1226 { // "Cell merge not possible if cells already merged"
1227 ScDocAttrIterator aIter( pDoc, nStartTab, nStartCol, nStartRow, nUndoEndCol, nUndoEndRow );
1228 const ScPatternAttr* pPattern = NULL;
1229 const ScMergeAttr* pMergeFlag = NULL;
1230 const ScMergeFlagAttr* pMergeFlagAttr = NULL;
1231 SCCOL nCol = -1;
1232 SCROW nRow1 = -1;
1233 SCROW nRow2 = -1;
1234 while ( ( pPattern = aIter.GetNext( nCol, nRow1, nRow2 ) ) != NULL )
1236 pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem(ATTR_MERGE);
1237 pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG);
1238 if( ( pMergeFlag && pMergeFlag->IsMerged() ) || ( pMergeFlagAttr && pMergeFlagAttr->IsOverlapped() ) )
1240 ScRange aRange(nCol, nRow1, nStartTab);
1241 pDoc->ExtendOverlapped(aRange);
1242 pDoc->ExtendMerge(aRange, TRUE, TRUE);
1243 rDocFunc.UnmergeCells(aRange, bRecord, TRUE);
1248 if ( !bCutMode )
1250 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
1251 if ( pChangeTrack )
1252 pChangeTrack->ResetLastCut(); // kein CutMode mehr
1255 BOOL bColInfo = ( nStartRow==0 && nEndRow==MAXROW );
1256 BOOL bRowInfo = ( nStartCol==0 && nEndCol==MAXCOL );
1258 ScDocument* pUndoDoc = NULL;
1259 ScDocument* pRefUndoDoc = NULL;
1260 ScDocument* pRedoDoc = NULL;
1261 ScRefUndoData* pUndoData = NULL;
1263 if ( bRecord )
1265 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1266 pUndoDoc->InitUndoSelected( pDoc, aFilteredMark, bColInfo, bRowInfo );
1268 // all sheets - CopyToDocument skips those that don't exist in pUndoDoc
1269 SCTAB nTabCount = pDoc->GetTableCount();
1270 pDoc->CopyToDocument( nStartCol, nStartRow, 0, nUndoEndCol, nUndoEndRow, nTabCount-1,
1271 nUndoFlags, FALSE, pUndoDoc );
1273 if ( bCutMode )
1275 pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1276 pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, FALSE, FALSE );
1278 pUndoData = new ScRefUndoData( pDoc );
1282 USHORT nExtFlags = 0;
1283 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab,
1284 nEndCol, nEndRow, nEndTab ); // content before the change
1286 if (GetViewData()->IsActive())
1288 DoneBlockMode();
1289 InitOwnBlockMode();
1291 rMark.SetMarkArea( aUserRange );
1292 MarkDataChanged();
1294 HideCursor(); // Cursor aendert sich !
1297 // Aus Clipboard kopieren,
1298 // wenn gerechnet werden soll, Originaldaten merken
1301 ScDocument* pMixDoc = NULL;
1302 if ( bSkipEmpty || nFunction )
1304 if ( nFlags & IDF_CONTENTS )
1306 pMixDoc = new ScDocument( SCDOCMODE_UNDO );
1307 pMixDoc->InitUndo( pDoc, nStartTab, nEndTab );
1308 pDoc->CopyToDocument( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab,
1309 IDF_CONTENTS, FALSE, pMixDoc );
1313 /* Make draw layer and start drawing undo.
1314 - Needed before AdjustBlockHeight to track moved drawing objects.
1315 - Needed before pDoc->CopyFromClip to track inserted note caption objects.
1317 if ( bPasteDraw )
1318 pDocSh->MakeDrawLayer();
1319 if ( bRecord )
1320 pDoc->BeginDrawUndo();
1322 USHORT nNoObjFlags = nFlags & ~IDF_OBJECTS;
1323 if (!bAsLink)
1325 // copy normally (original range)
1326 pDoc->CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags,
1327 pRefUndoDoc, pClipDoc, TRUE, FALSE, bIncludeFiltered,
1328 bSkipEmpty, (bMarkIsFiltered ? &aRangeList : NULL) );
1330 // bei Transpose Referenzen per Hand anpassen
1331 if ( bTranspose && bCutMode && (nFlags & IDF_CONTENTS) )
1332 pDoc->UpdateTranspose( aUserRange.aStart, pOrigClipDoc, aFilteredMark, pRefUndoDoc );
1334 else if (!bTranspose)
1336 // copy with bAsLink=TRUE
1337 pDoc->CopyFromClip( aUserRange, aFilteredMark, nNoObjFlags, pRefUndoDoc, pClipDoc,
1338 TRUE, TRUE, bIncludeFiltered, bSkipEmpty );
1340 else
1342 // alle Inhalte kopieren (im TransClipDoc stehen nur Formeln)
1343 pDoc->CopyFromClip( aUserRange, aFilteredMark, nContFlags, pRefUndoDoc, pClipDoc );
1346 // skipped rows and merged cells don't mix
1347 if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() )
1348 rDocFunc.UnmergeCells( aUserRange, FALSE, TRUE );
1350 pDoc->ExtendMergeSel( nStartCol, nStartRow, nEndCol, nEndRow, aFilteredMark, TRUE ); // Refresh
1351 // und Bereich neu
1353 if ( pMixDoc ) // Rechenfunktionen mit Original-Daten auszufuehren ?
1355 pDoc->MixDocument( aUserRange, nFunction, bSkipEmpty, pMixDoc );
1357 delete pMixDoc;
1359 AdjustBlockHeight(); // update row heights before pasting objects
1361 if ( nFlags & IDF_OBJECTS )
1363 // Paste the drawing objects after the row heights have been updated.
1365 pDoc->CopyFromClip( aUserRange, aFilteredMark, IDF_OBJECTS, pRefUndoDoc, pClipDoc,
1366 TRUE, FALSE, bIncludeFiltered );
1373 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab,
1374 nEndCol, nEndRow, nEndTab ); // content after the change
1377 // ggf. Autofilter-Koepfe loeschen
1378 if (bCutMode)
1379 if (pDoc->RefreshAutoFilter( nClipStartX,nClipStartY, nClipStartX+nClipSizeX,
1380 nClipStartY+nClipSizeY, nStartTab ))
1381 pDocSh->PostPaint( nClipStartX,nClipStartY,nStartTab,
1382 nClipStartX+nClipSizeX,nClipStartY,nStartTab,
1383 PAINT_GRID );
1385 ShowCursor(); // Cursor aendert sich !
1387 //! Block-Bereich bei RefUndoDoc weglassen !!!
1389 if ( bRecord )
1391 // Redo-Daten werden erst beim ersten Undo kopiert
1392 // ohne RefUndoDoc muss das Redo-Doc noch nicht angelegt werden
1394 if (pRefUndoDoc)
1396 pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
1397 pRedoDoc->InitUndo( pDoc, nStartTab, nEndTab, bColInfo, bRowInfo );
1399 // angepasste Referenzen ins Redo-Doc
1401 SCTAB nTabCount = pDoc->GetTableCount();
1402 pRedoDoc->AddUndoTab( 0, nTabCount-1 );
1403 pDoc->CopyUpdated( pRefUndoDoc, pRedoDoc );
1405 // alte Referenzen ins Undo-Doc
1407 //! Tabellen selektieren ?
1408 pUndoDoc->AddUndoTab( 0, nTabCount-1 );
1409 pRefUndoDoc->DeleteArea( nStartCol, nStartRow, nEndCol, nEndRow, aFilteredMark, IDF_ALL );
1410 pRefUndoDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,nTabCount-1,
1411 IDF_FORMULA, FALSE, pUndoDoc );
1412 delete pRefUndoDoc;
1415 // DeleteUnchanged for pUndoData is in ScUndoPaste ctor,
1416 // UndoData for redo is made during first undo
1418 ScUndoPasteOptions aOptions; // store options for repeat
1419 aOptions.nFunction = nFunction;
1420 aOptions.bSkipEmpty = bSkipEmpty;
1421 aOptions.bTranspose = bTranspose;
1422 aOptions.bAsLink = bAsLink;
1423 aOptions.eMoveMode = eMoveMode;
1425 SfxUndoAction* pUndo = new ScUndoPaste( pDocSh,
1426 nStartCol, nStartRow, nStartTab,
1427 nUndoEndCol, nUndoEndRow, nEndTab, aFilteredMark,
1428 pUndoDoc, pRedoDoc, nFlags | nUndoFlags,
1429 pUndoData, NULL, NULL, NULL,
1430 FALSE, &aOptions ); // FALSE = Redo data not yet copied
1432 if ( bInsertCells )
1434 // Merge the paste undo action into the insert action.
1435 // Use ScUndoWrapper so the ScUndoPaste pointer can be stored in the insert action.
1437 pUndoMgr->AddUndoAction( new ScUndoWrapper( pUndo ), TRUE );
1439 else
1440 pUndoMgr->AddUndoAction( pUndo );
1441 pUndoMgr->LeaveListAction();
1444 USHORT nPaint = PAINT_GRID;
1445 if (bColInfo)
1447 nPaint |= PAINT_TOP;
1448 nUndoEndCol = MAXCOL; // nur zum Zeichnen !
1450 if (bRowInfo)
1452 nPaint |= PAINT_LEFT;
1453 nUndoEndRow = MAXROW; // nur zum Zeichnen !
1455 pDocSh->PostPaint( nStartCol, nStartRow, nStartTab,
1456 nUndoEndCol, nUndoEndRow, nEndTab, nPaint, nExtFlags );
1457 // AdjustBlockHeight has already been called above
1459 aModificator.SetDocumentModified();
1460 PostPasteFromClip(aUserRange, rMark);
1461 return TRUE;
1464 bool ScViewFunc::PasteMultiRangesFromClip(
1465 sal_uInt16 nFlags, ScDocument* pClipDoc, sal_uInt16 nFunction,
1466 bool bSkipEmpty, bool bTranspose, bool bAsLink, bool bAllowDialogs,
1467 InsCellCmd eMoveMode, sal_uInt16 /*nContFlags*/, sal_uInt16 nUndoFlags)
1469 ScViewData& rViewData = *GetViewData();
1470 ScDocument* pDoc = rViewData.GetDocument();
1471 ScDocShell* pDocSh = rViewData.GetDocShell();
1472 ScMarkData aMark(rViewData.GetMarkData());
1473 const ScAddress& rCurPos = rViewData.GetCurPos();
1474 ScClipParam& rClipParam = pClipDoc->GetClipParam();
1475 SCCOL nColSize = rClipParam.getPasteColSize();
1476 SCROW nRowSize = rClipParam.getPasteRowSize();
1478 if (bTranspose)
1480 if (static_cast<SCROW>(rCurPos.Col()) + nRowSize-1 > static_cast<SCROW>(MAXCOL))
1482 ErrorMessage(STR_PASTE_FULL);
1483 return false;
1486 ::std::auto_ptr<ScDocument> pTransClip(new ScDocument(SCDOCMODE_CLIP));
1487 pClipDoc->TransposeClip(pTransClip.get(), nFlags, bAsLink);
1488 pClipDoc = pTransClip.release();
1489 SCCOL nTempColSize = nColSize;
1490 nColSize = static_cast<SCCOL>(nRowSize);
1491 nRowSize = static_cast<SCROW>(nTempColSize);
1494 if (!ValidCol(rCurPos.Col()+nColSize-1) || !ValidRow(rCurPos.Row()+nRowSize-1))
1496 ErrorMessage(STR_PASTE_FULL);
1497 return false;
1500 // Determine the first and last selected sheet numbers.
1501 SCTAB nTab1 = aMark.GetFirstSelected();
1502 SCTAB nTab2 = nTab1;
1503 for (SCTAB i = nTab1+1; i <= MAXTAB; ++i)
1504 if (aMark.GetTableSelect(i))
1505 nTab2 = i;
1507 ScDocShellModificator aModificator(*pDocSh);
1509 // For multi-selection paste, we don't support cell duplication for larger
1510 // destination range. In case the destination is marked, we reset it to
1511 // the clip size.
1512 ScRange aMarkedRange(rCurPos.Col(), rCurPos.Row(), nTab1,
1513 rCurPos.Col()+nColSize-1, rCurPos.Row()+nRowSize-1, nTab2);
1515 // Extend the marked range to account for filtered rows in the destination
1516 // area.
1517 if (ScViewUtil::HasFiltered(aMarkedRange, pDoc))
1519 if (!ScViewUtil::FitToUnfilteredRows(aMarkedRange, pDoc, nRowSize))
1520 return false;
1523 bool bAskIfNotEmpty =
1524 bAllowDialogs && (nFlags & IDF_CONTENTS) &&
1525 nFunction == PASTE_NOFUNC && SC_MOD()->GetInputOptions().GetReplaceCellsWarn();
1527 if (bAskIfNotEmpty)
1529 if (!lcl_checkDestRangeForOverwrite(aMarkedRange, pDoc, aMark, rViewData.GetDialogParent()))
1530 return false;
1533 aMark.SetMarkArea(aMarkedRange);
1534 MarkRange(aMarkedRange);
1536 bool bInsertCells = (eMoveMode != INS_NONE);
1537 if (bInsertCells)
1539 if (!InsertCells(eMoveMode, pDoc->IsUndoEnabled(), true))
1540 return false;
1543 ::std::auto_ptr<ScDocument> pUndoDoc;
1544 if (pDoc->IsUndoEnabled())
1546 pUndoDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1547 pUndoDoc->InitUndoSelected(pDoc, aMark, false, false);
1548 pDoc->CopyToDocument(aMarkedRange, nUndoFlags, false, pUndoDoc.get(), &aMark, true);
1551 ::std::auto_ptr<ScDocument> pMixDoc;
1552 if ( bSkipEmpty || nFunction )
1554 if ( nFlags & IDF_CONTENTS )
1556 pMixDoc.reset(new ScDocument(SCDOCMODE_UNDO));
1557 pMixDoc->InitUndoSelected(pDoc, aMark, false, false);
1558 pDoc->CopyToDocument(aMarkedRange, IDF_CONTENTS, false, pMixDoc.get(), &aMark, true);
1562 /* Make draw layer and start drawing undo.
1563 - Needed before AdjustBlockHeight to track moved drawing objects.
1564 - Needed before pDoc->CopyFromClip to track inserted note caption objects.
1566 if (nFlags & IDF_OBJECTS)
1567 pDocSh->MakeDrawLayer();
1568 if (pDoc->IsUndoEnabled())
1569 pDoc->BeginDrawUndo();
1571 CursorSwitcher aCursorSwitch(this);
1572 sal_uInt16 nNoObjFlags = nFlags & ~IDF_OBJECTS;
1573 pDoc->CopyMultiRangeFromClip(rCurPos, aMark, nNoObjFlags, pClipDoc,
1574 true, bAsLink, false, bSkipEmpty);
1576 if (pMixDoc.get())
1577 pDoc->MixDocument(aMarkedRange, nFunction, bSkipEmpty, pMixDoc.get());
1579 AdjustBlockHeight(); // update row heights before pasting objects
1581 if (nFlags & IDF_OBJECTS)
1583 // Paste the drawing objects after the row heights have been updated.
1584 pDoc->CopyMultiRangeFromClip(rCurPos, aMark, IDF_OBJECTS, pClipDoc,
1585 true, false, false, true);
1588 pDocSh->PostPaint(
1589 aMarkedRange.aStart.Col(), aMarkedRange.aStart.Row(), nTab1,
1590 aMarkedRange.aEnd.Col(), aMarkedRange.aEnd.Row(), nTab1, PAINT_GRID);
1592 if (pDoc->IsUndoEnabled())
1594 SfxUndoManager* pUndoMgr = pDocSh->GetUndoManager();
1595 String aUndo = ScGlobal::GetRscString(
1596 pClipDoc->IsCutMode() ? STR_UNDO_CUT : STR_UNDO_COPY);
1597 pUndoMgr->EnterListAction(aUndo, aUndo);
1599 ScUndoPasteOptions aOptions; // store options for repeat
1600 aOptions.nFunction = nFunction;
1601 aOptions.bSkipEmpty = bSkipEmpty;
1602 aOptions.bTranspose = bTranspose;
1603 aOptions.bAsLink = bAsLink;
1604 aOptions.eMoveMode = eMoveMode;
1606 ScUndoPaste* pUndo = new ScUndoPaste(pDocSh,
1607 aMarkedRange.aStart.Col(),
1608 aMarkedRange.aStart.Row(),
1609 aMarkedRange.aStart.Tab(),
1610 aMarkedRange.aEnd.Col(),
1611 aMarkedRange.aEnd.Row(),
1612 aMarkedRange.aEnd.Tab(),
1613 aMark, pUndoDoc.release(), NULL, nFlags|nUndoFlags, NULL, NULL, NULL, NULL, false, &aOptions);
1615 if (bInsertCells)
1616 pUndoMgr->AddUndoAction(new ScUndoWrapper(pUndo), true);
1617 else
1618 pUndoMgr->AddUndoAction(pUndo, false);
1620 pUndoMgr->LeaveListAction();
1622 aModificator.SetDocumentModified();
1623 PostPasteFromClip(aMarkedRange, aMark);
1624 return true;
1627 void ScViewFunc::PostPasteFromClip(const ScRange& rPasteRange, const ScMarkData& rMark)
1629 ScViewData* pViewData = GetViewData();
1630 ScDocShell* pDocSh = pViewData->GetDocShell();
1631 ScDocument* pDoc = pViewData->GetDocument();
1632 pDocSh->UpdateOle(pViewData);
1634 SelectionChanged();
1636 // #i97876# Spreadsheet data changes are not notified
1637 ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
1638 if ( pModelObj && pModelObj->HasChangesListeners() )
1640 ScRangeList aChangeRanges;
1641 SCTAB nTabCount = pDoc->GetTableCount();
1642 for ( SCTAB i = 0; i < nTabCount; ++i )
1644 if ( rMark.GetTableSelect( i ) )
1646 ScRange aChangeRange(rPasteRange);
1647 aChangeRange.aStart.SetTab( i );
1648 aChangeRange.aEnd.SetTab( i );
1649 aChangeRanges.Append( aChangeRange );
1652 pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges );
1657 //----------------------------------------------------------------------------
1658 // D R A G A N D D R O P
1660 // innerhalb des Dokuments
1662 BOOL ScViewFunc::MoveBlockTo( const ScRange& rSource, const ScAddress& rDestPos,
1663 BOOL bCut, BOOL bRecord, BOOL bPaint, BOOL bApi )
1665 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1666 HideAllCursors(); // wegen zusammengefassten
1668 BOOL bSuccess = TRUE;
1669 SCTAB nDestTab = rDestPos.Tab();
1670 const ScMarkData& rMark = GetViewData()->GetMarkData();
1671 if ( rSource.aStart.Tab() == nDestTab && rSource.aEnd.Tab() == nDestTab && rMark.GetSelectCount() > 1 )
1673 // moving within one table and several tables selected -> apply to all selected tables
1675 if ( bRecord )
1677 String aUndo = ScGlobal::GetRscString( bCut ? STR_UNDO_MOVE : STR_UNDO_COPY );
1678 pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
1681 // collect ranges of consecutive selected tables
1683 ScRange aLocalSource = rSource;
1684 ScAddress aLocalDest = rDestPos;
1685 SCTAB nTabCount = pDocSh->GetDocument()->GetTableCount();
1686 SCTAB nStartTab = 0;
1687 while ( nStartTab < nTabCount && bSuccess )
1689 while ( nStartTab < nTabCount && !rMark.GetTableSelect(nStartTab) )
1690 ++nStartTab;
1691 if ( nStartTab < nTabCount )
1693 SCTAB nEndTab = nStartTab;
1694 while ( nEndTab+1 < nTabCount && rMark.GetTableSelect(nEndTab+1) )
1695 ++nEndTab;
1697 aLocalSource.aStart.SetTab( nStartTab );
1698 aLocalSource.aEnd.SetTab( nEndTab );
1699 aLocalDest.SetTab( nStartTab );
1701 bSuccess = pDocSh->GetDocFunc().MoveBlock(
1702 aLocalSource, aLocalDest, bCut, bRecord, bPaint, bApi );
1704 nStartTab = nEndTab + 1;
1708 if ( bRecord )
1709 pDocSh->GetUndoManager()->LeaveListAction();
1711 else
1713 // move the block as specified
1714 bSuccess = pDocSh->GetDocFunc().MoveBlock(
1715 rSource, rDestPos, bCut, bRecord, bPaint, bApi );
1718 ShowAllCursors();
1719 if (bSuccess)
1721 // Zielbereich markieren
1722 ScAddress aDestEnd(
1723 rDestPos.Col() + rSource.aEnd.Col() - rSource.aStart.Col(),
1724 rDestPos.Row() + rSource.aEnd.Row() - rSource.aStart.Row(),
1725 nDestTab );
1727 BOOL bIncludeFiltered = bCut;
1728 if ( !bIncludeFiltered )
1730 // find number of non-filtered rows
1731 SCROW nPastedCount = pDocSh->GetDocument()->CountNonFilteredRows(
1732 rSource.aStart.Row(), rSource.aEnd.Row(), rSource.aStart.Tab());
1734 if ( nPastedCount == 0 )
1735 nPastedCount = 1;
1736 aDestEnd.SetRow( rDestPos.Row() + nPastedCount - 1 );
1739 MarkRange( ScRange( rDestPos, aDestEnd ), FALSE ); //! FALSE ???
1741 pDocSh->UpdateOle(GetViewData());
1742 SelectionChanged();
1744 return bSuccess;
1747 // Link innerhalb des Dokuments
1749 BOOL ScViewFunc::LinkBlock( const ScRange& rSource, const ScAddress& rDestPos, BOOL bApi )
1751 // Test auf Ueberlappung
1753 if ( rSource.aStart.Tab() == rDestPos.Tab() )
1755 SCCOL nDestEndCol = rDestPos.Col() + ( rSource.aEnd.Col() - rSource.aStart.Col() );
1756 SCROW nDestEndRow = rDestPos.Row() + ( rSource.aEnd.Row() - rSource.aStart.Row() );
1758 if ( rSource.aStart.Col() <= nDestEndCol && rDestPos.Col() <= rSource.aEnd.Col() &&
1759 rSource.aStart.Row() <= nDestEndRow && rDestPos.Row() <= rSource.aEnd.Row() )
1761 if (!bApi)
1762 ErrorMessage( STR_ERR_LINKOVERLAP );
1763 return FALSE;
1767 // Ausfuehren per Paste
1769 ScDocument* pDoc = GetViewData()->GetDocument();
1770 ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
1771 pDoc->CopyTabToClip( rSource.aStart.Col(), rSource.aStart.Row(),
1772 rSource.aEnd.Col(), rSource.aEnd.Row(),
1773 rSource.aStart.Tab(), pClipDoc );
1775 // Zielbereich markieren (Cursor setzen, keine Markierung)
1777 if ( GetViewData()->GetTabNo() != rDestPos.Tab() )
1778 SetTabNo( rDestPos.Tab() );
1780 MoveCursorAbs( rDestPos.Col(), rDestPos.Row(), SC_FOLLOW_NONE, FALSE, FALSE );
1782 // Paste
1784 PasteFromClip( IDF_ALL, pClipDoc, PASTE_NOFUNC, FALSE, FALSE, TRUE ); // als Link
1786 delete pClipDoc;
1788 return TRUE;
1791 void ScViewFunc::DataFormPutData( SCROW nCurrentRow ,
1792 SCROW nStartRow , SCCOL nStartCol ,
1793 SCROW nEndRow , SCCOL nEndCol ,
1794 Edit** pEdits ,
1795 sal_uInt16 aColLength )
1797 ScDocument* pDoc = GetViewData()->GetDocument();
1798 ScDocShell* pDocSh = GetViewData()->GetDocShell();
1799 ScMarkData& rMark = GetViewData()->GetMarkData();
1800 ScDocShellModificator aModificator( *pDocSh );
1801 SfxUndoManager* pUndoMgr = pDocSh->GetUndoManager();
1802 if ( pDoc )
1804 const BOOL bRecord( pDoc->IsUndoEnabled());
1805 ScDocument* pUndoDoc = NULL;
1806 ScDocument* pRedoDoc = NULL;
1807 ScDocument* pRefUndoDoc = NULL;
1808 ScRefUndoData* pUndoData = NULL;
1809 SCTAB nTab = GetViewData()->GetTabNo();
1810 SCTAB nStartTab = nTab;
1811 SCTAB nEndTab = nTab;
1814 ScChangeTrack* pChangeTrack = pDoc->GetChangeTrack();
1815 if ( pChangeTrack )
1816 pChangeTrack->ResetLastCut(); // kein CutMode mehr
1818 ScRange aUserRange( nStartCol, nCurrentRow, nStartTab, nEndCol, nCurrentRow, nEndTab );
1819 BOOL bColInfo = ( nStartRow==0 && nEndRow==MAXROW );
1820 BOOL bRowInfo = ( nStartCol==0 && nEndCol==MAXCOL );
1821 SCCOL nUndoEndCol = nStartCol+aColLength-1;
1822 SCROW nUndoEndRow = nCurrentRow;
1823 USHORT nUndoFlags = IDF_NONE;
1825 if ( bRecord )
1827 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1828 pUndoDoc->InitUndoSelected( pDoc , rMark , bColInfo , bRowInfo );
1829 pDoc->CopyToDocument( aUserRange , 1 , FALSE , pUndoDoc );
1831 USHORT nExtFlags = 0;
1832 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nStartRow, nStartTab , nEndCol, nEndRow, nEndTab ); // content before the change
1833 //rMark.SetMarkArea( aUserRange );
1834 pDoc->BeginDrawUndo();
1836 for(sal_uInt16 i = 0; i < aColLength; i++)
1838 if (pEdits[i])
1840 String aFieldName=pEdits[i]->GetText();
1841 pDoc->SetString( nStartCol + i, nCurrentRow, nTab, aFieldName );
1844 //pDoc->ExtendMergeSel( nStartCol, nStartRow, nEndCol, nEndRow, rMark, TRUE ); // Refresh
1845 pDocSh->UpdatePaintExt( nExtFlags, nStartCol, nCurrentRow, nStartTab, nEndCol, nCurrentRow, nEndTab ); // content after the change
1846 SfxUndoAction* pUndo = new ScUndoDataForm( pDocSh,
1847 nStartCol, nCurrentRow, nStartTab,
1848 nUndoEndCol, nUndoEndRow, nEndTab, rMark,
1849 pUndoDoc, pRedoDoc, nUndoFlags,
1850 pUndoData, NULL, NULL, NULL,
1851 FALSE ); // FALSE = Redo data not yet copied
1852 pUndoMgr->AddUndoAction( new ScUndoWrapper( pUndo ), TRUE );
1854 USHORT nPaint = PAINT_GRID;
1855 if (bColInfo)
1857 nPaint |= PAINT_TOP;
1858 nUndoEndCol = MAXCOL; // nur zum Zeichnen !
1860 if (bRowInfo)
1862 nPaint |= PAINT_LEFT;
1863 nUndoEndRow = MAXROW; // nur zum Zeichnen !
1866 pDocSh->PostPaint( nStartCol, nCurrentRow, nStartTab,
1867 nUndoEndCol, nUndoEndRow, nEndTab, nPaint, nExtFlags );
1868 pDocSh->UpdateOle(GetViewData());