1 /**************************************************************
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one
4 * or more contributor license agreements. See the NOTICE file
5 * distributed with this work for additional information
6 * regarding copyright ownership. The ASF licenses this file
7 * to you under the Apache License, Version 2.0 (the
8 * "License"); you may not use this file except in compliance
9 * with the License. You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing,
14 * software distributed under the License is distributed on an
15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16 * KIND, either express or implied. See the License for the
17 * specific language governing permissions and limitations
18 * under the License.
19 *
20 *************************************************************/
21
22 // MARKER(update_precomp.py): autogen include statement, do not remove
23 #include "precompiled_sc.hxx"
24
25 // INCLUDE ---------------------------------------------------------------
26
27 #include "scitems.hxx"
28 #include <editeng/eeitem.hxx>
29
30 #include <sfx2/app.hxx>
31 #include <editeng/editobj.hxx>
32 #include <sfx2/linkmgr.hxx>
33 #include <svx/svdundo.hxx>
34 #include <sfx2/bindings.hxx>
35 #include <sfx2/printer.hxx>
36 #include <vcl/msgbox.hxx>
37 #include <vcl/sound.hxx>
38 #include <vcl/virdev.hxx>
39 #include <vcl/waitobj.hxx>
40 #include <svl/zforlist.hxx>
41 #include <svl/PasswordHelper.hxx>
42
43 #include <basic/sbstar.hxx>
44 #include <com/sun/star/container/XNameContainer.hpp>
45 #include <com/sun/star/script/ModuleType.hpp>
46 #include <com/sun/star/script/XLibraryContainer.hpp>
47 #include <com/sun/star/script/vba/XVBAModuleInfo.hpp>
48
49 #include <list>
50
51 #include "docfunc.hxx"
52
53 #include "sc.hrc"
54
55 #include "arealink.hxx"
56 #include "attrib.hxx"
57 #include "dociter.hxx"
58 #include "autoform.hxx"
59 #include "cell.hxx"
60 #include "detdata.hxx"
61 #include "detfunc.hxx"
62 #include "docpool.hxx"
63 #include "docsh.hxx"
64 #include "drwlayer.hxx"
65 #include "editutil.hxx"
66 #include "globstr.hrc"
67 //CHINA001 #include "namecrea.hxx" // NAME_TOP etc.
68 #include "olinetab.hxx"
69 #include "patattr.hxx"
70 #include "rangenam.hxx"
71 #include "rangeutl.hxx"
72 #include "refundo.hxx"
73 #include "scresid.hxx"
74 #include "stlpool.hxx"
75 #include "stlsheet.hxx"
76 #include "tablink.hxx"
77 #include "tabvwsh.hxx"
78 #include "uiitems.hxx"
79 #include "undoblk.hxx"
80 #include "undocell.hxx"
81 #include "undodraw.hxx"
82 #include "undotab.hxx"
83 #include "waitoff.hxx"
84 #include "sizedev.hxx"
85 #include "scmod.hxx"
86 #include "inputhdl.hxx"
87 #include "inputwin.hxx"
88 #include "editable.hxx"
89 #include "compiler.hxx"
90 #include "scui_def.hxx" //CHINA001
91 #include "tabprotection.hxx"
92 #include "clipparam.hxx"
93 #include "externalrefmgr.hxx"
94
95 #include <memory>
96 #include <basic/basmgr.hxx>
97 #include <boost/scoped_ptr.hpp>
98
99 using namespace com::sun::star;
100 using ::com::sun::star::uno::Sequence;
101
102 // STATIC DATA -----------------------------------------------------------
103
104 //========================================================================
105
IMPL_LINK(ScDocFunc,NotifyDrawUndo,SdrUndoAction *,pUndoAction)106 IMPL_LINK( ScDocFunc, NotifyDrawUndo, SdrUndoAction*, pUndoAction )
107 {
108 // #i101118# if drawing layer collects the undo actions, add it there
109 ScDrawLayer* pDrawLayer = rDocShell.GetDocument()->GetDrawLayer();
110 if( pDrawLayer && pDrawLayer->IsUndoAllowed() && pDrawLayer->IsRecording() )
111 pDrawLayer->AddCalcUndo( pUndoAction );
112 else
113 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoDraw( pUndoAction, &rDocShell ) );
114 rDocShell.SetDrawModified();
115
116 // the affected sheet isn't known, so all stream positions are invalidated
117 ScDocument* pDoc = rDocShell.GetDocument();
118 SCTAB nTabCount = pDoc->GetTableCount();
119 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
120 if (pDoc->IsStreamValid(nTab))
121 pDoc->SetStreamValid(nTab, sal_False);
122
123 return 0;
124 }
125
126 //------------------------------------------------------------------------
127
128 // Zeile ueber dem Range painten (fuer Linien nach AdjustRowHeight)
129
lcl_PaintAbove(ScDocShell & rDocShell,const ScRange & rRange)130 void lcl_PaintAbove( ScDocShell& rDocShell, const ScRange& rRange )
131 {
132 SCROW nRow = rRange.aStart.Row();
133 if ( nRow > 0 )
134 {
135 SCTAB nTab = rRange.aStart.Tab(); //! alle?
136 --nRow;
137 rDocShell.PostPaint( ScRange(0,nRow,nTab, MAXCOL,nRow,nTab), PAINT_GRID );
138 }
139 }
140
141 //------------------------------------------------------------------------
142
AdjustRowHeight(const ScRange & rRange,sal_Bool bPaint)143 sal_Bool ScDocFunc::AdjustRowHeight( const ScRange& rRange, sal_Bool bPaint )
144 {
145 ScDocument* pDoc = rDocShell.GetDocument();
146 if ( pDoc->IsImportingXML() )
147 {
148 // for XML import, all row heights are updated together after importing
149 return sal_False;
150 }
151 if ( !pDoc->IsAdjustHeightEnabled() )
152 {
153 return sal_False;
154 }
155
156 SCTAB nTab = rRange.aStart.Tab();
157 SCROW nStartRow = rRange.aStart.Row();
158 SCROW nEndRow = rRange.aEnd.Row();
159
160 ScSizeDeviceProvider aProv( &rDocShell );
161 Fraction aOne(1,1);
162
163 sal_Bool bChanged = pDoc->SetOptimalHeight( nStartRow, nEndRow, nTab, 0, aProv.GetDevice(),
164 aProv.GetPPTX(), aProv.GetPPTY(), aOne, aOne, sal_False );
165
166 if ( bPaint && bChanged )
167 rDocShell.PostPaint( 0, nStartRow, nTab, MAXCOL, MAXROW, nTab,
168 PAINT_GRID | PAINT_LEFT );
169
170 return bChanged;
171 }
172
173
174 //------------------------------------------------------------------------
175
DetectiveAddPred(const ScAddress & rPos)176 sal_Bool ScDocFunc::DetectiveAddPred(const ScAddress& rPos)
177 {
178 ScDocShellModificator aModificator( rDocShell );
179
180 rDocShell.MakeDrawLayer();
181 ScDocument* pDoc = rDocShell.GetDocument();
182 sal_Bool bUndo (pDoc->IsUndoEnabled());
183 ScDrawLayer* pModel = pDoc->GetDrawLayer();
184 SCCOL nCol = rPos.Col();
185 SCROW nRow = rPos.Row();
186 SCTAB nTab = rPos.Tab();
187
188 if (bUndo)
189 pModel->BeginCalcUndo(false);
190 sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).ShowPred( nCol, nRow );
191 SdrUndoGroup* pUndo = NULL;
192 if (bUndo)
193 pUndo = pModel->GetCalcUndo();
194 if (bDone)
195 {
196 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDPRED );
197 pDoc->AddDetectiveOperation( aOperation );
198 if (bUndo)
199 {
200 rDocShell.GetUndoManager()->AddUndoAction(
201 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
202 }
203 aModificator.SetDocumentModified();
204 SfxBindings* pBindings = rDocShell.GetViewBindings();
205 if (pBindings)
206 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
207 }
208 else
209 delete pUndo;
210
211 return bDone;
212 }
213
DetectiveDelPred(const ScAddress & rPos)214 sal_Bool ScDocFunc::DetectiveDelPred(const ScAddress& rPos)
215 {
216 ScDocument* pDoc = rDocShell.GetDocument();
217
218 sal_Bool bUndo(pDoc->IsUndoEnabled());
219 ScDrawLayer* pModel = pDoc->GetDrawLayer();
220 if (!pModel)
221 return sal_False;
222
223 ScDocShellModificator aModificator( rDocShell );
224
225 SCCOL nCol = rPos.Col();
226 SCROW nRow = rPos.Row();
227 SCTAB nTab = rPos.Tab();
228
229 if (bUndo)
230 pModel->BeginCalcUndo(false);
231 sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).DeletePred( nCol, nRow );
232 SdrUndoGroup* pUndo = NULL;
233 if (bUndo)
234 pUndo = pModel->GetCalcUndo();
235 if (bDone)
236 {
237 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_DELPRED );
238 pDoc->AddDetectiveOperation( aOperation );
239 if (bUndo)
240 {
241 rDocShell.GetUndoManager()->AddUndoAction(
242 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
243 }
244 aModificator.SetDocumentModified();
245 SfxBindings* pBindings = rDocShell.GetViewBindings();
246 if (pBindings)
247 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
248 }
249 else
250 delete pUndo;
251
252 return bDone;
253 }
254
DetectiveAddSucc(const ScAddress & rPos)255 sal_Bool ScDocFunc::DetectiveAddSucc(const ScAddress& rPos)
256 {
257 ScDocShellModificator aModificator( rDocShell );
258
259 rDocShell.MakeDrawLayer();
260 ScDocument* pDoc = rDocShell.GetDocument();
261
262 sal_Bool bUndo(pDoc->IsUndoEnabled());
263 ScDrawLayer* pModel = pDoc->GetDrawLayer();
264 SCCOL nCol = rPos.Col();
265 SCROW nRow = rPos.Row();
266 SCTAB nTab = rPos.Tab();
267
268 if (bUndo)
269 pModel->BeginCalcUndo(false);
270 sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).ShowSucc( nCol, nRow );
271 SdrUndoGroup* pUndo = NULL;
272 if (bUndo)
273 pUndo = pModel->GetCalcUndo();
274 if (bDone)
275 {
276 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDSUCC );
277 pDoc->AddDetectiveOperation( aOperation );
278 if (bUndo)
279 {
280 rDocShell.GetUndoManager()->AddUndoAction(
281 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
282 }
283 aModificator.SetDocumentModified();
284 SfxBindings* pBindings = rDocShell.GetViewBindings();
285 if (pBindings)
286 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
287 }
288 else
289 delete pUndo;
290
291 return bDone;
292 }
293
DetectiveDelSucc(const ScAddress & rPos)294 sal_Bool ScDocFunc::DetectiveDelSucc(const ScAddress& rPos)
295 {
296 ScDocument* pDoc = rDocShell.GetDocument();
297
298 sal_Bool bUndo (pDoc->IsUndoEnabled());
299 ScDrawLayer* pModel = pDoc->GetDrawLayer();
300 if (!pModel)
301 return sal_False;
302
303 ScDocShellModificator aModificator( rDocShell );
304
305 SCCOL nCol = rPos.Col();
306 SCROW nRow = rPos.Row();
307 SCTAB nTab = rPos.Tab();
308
309 if (bUndo)
310 pModel->BeginCalcUndo(false);
311 sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).DeleteSucc( nCol, nRow );
312 SdrUndoGroup* pUndo = NULL;
313 if (bUndo)
314 pUndo = pModel->GetCalcUndo();
315 if (bDone)
316 {
317 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_DELSUCC );
318 pDoc->AddDetectiveOperation( aOperation );
319 if (bUndo)
320 {
321 rDocShell.GetUndoManager()->AddUndoAction(
322 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
323 }
324 aModificator.SetDocumentModified();
325 SfxBindings* pBindings = rDocShell.GetViewBindings();
326 if (pBindings)
327 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
328 }
329 else
330 delete pUndo;
331
332 return bDone;
333 }
334
DetectiveAddError(const ScAddress & rPos)335 sal_Bool ScDocFunc::DetectiveAddError(const ScAddress& rPos)
336 {
337 ScDocShellModificator aModificator( rDocShell );
338
339 rDocShell.MakeDrawLayer();
340 ScDocument* pDoc = rDocShell.GetDocument();
341
342 sal_Bool bUndo (pDoc->IsUndoEnabled());
343 ScDrawLayer* pModel = pDoc->GetDrawLayer();
344 SCCOL nCol = rPos.Col();
345 SCROW nRow = rPos.Row();
346 SCTAB nTab = rPos.Tab();
347
348 if (bUndo)
349 pModel->BeginCalcUndo(false);
350 sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).ShowError( nCol, nRow );
351 SdrUndoGroup* pUndo = NULL;
352 if (bUndo)
353 pUndo = pModel->GetCalcUndo();
354 if (bDone)
355 {
356 ScDetOpData aOperation( ScAddress(nCol,nRow,nTab), SCDETOP_ADDERROR );
357 pDoc->AddDetectiveOperation( aOperation );
358 if (bUndo)
359 {
360 rDocShell.GetUndoManager()->AddUndoAction(
361 new ScUndoDetective( &rDocShell, pUndo, &aOperation ) );
362 }
363 aModificator.SetDocumentModified();
364 SfxBindings* pBindings = rDocShell.GetViewBindings();
365 if (pBindings)
366 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
367 }
368 else
369 delete pUndo;
370
371 return bDone;
372 }
373
DetectiveMarkInvalid(SCTAB nTab)374 sal_Bool ScDocFunc::DetectiveMarkInvalid(SCTAB nTab)
375 {
376 ScDocShellModificator aModificator( rDocShell );
377
378 rDocShell.MakeDrawLayer();
379 ScDocument* pDoc = rDocShell.GetDocument();
380
381 sal_Bool bUndo (pDoc->IsUndoEnabled());
382 ScDrawLayer* pModel = pDoc->GetDrawLayer();
383
384 Window* pWaitWin = rDocShell.GetActiveDialogParent();
385 if (pWaitWin)
386 pWaitWin->EnterWait();
387 if (bUndo)
388 pModel->BeginCalcUndo(false);
389 sal_Bool bOverflow;
390 sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).MarkInvalid( bOverflow );
391 SdrUndoGroup* pUndo = NULL;
392 if (bUndo)
393 pUndo = pModel->GetCalcUndo();
394 if (pWaitWin)
395 pWaitWin->LeaveWait();
396 if (bDone)
397 {
398 if (pUndo && bUndo)
399 {
400 pUndo->SetComment( ScGlobal::GetRscString( STR_UNDO_DETINVALID ) );
401 rDocShell.GetUndoManager()->AddUndoAction( pUndo );
402 }
403 aModificator.SetDocumentModified();
404 if ( bOverflow )
405 {
406 InfoBox( NULL,
407 ScGlobal::GetRscString( STR_DETINVALID_OVERFLOW ) ).Execute();
408 }
409 }
410 else
411 delete pUndo;
412
413 return bDone;
414 }
415
DetectiveDelAll(SCTAB nTab)416 sal_Bool ScDocFunc::DetectiveDelAll(SCTAB nTab)
417 {
418 ScDocument* pDoc = rDocShell.GetDocument();
419
420 sal_Bool bUndo (pDoc->IsUndoEnabled());
421 ScDrawLayer* pModel = pDoc->GetDrawLayer();
422 if (!pModel)
423 return sal_False;
424
425 ScDocShellModificator aModificator( rDocShell );
426
427 if (bUndo)
428 pModel->BeginCalcUndo(false);
429 sal_Bool bDone = ScDetectiveFunc( pDoc,nTab ).DeleteAll( SC_DET_DETECTIVE );
430 SdrUndoGroup* pUndo = NULL;
431 if (bUndo)
432 pUndo = pModel->GetCalcUndo();
433 if (bDone)
434 {
435 ScDetOpList* pOldList = pDoc->GetDetOpList();
436 ScDetOpList* pUndoList = NULL;
437 if (bUndo)
438 pUndoList = pOldList ? new ScDetOpList(*pOldList) : NULL;
439
440 pDoc->ClearDetectiveOperations();
441
442 if (bUndo)
443 {
444 rDocShell.GetUndoManager()->AddUndoAction(
445 new ScUndoDetective( &rDocShell, pUndo, NULL, pUndoList ) );
446 }
447 aModificator.SetDocumentModified();
448 SfxBindings* pBindings = rDocShell.GetViewBindings();
449 if (pBindings)
450 pBindings->Invalidate( SID_DETECTIVE_REFRESH );
451 }
452 else
453 delete pUndo;
454
455 return bDone;
456 }
457
DetectiveRefresh(sal_Bool bAutomatic)458 sal_Bool ScDocFunc::DetectiveRefresh( sal_Bool bAutomatic )
459 {
460 sal_Bool bDone = sal_False;
461 ScDocument* pDoc = rDocShell.GetDocument();
462
463 sal_Bool bUndo (pDoc->IsUndoEnabled());
464 ScDetOpList* pList = pDoc->GetDetOpList();
465 if ( pList && pList->Count() )
466 {
467 rDocShell.MakeDrawLayer();
468 ScDrawLayer* pModel = pDoc->GetDrawLayer();
469 if (bUndo)
470 pModel->BeginCalcUndo(false);
471
472 // Loeschen auf allen Tabellen
473
474 SCTAB nTabCount = pDoc->GetTableCount();
475 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
476 ScDetectiveFunc( pDoc,nTab ).DeleteAll( SC_DET_ARROWS ); // don't remove circles
477
478 // Wiederholen
479
480 sal_uInt16 nCount = pList->Count();
481 for (sal_uInt16 i=0; i<nCount; i++)
482 {
483 ScDetOpData* pData = (*pList)[i];
484 if (pData)
485 {
486 ScAddress aPos = pData->GetPos();
487 ScDetectiveFunc aFunc( pDoc, aPos.Tab() );
488 SCCOL nCol = aPos.Col();
489 SCROW nRow = aPos.Row();
490 switch (pData->GetOperation())
491 {
492 case SCDETOP_ADDSUCC:
493 aFunc.ShowSucc( nCol, nRow );
494 break;
495 case SCDETOP_DELSUCC:
496 aFunc.DeleteSucc( nCol, nRow );
497 break;
498 case SCDETOP_ADDPRED:
499 aFunc.ShowPred( nCol, nRow );
500 break;
501 case SCDETOP_DELPRED:
502 aFunc.DeletePred( nCol, nRow );
503 break;
504 case SCDETOP_ADDERROR:
505 aFunc.ShowError( nCol, nRow );
506 break;
507 default:
508 DBG_ERROR("falsche Op bei DetectiveRefresh");
509 }
510 }
511 }
512
513 if (bUndo)
514 {
515 SdrUndoGroup* pUndo = pModel->GetCalcUndo();
516 if (pUndo)
517 {
518 pUndo->SetComment( ScGlobal::GetRscString( STR_UNDO_DETREFRESH ) );
519 // wenn automatisch, an letzte Aktion anhaengen
520 rDocShell.GetUndoManager()->AddUndoAction(
521 new ScUndoDraw( pUndo, &rDocShell ),
522 bAutomatic );
523 }
524 }
525 rDocShell.SetDrawModified();
526 bDone = sal_True;
527 }
528 return bDone;
529 }
530
531 //------------------------------------------------------------------------
532
DeleteContents(const ScMarkData & rMark,sal_uInt16 nFlags,sal_Bool bRecord,sal_Bool bApi)533 sal_Bool ScDocFunc::DeleteContents( const ScMarkData& rMark, sal_uInt16 nFlags,
534 sal_Bool bRecord, sal_Bool bApi )
535 {
536 ScDocShellModificator aModificator( rDocShell );
537
538 if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
539 {
540 DBG_ERROR("ScDocFunc::DeleteContents ohne Markierung");
541 return sal_False;
542 }
543
544 ScDocument* pDoc = rDocShell.GetDocument();
545
546 if (bRecord && !pDoc->IsUndoEnabled())
547 bRecord = sal_False;
548
549 ScEditableTester aTester( pDoc, rMark );
550 if (!aTester.IsEditable())
551 {
552 if (!bApi)
553 rDocShell.ErrorMessage(aTester.GetMessageId());
554 return sal_False;
555 }
556
557 ScRange aMarkRange;
558 sal_Bool bSimple = sal_False;
559
560 ScMarkData aMultiMark = rMark;
561 aMultiMark.SetMarking(sal_False); // fuer MarkToMulti
562
563 ScDocument* pUndoDoc = NULL;
564 sal_Bool bMulti = !bSimple && aMultiMark.IsMultiMarked();
565 if (!bSimple)
566 {
567 aMultiMark.MarkToMulti();
568 aMultiMark.GetMultiMarkArea( aMarkRange );
569 }
570 ScRange aExtendedRange(aMarkRange);
571 if (!bSimple)
572 {
573 if ( pDoc->ExtendMerge( aExtendedRange, sal_True ) )
574 bMulti = sal_False;
575 }
576
577 // keine Objekte auf geschuetzten Tabellen
578 sal_Bool bObjects = sal_False;
579 if ( nFlags & IDF_OBJECTS )
580 {
581 bObjects = sal_True;
582 SCTAB nTabCount = pDoc->GetTableCount();
583 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
584 if (aMultiMark.GetTableSelect(nTab) && pDoc->IsTabProtected(nTab))
585 bObjects = sal_False;
586 }
587
588 sal_uInt16 nExtFlags = 0; // extra flags are needed only if attributes are deleted
589 if ( nFlags & IDF_ATTRIB )
590 rDocShell.UpdatePaintExt( nExtFlags, aMarkRange );
591
592 // Reihenfolge:
593 // 1) BeginDrawUndo
594 // 2) Objekte loeschen (DrawUndo wird gefuellt)
595 // 3) Inhalte fuer Undo kopieren und Undo-Aktion anlegen
596 // 4) Inhalte loeschen
597
598 bool bDrawUndo = bObjects || (nFlags & IDF_NOTE);
599 if (bRecord && bDrawUndo)
600 pDoc->BeginDrawUndo();
601
602 if (bObjects)
603 {
604 if (bMulti)
605 pDoc->DeleteObjectsInSelection( aMultiMark );
606 else
607 pDoc->DeleteObjectsInArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
608 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(),
609 aMultiMark );
610 }
611
612 if ( bRecord )
613 {
614 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
615 pUndoDoc->InitUndo( pDoc, aMarkRange.aStart.Tab(), aMarkRange.aEnd.Tab() );
616
617 // bei "Format/Standard" alle Attribute kopieren, weil CopyToDocument
618 // nur mit IDF_HARDATTR zu langsam ist:
619 sal_uInt16 nUndoDocFlags = nFlags;
620 if (nFlags & IDF_ATTRIB)
621 nUndoDocFlags |= IDF_ATTRIB;
622 if (nFlags & IDF_EDITATTR) // Edit-Engine-Attribute
623 nUndoDocFlags |= IDF_STRING; // -> Zellen werden geaendert
624 if (nFlags & IDF_NOTE)
625 nUndoDocFlags |= IDF_CONTENTS; // #68795# copy all cells with their notes
626 // note captions are handled in drawing undo
627 nUndoDocFlags |= IDF_NOCAPTIONS;
628 pDoc->CopyToDocument( aExtendedRange, nUndoDocFlags, bMulti, pUndoDoc, &aMultiMark );
629 }
630
631 //! HideAllCursors(); // falls Zusammenfassung aufgehoben wird
632 if (bSimple)
633 pDoc->DeleteArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
634 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(),
635 aMultiMark, nFlags );
636 else
637 {
638 pDoc->DeleteSelection( nFlags, aMultiMark );
639 // aMultiMark.MarkToSimple();
640 }
641
642 // add undo action after drawing undo is complete (objects and note captions)
643 if( bRecord )
644 rDocShell.GetUndoManager()->AddUndoAction(
645 new ScUndoDeleteContents( &rDocShell, aMultiMark, aExtendedRange,
646 pUndoDoc, bMulti, nFlags, bDrawUndo ) );
647
648 if (!AdjustRowHeight( aExtendedRange ))
649 rDocShell.PostPaint( aExtendedRange, PAINT_GRID, nExtFlags );
650 else if (nExtFlags & SC_PF_LINES)
651 lcl_PaintAbove( rDocShell, aExtendedRange ); // fuer Linien ueber dem Bereich
652
653 // rDocShell.UpdateOle(GetViewData()); //! an der View?
654 aModificator.SetDocumentModified();
655 //! CellContentChanged();
656 //! ShowAllCursors();
657
658 #if 0
659 //! muss an der View bleiben !!!!
660 if ( nFlags & IDF_ATTRIB )
661 {
662 if ( nFlags & IDF_CONTENTS )
663 ForgetFormatArea();
664 else
665 StartFormatArea(); // Attribute loeschen ist auch Attributierung
666 }
667 #endif
668
669 return sal_True;
670 }
671
672 //------------------------------------------------------------------------
673
TransliterateText(const ScMarkData & rMark,sal_Int32 nType,sal_Bool bRecord,sal_Bool bApi)674 sal_Bool ScDocFunc::TransliterateText( const ScMarkData& rMark, sal_Int32 nType,
675 sal_Bool bRecord, sal_Bool bApi )
676 {
677 ScDocShellModificator aModificator( rDocShell );
678
679 ScDocument* pDoc = rDocShell.GetDocument();
680 if (bRecord && !pDoc->IsUndoEnabled())
681 bRecord = sal_False;
682
683 ScEditableTester aTester( pDoc, rMark );
684 if (!aTester.IsEditable())
685 {
686 if (!bApi)
687 rDocShell.ErrorMessage(aTester.GetMessageId());
688 return sal_False;
689 }
690
691 ScRange aMarkRange;
692 ScMarkData aMultiMark = rMark;
693 aMultiMark.SetMarking(sal_False); // for MarkToMulti
694 aMultiMark.MarkToMulti();
695 aMultiMark.GetMultiMarkArea( aMarkRange );
696
697 if (bRecord)
698 {
699 SCTAB nStartTab = aMarkRange.aStart.Tab();
700 SCTAB nTabCount = pDoc->GetTableCount();
701
702 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
703 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
704 for (SCTAB i=0; i<nTabCount; i++)
705 if (i != nStartTab && rMark.GetTableSelect(i))
706 pUndoDoc->AddUndoTab( i, i );
707
708 ScRange aCopyRange = aMarkRange;
709 aCopyRange.aStart.SetTab(0);
710 aCopyRange.aEnd.SetTab(nTabCount-1);
711 pDoc->CopyToDocument( aCopyRange, IDF_CONTENTS, sal_True, pUndoDoc, &aMultiMark );
712
713 rDocShell.GetUndoManager()->AddUndoAction(
714 new ScUndoTransliterate( &rDocShell, aMultiMark, pUndoDoc, nType ) );
715 }
716
717 pDoc->TransliterateText( aMultiMark, nType );
718
719 if (!AdjustRowHeight( aMarkRange ))
720 rDocShell.PostPaint( aMarkRange, PAINT_GRID );
721
722 aModificator.SetDocumentModified();
723
724 return sal_True;
725 }
726
727 //------------------------------------------------------------------------
728
SetNormalString(const ScAddress & rPos,const String & rText,sal_Bool bApi)729 sal_Bool ScDocFunc::SetNormalString( const ScAddress& rPos, const String& rText, sal_Bool bApi )
730 {
731 ScDocShellModificator aModificator( rDocShell );
732 ScDocument* pDoc = rDocShell.GetDocument();
733
734 sal_Bool bUndo(pDoc->IsUndoEnabled());
735 ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
736 if (!aTester.IsEditable())
737 {
738 if (!bApi)
739 rDocShell.ErrorMessage(aTester.GetMessageId());
740 return sal_False;
741 }
742
743 SCTAB* pTabs = NULL;
744 ScBaseCell** ppOldCells = NULL;
745 sal_Bool* pHasFormat = NULL;
746 sal_uLong* pOldFormats = NULL;
747 ScBaseCell* pDocCell = pDoc->GetCell( rPos );
748 sal_Bool bEditDeleted = (pDocCell && pDocCell->GetCellType() == CELLTYPE_EDIT);
749 if (bUndo)
750 {
751 pTabs = new SCTAB[1];
752 pTabs[0] = rPos.Tab();
753 ppOldCells = new ScBaseCell*[1];
754 ppOldCells[0] = pDocCell ? pDocCell->CloneWithoutNote( *pDoc ) : 0;
755
756 pHasFormat = new sal_Bool[1];
757 pOldFormats = new sal_uLong[1];
758 const SfxPoolItem* pItem;
759 const ScPatternAttr* pPattern = pDoc->GetPattern( rPos.Col(),rPos.Row(),rPos.Tab() );
760 if ( SFX_ITEM_SET == pPattern->GetItemSet().GetItemState(
761 ATTR_VALUE_FORMAT,sal_False,&pItem) )
762 {
763 pHasFormat[0] = sal_True;
764 pOldFormats[0] = ((const SfxUInt32Item*)pItem)->GetValue();
765 }
766 else
767 pHasFormat[0] = sal_False;
768 }
769
770 pDoc->SetString( rPos.Col(), rPos.Row(), rPos.Tab(), rText );
771
772 if (bUndo)
773 {
774 // wegen ChangeTracking darf UndoAction erst nach SetString angelegt werden
775 rDocShell.GetUndoManager()->AddUndoAction(new ScUndoEnterData( &rDocShell, rPos.Col(),rPos.Row(),rPos.Tab(), 1,pTabs,
776 ppOldCells, pHasFormat, pOldFormats, rText, NULL ) );
777 }
778
779 if ( bEditDeleted || pDoc->HasAttrib( ScRange(rPos), HASATTR_NEEDHEIGHT ) )
780 AdjustRowHeight( ScRange(rPos) );
781
782 rDocShell.PostPaintCell( rPos );
783 aModificator.SetDocumentModified();
784
785 // #107160# notify input handler here the same way as in PutCell
786 if (bApi)
787 NotifyInputHandler( rPos );
788
789 return sal_True;
790 }
791
PutCell(const ScAddress & rPos,ScBaseCell * pNewCell,sal_Bool bApi)792 sal_Bool ScDocFunc::PutCell( const ScAddress& rPos, ScBaseCell* pNewCell, sal_Bool bApi )
793 {
794 ScDocShellModificator aModificator( rDocShell );
795 ScDocument* pDoc = rDocShell.GetDocument();
796 sal_Bool bUndo (pDoc->IsUndoEnabled());
797 sal_Bool bXMLLoading(pDoc->IsImportingXML());
798
799 // #i925#; it is not necessary to test whether the cell is editable on loading a XML document
800 if (!bXMLLoading)
801 {
802 ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
803 if (!aTester.IsEditable())
804 {
805 if (!bApi)
806 rDocShell.ErrorMessage(aTester.GetMessageId());
807 pNewCell->Delete();
808 return sal_False;
809 }
810 }
811
812 sal_Bool bEditCell = ( pNewCell->GetCellType() == CELLTYPE_EDIT );
813 ScBaseCell* pDocCell = pDoc->GetCell( rPos );
814 sal_Bool bEditDeleted = (pDocCell && pDocCell->GetCellType() == CELLTYPE_EDIT);
815 sal_Bool bHeight = ( bEditDeleted || bEditCell ||
816 pDoc->HasAttrib( ScRange(rPos), HASATTR_NEEDHEIGHT ) );
817
818 ScBaseCell* pUndoCell = (bUndo && pDocCell) ? pDocCell->CloneWithoutNote( *pDoc, rPos ) : 0;
819 ScBaseCell* pRedoCell = (bUndo && pNewCell) ? pNewCell->CloneWithoutNote( *pDoc, rPos ) : 0;
820
821 pDoc->PutCell( rPos, pNewCell );
822
823 // wegen ChangeTracking darf UndoAction erst nach PutCell angelegt werden
824 if (bUndo)
825 {
826 rDocShell.GetUndoManager()->AddUndoAction(
827 new ScUndoPutCell( &rDocShell, rPos, pUndoCell, pRedoCell, bHeight ) );
828 }
829
830 if (bHeight)
831 AdjustRowHeight( ScRange(rPos) );
832
833 if (!bXMLLoading)
834 rDocShell.PostPaintCell( rPos );
835
836 aModificator.SetDocumentModified();
837
838 // #i925#; it is not necessary to notify on loading a XML document
839 // #103934#; notify editline and cell in edit mode
840 if (bApi && !bXMLLoading)
841 NotifyInputHandler( rPos );
842
843 return sal_True;
844 }
845
NotifyInputHandler(const ScAddress & rPos)846 void ScDocFunc::NotifyInputHandler( const ScAddress& rPos )
847 {
848 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
849 if ( pViewSh && pViewSh->GetViewData()->GetDocShell() == &rDocShell )
850 {
851 ScInputHandler* pInputHdl = SC_MOD()->GetInputHdl();
852 if ( pInputHdl && pInputHdl->GetCursorPos() == rPos )
853 {
854 sal_Bool bIsEditMode(pInputHdl->IsEditMode());
855
856 // set modified if in editmode, because so the string is not set in the InputWindow like in the cell
857 // (the cell shows the same like the InputWindow)
858 if (bIsEditMode)
859 pInputHdl->SetModified();
860 pViewSh->UpdateInputHandler(sal_False, !bIsEditMode);
861 }
862 }
863 }
864
865 struct ScMyRememberItem
866 {
867 sal_uInt32 nIndex;
868 SfxItemSet aItemSet;
869
ScMyRememberItemScMyRememberItem870 ScMyRememberItem(const SfxItemSet& rItemSet, sal_uInt32 nTempIndex) :
871 nIndex(nTempIndex), aItemSet(rItemSet) {}
872 };
873
874 typedef ::std::list<ScMyRememberItem*> ScMyRememberItemList;
875
PutData(const ScAddress & rPos,ScEditEngineDefaulter & rEngine,sal_Bool bInterpret,sal_Bool bApi)876 sal_Bool ScDocFunc::PutData( const ScAddress& rPos, ScEditEngineDefaulter& rEngine, sal_Bool bInterpret, sal_Bool bApi )
877 {
878 // PutData ruft PutCell oder SetNormalString
879
880 sal_Bool bRet = sal_False;
881 ScDocument* pDoc = rDocShell.GetDocument();
882 ScEditAttrTester aTester( &rEngine );
883 sal_Bool bEditCell = aTester.NeedsObject();
884 if ( bEditCell )
885 {
886 // #i61702# With bLoseContent set, the content of rEngine isn't restored
887 // (used in loading XML, where after the removeActionLock call the API object's
888 // EditEngine isn't accessed again.
889 sal_Bool bLoseContent = pDoc->IsImportingXML();
890
891 sal_Bool bUpdateMode(rEngine.GetUpdateMode());
892 if (bUpdateMode)
893 rEngine.SetUpdateMode(sal_False);
894
895 ScMyRememberItemList aRememberItems;
896 ScMyRememberItem* pRememberItem = NULL;
897
898 // All paragraph attributes must be removed before calling CreateTextObject,
899 // not only alignment, so the object doesn't contain the cell attributes as
900 // paragraph attributes. Before remove the attributes store they in a list to
901 // set they back to the EditEngine.
902 sal_uInt32 nCount = rEngine.GetParagraphCount();
903 for (sal_uInt32 i=0; i<nCount; i++)
904 {
905 const SfxItemSet& rOld = rEngine.GetParaAttribs( i );
906 if ( rOld.Count() )
907 {
908 if ( !bLoseContent )
909 {
910 pRememberItem = new ScMyRememberItem(rEngine.GetParaAttribs(i), i);
911 aRememberItems.push_back(pRememberItem);
912 }
913 rEngine.SetParaAttribs( i, SfxItemSet( *rOld.GetPool(), rOld.GetRanges() ) );
914 }
915 }
916
917 EditTextObject* pNewData = rEngine.CreateTextObject();
918 bRet = PutCell( rPos,
919 new ScEditCell( pNewData, pDoc, rEngine.GetEditTextObjectPool() ),
920 bApi );
921 delete pNewData;
922
923 // Set the paragraph attributes back to the EditEngine.
924 if (!aRememberItems.empty())
925 {
926 // ScMyRememberItem* pRememberItem = NULL;
927 ScMyRememberItemList::iterator aItr = aRememberItems.begin();
928 while (aItr != aRememberItems.end())
929 {
930 pRememberItem = *aItr;
931 rEngine.SetParaAttribs(pRememberItem->nIndex, pRememberItem->aItemSet);
932 delete pRememberItem;
933 aItr = aRememberItems.erase(aItr);
934 }
935 }
936
937 // #i61702# if the content isn't accessed, there's no need to set the UpdateMode again
938 if ( bUpdateMode && !bLoseContent )
939 rEngine.SetUpdateMode(sal_True);
940 }
941 else
942 {
943 String aText = rEngine.GetText();
944 if ( bInterpret || !aText.Len() )
945 bRet = SetNormalString( rPos, aText, bApi );
946 else
947 bRet = PutCell( rPos, new ScStringCell( aText ), bApi );
948 }
949
950 if ( bRet && aTester.NeedsCellAttr() )
951 {
952 const SfxItemSet& rEditAttr = aTester.GetAttribs();
953 ScPatternAttr aPattern( pDoc->GetPool() );
954 aPattern.GetFromEditItemSet( &rEditAttr );
955 aPattern.DeleteUnchanged( pDoc->GetPattern( rPos.Col(), rPos.Row(), rPos.Tab() ) );
956 aPattern.GetItemSet().ClearItem( ATTR_HOR_JUSTIFY ); // wasn't removed above if no edit object
957 if ( aPattern.GetItemSet().Count() > 0 )
958 {
959 ScMarkData aMark;
960 aMark.SelectTable( rPos.Tab(), sal_True );
961 aMark.SetMarkArea( ScRange( rPos ) );
962 ApplyAttributes( aMark, aPattern, sal_True, bApi );
963 }
964 }
965
966 return bRet;
967 }
968
969
lcl_ScDocFunc_CreateTokenArrayXML(const String & rText,const String & rFormulaNmsp,const formula::FormulaGrammar::Grammar eGrammar)970 ScTokenArray* lcl_ScDocFunc_CreateTokenArrayXML( const String& rText, const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
971 {
972 ScTokenArray* pCode = new ScTokenArray;
973 pCode->AddString( rText );
974 if( (eGrammar == formula::FormulaGrammar::GRAM_EXTERNAL) && (rFormulaNmsp.Len() > 0) )
975 pCode->AddString( rFormulaNmsp );
976 return pCode;
977 }
978
979
InterpretEnglishString(const ScAddress & rPos,const String & rText,const String & rFormulaNmsp,const formula::FormulaGrammar::Grammar eGrammar,short * pRetFormatType)980 ScBaseCell* ScDocFunc::InterpretEnglishString( const ScAddress& rPos,
981 const String& rText, const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar, short* pRetFormatType )
982 {
983 ScDocument* pDoc = rDocShell.GetDocument();
984 ScBaseCell* pNewCell = NULL;
985
986 if ( rText.Len() > 1 && rText.GetChar(0) == '=' )
987 {
988 ScTokenArray* pCode;
989 if ( pDoc->IsImportingXML() )
990 { // temporary formula string as string tokens
991 pCode = lcl_ScDocFunc_CreateTokenArrayXML( rText, rFormulaNmsp, eGrammar );
992 pDoc->IncXMLImportedFormulaCount( rText.Len() );
993 }
994 else
995 {
996 ScCompiler aComp( pDoc, rPos );
997 aComp.SetGrammar(eGrammar);
998 pCode = aComp.CompileString( rText );
999 }
1000 pNewCell = new ScFormulaCell( pDoc, rPos, pCode, eGrammar, MM_NONE );
1001 delete pCode; // Zell-ctor hat das TokenArray kopiert
1002 }
1003 else if ( rText.Len() > 1 && rText.GetChar(0) == '\'' )
1004 {
1005 // for bEnglish, "'" at the beginning is always interpreted as text
1006 // marker and stripped
1007 pNewCell = ScBaseCell::CreateTextCell( rText.Copy( 1 ), pDoc );
1008 }
1009 else // (nur) auf englisches Zahlformat testen
1010 {
1011 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
1012 sal_uInt32 nEnglish = pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US);
1013 double fVal;
1014 if ( pFormatter->IsNumberFormat( rText, nEnglish, fVal ) )
1015 {
1016 pNewCell = new ScValueCell( fVal );
1017 // return the format type from the English format, so a localized format can be created
1018 if ( pRetFormatType )
1019 *pRetFormatType = pFormatter->GetType( nEnglish );
1020 }
1021 else if ( rText.Len() )
1022 pNewCell = ScBaseCell::CreateTextCell( rText, pDoc );
1023
1024 // das (englische) Zahlformat wird nicht gesetzt
1025 //! passendes lokales Format suchen und setzen???
1026 }
1027
1028 return pNewCell;
1029 }
1030
1031
SetCellText(const ScAddress & rPos,const String & rText,sal_Bool bInterpret,sal_Bool bEnglish,sal_Bool bApi,const String & rFormulaNmsp,const formula::FormulaGrammar::Grammar eGrammar)1032 sal_Bool ScDocFunc::SetCellText( const ScAddress& rPos, const String& rText,
1033 sal_Bool bInterpret, sal_Bool bEnglish, sal_Bool bApi,
1034 const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
1035 {
1036 // SetCellText ruft PutCell oder SetNormalString
1037
1038 ScDocument* pDoc = rDocShell.GetDocument();
1039 ScBaseCell* pNewCell = NULL;
1040 if ( bInterpret )
1041 {
1042 if ( bEnglish )
1043 {
1044 ::boost::scoped_ptr<ScExternalRefManager::ApiGuard> pExtRefGuard;
1045 if (bApi)
1046 pExtRefGuard.reset(new ScExternalRefManager::ApiGuard(pDoc));
1047
1048 // code moved to own method InterpretEnglishString because it is also used in
1049 // ScCellRangeObj::setFormulaArray
1050
1051 pNewCell = InterpretEnglishString( rPos, rText, rFormulaNmsp, eGrammar );
1052 }
1053 // sonst Null behalten -> SetString mit lokalen Formeln/Zahlformat
1054 }
1055 else if ( rText.Len() )
1056 {
1057 OSL_ENSURE( rFormulaNmsp.Len() == 0, "ScDocFunc::SetCellText - formula namespace, but do not interpret?" );
1058 pNewCell = ScBaseCell::CreateTextCell( rText, pDoc ); // immer Text
1059 }
1060
1061 if (pNewCell)
1062 return PutCell( rPos, pNewCell, bApi );
1063 else
1064 return SetNormalString( rPos, rText, bApi );
1065 }
1066
1067 //------------------------------------------------------------------------
1068
ShowNote(const ScAddress & rPos,bool bShow)1069 bool ScDocFunc::ShowNote( const ScAddress& rPos, bool bShow )
1070 {
1071 ScDocument& rDoc = *rDocShell.GetDocument();
1072 ScPostIt* pNote = rDoc.GetNote( rPos );
1073 if( !pNote || (bShow == pNote->IsCaptionShown()) ) return false;
1074
1075 // move the caption to internal or hidden layer and create undo action
1076 pNote->ShowCaption( rPos, bShow );
1077 if( rDoc.IsUndoEnabled() )
1078 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoShowHideNote( rDocShell, rPos, bShow ) );
1079
1080 if (rDoc.IsStreamValid(rPos.Tab()))
1081 rDoc.SetStreamValid(rPos.Tab(), sal_False);
1082
1083 rDocShell.SetDocumentModified();
1084
1085 return true;
1086 }
1087
1088 //------------------------------------------------------------------------
1089
SetNoteText(const ScAddress & rPos,const String & rText,sal_Bool bApi)1090 bool ScDocFunc::SetNoteText( const ScAddress& rPos, const String& rText, sal_Bool bApi )
1091 {
1092 ScDocShellModificator aModificator( rDocShell );
1093
1094 ScDocument* pDoc = rDocShell.GetDocument();
1095 ScEditableTester aTester( pDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
1096 if (!aTester.IsEditable())
1097 {
1098 if (!bApi)
1099 rDocShell.ErrorMessage(aTester.GetMessageId());
1100 return false;
1101 }
1102
1103 String aNewText = rText;
1104 aNewText.ConvertLineEnd(); //! ist das noetig ???
1105
1106 if( ScPostIt* pNote = (aNewText.Len() > 0) ? pDoc->GetOrCreateNote( rPos ) : pDoc->GetNote( rPos ) )
1107 pNote->SetText( rPos, aNewText );
1108
1109 //! Undo !!!
1110
1111 if (pDoc->IsStreamValid(rPos.Tab()))
1112 pDoc->SetStreamValid(rPos.Tab(), sal_False);
1113
1114 rDocShell.PostPaintCell( rPos );
1115 aModificator.SetDocumentModified();
1116
1117 return true;
1118 }
1119
1120 //------------------------------------------------------------------------
1121
ReplaceNote(const ScAddress & rPos,const String & rNoteText,const String * pAuthor,const String * pDate,sal_Bool bApi)1122 bool ScDocFunc::ReplaceNote( const ScAddress& rPos, const String& rNoteText, const String* pAuthor, const String* pDate, sal_Bool bApi )
1123 {
1124 bool bDone = false;
1125
1126 ScDocShellModificator aModificator( rDocShell );
1127 ScDocument& rDoc = *rDocShell.GetDocument();
1128 ScEditableTester aTester( &rDoc, rPos.Tab(), rPos.Col(),rPos.Row(), rPos.Col(),rPos.Row() );
1129 if (aTester.IsEditable())
1130 {
1131 ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
1132 ::svl::IUndoManager* pUndoMgr = (pDrawLayer && rDoc.IsUndoEnabled()) ? rDocShell.GetUndoManager() : 0;
1133
1134 ScNoteData aOldData;
1135 ScPostIt* pOldNote = rDoc.ReleaseNote( rPos );
1136 if( pOldNote )
1137 {
1138 // ensure existing caption object before draw undo tracking starts
1139 pOldNote->GetOrCreateCaption( rPos );
1140 // rescue note data for undo
1141 aOldData = pOldNote->GetNoteData();
1142 }
1143
1144 // collect drawing undo actions for deleting/inserting caption objects
1145 if( pUndoMgr )
1146 pDrawLayer->BeginCalcUndo(false);
1147
1148 // delete the note (creates drawing undo action for the caption object)
1149 delete pOldNote;
1150
1151 // create new note (creates drawing undo action for the new caption object)
1152 ScNoteData aNewData;
1153 if( ScPostIt* pNewNote = ScNoteUtil::CreateNoteFromString( rDoc, rPos, rNoteText, false, true ) )
1154 {
1155 if( pAuthor ) pNewNote->SetAuthor( *pAuthor );
1156 if( pDate ) pNewNote->SetDate( *pDate );
1157 // rescue note data for undo
1158 aNewData = pNewNote->GetNoteData();
1159 }
1160
1161 // create the undo action
1162 if( pUndoMgr && (aOldData.mpCaption || aNewData.mpCaption) )
1163 pUndoMgr->AddUndoAction( new ScUndoReplaceNote( rDocShell, rPos, aOldData, aNewData, pDrawLayer->GetCalcUndo() ) );
1164
1165 // repaint cell (to make note marker visible)
1166 rDocShell.PostPaintCell( rPos );
1167
1168 if (rDoc.IsStreamValid(rPos.Tab()))
1169 rDoc.SetStreamValid(rPos.Tab(), sal_False);
1170
1171 aModificator.SetDocumentModified();
1172 bDone = true;
1173 }
1174 else if (!bApi)
1175 {
1176 rDocShell.ErrorMessage(aTester.GetMessageId());
1177 }
1178
1179 return bDone;
1180 }
1181
1182 //------------------------------------------------------------------------
1183
ApplyAttributes(const ScMarkData & rMark,const ScPatternAttr & rPattern,sal_Bool bRecord,sal_Bool bApi)1184 sal_Bool ScDocFunc::ApplyAttributes( const ScMarkData& rMark, const ScPatternAttr& rPattern,
1185 sal_Bool bRecord, sal_Bool bApi )
1186 {
1187 ScDocument* pDoc = rDocShell.GetDocument();
1188 if ( bRecord && !pDoc->IsUndoEnabled() )
1189 bRecord = sal_False;
1190
1191 sal_Bool bImportingXML = pDoc->IsImportingXML();
1192 // Cell formats can still be set if the range isn't editable only because of matrix formulas.
1193 // #i62483# When loading XML, the check can be skipped altogether.
1194 sal_Bool bOnlyNotBecauseOfMatrix;
1195 if ( !bImportingXML && !pDoc->IsSelectionEditable( rMark, &bOnlyNotBecauseOfMatrix )
1196 && !bOnlyNotBecauseOfMatrix )
1197 {
1198 if (!bApi)
1199 rDocShell.ErrorMessage(STR_PROTECTIONERR);
1200 return sal_False;
1201 }
1202
1203 ScDocShellModificator aModificator( rDocShell );
1204
1205 //! Umrandung
1206
1207 ScRange aMultiRange;
1208 sal_Bool bMulti = rMark.IsMultiMarked();
1209 if ( bMulti )
1210 rMark.GetMultiMarkArea( aMultiRange );
1211 else
1212 rMark.GetMarkArea( aMultiRange );
1213
1214 if ( bRecord )
1215 {
1216 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1217 pUndoDoc->InitUndo( pDoc, aMultiRange.aStart.Tab(), aMultiRange.aEnd.Tab() );
1218 pDoc->CopyToDocument( aMultiRange, IDF_ATTRIB, bMulti, pUndoDoc, &rMark );
1219
1220 rDocShell.GetUndoManager()->AddUndoAction(
1221 new ScUndoSelectionAttr(
1222 &rDocShell, rMark,
1223 aMultiRange.aStart.Col(), aMultiRange.aStart.Row(), aMultiRange.aStart.Tab(),
1224 aMultiRange.aEnd.Col(), aMultiRange.aEnd.Row(), aMultiRange.aEnd.Tab(),
1225 pUndoDoc, bMulti, &rPattern ) );
1226 }
1227
1228 // While loading XML it is not necessary to ask HasAttrib. It needs too much time.
1229 sal_uInt16 nExtFlags = 0;
1230 if ( !bImportingXML )
1231 rDocShell.UpdatePaintExt( nExtFlags, aMultiRange ); // content before the change
1232 pDoc->ApplySelectionPattern( rPattern, rMark );
1233 if ( !bImportingXML )
1234 rDocShell.UpdatePaintExt( nExtFlags, aMultiRange ); // content after the change
1235
1236 if (!AdjustRowHeight( aMultiRange ))
1237 rDocShell.PostPaint( aMultiRange, PAINT_GRID, nExtFlags );
1238 else if (nExtFlags & SC_PF_LINES)
1239 lcl_PaintAbove( rDocShell, aMultiRange ); // fuer Linien ueber dem Bereich
1240
1241 aModificator.SetDocumentModified();
1242
1243 return sal_True;
1244 }
1245
1246
ApplyStyle(const ScMarkData & rMark,const String & rStyleName,sal_Bool bRecord,sal_Bool bApi)1247 sal_Bool ScDocFunc::ApplyStyle( const ScMarkData& rMark, const String& rStyleName,
1248 sal_Bool bRecord, sal_Bool bApi )
1249 {
1250 ScDocument* pDoc = rDocShell.GetDocument();
1251 if ( bRecord && !pDoc->IsUndoEnabled() )
1252 bRecord = sal_False;
1253
1254 sal_Bool bImportingXML = pDoc->IsImportingXML();
1255 // Cell formats can still be set if the range isn't editable only because of matrix formulas.
1256 // #i62483# When loading XML, the check can be skipped altogether.
1257 sal_Bool bOnlyNotBecauseOfMatrix;
1258 if ( !bImportingXML && !pDoc->IsSelectionEditable( rMark, &bOnlyNotBecauseOfMatrix )
1259 && !bOnlyNotBecauseOfMatrix )
1260 {
1261 if (!bApi)
1262 rDocShell.ErrorMessage(STR_PROTECTIONERR);
1263 return sal_False;
1264 }
1265
1266 ScStyleSheet* pStyleSheet = (ScStyleSheet*) pDoc->GetStyleSheetPool()->Find(
1267 rStyleName, SFX_STYLE_FAMILY_PARA );
1268 if (!pStyleSheet)
1269 return sal_False;
1270
1271 ScDocShellModificator aModificator( rDocShell );
1272
1273 ScRange aMultiRange;
1274 sal_Bool bMulti = rMark.IsMultiMarked();
1275 if ( bMulti )
1276 rMark.GetMultiMarkArea( aMultiRange );
1277 else
1278 rMark.GetMarkArea( aMultiRange );
1279
1280 if ( bRecord )
1281 {
1282 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1283 SCTAB nStartTab = aMultiRange.aStart.Tab();
1284 SCTAB nTabCount = pDoc->GetTableCount();
1285 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
1286 for (SCTAB i=0; i<nTabCount; i++)
1287 if (i != nStartTab && rMark.GetTableSelect(i))
1288 pUndoDoc->AddUndoTab( i, i );
1289
1290 ScRange aCopyRange = aMultiRange;
1291 aCopyRange.aStart.SetTab(0);
1292 aCopyRange.aEnd.SetTab(nTabCount-1);
1293 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &rMark );
1294
1295 rDocShell.GetUndoManager()->AddUndoAction(
1296 new ScUndoSelectionStyle(
1297 &rDocShell, rMark, aMultiRange, rStyleName, pUndoDoc ) );
1298
1299 }
1300
1301 // sal_Bool bPaintExt = pDoc->HasAttrib( aMultiRange, HASATTR_PAINTEXT );
1302 // pDoc->ApplySelectionPattern( rPattern, rMark );
1303
1304 pDoc->ApplySelectionStyle( (ScStyleSheet&)*pStyleSheet, rMark );
1305
1306 // if (!bPaintExt)
1307 // bPaintExt = pDoc->HasAttrib( aMultiRange, HASATTR_PAINTEXT );
1308 // sal_uInt16 nExtFlags = bPaintExt ? SC_PF_LINES : 0;
1309 sal_uInt16 nExtFlags = 0;
1310 if (!AdjustRowHeight( aMultiRange ))
1311 rDocShell.PostPaint( aMultiRange, PAINT_GRID, nExtFlags );
1312 else if (nExtFlags & SC_PF_LINES)
1313 lcl_PaintAbove( rDocShell, aMultiRange ); // fuer Linien ueber dem Bereich
1314
1315 aModificator.SetDocumentModified();
1316
1317 return sal_True;
1318 }
1319
1320 //------------------------------------------------------------------------
1321
InsertCells(const ScRange & rRange,const ScMarkData * pTabMark,InsCellCmd eCmd,sal_Bool bRecord,sal_Bool bApi,sal_Bool bPartOfPaste)1322 sal_Bool ScDocFunc::InsertCells( const ScRange& rRange, const ScMarkData* pTabMark, InsCellCmd eCmd,
1323 sal_Bool bRecord, sal_Bool bApi, sal_Bool bPartOfPaste )
1324 {
1325 ScDocShellModificator aModificator( rDocShell );
1326
1327 SCCOL nStartCol = rRange.aStart.Col();
1328 SCROW nStartRow = rRange.aStart.Row();
1329 SCTAB nStartTab = rRange.aStart.Tab();
1330 SCCOL nEndCol = rRange.aEnd.Col();
1331 SCROW nEndRow = rRange.aEnd.Row();
1332 SCTAB nEndTab = rRange.aEnd.Tab();
1333
1334 if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) )
1335 {
1336 DBG_ERROR("invalid row in InsertCells");
1337 return sal_False;
1338 }
1339
1340 ScDocument* pDoc = rDocShell.GetDocument();
1341 SCTAB nTabCount = pDoc->GetTableCount();
1342 SCCOL nPaintStartX = nStartCol;
1343 SCROW nPaintStartY = nStartRow;
1344 SCCOL nPaintEndX = nEndCol;
1345 SCROW nPaintEndY = nEndRow;
1346 sal_uInt16 nPaintFlags = PAINT_GRID;
1347 sal_Bool bSuccess;
1348 SCTAB i;
1349
1350 ScTabViewShell* pViewSh = rDocShell.GetBestViewShell(); //preserve current cursor position
1351 SCCOL nCursorCol = 0;
1352 SCROW nCursorRow = 0;
1353 if( pViewSh )
1354 {
1355 nCursorCol = pViewSh->GetViewData()->GetCurX();
1356 nCursorRow = pViewSh->GetViewData()->GetCurY();
1357 }
1358
1359 if (bRecord && !pDoc->IsUndoEnabled())
1360 bRecord = sal_False;
1361
1362 ScMarkData aMark;
1363 if (pTabMark)
1364 aMark = *pTabMark;
1365 else
1366 {
1367 SCTAB nCount = 0;
1368 for( i=0; i<nTabCount; i++ )
1369 {
1370 if( !pDoc->IsScenario(i) )
1371 {
1372 nCount++;
1373 if( nCount == nEndTab+1 )
1374 {
1375 aMark.SelectTable( i, sal_True );
1376 break;
1377 }
1378 }
1379 }
1380 }
1381
1382 ScMarkData aFullMark( aMark ); // including scenario sheets
1383 for( i=0; i<nTabCount; i++ )
1384 if( aMark.GetTableSelect( i ) )
1385 {
1386 for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
1387 aFullMark.SelectTable( j, sal_True );
1388 }
1389
1390 SCTAB nSelCount = aMark.GetSelectCount();
1391
1392 // zugehoerige Szenarien auch anpassen
1393 // Test zusammengefasste
1394
1395 SCCOL nMergeTestStartX = nStartCol;
1396 SCROW nMergeTestStartY = nStartRow;
1397 SCCOL nMergeTestEndX = nEndCol;
1398 SCROW nMergeTestEndY = nEndRow;
1399
1400 ScRange aExtendMergeRange( rRange );
1401
1402 if( rRange.aStart == rRange.aEnd && pDoc->HasAttrib(rRange, HASATTR_MERGED) )
1403 {
1404 pDoc->ExtendMerge( aExtendMergeRange );
1405 pDoc->ExtendOverlapped( aExtendMergeRange );
1406 nMergeTestEndX = aExtendMergeRange.aEnd.Col();
1407 nMergeTestEndY = aExtendMergeRange.aEnd.Row();
1408 nPaintEndX = nMergeTestEndX;
1409 nPaintEndY = nMergeTestEndY;
1410 }
1411
1412 if ( eCmd == INS_INSROWS )
1413 {
1414 nMergeTestStartX = 0;
1415 nMergeTestEndX = MAXCOL;
1416 }
1417 if ( eCmd == INS_INSCOLS )
1418 {
1419 nMergeTestStartY = 0;
1420 nMergeTestEndY = MAXROW;
1421 }
1422 if ( eCmd == INS_CELLSDOWN )
1423 nMergeTestEndY = MAXROW;
1424 if ( eCmd == INS_CELLSRIGHT )
1425 nMergeTestEndX = MAXCOL;
1426
1427 sal_Bool bNeedRefresh = sal_False;
1428
1429 SCCOL nEditTestEndX = (eCmd==INS_INSCOLS) ? MAXCOL : nMergeTestEndX;
1430 SCROW nEditTestEndY = (eCmd==INS_INSROWS) ? MAXROW : nMergeTestEndY;
1431 ScEditableTester aTester( pDoc, nMergeTestStartX, nMergeTestStartY, nEditTestEndX, nEditTestEndY, aMark );
1432 if (!aTester.IsEditable())
1433 {
1434 if (!bApi)
1435 rDocShell.ErrorMessage(aTester.GetMessageId());
1436 return sal_False;
1437 }
1438
1439 WaitObject aWait( rDocShell.GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference
1440
1441 ScDocument* pRefUndoDoc = NULL;
1442 ScRefUndoData* pUndoData = NULL;
1443 if ( bRecord )
1444 {
1445 pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1446 pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, sal_False, sal_False );
1447
1448 // pRefUndoDoc is filled in InsertCol / InsertRow
1449
1450 pUndoData = new ScRefUndoData( pDoc );
1451
1452 pDoc->BeginDrawUndo();
1453 }
1454
1455 // #i8302 : we unmerge overwhelming ranges, before insertion all the actions are put in the same ListAction
1456 // the patch comes from mloiseleur and maoyg
1457 sal_Bool bInsertMerge = sal_False;
1458 std::vector<ScRange> qIncreaseRange;
1459 String aUndo = ScGlobal::GetRscString( STR_UNDO_INSERTCELLS );
1460 if (bRecord)
1461 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
1462
1463 for( i=0; i<nTabCount; i++ )
1464 {
1465 if( aMark.GetTableSelect(i) )
1466 {
1467 if( pDoc->HasAttrib( nMergeTestStartX, nMergeTestStartY, i, nMergeTestEndX, nMergeTestEndY, i, HASATTR_MERGED | HASATTR_OVERLAPPED ) )
1468 {
1469 if (eCmd==INS_CELLSRIGHT)
1470 bNeedRefresh = sal_True;
1471
1472 SCCOL nMergeStartX = nMergeTestStartX;
1473 SCROW nMergeStartY = nMergeTestStartY;
1474 SCCOL nMergeEndX = nMergeTestEndX;
1475 SCROW nMergeEndY = nMergeTestEndY;
1476
1477 pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i );
1478 pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i );
1479
1480 if(( eCmd == INS_CELLSDOWN && ( nMergeStartX != nMergeTestStartX || nMergeEndX != nMergeTestEndX )) ||
1481 (eCmd == INS_CELLSRIGHT && ( nMergeStartY != nMergeTestStartY || nMergeEndY != nMergeTestEndY )) )
1482 {
1483 if (!bApi)
1484 rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0);
1485 rDocShell.GetUndoManager()->LeaveListAction();
1486 return sal_False;
1487 }
1488
1489 SCCOL nTestCol = -1;
1490 SCROW nTestRow1 = -1;
1491 SCROW nTestRow2 = -1;
1492
1493 ScDocAttrIterator aTestIter( pDoc, i, nMergeTestStartX, nMergeTestStartY, nMergeTestEndX, nMergeTestEndY );
1494 ScRange aExtendRange( nMergeTestStartX, nMergeTestStartY, i, nMergeTestEndX, nMergeTestEndY, i );
1495 const ScPatternAttr* pPattern = NULL;
1496 const ScMergeAttr* pMergeFlag = NULL;
1497 const ScMergeFlagAttr* pMergeFlagAttr = NULL;
1498 while ( ( pPattern = aTestIter.GetNext( nTestCol, nTestRow1, nTestRow2 ) ) != NULL )
1499 {
1500 pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem(ATTR_MERGE);
1501 pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem(ATTR_MERGE_FLAG);
1502 sal_Int16 nNewFlags = pMergeFlagAttr->GetValue() & ( SC_MF_HOR | SC_MF_VER );
1503 if( ( pMergeFlag && pMergeFlag->IsMerged() ) || nNewFlags == SC_MF_HOR || nNewFlags == SC_MF_VER )
1504 {
1505 ScRange aRange( nTestCol, nTestRow1, i );
1506 pDoc->ExtendOverlapped(aRange);
1507 pDoc->ExtendMerge(aRange, sal_True, sal_True);
1508
1509 if( nTestRow1 < nTestRow2 && nNewFlags == SC_MF_HOR )
1510 {
1511 for( SCROW nTestRow = nTestRow1; nTestRow <= nTestRow2; nTestRow++ )
1512 {
1513 ScRange aTestRange( nTestCol, nTestRow, i );
1514 pDoc->ExtendOverlapped( aTestRange );
1515 pDoc->ExtendMerge( aTestRange, sal_True, sal_True);
1516 ScRange aMergeRange( aTestRange.aStart.Col(),aTestRange.aStart.Row(), i );
1517 if( !aExtendRange.In( aMergeRange ) )
1518 {
1519 qIncreaseRange.push_back( aTestRange );
1520 bInsertMerge = sal_True;
1521 }
1522 }
1523 }
1524 else
1525 {
1526 ScRange aMergeRange( aRange.aStart.Col(),aRange.aStart.Row(), i );
1527 if( !aExtendRange.In( aMergeRange ) )
1528 {
1529 qIncreaseRange.push_back( aRange );
1530 }
1531 bInsertMerge = sal_True;
1532 }
1533 }
1534 }
1535
1536 if( bInsertMerge )
1537 {
1538 if( eCmd == INS_INSROWS || eCmd == INS_CELLSDOWN )
1539 {
1540 nStartRow = aExtendMergeRange.aStart.Row();
1541 nEndRow = aExtendMergeRange.aEnd.Row();
1542
1543 if( eCmd == INS_CELLSDOWN )
1544 nEndCol = nMergeTestEndX;
1545 else
1546 {
1547 nStartCol = 0;
1548 nEndCol = MAXCOL;
1549 }
1550 }
1551 else if( eCmd == INS_CELLSRIGHT || eCmd == INS_INSCOLS )
1552 {
1553
1554 nStartCol = aExtendMergeRange.aStart.Col();
1555 nEndCol = aExtendMergeRange.aEnd.Col();
1556 if( eCmd == INS_CELLSRIGHT )
1557 {
1558 nEndRow = nMergeTestEndY;
1559 }
1560 else
1561 {
1562 nStartRow = 0;
1563 nEndRow = MAXROW;
1564 }
1565 }
1566
1567 if( !qIncreaseRange.empty() )
1568 {
1569 for( ::std::vector<ScRange>::const_iterator iIter( qIncreaseRange.begin()); iIter != qIncreaseRange.end(); iIter++ )
1570 {
1571 ScRange aRange( *iIter );
1572 if( pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
1573 {
1574 UnmergeCells( aRange, sal_True, sal_True );
1575 }
1576 }
1577 }
1578 }
1579 else
1580 {
1581 if (!bApi)
1582 rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0);
1583 rDocShell.GetUndoManager()->LeaveListAction();
1584 return sal_False;
1585 }
1586 }
1587 }
1588 }
1589
1590 switch (eCmd)
1591 {
1592 case INS_CELLSDOWN:
1593 bSuccess = pDoc->InsertRow( nStartCol, 0, nEndCol, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &aFullMark );
1594 nPaintEndY = MAXROW;
1595 break;
1596 case INS_INSROWS:
1597 bSuccess = pDoc->InsertRow( 0, 0, MAXCOL, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &aFullMark );
1598 nPaintStartX = 0;
1599 nPaintEndX = MAXCOL;
1600 nPaintEndY = MAXROW;
1601 nPaintFlags |= PAINT_LEFT;
1602 break;
1603 case INS_CELLSRIGHT:
1604 bSuccess = pDoc->InsertCol( nStartRow, 0, nEndRow, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &aFullMark );
1605 nPaintEndX = MAXCOL;
1606 break;
1607 case INS_INSCOLS:
1608 bSuccess = pDoc->InsertCol( 0, 0, MAXROW, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &aFullMark );
1609 nPaintStartY = 0;
1610 nPaintEndY = MAXROW;
1611 nPaintEndX = MAXCOL;
1612 nPaintFlags |= PAINT_TOP;
1613 break;
1614 default:
1615 DBG_ERROR("Falscher Code beim Einfuegen");
1616 bSuccess = sal_False;
1617 break;
1618 }
1619
1620 if ( bSuccess )
1621 {
1622 SCTAB* pTabs = NULL;
1623 SCTAB* pScenarios = NULL;
1624 SCTAB nUndoPos = 0;
1625
1626 if ( bRecord )
1627 {
1628 pTabs = new SCTAB[nSelCount];
1629 pScenarios = new SCTAB[nSelCount];
1630 nUndoPos = 0;
1631 for( i=0; i<nTabCount; i++ )
1632 {
1633 if( aMark.GetTableSelect( i ) )
1634 {
1635 SCTAB nCount = 0;
1636 for( SCTAB j=i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
1637 nCount ++;
1638
1639 pScenarios[nUndoPos] = nCount;
1640 pTabs[nUndoPos] = i;
1641 nUndoPos ++;
1642 }
1643 }
1644
1645 if( !bInsertMerge )
1646 {
1647 rDocShell.GetUndoManager()->LeaveListAction();
1648 }
1649
1650 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoInsertCells(
1651 &rDocShell, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ),
1652 nUndoPos, pTabs, pScenarios, eCmd, pRefUndoDoc, pUndoData, bPartOfPaste ) );
1653 }
1654
1655 // #i8302 : we remerge growing ranges, with the new part inserted
1656
1657 while( !qIncreaseRange.empty() )
1658 {
1659 ScRange aRange = qIncreaseRange.back();
1660 if( !pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
1661 {
1662 switch (eCmd)
1663 {
1664 case INS_CELLSDOWN:
1665 case INS_INSROWS:
1666 aRange.aEnd.IncRow(static_cast<SCsCOL>(nEndRow-nStartRow+1));
1667 break;
1668 case INS_CELLSRIGHT:
1669 case INS_INSCOLS:
1670 aRange.aEnd.IncCol(static_cast<SCsCOL>(nEndCol-nStartCol+1));
1671 break;
1672 default:
1673 break;
1674 }
1675 MergeCells(aRange, sal_False, sal_True, sal_True);
1676 }
1677 qIncreaseRange.pop_back();
1678 }
1679
1680 if( bInsertMerge )
1681 rDocShell.GetUndoManager()->LeaveListAction();
1682
1683 for( i=0; i<nTabCount; i++ )
1684 {
1685 if( aMark.GetTableSelect( i ) )
1686 {
1687 if (bNeedRefresh)
1688 pDoc->ExtendMerge( nMergeTestStartX, nMergeTestStartY, nMergeTestEndX, nMergeTestEndY, i, sal_True );
1689 else
1690 pDoc->RefreshAutoFilter( nMergeTestStartX, nMergeTestStartY, nMergeTestEndX, nMergeTestEndY, i );
1691
1692 if ( eCmd == INS_INSROWS || eCmd == INS_INSCOLS )
1693 pDoc->UpdatePageBreaks( i );
1694
1695 sal_uInt16 nExtFlags = 0;
1696 rDocShell.UpdatePaintExt( nExtFlags, nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i );
1697
1698 SCTAB nScenarioCount = 0;
1699
1700 for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
1701 nScenarioCount ++;
1702
1703 sal_Bool bAdjusted = ( eCmd == INS_INSROWS ) ? AdjustRowHeight(ScRange(0, nStartRow, i, MAXCOL, nEndRow, i+nScenarioCount )) :
1704 AdjustRowHeight(ScRange(0, nPaintStartY, i, MAXCOL, nPaintEndY, i+nScenarioCount ));
1705 if (bAdjusted)
1706 {
1707 // paint only what is not done by AdjustRowHeight
1708 if (nPaintFlags & PAINT_TOP)
1709 rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, PAINT_TOP );
1710 }
1711 else
1712 rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, nPaintFlags, nExtFlags );
1713 }
1714 }
1715 //aModificator.SetDocumentModified();
1716 }
1717 else
1718 {
1719 if( bInsertMerge )
1720 {
1721 while( !qIncreaseRange.empty() )
1722 {
1723 ScRange aRange = qIncreaseRange.back();
1724 MergeCells(aRange, sal_False, sal_True, sal_True);
1725 qIncreaseRange.pop_back();
1726 }
1727
1728 if( pViewSh )
1729 {
1730 pViewSh->MarkRange( rRange, sal_False );
1731 pViewSh->SetCursor( nCursorCol, nCursorRow );
1732 }
1733 }
1734
1735 rDocShell.GetUndoManager()->LeaveListAction();
1736 rDocShell.GetUndoManager()->RemoveLastUndoAction();
1737
1738 delete pRefUndoDoc;
1739 delete pUndoData;
1740 if (!bApi)
1741 rDocShell.ErrorMessage(STR_INSERT_FULL); // Spalte/Zeile voll
1742 }
1743
1744 aModificator.SetDocumentModified();
1745
1746 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
1747 return bSuccess;
1748 }
1749
DeleteCells(const ScRange & rRange,const ScMarkData * pTabMark,DelCellCmd eCmd,sal_Bool bRecord,sal_Bool bApi)1750 sal_Bool ScDocFunc::DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark, DelCellCmd eCmd,
1751 sal_Bool bRecord, sal_Bool bApi )
1752 {
1753 ScDocShellModificator aModificator( rDocShell );
1754
1755 SCCOL nStartCol = rRange.aStart.Col();
1756 SCROW nStartRow = rRange.aStart.Row();
1757 SCTAB nStartTab = rRange.aStart.Tab();
1758 SCCOL nEndCol = rRange.aEnd.Col();
1759 SCROW nEndRow = rRange.aEnd.Row();
1760 SCTAB nEndTab = rRange.aEnd.Tab();
1761
1762 if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) )
1763 {
1764 DBG_ERROR("invalid row in DeleteCells");
1765 return sal_False;
1766 }
1767
1768 ScDocument* pDoc = rDocShell.GetDocument();
1769 SCTAB nTabCount = pDoc->GetTableCount();
1770 SCCOL nPaintStartX = nStartCol;
1771 SCROW nPaintStartY = nStartRow;
1772 SCCOL nPaintEndX = nEndCol;
1773 SCROW nPaintEndY = nEndRow;
1774 sal_uInt16 nPaintFlags = PAINT_GRID;
1775 SCTAB i;
1776
1777 if (bRecord && !pDoc->IsUndoEnabled())
1778 bRecord = sal_False;
1779
1780 ScMarkData aMark;
1781 if (pTabMark)
1782 aMark = *pTabMark;
1783 else
1784 {
1785 SCTAB nCount = 0;
1786 for( i=0; i<nTabCount; i++ )
1787 {
1788 if( !pDoc->IsScenario(i) )
1789 {
1790 nCount++;
1791 if( nCount == nEndTab+1 )
1792 {
1793 aMark.SelectTable( i, sal_True );
1794 break;
1795 }
1796 }
1797 }
1798 }
1799
1800 ScMarkData aFullMark( aMark ); // including scenario sheets
1801 for( i=0; i<nTabCount; i++ )
1802 if( aMark.GetTableSelect( i ) )
1803 {
1804 for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
1805 aFullMark.SelectTable( j, sal_True );
1806 }
1807
1808 SCTAB nSelCount = aMark.GetSelectCount();
1809
1810 SCCOL nUndoStartX = nStartCol;
1811 SCROW nUndoStartY = nStartRow;
1812 SCCOL nUndoEndX = nEndCol;
1813 SCROW nUndoEndY = nEndRow;
1814
1815 ScRange aExtendMergeRange( rRange );
1816
1817 if( rRange.aStart == rRange.aEnd && pDoc->HasAttrib(rRange, HASATTR_MERGED) )
1818 {
1819 pDoc->ExtendMerge( aExtendMergeRange );
1820 pDoc->ExtendOverlapped( aExtendMergeRange );
1821 nUndoEndX = aExtendMergeRange.aEnd.Col();
1822 nUndoEndY = aExtendMergeRange.aEnd.Row();
1823 nPaintEndX = nUndoEndX;
1824 nPaintEndY = nUndoEndY;
1825 }
1826
1827 if (eCmd==DEL_DELROWS)
1828 {
1829 nUndoStartX = 0;
1830 nUndoEndX = MAXCOL;
1831 }
1832 if (eCmd==DEL_DELCOLS)
1833 {
1834 nUndoStartY = 0;
1835 nUndoEndY = MAXROW;
1836 }
1837 // Test Zellschutz
1838
1839 SCCOL nEditTestEndX = nUndoEndX;
1840 if ( eCmd==DEL_DELCOLS || eCmd==DEL_CELLSLEFT )
1841 nEditTestEndX = MAXCOL;
1842 SCROW nEditTestEndY = nUndoEndY;
1843 if ( eCmd==DEL_DELROWS || eCmd==DEL_CELLSUP )
1844 nEditTestEndY = MAXROW;
1845 ScEditableTester aTester( pDoc, nUndoStartX, nUndoStartY, nEditTestEndX, nEditTestEndY, aMark );
1846 if (!aTester.IsEditable())
1847 {
1848 if (!bApi)
1849 rDocShell.ErrorMessage(aTester.GetMessageId());
1850 return sal_False;
1851 }
1852
1853 // Test zusammengefasste
1854
1855 SCCOL nMergeTestEndX = (eCmd==DEL_CELLSLEFT) ? MAXCOL : nUndoEndX;
1856 SCROW nMergeTestEndY = (eCmd==DEL_CELLSUP) ? MAXROW : nUndoEndY;
1857 SCCOL nExtendStartCol = nUndoStartX;
1858 SCROW nExtendStartRow = nUndoStartY;
1859 sal_Bool bNeedRefresh = sal_False;
1860
1861 //Issue 8302 want to be able to insert into the middle of merged cells
1862 //the patch comes from maoyg
1863 ::std::vector<ScRange> qDecreaseRange;
1864 sal_Bool bDeletingMerge = sal_False;
1865 String aUndo = ScGlobal::GetRscString( STR_UNDO_DELETECELLS );
1866 if (bRecord)
1867 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
1868
1869 for( i=0; i<nTabCount; i++ )
1870 {
1871 if( aMark.GetTableSelect(i) )
1872 {
1873 if ( pDoc->HasAttrib( nUndoStartX, nUndoStartY, i, nMergeTestEndX, nMergeTestEndY, i, HASATTR_MERGED | HASATTR_OVERLAPPED ))
1874 {
1875 SCCOL nMergeStartX = nUndoStartX;
1876 SCROW nMergeStartY = nUndoStartY;
1877 SCCOL nMergeEndX = nMergeTestEndX;
1878 SCROW nMergeEndY = nMergeTestEndY;
1879
1880 pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i );
1881 pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i );
1882 if( ( eCmd == DEL_CELLSUP && ( nMergeStartX != nUndoStartX || nMergeEndX != nMergeTestEndX))||
1883 ( eCmd == DEL_CELLSLEFT && ( nMergeStartY != nUndoStartY || nMergeEndY != nMergeTestEndY)))
1884 {
1885 if (!bApi)
1886 rDocShell.ErrorMessage(STR_MSSG_DELETECELLS_0);
1887 rDocShell.GetUndoManager()->LeaveListAction();
1888 return sal_False;
1889 }
1890
1891 nExtendStartCol = nMergeStartX;
1892 nExtendStartRow = nMergeStartY;
1893 SCCOL nTestCol = -1;
1894 SCROW nTestRow1 = -1;
1895 SCROW nTestRow2 = -1;
1896
1897 ScDocAttrIterator aTestIter( pDoc, i, nUndoStartX, nUndoStartY, nMergeTestEndX, nMergeTestEndY );
1898 ScRange aExtendRange( nUndoStartX, nUndoStartY, i, nMergeTestEndX, nMergeTestEndY, i );
1899 const ScPatternAttr* pPattern = NULL;
1900 const ScMergeAttr* pMergeFlag = NULL;
1901 const ScMergeFlagAttr* pMergeFlagAttr = NULL;
1902 while ( ( pPattern = aTestIter.GetNext( nTestCol, nTestRow1, nTestRow2 ) ) != NULL )
1903 {
1904 pMergeFlag = (const ScMergeAttr*) &pPattern->GetItem( ATTR_MERGE );
1905 pMergeFlagAttr = (const ScMergeFlagAttr*) &pPattern->GetItem( ATTR_MERGE_FLAG );
1906 sal_Int16 nNewFlags = pMergeFlagAttr->GetValue() & ( SC_MF_HOR | SC_MF_VER );
1907 if( ( pMergeFlag && pMergeFlag->IsMerged() ) || nNewFlags == SC_MF_HOR || nNewFlags == SC_MF_VER )
1908 {
1909 ScRange aRange( nTestCol, nTestRow1, i );
1910 pDoc->ExtendOverlapped( aRange );
1911 pDoc->ExtendMerge( aRange, sal_True, sal_True );
1912
1913 if( nTestRow1 < nTestRow2 && nNewFlags == SC_MF_HOR )
1914 {
1915 for( SCROW nTestRow = nTestRow1; nTestRow <= nTestRow2; nTestRow++ )
1916 {
1917 ScRange aTestRange( nTestCol, nTestRow, i );
1918 pDoc->ExtendOverlapped( aTestRange );
1919 pDoc->ExtendMerge( aTestRange, sal_True, sal_True);
1920 ScRange aMergeRange( aTestRange.aStart.Col(),aTestRange.aStart.Row(), i );
1921 if( !aExtendRange.In( aMergeRange ) )
1922 {
1923 qDecreaseRange.push_back( aTestRange );
1924 bDeletingMerge = sal_True;
1925 }
1926 }
1927 }
1928 else
1929 {
1930 ScRange aMergeRange( aRange.aStart.Col(),aRange.aStart.Row(), i );
1931 if( !aExtendRange.In( aMergeRange ) )
1932 {
1933 qDecreaseRange.push_back( aRange );
1934 }
1935 bDeletingMerge = sal_True;
1936 }
1937 }
1938 }
1939
1940 if( bDeletingMerge )
1941 {
1942
1943 if( eCmd == DEL_DELROWS || eCmd == DEL_CELLSUP )
1944 {
1945 nStartRow = aExtendMergeRange.aStart.Row();
1946 nEndRow = aExtendMergeRange.aEnd.Row();
1947 bNeedRefresh = sal_True;
1948
1949 if( eCmd == DEL_CELLSUP )
1950 {
1951 nEndCol = aExtendMergeRange.aEnd.Col();
1952 }
1953 else
1954 {
1955 nStartCol = 0;
1956 nEndCol = MAXCOL;
1957 }
1958 }
1959 else if( eCmd == DEL_CELLSLEFT || eCmd == DEL_DELCOLS )
1960 {
1961
1962 nStartCol = aExtendMergeRange.aStart.Col();
1963 nEndCol = aExtendMergeRange.aEnd.Col();
1964 if( eCmd == DEL_CELLSLEFT )
1965 {
1966 nEndRow = aExtendMergeRange.aEnd.Row();
1967 bNeedRefresh = sal_True;
1968 }
1969 else
1970 {
1971 nStartRow = 0;
1972 nEndRow = MAXROW;
1973 }
1974 }
1975
1976 if( !qDecreaseRange.empty() )
1977 {
1978 for( ::std::vector<ScRange>::const_iterator iIter( qDecreaseRange.begin()); iIter != qDecreaseRange.end(); iIter++ )
1979 {
1980 ScRange aRange( *iIter );
1981 if( pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
1982 {
1983 UnmergeCells( aRange, sal_True, sal_True );
1984 }
1985 }
1986 }
1987 }
1988 else
1989 {
1990 if (!bApi)
1991 rDocShell.ErrorMessage(STR_MSSG_DELETECELLS_0);
1992 rDocShell.GetUndoManager()->LeaveListAction();
1993 return sal_False;
1994 }
1995 }
1996 }
1997 }
1998
1999 //
2000 // ausfuehren
2001 //
2002
2003 WaitObject aWait( rDocShell.GetActiveDialogParent() ); // wichtig wegen TrackFormulas bei UpdateReference
2004
2005 ScDocument* pUndoDoc = NULL;
2006 ScDocument* pRefUndoDoc = NULL;
2007 ScRefUndoData* pUndoData = NULL;
2008 if ( bRecord )
2009 {
2010 // With the fix for #101329#, UpdateRef always puts cells into pRefUndoDoc at their old position,
2011 // so it's no longer necessary to copy more than the deleted range into pUndoDoc.
2012
2013 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2014 pUndoDoc->InitUndo( pDoc, 0, nTabCount-1, (eCmd==DEL_DELCOLS), (eCmd==DEL_DELROWS) );
2015 for( i=0; i<nTabCount; i++ )
2016 {
2017 if( aMark.GetTableSelect( i ) )
2018 {
2019 SCTAB nScenarioCount = 0;
2020
2021 for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
2022 nScenarioCount ++;
2023
2024 pDoc->CopyToDocument( nUndoStartX, nUndoStartY, i, nUndoEndX, nUndoEndY, i+nScenarioCount,
2025 IDF_ALL | IDF_NOCAPTIONS, sal_False, pUndoDoc );
2026 }
2027 }
2028
2029 pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2030 pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, sal_False, sal_False );
2031
2032 pUndoData = new ScRefUndoData( pDoc );
2033
2034 pDoc->BeginDrawUndo();
2035 }
2036
2037 sal_uInt16 nExtFlags = 0;
2038 for( i=0; i<nTabCount; i++ )
2039 {
2040 if( aMark.GetTableSelect( i ) )
2041 rDocShell.UpdatePaintExt( nExtFlags, nStartCol, nStartRow, i, nEndCol, nEndRow, i );
2042 }
2043
2044 sal_Bool bUndoOutline = sal_False;
2045 switch (eCmd)
2046 {
2047 case DEL_CELLSUP:
2048 pDoc->DeleteRow( nStartCol, 0, nEndCol, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, NULL, &aFullMark );
2049 nPaintEndY = MAXROW;
2050 break;
2051 case DEL_DELROWS:
2052 pDoc->DeleteRow( 0, 0, MAXCOL, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &bUndoOutline, &aFullMark );
2053 nPaintStartX = 0;
2054 nPaintEndX = MAXCOL;
2055 nPaintEndY = MAXROW;
2056 nPaintFlags |= PAINT_LEFT;
2057 break;
2058 case DEL_CELLSLEFT:
2059 pDoc->DeleteCol( nStartRow, 0, nEndRow, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, NULL, &aFullMark );
2060 nPaintEndX = MAXCOL;
2061 break;
2062 case DEL_DELCOLS:
2063 pDoc->DeleteCol( 0, 0, MAXROW, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &bUndoOutline, &aFullMark );
2064 nPaintStartY = 0;
2065 nPaintEndY = MAXROW;
2066 nPaintEndX = MAXCOL;
2067 nPaintFlags |= PAINT_TOP;
2068 break;
2069 default:
2070 DBG_ERROR("Falscher Code beim Loeschen");
2071 break;
2072 }
2073
2074 //! Test, ob Outline in Groesse geaendert
2075
2076 if ( bRecord )
2077 {
2078 for( i=0; i<nTabCount; i++ )
2079 if( aFullMark.GetTableSelect( i ) )
2080 pRefUndoDoc->DeleteAreaTab(nUndoStartX,nUndoStartY,nUndoEndX,nUndoEndY, i, IDF_ALL);
2081
2082 // alle Tabellen anlegen, damit Formeln kopiert werden koennen:
2083 pUndoDoc->AddUndoTab( 0, nTabCount-1, sal_False, sal_False );
2084
2085 // kopieren mit bColRowFlags=sal_False (#54194#)
2086 pRefUndoDoc->CopyToDocument(0,0,0,MAXCOL,MAXROW,MAXTAB,IDF_FORMULA,sal_False,pUndoDoc,NULL,sal_False);
2087 delete pRefUndoDoc;
2088
2089 SCTAB* pTabs = new SCTAB[nSelCount];
2090 SCTAB* pScenarios = new SCTAB[nSelCount];
2091 SCTAB nUndoPos = 0;
2092
2093 for( i=0; i<nTabCount; i++ )
2094 {
2095 if( aMark.GetTableSelect( i ) )
2096 {
2097 SCTAB nCount = 0;
2098 for( SCTAB j=i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
2099 nCount ++;
2100
2101 pScenarios[nUndoPos] = nCount;
2102 pTabs[nUndoPos] = i;
2103 nUndoPos ++;
2104 }
2105 }
2106
2107 if( !bDeletingMerge )
2108 {
2109 rDocShell.GetUndoManager()->LeaveListAction();
2110 }
2111
2112 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoDeleteCells(
2113 &rDocShell, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ),nUndoPos, pTabs, pScenarios,
2114 eCmd, pUndoDoc, pUndoData ) );
2115 }
2116
2117 // #i8302 want to be able to insert into the middle of merged cells
2118 // the patch comes from maoyg
2119
2120 while( !qDecreaseRange.empty() )
2121 {
2122 ScRange aRange = qDecreaseRange.back();
2123
2124 long nDecreaseRowCount = 0;
2125 long nDecreaseColCount = 0;
2126 if( eCmd == DEL_CELLSUP || eCmd == DEL_DELROWS )
2127 {
2128 if( nStartRow >= aRange.aStart.Row() && nStartRow <= aRange.aEnd.Row() && nEndRow>= aRange.aStart.Row() && nEndRow <= aRange.aEnd.Row() )
2129 nDecreaseRowCount = nEndRow-nStartRow+1;
2130 else if( nStartRow >= aRange.aStart.Row() && nStartRow <= aRange.aEnd.Row() && nEndRow >= aRange.aStart.Row() && nEndRow >= aRange.aEnd.Row() )
2131 nDecreaseRowCount = aRange.aEnd.Row()-nStartRow+1;
2132 else if( nStartRow >= aRange.aStart.Row() && nStartRow >= aRange.aEnd.Row() && nEndRow>= aRange.aStart.Row() && nEndRow <= aRange.aEnd.Row() )
2133 nDecreaseRowCount = aRange.aEnd.Row()-nEndRow+1;
2134 }
2135 else if( eCmd == DEL_CELLSLEFT || eCmd == DEL_DELCOLS )
2136 {
2137 if( nStartCol >= aRange.aStart.Col() && nStartCol <= aRange.aEnd.Col() && nEndCol>= aRange.aStart.Col() && nEndCol <= aRange.aEnd.Col() )
2138 nDecreaseColCount = nEndCol-nStartCol+1;
2139 else if( nStartCol >= aRange.aStart.Col() && nStartCol <= aRange.aEnd.Col() && nEndCol >= aRange.aStart.Col() && nEndCol >= aRange.aEnd.Col() )
2140 nDecreaseColCount = aRange.aEnd.Col()-nStartCol+1;
2141 else if( nStartCol >= aRange.aStart.Col() && nStartCol >= aRange.aEnd.Col() && nEndCol>= aRange.aStart.Col() && nEndCol <= aRange.aEnd.Col() )
2142 nDecreaseColCount = aRange.aEnd.Col()-nEndCol+1;
2143 }
2144
2145 switch (eCmd)
2146 {
2147 case DEL_CELLSUP:
2148 case DEL_DELROWS:
2149 aRange.aEnd.SetRow(static_cast<SCsCOL>( aRange.aEnd.Row()-nDecreaseRowCount));
2150 break;
2151 case DEL_CELLSLEFT:
2152 case DEL_DELCOLS:
2153 aRange.aEnd.SetCol(static_cast<SCsCOL>( aRange.aEnd.Col()-nDecreaseColCount));
2154 break;
2155 default:
2156 break;
2157 }
2158
2159 if( !pDoc->HasAttrib( aRange, HASATTR_OVERLAPPED | HASATTR_MERGED ) )
2160 {
2161 MergeCells( aRange, sal_False, sal_True, sal_True );
2162 }
2163 qDecreaseRange.pop_back();
2164 }
2165
2166 if( bDeletingMerge )
2167 rDocShell.GetUndoManager()->LeaveListAction();
2168
2169 if ( bNeedRefresh )
2170 {
2171 // #i51445# old merge flag attributes must be deleted also for single cells,
2172 // not only for whole columns/rows
2173
2174 if ( eCmd==DEL_DELCOLS || eCmd==DEL_CELLSLEFT )
2175 nMergeTestEndX = MAXCOL;
2176 if ( eCmd==DEL_DELROWS || eCmd==DEL_CELLSUP )
2177 nMergeTestEndY = MAXROW;
2178 ScPatternAttr aPattern( pDoc->GetPool() );
2179 aPattern.GetItemSet().Put( ScMergeFlagAttr() );
2180
2181 pDoc->ApplyPatternArea( nExtendStartCol, nExtendStartRow, nMergeTestEndX, nMergeTestEndY, aMark, aPattern );
2182
2183 for( i=0; i<nTabCount; i++ )
2184 {
2185 if( aMark.GetTableSelect( i ) )
2186 {
2187 SCTAB nScenarioCount = 0;
2188
2189 for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
2190 nScenarioCount ++;
2191
2192 ScRange aMergedRange( nExtendStartCol, nExtendStartRow, i, nMergeTestEndX, nMergeTestEndY, i+nScenarioCount );
2193 pDoc->ExtendMerge( aMergedRange, sal_True );
2194 }
2195 }
2196 }
2197
2198 for( i=0; i<nTabCount; i++ )
2199 {
2200 if( aMark.GetTableSelect( i ) )
2201 {
2202 if ( eCmd == DEL_DELCOLS || eCmd == DEL_DELROWS )
2203 pDoc->UpdatePageBreaks( i );
2204
2205 rDocShell.UpdatePaintExt( nExtFlags, nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i );
2206
2207 SCTAB nScenarioCount = 0;
2208
2209 for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ )
2210 nScenarioCount ++;
2211
2212 // ganze Zeilen loeschen: nichts anpassen
2213 if ( eCmd == DEL_DELROWS || !AdjustRowHeight(ScRange( 0, nPaintStartY, i, MAXCOL, nPaintEndY, i+nScenarioCount )) )
2214 rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, nPaintFlags, nExtFlags );
2215 else
2216 {
2217 // paint only what is not done by AdjustRowHeight
2218 if (nExtFlags & SC_PF_LINES)
2219 lcl_PaintAbove( rDocShell, ScRange( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount) );
2220 if (nPaintFlags & PAINT_TOP)
2221 rDocShell.PostPaint( nPaintStartX, nPaintStartY, i, nPaintEndX, nPaintEndY, i+nScenarioCount, PAINT_TOP );
2222 }
2223 }
2224 }
2225 aModificator.SetDocumentModified();
2226
2227 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
2228
2229 return sal_True;
2230 }
2231
MoveBlock(const ScRange & rSource,const ScAddress & rDestPos,sal_Bool bCut,sal_Bool bRecord,sal_Bool bPaint,sal_Bool bApi)2232 sal_Bool ScDocFunc::MoveBlock( const ScRange& rSource, const ScAddress& rDestPos,
2233 sal_Bool bCut, sal_Bool bRecord, sal_Bool bPaint, sal_Bool bApi )
2234 {
2235 ScDocShellModificator aModificator( rDocShell );
2236
2237 SCCOL nStartCol = rSource.aStart.Col();
2238 SCROW nStartRow = rSource.aStart.Row();
2239 SCTAB nStartTab = rSource.aStart.Tab();
2240 SCCOL nEndCol = rSource.aEnd.Col();
2241 SCROW nEndRow = rSource.aEnd.Row();
2242 SCTAB nEndTab = rSource.aEnd.Tab();
2243 SCCOL nDestCol = rDestPos.Col();
2244 SCROW nDestRow = rDestPos.Row();
2245 SCTAB nDestTab = rDestPos.Tab();
2246
2247 if ( !ValidRow(nStartRow) || !ValidRow(nEndRow) || !ValidRow(nDestRow) )
2248 {
2249 DBG_ERROR("invalid row in MoveBlock");
2250 return sal_False;
2251 }
2252
2253 // zugehoerige Szenarien auch anpassen - nur wenn innerhalb einer Tabelle verschoben wird!
2254 sal_Bool bScenariosAdded = sal_False;
2255 ScDocument* pDoc = rDocShell.GetDocument();
2256 if (bRecord && !pDoc->IsUndoEnabled())
2257 bRecord = sal_False;
2258
2259 SCTAB nTabCount = pDoc->GetTableCount();
2260 if ( nDestTab == nStartTab && !pDoc->IsScenario(nEndTab) )
2261 while ( nEndTab+1 < nTabCount && pDoc->IsScenario(nEndTab+1) )
2262 {
2263 ++nEndTab;
2264 bScenariosAdded = sal_True;
2265 }
2266
2267 SCTAB nSrcTabCount = nEndTab-nStartTab+1;
2268 SCTAB nDestEndTab = nDestTab+nSrcTabCount-1;
2269 SCTAB nTab;
2270
2271 ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP );
2272
2273 ScMarkData aSourceMark;
2274 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2275 aSourceMark.SelectTable( nTab, sal_True ); // Source selektieren
2276 aSourceMark.SetMarkArea( rSource );
2277
2278 ScDocShellRef aDragShellRef;
2279 if ( pDoc->HasOLEObjectsInArea( rSource ) )
2280 {
2281 aDragShellRef = new ScDocShell; // DocShell needs a Ref immediately
2282 aDragShellRef->DoInitNew(NULL);
2283 }
2284 ScDrawLayer::SetGlobalDrawPersist(aDragShellRef);
2285
2286 ScClipParam aClipParam(ScRange(nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nStartTab), bCut);
2287 pDoc->CopyToClip(aClipParam, pClipDoc, &aSourceMark, false, bScenariosAdded, true);
2288
2289 ScDrawLayer::SetGlobalDrawPersist(NULL);
2290
2291 SCCOL nOldEndCol = nEndCol;
2292 SCROW nOldEndRow = nEndRow;
2293 sal_Bool bClipOver = sal_False;
2294 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2295 {
2296 SCCOL nTmpEndCol = nOldEndCol;
2297 SCROW nTmpEndRow = nOldEndRow;
2298 if (pDoc->ExtendMerge( nStartCol, nStartRow, nTmpEndCol, nTmpEndRow, nTab ))
2299 bClipOver = sal_True;
2300 if ( nTmpEndCol > nEndCol ) nEndCol = nTmpEndCol;
2301 if ( nTmpEndRow > nEndRow ) nEndRow = nTmpEndRow;
2302 }
2303
2304 SCCOL nDestEndCol = nDestCol + ( nOldEndCol-nStartCol );
2305 SCROW nDestEndRow = nDestRow + ( nOldEndRow-nStartRow );
2306
2307 SCCOL nUndoEndCol = nDestCol + ( nEndCol-nStartCol ); // erweitert im Zielblock
2308 SCROW nUndoEndRow = nDestRow + ( nEndRow-nStartRow );
2309
2310 sal_Bool bIncludeFiltered = bCut;
2311 if ( !bIncludeFiltered )
2312 {
2313 // adjust sizes to include only non-filtered rows
2314
2315 SCCOL nClipX;
2316 SCROW nClipY;
2317 pClipDoc->GetClipArea( nClipX, nClipY, sal_False );
2318 SCROW nUndoAdd = nUndoEndRow - nDestEndRow;
2319 nDestEndRow = nDestRow + nClipY;
2320 nUndoEndRow = nDestEndRow + nUndoAdd;
2321 }
2322
2323 if (!ValidCol(nUndoEndCol) || !ValidRow(nUndoEndRow))
2324 {
2325 if (!bApi)
2326 rDocShell.ErrorMessage(STR_PASTE_FULL);
2327 delete pClipDoc;
2328 return sal_False;
2329 }
2330
2331 // Test auf Zellschutz
2332
2333 ScEditableTester aTester;
2334 for (nTab=nDestTab; nTab<=nDestEndTab; nTab++)
2335 aTester.TestBlock( pDoc, nTab, nDestCol,nDestRow, nUndoEndCol,nUndoEndRow );
2336 if (bCut)
2337 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2338 aTester.TestBlock( pDoc, nTab, nStartCol,nStartRow, nEndCol,nEndRow );
2339
2340 if (!aTester.IsEditable())
2341 {
2342 if (!bApi)
2343 rDocShell.ErrorMessage(aTester.GetMessageId());
2344 delete pClipDoc;
2345 return sal_False;
2346 }
2347
2348 // Test auf zusammengefasste - beim Verschieben erst nach dem Loeschen
2349
2350 if (bClipOver && !bCut)
2351 if (pDoc->HasAttrib( nDestCol,nDestRow,nDestTab, nUndoEndCol,nUndoEndRow,nDestEndTab,
2352 HASATTR_MERGED | HASATTR_OVERLAPPED ))
2353 { // "Zusammenfassen nicht verschachteln !"
2354 if (!bApi)
2355 rDocShell.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0);
2356 delete pClipDoc;
2357 return sal_False;
2358 }
2359
2360 // Are there borders in the cells? (for painting)
2361
2362 sal_uInt16 nSourceExt = 0;
2363 rDocShell.UpdatePaintExt( nSourceExt, nStartCol,nStartRow,nStartTab, nEndCol,nEndRow,nEndTab );
2364 sal_uInt16 nDestExt = 0;
2365 rDocShell.UpdatePaintExt( nDestExt, nDestCol,nDestRow,nDestTab, nDestEndCol,nDestEndRow,nDestEndTab );
2366
2367 //
2368 // ausfuehren
2369 //
2370
2371 ScDocument* pUndoDoc = NULL;
2372 ScDocument* pRefUndoDoc = NULL;
2373 ScRefUndoData* pUndoData = NULL;
2374 if (bRecord)
2375 {
2376 sal_Bool bWholeCols = ( nStartRow == 0 && nEndRow == MAXROW );
2377 sal_Bool bWholeRows = ( nStartCol == 0 && nEndCol == MAXCOL );
2378 sal_uInt16 nUndoFlags = (IDF_ALL & ~IDF_OBJECTS) | IDF_NOCAPTIONS;
2379
2380 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2381 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab, bWholeCols, bWholeRows );
2382
2383 if (bCut)
2384 {
2385 pDoc->CopyToDocument( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab,
2386 nUndoFlags, sal_False, pUndoDoc );
2387 pRefUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2388 pRefUndoDoc->InitUndo( pDoc, 0, nTabCount-1, sal_False, sal_False );
2389 }
2390
2391 if ( nDestTab != nStartTab )
2392 pUndoDoc->AddUndoTab( nDestTab, nDestEndTab, bWholeCols, bWholeRows );
2393 pDoc->CopyToDocument( nDestCol, nDestRow, nDestTab,
2394 nDestEndCol, nDestEndRow, nDestEndTab,
2395 nUndoFlags, sal_False, pUndoDoc );
2396
2397 pUndoData = new ScRefUndoData( pDoc );
2398
2399 pDoc->BeginDrawUndo();
2400 }
2401
2402 sal_Bool bSourceHeight = sal_False; // Hoehen angepasst?
2403 if (bCut)
2404 {
2405 ScMarkData aDelMark; // only for tables
2406 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2407 {
2408 pDoc->DeleteAreaTab( nStartCol,nStartRow, nOldEndCol,nOldEndRow, nTab, IDF_ALL );
2409 aDelMark.SelectTable( nTab, sal_True );
2410 }
2411 pDoc->DeleteObjectsInArea( nStartCol,nStartRow, nOldEndCol,nOldEndRow, aDelMark );
2412
2413 // Test auf zusammengefasste
2414
2415 if (bClipOver)
2416 if (pDoc->HasAttrib( nDestCol,nDestRow,nDestTab,
2417 nUndoEndCol,nUndoEndRow,nDestEndTab,
2418 HASATTR_MERGED | HASATTR_OVERLAPPED ))
2419 {
2420 pDoc->CopyFromClip( rSource, aSourceMark, IDF_ALL, pRefUndoDoc, pClipDoc );
2421 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2422 {
2423 SCCOL nTmpEndCol = nEndCol;
2424 SCROW nTmpEndRow = nEndRow;
2425 pDoc->ExtendMerge( nStartCol, nStartRow, nTmpEndCol, nTmpEndRow, nTab, sal_True );
2426 }
2427
2428 // Fehlermeldung erst nach dem Wiederherstellen des Inhalts
2429 if (!bApi) // "Zusammenfassen nicht verschachteln !"
2430 rDocShell.ErrorMessage(STR_MSSG_MOVEBLOCKTO_0);
2431
2432 delete pUndoDoc;
2433 delete pRefUndoDoc;
2434 delete pUndoData;
2435 delete pClipDoc;
2436 return sal_False;
2437 }
2438
2439 bSourceHeight = AdjustRowHeight( rSource, sal_False );
2440 }
2441
2442 ScRange aPasteDest( nDestCol, nDestRow, nDestTab, nDestEndCol, nDestEndRow, nDestEndTab );
2443
2444 ScMarkData aDestMark;
2445 for (nTab=nDestTab; nTab<=nDestEndTab; nTab++)
2446 aDestMark.SelectTable( nTab, sal_True ); // Destination selektieren
2447 aDestMark.SetMarkArea( aPasteDest );
2448
2449 /* Do not copy cell notes and drawing objects here. While pasting, the
2450 function ScDocument::UpdateReference() is called which calls
2451 ScDrawLayer::MoveCells() which may move away inserted objects to wrong
2452 positions (e.g. if source and destination range overlaps). Cell notes
2453 and drawing objects are pasted below after doing all adjusting. */
2454 pDoc->CopyFromClip( aPasteDest, aDestMark, IDF_ALL & ~(IDF_NOTE | IDF_OBJECTS),
2455 pRefUndoDoc, pClipDoc, sal_True, sal_False, bIncludeFiltered );
2456
2457 // skipped rows and merged cells don't mix
2458 if ( !bIncludeFiltered && pClipDoc->HasClipFilteredRows() )
2459 UnmergeCells( aPasteDest, sal_False, sal_True );
2460
2461 VirtualDevice aVirtDev;
2462 sal_Bool bDestHeight = AdjustRowHeight(
2463 ScRange( 0,nDestRow,nDestTab, MAXCOL,nDestEndRow,nDestEndTab ),
2464 sal_False );
2465
2466 /* Paste cell notes and drawing objects after adjusting formula references
2467 and row heights. There are no cell notes or drawing objects, if the
2468 clipdoc does not contain a drawing layer.
2469 #i102056# Passing IDF_NOTE only would overwrite cell contents with
2470 empty note cells, therefore the special modifier IDF_ADDNOTES is passed
2471 here too which changes the behavior of ScColumn::CopyFromClip() to not
2472 touch existing cells. */
2473 if ( pClipDoc->GetDrawLayer() )
2474 pDoc->CopyFromClip( aPasteDest, aDestMark, IDF_NOTE | IDF_ADDNOTES | IDF_OBJECTS,
2475 pRefUndoDoc, pClipDoc, sal_True, sal_False, bIncludeFiltered );
2476
2477 if (bRecord)
2478 {
2479 if (pRefUndoDoc)
2480 {
2481 // alle Tabellen anlegen, damit Formeln kopiert werden koennen:
2482 pUndoDoc->AddUndoTab( 0, nTabCount-1, sal_False, sal_False );
2483
2484 pRefUndoDoc->DeleteArea( nDestCol, nDestRow, nDestEndCol, nDestEndRow, aSourceMark, IDF_ALL );
2485 // kopieren mit bColRowFlags=sal_False (#54194#)
2486 pRefUndoDoc->CopyToDocument( 0, 0, 0, MAXCOL, MAXROW, MAXTAB,
2487 IDF_FORMULA, sal_False, pUndoDoc, NULL, sal_False );
2488 delete pRefUndoDoc;
2489 }
2490
2491 rDocShell.GetUndoManager()->AddUndoAction(
2492 new ScUndoDragDrop( &rDocShell, ScRange(
2493 nStartCol, nStartRow, nStartTab,
2494 nOldEndCol, nOldEndRow, nEndTab ),
2495 ScAddress( nDestCol, nDestRow, nDestTab ),
2496 bCut, pUndoDoc, pUndoData, bScenariosAdded ) );
2497 }
2498
2499 SCCOL nDestPaintEndCol = nDestEndCol;
2500 SCROW nDestPaintEndRow = nDestEndRow;
2501 for (nTab=nDestTab; nTab<=nDestEndTab; nTab++)
2502 {
2503 SCCOL nTmpEndCol = nDestEndCol;
2504 SCROW nTmpEndRow = nDestEndRow;
2505 pDoc->ExtendMerge( nDestCol, nDestRow, nTmpEndCol, nTmpEndRow, nTab, sal_True );
2506 if (nTmpEndCol > nDestPaintEndCol) nDestPaintEndCol = nTmpEndCol;
2507 if (nTmpEndRow > nDestPaintEndRow) nDestPaintEndRow = nTmpEndRow;
2508 }
2509
2510 if (bCut)
2511 for (nTab=nStartTab; nTab<=nEndTab; nTab++)
2512 pDoc->RefreshAutoFilter( nStartCol, nStartRow, nEndCol, nEndRow, nTab );
2513
2514 if (bPaint)
2515 {
2516 // Zielbereich:
2517
2518 SCCOL nPaintStartX = nDestCol;
2519 SCROW nPaintStartY = nDestRow;
2520 SCCOL nPaintEndX = nDestPaintEndCol;
2521 SCROW nPaintEndY = nDestPaintEndRow;
2522 sal_uInt16 nFlags = PAINT_GRID;
2523
2524 if ( nStartRow==0 && nEndRow==MAXROW ) // Breiten mitkopiert?
2525 {
2526 nPaintEndX = MAXCOL;
2527 nPaintStartY = 0;
2528 nPaintEndY = MAXROW;
2529 nFlags |= PAINT_TOP;
2530 }
2531 if ( bDestHeight || ( nStartCol == 0 && nEndCol == MAXCOL ) )
2532 {
2533 nPaintEndY = MAXROW;
2534 nPaintStartX = 0;
2535 nPaintEndX = MAXCOL;
2536 nFlags |= PAINT_LEFT;
2537 }
2538 if ( bScenariosAdded )
2539 {
2540 nPaintStartX = 0;
2541 nPaintStartY = 0;
2542 nPaintEndX = MAXCOL;
2543 nPaintEndY = MAXROW;
2544 }
2545
2546 rDocShell.PostPaint( nPaintStartX,nPaintStartY,nDestTab,
2547 nPaintEndX,nPaintEndY,nDestEndTab, nFlags, nSourceExt | nDestExt );
2548
2549 if ( bCut )
2550 {
2551 // Quellbereich:
2552
2553 nPaintStartX = nStartCol;
2554 nPaintStartY = nStartRow;
2555 nPaintEndX = nEndCol;
2556 nPaintEndY = nEndRow;
2557 nFlags = PAINT_GRID;
2558
2559 if ( bSourceHeight )
2560 {
2561 nPaintEndY = MAXROW;
2562 nPaintStartX = 0;
2563 nPaintEndX = MAXCOL;
2564 nFlags |= PAINT_LEFT;
2565 }
2566 if ( bScenariosAdded )
2567 {
2568 nPaintStartX = 0;
2569 nPaintStartY = 0;
2570 nPaintEndX = MAXCOL;
2571 nPaintEndY = MAXROW;
2572 }
2573
2574 rDocShell.PostPaint( nPaintStartX,nPaintStartY,nStartTab,
2575 nPaintEndX,nPaintEndY,nEndTab, nFlags, nSourceExt );
2576 }
2577 }
2578
2579 aModificator.SetDocumentModified();
2580
2581 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
2582
2583 delete pClipDoc;
2584 return sal_True;
2585 }
2586
2587 //------------------------------------------------------------------------
GetDocModuleObject(SfxObjectShell & rDocSh,String & sCodeName)2588 uno::Reference< uno::XInterface > GetDocModuleObject( SfxObjectShell& rDocSh, String& sCodeName )
2589 {
2590 uno::Reference< lang::XMultiServiceFactory> xSF(rDocSh.GetModel(), uno::UNO_QUERY);
2591 uno::Reference< container::XNameAccess > xVBACodeNamedObjectAccess;
2592 uno::Reference< uno::XInterface > xDocModuleApiObject;
2593 if ( xSF.is() )
2594 {
2595 xVBACodeNamedObjectAccess.set( xSF->createInstance( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.VBAObjectModuleObjectProvider"))), uno::UNO_QUERY );
2596 xDocModuleApiObject.set( xVBACodeNamedObjectAccess->getByName( sCodeName ), uno::UNO_QUERY );
2597 }
2598 return xDocModuleApiObject;
2599
2600 }
2601
lcl_InitModuleInfo(SfxObjectShell & rDocSh,String & sModule)2602 script::ModuleInfo lcl_InitModuleInfo( SfxObjectShell& rDocSh, String& sModule )
2603 {
2604 script::ModuleInfo sModuleInfo;
2605 sModuleInfo.ModuleType = script::ModuleType::DOCUMENT;
2606 sModuleInfo.ModuleObject = GetDocModuleObject( rDocSh, sModule );
2607 return sModuleInfo;
2608 }
2609
VBA_InsertModule(ScDocument & rDoc,SCTAB nTab,String & sModuleName,String & sSource)2610 void VBA_InsertModule( ScDocument& rDoc, SCTAB nTab, String& sModuleName, String& sSource )
2611 {
2612 SfxObjectShell& rDocSh = *rDoc.GetDocumentShell();
2613 uno::Reference< script::XLibraryContainer > xLibContainer = rDocSh.GetBasicContainer();
2614 DBG_ASSERT( xLibContainer.is(), "No BasicContainer!" );
2615
2616 uno::Reference< container::XNameContainer > xLib;
2617 if( xLibContainer.is() )
2618 {
2619 String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) );
2620 if ( rDocSh.GetBasicManager() && rDocSh.GetBasicManager()->GetName().Len() )
2621 aLibName = rDocSh.GetBasicManager()->GetName();
2622 uno::Any aLibAny = xLibContainer->getByName( aLibName );
2623 aLibAny >>= xLib;
2624 }
2625 if( xLib.is() )
2626 {
2627 // if the Module with codename exists then find a new name
2628 sal_Int32 nNum = 0;
2629 String genModuleName;
2630 if ( sModuleName.Len() )
2631 sModuleName = sModuleName;
2632 else
2633 {
2634 genModuleName = String::CreateFromAscii( "Sheet1" );
2635 nNum = 1;
2636 }
2637 while( xLib->hasByName( genModuleName ) )
2638 genModuleName = rtl::OUString::createFromAscii( "Sheet" ) + rtl::OUString::valueOf( ++nNum );
2639
2640 uno::Any aSourceAny;
2641 rtl::OUString sTmpSource = sSource;
2642 if ( sTmpSource.getLength() == 0 )
2643 sTmpSource = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Rem Attribute VBA_ModuleType=VBADocumentModule\nOption VBASupport 1\n" ));
2644 aSourceAny <<= sTmpSource;
2645 uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY );
2646 if ( xVBAModuleInfo.is() )
2647 {
2648 rDoc.SetCodeName( nTab, genModuleName );
2649 script::ModuleInfo sModuleInfo = lcl_InitModuleInfo( rDocSh, genModuleName );
2650 xVBAModuleInfo->insertModuleInfo( genModuleName, sModuleInfo );
2651 xLib->insertByName( genModuleName, aSourceAny );
2652 }
2653
2654 }
2655 }
2656
VBA_DeleteModule(ScDocShell & rDocSh,String & sModuleName)2657 void VBA_DeleteModule( ScDocShell& rDocSh, String& sModuleName )
2658 {
2659 uno::Reference< script::XLibraryContainer > xLibContainer = rDocSh.GetBasicContainer();
2660 DBG_ASSERT( xLibContainer.is(), "No BasicContainer!" );
2661
2662 uno::Reference< container::XNameContainer > xLib;
2663 if( xLibContainer.is() )
2664 {
2665 String aLibName( RTL_CONSTASCII_USTRINGPARAM( "Standard" ) );
2666 if ( rDocSh.GetBasicManager() && rDocSh.GetBasicManager()->GetName().Len() )
2667 aLibName = rDocSh.GetBasicManager()->GetName();
2668 uno::Any aLibAny = xLibContainer->getByName( aLibName );
2669 aLibAny >>= xLib;
2670 }
2671 if( xLib.is() )
2672 {
2673 uno::Reference< script::vba::XVBAModuleInfo > xVBAModuleInfo( xLib, uno::UNO_QUERY );
2674 if( xLib->hasByName( sModuleName ) )
2675 xLib->removeByName( sModuleName );
2676 if ( xVBAModuleInfo.is() )
2677 xVBAModuleInfo->removeModuleInfo( sModuleName );
2678
2679 }
2680 }
2681
2682
InsertTable(SCTAB nTab,const String & rName,sal_Bool bRecord,sal_Bool bApi)2683 sal_Bool ScDocFunc::InsertTable( SCTAB nTab, const String& rName, sal_Bool bRecord, sal_Bool bApi )
2684 {
2685 sal_Bool bSuccess = sal_False;
2686 WaitObject aWait( rDocShell.GetActiveDialogParent() );
2687
2688 ScDocShellModificator aModificator( rDocShell );
2689
2690 ScDocument* pDoc = rDocShell.GetDocument();
2691
2692
2693 // Strange loop, also basic is loaded too early ( InsertTable )
2694 // is called via the xml import for sheets in described in odf
2695 sal_Bool bInsertDocModule = false;
2696
2697 if( !rDocShell.GetDocument()->IsImportingXML() )
2698 {
2699 bInsertDocModule = pDoc ? pDoc->IsInVBAMode() : false;
2700 }
2701 if ( bInsertDocModule || ( bRecord && !pDoc->IsUndoEnabled() ) )
2702 bRecord = sal_False;
2703
2704 if (bRecord)
2705 pDoc->BeginDrawUndo(); // InsertTab erzeugt ein SdrUndoNewPage
2706
2707 SCTAB nTabCount = pDoc->GetTableCount();
2708 sal_Bool bAppend = ( nTab >= nTabCount );
2709 if ( bAppend )
2710 nTab = nTabCount; // wichtig fuer Undo
2711
2712 if (pDoc->InsertTab( nTab, rName ))
2713 {
2714 String sCodeName;
2715 if (bRecord)
2716 rDocShell.GetUndoManager()->AddUndoAction(
2717 new ScUndoInsertTab( &rDocShell, nTab, bAppend, rName));
2718 // Views updaten:
2719 // Only insert vba modules if vba mode ( and not currently importing XML )
2720 if( bInsertDocModule )
2721 {
2722 String sSource;
2723 VBA_InsertModule( *pDoc, nTab, sCodeName, sSource );
2724 }
2725 rDocShell.Broadcast( ScTablesHint( SC_TAB_INSERTED, nTab ) );
2726
2727 rDocShell.PostPaintExtras();
2728 aModificator.SetDocumentModified();
2729 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2730 bSuccess = sal_True;
2731 }
2732 else if (!bApi)
2733 rDocShell.ErrorMessage(STR_TABINSERT_ERROR);
2734
2735 return bSuccess;
2736 }
2737
DeleteTable(SCTAB nTab,sal_Bool bRecord,sal_Bool)2738 sal_Bool ScDocFunc::DeleteTable( SCTAB nTab, sal_Bool bRecord, sal_Bool /* bApi */ )
2739 {
2740 WaitObject aWait( rDocShell.GetActiveDialogParent() );
2741
2742 ScDocShellModificator aModificator( rDocShell );
2743
2744 sal_Bool bSuccess = sal_False;
2745 ScDocument* pDoc = rDocShell.GetDocument();
2746 sal_Bool bVbaEnabled = pDoc ? pDoc->IsInVBAMode() : false;
2747 if (bRecord && !pDoc->IsUndoEnabled())
2748 bRecord = sal_False;
2749 if ( bVbaEnabled )
2750 bRecord = sal_False;
2751 sal_Bool bWasLinked = pDoc->IsLinked(nTab);
2752 ScDocument* pUndoDoc = NULL;
2753 ScRefUndoData* pUndoData = NULL;
2754 if (bRecord)
2755 {
2756 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2757 SCTAB nCount = pDoc->GetTableCount();
2758
2759 pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True ); // nur nTab mit Flags
2760 pUndoDoc->AddUndoTab( 0, nCount-1 ); // alle Tabs fuer Referenzen
2761
2762 pDoc->CopyToDocument(0,0,nTab, MAXCOL,MAXROW,nTab, IDF_ALL,sal_False, pUndoDoc );
2763 String aOldName;
2764 pDoc->GetName( nTab, aOldName );
2765 pUndoDoc->RenameTab( nTab, aOldName, sal_False );
2766 if (bWasLinked)
2767 pUndoDoc->SetLink( nTab, pDoc->GetLinkMode(nTab), pDoc->GetLinkDoc(nTab),
2768 pDoc->GetLinkFlt(nTab), pDoc->GetLinkOpt(nTab),
2769 pDoc->GetLinkTab(nTab),
2770 pDoc->GetLinkRefreshDelay(nTab) );
2771
2772 if ( pDoc->IsScenario(nTab) )
2773 {
2774 pUndoDoc->SetScenario( nTab, sal_True );
2775 String aComment;
2776 Color aColor;
2777 sal_uInt16 nScenFlags;
2778 pDoc->GetScenarioData( nTab, aComment, aColor, nScenFlags );
2779 pUndoDoc->SetScenarioData( nTab, aComment, aColor, nScenFlags );
2780 sal_Bool bActive = pDoc->IsActiveScenario( nTab );
2781 pUndoDoc->SetActiveScenario( nTab, bActive );
2782 }
2783 pUndoDoc->SetVisible( nTab, pDoc->IsVisible( nTab ) );
2784 pUndoDoc->SetTabBgColor( nTab, pDoc->GetTabBgColor(nTab) );
2785 pUndoDoc->SetSheetEvents( nTab, pDoc->GetSheetEvents( nTab ) );
2786
2787 // Drawing-Layer muss sein Undo selbst in der Hand behalten !!!
2788 pDoc->BeginDrawUndo(); // DeleteTab erzeugt ein SdrUndoDelPage
2789
2790 pUndoData = new ScRefUndoData( pDoc );
2791 }
2792
2793 String sCodeName;
2794 sal_Bool bHasCodeName = pDoc->GetCodeName( nTab, sCodeName );
2795 if (pDoc->DeleteTab( nTab, pUndoDoc ))
2796 {
2797 if (bRecord)
2798 {
2799 SvShorts theTabs;
2800 theTabs.push_back(nTab);
2801 rDocShell.GetUndoManager()->AddUndoAction(
2802 new ScUndoDeleteTab( &rDocShell, theTabs, pUndoDoc, pUndoData ));
2803 }
2804 // Views updaten:
2805 if( bVbaEnabled )
2806 {
2807 if( bHasCodeName )
2808 {
2809 VBA_DeleteModule( rDocShell, sCodeName );
2810 }
2811 }
2812 rDocShell.Broadcast( ScTablesHint( SC_TAB_DELETED, nTab ) );
2813
2814 if (bWasLinked)
2815 {
2816 rDocShell.UpdateLinks(); // Link-Manager updaten
2817 SfxBindings* pBindings = rDocShell.GetViewBindings();
2818 if (pBindings)
2819 pBindings->Invalidate(SID_LINKS);
2820 }
2821
2822 rDocShell.PostPaintExtras();
2823 aModificator.SetDocumentModified();
2824
2825 SfxApplication* pSfxApp = SFX_APP(); // Navigator
2826 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2827 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
2828 pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
2829
2830 bSuccess = sal_True;
2831 }
2832 else
2833 {
2834 delete pUndoDoc;
2835 delete pUndoData;
2836 }
2837 return bSuccess;
2838 }
2839
SetTableVisible(SCTAB nTab,sal_Bool bVisible,sal_Bool bApi)2840 sal_Bool ScDocFunc::SetTableVisible( SCTAB nTab, sal_Bool bVisible, sal_Bool bApi )
2841 {
2842 ScDocument* pDoc = rDocShell.GetDocument();
2843 sal_Bool bUndo(pDoc->IsUndoEnabled());
2844 if ( pDoc->IsVisible( nTab ) == bVisible )
2845 return sal_True; // nichts zu tun - ok
2846
2847 if ( !pDoc->IsDocEditable() )
2848 {
2849 if (!bApi)
2850 rDocShell.ErrorMessage(STR_PROTECTIONERR);
2851 return sal_False;
2852 }
2853
2854 ScDocShellModificator aModificator( rDocShell );
2855
2856 if ( !bVisible && !pDoc->IsImportingXML() ) // #i57869# allow hiding in any order for loading
2857 {
2858 // nicht alle Tabellen ausblenden
2859
2860 sal_uInt16 nVisCount = 0;
2861 SCTAB nCount = pDoc->GetTableCount();
2862 for (SCTAB i=0; i<nCount; i++)
2863 if (pDoc->IsVisible(i))
2864 ++nVisCount;
2865
2866 if (nVisCount <= 1)
2867 {
2868 if (!bApi)
2869 rDocShell.ErrorMessage(STR_PROTECTIONERR); //! eigene Meldung?
2870 return sal_False;
2871 }
2872 }
2873
2874 pDoc->SetVisible( nTab, bVisible );
2875 if (bUndo)
2876 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoShowHideTab( &rDocShell, nTab, bVisible ) );
2877
2878 // Views updaten:
2879 if (!bVisible)
2880 rDocShell.Broadcast( ScTablesHint( SC_TAB_HIDDEN, nTab ) );
2881
2882 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2883 rDocShell.PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS);
2884 aModificator.SetDocumentModified();
2885
2886 return sal_True;
2887 }
2888
SetLayoutRTL(SCTAB nTab,sal_Bool bRTL,sal_Bool)2889 sal_Bool ScDocFunc::SetLayoutRTL( SCTAB nTab, sal_Bool bRTL, sal_Bool /* bApi */ )
2890 {
2891 ScDocument* pDoc = rDocShell.GetDocument();
2892 sal_Bool bUndo(pDoc->IsUndoEnabled());
2893 if ( pDoc->IsLayoutRTL( nTab ) == bRTL )
2894 return sal_True; // nothing to do - ok
2895
2896 //! protection (sheet or document?)
2897
2898 ScDocShellModificator aModificator( rDocShell );
2899
2900 pDoc->SetLayoutRTL( nTab, bRTL );
2901
2902 if (bUndo)
2903 {
2904 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoLayoutRTL( &rDocShell, nTab, bRTL ) );
2905 }
2906
2907 rDocShell.PostPaint( 0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_ALL );
2908 aModificator.SetDocumentModified();
2909
2910 SfxBindings* pBindings = rDocShell.GetViewBindings();
2911 if (pBindings)
2912 {
2913 pBindings->Invalidate( FID_TAB_RTL );
2914 pBindings->Invalidate( SID_ATTR_SIZE );
2915 }
2916
2917 return sal_True;
2918 }
2919
2920 //UNUSED2009-05 sal_Bool ScDocFunc::SetGrammar( formula::FormulaGrammar::Grammar eGrammar )
2921 //UNUSED2009-05 {
2922 //UNUSED2009-05 ScDocument* pDoc = rDocShell.GetDocument();
2923 //UNUSED2009-05
2924 //UNUSED2009-05 if ( pDoc->GetGrammar() == eGrammar )
2925 //UNUSED2009-05 return sal_True;
2926 //UNUSED2009-05
2927 //UNUSED2009-05 sal_Bool bUndo(pDoc->IsUndoEnabled());
2928 //UNUSED2009-05 ScDocShellModificator aModificator( rDocShell );
2929 //UNUSED2009-05
2930 //UNUSED2009-05 pDoc->SetGrammar( eGrammar );
2931 //UNUSED2009-05
2932 //UNUSED2009-05 if (bUndo)
2933 //UNUSED2009-05 {
2934 //UNUSED2009-05 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoSetGrammar( &rDocShell, eGrammar ) );
2935 //UNUSED2009-05 }
2936 //UNUSED2009-05
2937 //UNUSED2009-05 rDocShell.PostPaint( 0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_ALL );
2938 //UNUSED2009-05
2939 //UNUSED2009-05 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
2940 //UNUSED2009-05 if (NULL != pViewSh)
2941 //UNUSED2009-05 {
2942 //UNUSED2009-05 pViewSh->UpdateInputHandler( sal_False, sal_False );
2943 //UNUSED2009-05 }
2944 //UNUSED2009-05
2945 //UNUSED2009-05 aModificator.SetDocumentModified();
2946 //UNUSED2009-05
2947 //UNUSED2009-05 SfxBindings* pBindings = rDocShell.GetViewBindings();
2948 //UNUSED2009-05 if (pBindings)
2949 //UNUSED2009-05 {
2950 //UNUSED2009-05 // erAck: 2006-09-07T22:19+0200 commented out in CWS scr1c1
2951 //UNUSED2009-05 //pBindings->Invalidate( FID_TAB_USE_R1C1 );
2952 //UNUSED2009-05 }
2953 //UNUSED2009-05
2954 //UNUSED2009-05 return sal_True;
2955 //UNUSED2009-05 }
2956
RenameTable(SCTAB nTab,const String & rName,sal_Bool bRecord,sal_Bool bApi)2957 sal_Bool ScDocFunc::RenameTable( SCTAB nTab, const String& rName, sal_Bool bRecord, sal_Bool bApi )
2958 {
2959 ScDocument* pDoc = rDocShell.GetDocument();
2960 if (bRecord && !pDoc->IsUndoEnabled())
2961 bRecord = sal_False;
2962 if ( !pDoc->IsDocEditable() )
2963 {
2964 if (!bApi)
2965 rDocShell.ErrorMessage(STR_PROTECTIONERR);
2966 return sal_False;
2967 }
2968
2969 ScDocShellModificator aModificator( rDocShell );
2970
2971 sal_Bool bSuccess = sal_False;
2972 String sOldName;
2973 pDoc->GetName(nTab, sOldName);
2974 if (pDoc->RenameTab( nTab, rName ))
2975 {
2976 if (bRecord)
2977 {
2978 rDocShell.GetUndoManager()->AddUndoAction(
2979 new ScUndoRenameTab( &rDocShell, nTab, sOldName, rName));
2980 }
2981 rDocShell.PostPaintExtras();
2982 aModificator.SetDocumentModified();
2983 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2984
2985 bSuccess = sal_True;
2986 }
2987 return bSuccess;
2988 }
2989
SetTabBgColor(SCTAB nTab,const Color & rColor,bool bRecord,bool bApi)2990 bool ScDocFunc::SetTabBgColor( SCTAB nTab, const Color& rColor, bool bRecord, bool bApi )
2991 {
2992
2993 ScDocument* pDoc = rDocShell.GetDocument();
2994 if (bRecord && !pDoc->IsUndoEnabled())
2995 bRecord = false;
2996 if ( !pDoc->IsDocEditable() || pDoc->IsTabProtected(nTab) )
2997 {
2998 if (!bApi)
2999 rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Check to see what this string is...
3000 return false;
3001 }
3002
3003 Color aOldTabBgColor;
3004 aOldTabBgColor = pDoc->GetTabBgColor(nTab);
3005
3006 bool bSuccess = false;
3007 pDoc->SetTabBgColor(nTab, rColor);
3008 if ( pDoc->GetTabBgColor(nTab) == rColor)
3009 bSuccess = true;
3010 if (bSuccess)
3011 {
3012 if (bRecord)
3013 {
3014 rDocShell.GetUndoManager()->AddUndoAction(
3015 new ScUndoTabColor( &rDocShell, nTab, aOldTabBgColor, rColor));
3016 }
3017 rDocShell.PostPaintExtras();
3018 ScDocShellModificator aModificator( rDocShell );
3019 aModificator.SetDocumentModified();
3020 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
3021
3022 bSuccess = true;
3023 }
3024 return bSuccess;
3025 }
3026
SetTabBgColor(ScUndoTabColorInfo::List & rUndoTabColorList,bool bRecord,bool bApi)3027 bool ScDocFunc::SetTabBgColor(
3028 ScUndoTabColorInfo::List& rUndoTabColorList, bool bRecord, bool bApi )
3029 {
3030 ScDocument* pDoc = rDocShell.GetDocument();
3031 if (bRecord && !pDoc->IsUndoEnabled())
3032 bRecord = false;
3033
3034 if ( !pDoc->IsDocEditable() )
3035 {
3036 if (!bApi)
3037 rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Get a better String Error...
3038 return false;
3039 }
3040
3041 sal_uInt16 nTab;
3042 Color aNewTabBgColor;
3043 bool bSuccess = true;
3044 size_t nTabProtectCount = 0;
3045 size_t nTabListCount = rUndoTabColorList.size();
3046 for ( size_t i = 0; i < nTabListCount; ++i )
3047 {
3048 ScUndoTabColorInfo& rInfo = rUndoTabColorList[i];
3049 nTab = rInfo.mnTabId;
3050 if ( !pDoc->IsTabProtected(nTab) )
3051 {
3052 aNewTabBgColor = rInfo.maNewTabBgColor;
3053 rInfo.maOldTabBgColor = pDoc->GetTabBgColor(nTab);
3054 pDoc->SetTabBgColor(nTab, aNewTabBgColor);
3055 if ( pDoc->GetTabBgColor(nTab) != aNewTabBgColor)
3056 {
3057 bSuccess = false;
3058 break;
3059 }
3060 }
3061 else
3062 {
3063 nTabProtectCount++;
3064 }
3065 }
3066
3067 if ( nTabProtectCount == nTabListCount )
3068 {
3069 if (!bApi)
3070 rDocShell.ErrorMessage(STR_PROTECTIONERR); //TODO Get a better String Error...
3071 return false;
3072 }
3073
3074 if (bSuccess)
3075 {
3076 if (bRecord)
3077 {
3078 rDocShell.GetUndoManager()->AddUndoAction(
3079 new ScUndoTabColor( &rDocShell, rUndoTabColorList));
3080 }
3081 rDocShell.PostPaintExtras();
3082 ScDocShellModificator aModificator( rDocShell );
3083 aModificator.SetDocumentModified();
3084 }
3085 return bSuccess;
3086 }
3087
3088 //------------------------------------------------------------------------
3089
3090 //! SetWidthOrHeight - noch doppelt zu ViewFunc !!!!!!
3091 //! Probleme:
3092 //! - Optimale Hoehe fuer Edit-Zellen ist unterschiedlich zwischen Drucker und Bildschirm
3093 //! - Optimale Breite braucht Selektion, um evtl. nur selektierte Zellen zu beruecksichtigen
3094
lcl_GetOptimalColWidth(ScDocShell & rDocShell,SCCOL nCol,SCTAB nTab,sal_Bool bFormula)3095 sal_uInt16 lcl_GetOptimalColWidth( ScDocShell& rDocShell, SCCOL nCol, SCTAB nTab, sal_Bool bFormula )
3096 {
3097 sal_uInt16 nTwips = 0;
3098
3099 ScSizeDeviceProvider aProv(&rDocShell);
3100 OutputDevice* pDev = aProv.GetDevice(); // has pixel MapMode
3101 double nPPTX = aProv.GetPPTX();
3102 double nPPTY = aProv.GetPPTY();
3103
3104 ScDocument* pDoc = rDocShell.GetDocument();
3105 Fraction aOne(1,1);
3106 nTwips = pDoc->GetOptimalColWidth( nCol, nTab, pDev, nPPTX, nPPTY, aOne, aOne,
3107 bFormula, NULL );
3108
3109 return nTwips;
3110 }
3111
SetWidthOrHeight(sal_Bool bWidth,SCCOLROW nRangeCnt,SCCOLROW * pRanges,SCTAB nTab,ScSizeMode eMode,sal_uInt16 nSizeTwips,sal_Bool bRecord,sal_Bool bApi)3112 sal_Bool ScDocFunc::SetWidthOrHeight( sal_Bool bWidth, SCCOLROW nRangeCnt, SCCOLROW* pRanges, SCTAB nTab,
3113 ScSizeMode eMode, sal_uInt16 nSizeTwips,
3114 sal_Bool bRecord, sal_Bool bApi )
3115 {
3116 ScDocShellModificator aModificator( rDocShell );
3117
3118 if (!nRangeCnt)
3119 return sal_True;
3120
3121 ScDocument* pDoc = rDocShell.GetDocument();
3122 if ( bRecord && !pDoc->IsUndoEnabled() )
3123 bRecord = sal_False;
3124
3125 // import into read-only document is possible
3126 if ( !pDoc->IsChangeReadOnlyEnabled() && !rDocShell.IsEditable() )
3127 {
3128 if (!bApi)
3129 rDocShell.ErrorMessage(STR_PROTECTIONERR); //! eigene Meldung?
3130 return sal_False;
3131 }
3132
3133 sal_Bool bSuccess = sal_False;
3134 SCCOLROW nStart = pRanges[0];
3135 SCCOLROW nEnd = pRanges[2*nRangeCnt-1];
3136
3137 sal_Bool bFormula = sal_False;
3138 if ( eMode == SC_SIZE_OPTIMAL )
3139 {
3140 //! Option "Formeln anzeigen" - woher nehmen?
3141 }
3142
3143 ScDocument* pUndoDoc = NULL;
3144 ScOutlineTable* pUndoTab = NULL;
3145 SCCOLROW* pUndoRanges = NULL;
3146
3147 if ( bRecord )
3148 {
3149 pDoc->BeginDrawUndo(); // Drawing Updates
3150
3151 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3152 if (bWidth)
3153 {
3154 pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_False );
3155 pDoc->CopyToDocument( static_cast<SCCOL>(nStart), 0, nTab, static_cast<SCCOL>(nEnd), MAXROW, nTab, IDF_NONE, sal_False, pUndoDoc );
3156 }
3157 else
3158 {
3159 pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_False, sal_True );
3160 pDoc->CopyToDocument( 0, static_cast<SCROW>(nStart), nTab, MAXCOL, static_cast<SCROW>(nEnd), nTab, IDF_NONE, sal_False, pUndoDoc );
3161 }
3162
3163 pUndoRanges = new SCCOLROW[ 2*nRangeCnt ];
3164 memmove( pUndoRanges, pRanges, 2*nRangeCnt*sizeof(SCCOLROW) );
3165
3166 ScOutlineTable* pTable = pDoc->GetOutlineTable( nTab );
3167 if (pTable)
3168 pUndoTab = new ScOutlineTable( *pTable );
3169 }
3170
3171 sal_Bool bShow = nSizeTwips > 0 || eMode != SC_SIZE_DIRECT;
3172 sal_Bool bOutline = sal_False;
3173
3174 pDoc->IncSizeRecalcLevel( nTab ); // nicht fuer jede Spalte einzeln
3175 for (SCCOLROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
3176 {
3177 SCCOLROW nStartNo = *(pRanges++);
3178 SCCOLROW nEndNo = *(pRanges++);
3179
3180 if ( !bWidth ) // Hoehen immer blockweise
3181 {
3182 if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
3183 {
3184 sal_Bool bAll = ( eMode==SC_SIZE_OPTIMAL );
3185 if (!bAll)
3186 {
3187 // fuer alle eingeblendeten CR_MANUALSIZE loeschen,
3188 // dann SetOptimalHeight mit bShrink = FALSE
3189 for (SCROW nRow=nStartNo; nRow<=nEndNo; nRow++)
3190 {
3191 sal_uInt8 nOld = pDoc->GetRowFlags(nRow,nTab);
3192 SCROW nLastRow = -1;
3193 bool bHidden = pDoc->RowHidden(nRow, nTab, nLastRow);
3194 if ( !bHidden && ( nOld & CR_MANUALSIZE ) )
3195 pDoc->SetRowFlags( nRow, nTab, nOld & ~CR_MANUALSIZE );
3196 }
3197 }
3198
3199 ScSizeDeviceProvider aProv( &rDocShell );
3200 Fraction aOne(1,1);
3201 pDoc->SetOptimalHeight( nStartNo, nEndNo, nTab, 0, aProv.GetDevice(),
3202 aProv.GetPPTX(), aProv.GetPPTY(), aOne, aOne, bAll );
3203
3204 if (bAll)
3205 pDoc->ShowRows( nStartNo, nEndNo, nTab, sal_True );
3206
3207 // Manual-Flag wird bei bAll=sal_True schon in SetOptimalHeight gesetzt
3208 // (an bei Extra-Height, sonst aus).
3209 }
3210 else if ( eMode==SC_SIZE_DIRECT || eMode==SC_SIZE_ORIGINAL )
3211 {
3212 if (nSizeTwips)
3213 {
3214 pDoc->SetRowHeightRange( nStartNo, nEndNo, nTab, nSizeTwips );
3215 pDoc->SetManualHeight( nStartNo, nEndNo, nTab, sal_True ); // height was set manually
3216 }
3217 if ( eMode != SC_SIZE_ORIGINAL )
3218 pDoc->ShowRows( nStartNo, nEndNo, nTab, nSizeTwips != 0 );
3219 }
3220 else if ( eMode==SC_SIZE_SHOW )
3221 {
3222 pDoc->ShowRows( nStartNo, nEndNo, nTab, sal_True );
3223 }
3224 }
3225 else // Spaltenbreiten
3226 {
3227 for (SCCOL nCol=static_cast<SCCOL>(nStartNo); nCol<=static_cast<SCCOL>(nEndNo); nCol++)
3228 {
3229 SCCOL nLastCol = -1;
3230 if ( eMode != SC_SIZE_VISOPT || !pDoc->ColHidden(nCol, nTab, nLastCol) )
3231 {
3232 sal_uInt16 nThisSize = nSizeTwips;
3233
3234 if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
3235 nThisSize = nSizeTwips +
3236 lcl_GetOptimalColWidth( rDocShell, nCol, nTab, bFormula );
3237 if ( nThisSize )
3238 pDoc->SetColWidth( nCol, nTab, nThisSize );
3239
3240 if ( eMode != SC_SIZE_ORIGINAL )
3241 pDoc->ShowCol( nCol, nTab, bShow );
3242 }
3243 }
3244 }
3245
3246 // adjust outlines
3247
3248 if ( eMode != SC_SIZE_ORIGINAL )
3249 {
3250 if (bWidth)
3251 bOutline = bOutline || pDoc->UpdateOutlineCol(
3252 static_cast<SCCOL>(nStartNo),
3253 static_cast<SCCOL>(nEndNo), nTab, bShow );
3254 else
3255 bOutline = bOutline || pDoc->UpdateOutlineRow(
3256 static_cast<SCROW>(nStartNo),
3257 static_cast<SCROW>(nEndNo), nTab, bShow );
3258 }
3259 }
3260 pDoc->DecSizeRecalcLevel( nTab ); // nicht fuer jede Spalte einzeln
3261
3262 if (!bOutline)
3263 DELETEZ(pUndoTab);
3264
3265 if (bRecord)
3266 {
3267 ScMarkData aMark;
3268 aMark.SelectOneTable( nTab );
3269 rDocShell.GetUndoManager()->AddUndoAction(
3270 new ScUndoWidthOrHeight( &rDocShell, aMark,
3271 nStart, nTab, nEnd, nTab,
3272 pUndoDoc, nRangeCnt, pUndoRanges,
3273 pUndoTab, eMode, nSizeTwips, bWidth ) );
3274 }
3275
3276 pDoc->UpdatePageBreaks( nTab );
3277
3278 rDocShell.PostPaint(0,0,nTab,MAXCOL,MAXROW,nTab,PAINT_ALL);
3279 aModificator.SetDocumentModified();
3280
3281 return bSuccess;
3282 }
3283
3284
InsertPageBreak(sal_Bool bColumn,const ScAddress & rPos,sal_Bool bRecord,sal_Bool bSetModified,sal_Bool)3285 sal_Bool ScDocFunc::InsertPageBreak( sal_Bool bColumn, const ScAddress& rPos,
3286 sal_Bool bRecord, sal_Bool bSetModified, sal_Bool /* bApi */ )
3287 {
3288 ScDocShellModificator aModificator( rDocShell );
3289
3290 ScDocument* pDoc = rDocShell.GetDocument();
3291 if (bRecord && !pDoc->IsUndoEnabled())
3292 bRecord = sal_False;
3293 SCTAB nTab = rPos.Tab();
3294 SfxBindings* pBindings = rDocShell.GetViewBindings();
3295
3296 SCCOLROW nPos = bColumn ? static_cast<SCCOLROW>(rPos.Col()) :
3297 static_cast<SCCOLROW>(rPos.Row());
3298 if (nPos == 0)
3299 return sal_False; // erste Spalte / Zeile
3300
3301 ScBreakType nBreak = bColumn ?
3302 pDoc->HasColBreak(static_cast<SCCOL>(nPos), nTab) :
3303 pDoc->HasRowBreak(static_cast<SCROW>(nPos), nTab);
3304 if (nBreak & BREAK_MANUAL)
3305 return true;
3306
3307 if (bRecord)
3308 rDocShell.GetUndoManager()->AddUndoAction(
3309 new ScUndoPageBreak( &rDocShell, rPos.Col(), rPos.Row(), nTab, bColumn, sal_True ) );
3310
3311 if (bColumn)
3312 pDoc->SetColBreak(static_cast<SCCOL>(nPos), nTab, false, true);
3313 else
3314 pDoc->SetRowBreak(static_cast<SCROW>(nPos), nTab, false, true);
3315
3316 pDoc->InvalidatePageBreaks(nTab);
3317 pDoc->UpdatePageBreaks( nTab );
3318
3319 if (pDoc->IsStreamValid(nTab))
3320 pDoc->SetStreamValid(nTab, sal_False);
3321
3322 if (bColumn)
3323 {
3324 rDocShell.PostPaint( static_cast<SCCOL>(nPos)-1, 0, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
3325 if (pBindings)
3326 {
3327 pBindings->Invalidate( FID_INS_COLBRK );
3328 pBindings->Invalidate( FID_DEL_COLBRK );
3329 }
3330 }
3331 else
3332 {
3333 rDocShell.PostPaint( 0, static_cast<SCROW>(nPos)-1, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
3334 if (pBindings)
3335 {
3336 pBindings->Invalidate( FID_INS_ROWBRK );
3337 pBindings->Invalidate( FID_DEL_ROWBRK );
3338 }
3339 }
3340 if (pBindings)
3341 pBindings->Invalidate( FID_DEL_MANUALBREAKS );
3342
3343 if (bSetModified)
3344 aModificator.SetDocumentModified();
3345
3346 return sal_True;
3347 }
3348
RemovePageBreak(sal_Bool bColumn,const ScAddress & rPos,sal_Bool bRecord,sal_Bool bSetModified,sal_Bool)3349 sal_Bool ScDocFunc::RemovePageBreak( sal_Bool bColumn, const ScAddress& rPos,
3350 sal_Bool bRecord, sal_Bool bSetModified, sal_Bool /* bApi */ )
3351 {
3352 ScDocShellModificator aModificator( rDocShell );
3353
3354 ScDocument* pDoc = rDocShell.GetDocument();
3355 if (bRecord && !pDoc->IsUndoEnabled())
3356 bRecord = sal_False;
3357 SCTAB nTab = rPos.Tab();
3358 SfxBindings* pBindings = rDocShell.GetViewBindings();
3359
3360 SCCOLROW nPos = bColumn ? static_cast<SCCOLROW>(rPos.Col()) :
3361 static_cast<SCCOLROW>(rPos.Row());
3362
3363 ScBreakType nBreak;
3364 if (bColumn)
3365 nBreak = pDoc->HasColBreak(static_cast<SCCOL>(nPos), nTab);
3366 else
3367 nBreak = pDoc->HasRowBreak(static_cast<SCROW>(nPos), nTab);
3368 if ((nBreak & BREAK_MANUAL) == 0)
3369 // There is no manual break.
3370 return false;
3371
3372 if (bRecord)
3373 rDocShell.GetUndoManager()->AddUndoAction(
3374 new ScUndoPageBreak( &rDocShell, rPos.Col(), rPos.Row(), nTab, bColumn, sal_False ) );
3375
3376 if (bColumn)
3377 pDoc->RemoveColBreak(static_cast<SCCOL>(nPos), nTab, false, true);
3378 else
3379 pDoc->RemoveRowBreak(static_cast<SCROW>(nPos), nTab, false, true);
3380
3381 pDoc->UpdatePageBreaks( nTab );
3382
3383 if (pDoc->IsStreamValid(nTab))
3384 pDoc->SetStreamValid(nTab, sal_False);
3385
3386 if (bColumn)
3387 {
3388 rDocShell.PostPaint( static_cast<SCCOL>(nPos)-1, 0, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
3389 if (pBindings)
3390 {
3391 pBindings->Invalidate( FID_INS_COLBRK );
3392 pBindings->Invalidate( FID_DEL_COLBRK );
3393 }
3394 }
3395 else
3396 {
3397 rDocShell.PostPaint( 0, nPos-1, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID );
3398 if (pBindings)
3399 {
3400 pBindings->Invalidate( FID_INS_ROWBRK );
3401 pBindings->Invalidate( FID_DEL_ROWBRK );
3402 }
3403 }
3404 if (pBindings)
3405 pBindings->Invalidate( FID_DEL_MANUALBREAKS );
3406
3407 if (bSetModified)
3408 aModificator.SetDocumentModified();
3409
3410 return sal_True;
3411 }
3412
3413 //------------------------------------------------------------------------
3414
ProtectSheet(SCTAB nTab,const ScTableProtection & rProtect)3415 void ScDocFunc::ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect )
3416 {
3417 ScDocument* pDoc = rDocShell.GetDocument();
3418
3419 pDoc->SetTabProtection(nTab, &rProtect);
3420 if (pDoc->IsUndoEnabled())
3421 {
3422 ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
3423 DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!");
3424 if (pProtect)
3425 {
3426 ::std::auto_ptr<ScTableProtection> p(new ScTableProtection(*pProtect));
3427 p->setProtected(true); // just in case ...
3428 rDocShell.GetUndoManager()->AddUndoAction(
3429 new ScUndoTabProtect(&rDocShell, nTab, p) );
3430
3431 // ownership of auto_ptr now transferred to ScUndoTabProtect.
3432 }
3433 }
3434
3435 rDocShell.PostPaintGridAll();
3436 ScDocShellModificator aModificator(rDocShell);
3437 aModificator.SetDocumentModified();
3438 }
3439
Protect(SCTAB nTab,const String & rPassword,sal_Bool)3440 sal_Bool ScDocFunc::Protect( SCTAB nTab, const String& rPassword, sal_Bool /*bApi*/ )
3441 {
3442 ScDocument* pDoc = rDocShell.GetDocument();
3443 if (nTab == TABLEID_DOC)
3444 {
3445 // document protection
3446 ScDocProtection aProtection;
3447 aProtection.setProtected(true);
3448 aProtection.setPassword(rPassword);
3449 pDoc->SetDocProtection(&aProtection);
3450 if (pDoc->IsUndoEnabled())
3451 {
3452 ScDocProtection* pProtect = pDoc->GetDocProtection();
3453 DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScDocProtection pointer is NULL!");
3454 if (pProtect)
3455 {
3456 ::std::auto_ptr<ScDocProtection> p(new ScDocProtection(*pProtect));
3457 p->setProtected(true); // just in case ...
3458 rDocShell.GetUndoManager()->AddUndoAction(
3459 new ScUndoDocProtect(&rDocShell, p) );
3460 // ownership of auto_ptr is transferred to ScUndoDocProtect.
3461 }
3462 }
3463 }
3464 else
3465 {
3466 // sheet protection
3467
3468 ScTableProtection aProtection;
3469 aProtection.setProtected(true);
3470 aProtection.setPassword(rPassword);
3471 pDoc->SetTabProtection(nTab, &aProtection);
3472 if (pDoc->IsUndoEnabled())
3473 {
3474 ScTableProtection* pProtect = pDoc->GetTabProtection(nTab);
3475 DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!");
3476 if (pProtect)
3477 {
3478 ::std::auto_ptr<ScTableProtection> p(new ScTableProtection(*pProtect));
3479 p->setProtected(true); // just in case ...
3480 rDocShell.GetUndoManager()->AddUndoAction(
3481 new ScUndoTabProtect(&rDocShell, nTab, p) );
3482 // ownership of auto_ptr now transferred to ScUndoTabProtect.
3483 }
3484 }
3485 }
3486
3487 rDocShell.PostPaintGridAll();
3488 ScDocShellModificator aModificator( rDocShell );
3489 aModificator.SetDocumentModified();
3490
3491 return true;
3492 }
3493
Unprotect(SCTAB nTab,const String & rPassword,sal_Bool bApi)3494 sal_Bool ScDocFunc::Unprotect( SCTAB nTab, const String& rPassword, sal_Bool bApi )
3495 {
3496 ScDocument* pDoc = rDocShell.GetDocument();
3497
3498 if (nTab == TABLEID_DOC)
3499 {
3500 // document protection
3501
3502 ScDocProtection* pDocProtect = pDoc->GetDocProtection();
3503 if (!pDocProtect || !pDocProtect->isProtected())
3504 // already unprotected (should not happen)!
3505 return true;
3506
3507 // save the protection state before unprotect (for undo).
3508 ::std::auto_ptr<ScDocProtection> pProtectCopy(new ScDocProtection(*pDocProtect));
3509
3510 if (!pDocProtect->verifyPassword(rPassword))
3511 {
3512 if (!bApi)
3513 {
3514 InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) );
3515 aBox.Execute();
3516 }
3517 return false;
3518 }
3519
3520 pDoc->SetDocProtection(NULL);
3521 if (pDoc->IsUndoEnabled())
3522 {
3523 pProtectCopy->setProtected(false);
3524 rDocShell.GetUndoManager()->AddUndoAction(
3525 new ScUndoDocProtect(&rDocShell, pProtectCopy) );
3526 // ownership of auto_ptr now transferred to ScUndoDocProtect.
3527 }
3528 }
3529 else
3530 {
3531 // sheet protection
3532
3533 ScTableProtection* pTabProtect = pDoc->GetTabProtection(nTab);
3534 if (!pTabProtect || !pTabProtect->isProtected())
3535 // already unprotected (should not happen)!
3536 return true;
3537
3538 // save the protection state before unprotect (for undo).
3539 ::std::auto_ptr<ScTableProtection> pProtectCopy(new ScTableProtection(*pTabProtect));
3540 if (!pTabProtect->verifyPassword(rPassword))
3541 {
3542 if (!bApi)
3543 {
3544 InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) );
3545 aBox.Execute();
3546 }
3547 return false;
3548 }
3549
3550 pDoc->SetTabProtection(nTab, NULL);
3551 if (pDoc->IsUndoEnabled())
3552 {
3553 pProtectCopy->setProtected(false);
3554 rDocShell.GetUndoManager()->AddUndoAction(
3555 new ScUndoTabProtect(&rDocShell, nTab, pProtectCopy) );
3556 // ownership of auto_ptr now transferred to ScUndoTabProtect.
3557 }
3558 }
3559
3560 rDocShell.PostPaintGridAll();
3561 ScDocShellModificator aModificator( rDocShell );
3562 aModificator.SetDocumentModified();
3563
3564 return true;
3565 }
3566
3567 //------------------------------------------------------------------------
3568
ClearItems(const ScMarkData & rMark,const sal_uInt16 * pWhich,sal_Bool bApi)3569 sal_Bool ScDocFunc::ClearItems( const ScMarkData& rMark, const sal_uInt16* pWhich, sal_Bool bApi )
3570 {
3571 ScDocShellModificator aModificator( rDocShell );
3572
3573 ScDocument* pDoc = rDocShell.GetDocument();
3574 sal_Bool bUndo (pDoc->IsUndoEnabled());
3575 ScEditableTester aTester( pDoc, rMark );
3576 if (!aTester.IsEditable())
3577 {
3578 if (!bApi)
3579 rDocShell.ErrorMessage(aTester.GetMessageId());
3580 return sal_False;
3581 }
3582
3583 // #i12940# ClearItems is called (from setPropertyToDefault) directly with uno object's cached
3584 // MarkData (GetMarkData), so rMark must be changed to multi selection for ClearSelectionItems
3585 // here.
3586
3587 ScRange aMarkRange;
3588 ScMarkData aMultiMark = rMark;
3589 aMultiMark.SetMarking(sal_False); // for MarkToMulti
3590 aMultiMark.MarkToMulti();
3591 aMultiMark.GetMultiMarkArea( aMarkRange );
3592
3593 // if (bRecord)
3594 if (bUndo)
3595 {
3596 SCTAB nStartTab = aMarkRange.aStart.Tab();
3597 SCTAB nEndTab = aMarkRange.aEnd.Tab();
3598
3599 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3600 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
3601 pDoc->CopyToDocument( aMarkRange, IDF_ATTRIB, sal_True, pUndoDoc, (ScMarkData*)&aMultiMark );
3602
3603 rDocShell.GetUndoManager()->AddUndoAction(
3604 new ScUndoClearItems( &rDocShell, aMultiMark, pUndoDoc, pWhich ) );
3605 }
3606
3607 pDoc->ClearSelectionItems( pWhich, aMultiMark );
3608
3609 rDocShell.PostPaint( aMarkRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
3610 aModificator.SetDocumentModified();
3611
3612 //! Bindings-Invalidate etc.?
3613
3614 return sal_True;
3615 }
3616
ChangeIndent(const ScMarkData & rMark,sal_Bool bIncrement,sal_Bool bApi)3617 sal_Bool ScDocFunc::ChangeIndent( const ScMarkData& rMark, sal_Bool bIncrement, sal_Bool bApi )
3618 {
3619 ScDocShellModificator aModificator( rDocShell );
3620
3621 ScDocument* pDoc = rDocShell.GetDocument();
3622 sal_Bool bUndo(pDoc->IsUndoEnabled());
3623 ScEditableTester aTester( pDoc, rMark );
3624 if (!aTester.IsEditable())
3625 {
3626 if (!bApi)
3627 rDocShell.ErrorMessage(aTester.GetMessageId());
3628 return sal_False;
3629 }
3630
3631 ScRange aMarkRange;
3632 rMark.GetMultiMarkArea( aMarkRange );
3633
3634 // if (bRecord)
3635 if (bUndo)
3636 {
3637 SCTAB nStartTab = aMarkRange.aStart.Tab();
3638 SCTAB nTabCount = pDoc->GetTableCount();
3639
3640 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3641 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
3642 for (SCTAB i=0; i<nTabCount; i++)
3643 if (i != nStartTab && rMark.GetTableSelect(i))
3644 pUndoDoc->AddUndoTab( i, i );
3645
3646 ScRange aCopyRange = aMarkRange;
3647 aCopyRange.aStart.SetTab(0);
3648 aCopyRange.aEnd.SetTab(nTabCount-1);
3649 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_True, pUndoDoc, (ScMarkData*)&rMark );
3650
3651 rDocShell.GetUndoManager()->AddUndoAction(
3652 new ScUndoIndent( &rDocShell, rMark, pUndoDoc, bIncrement ) );
3653 }
3654
3655 pDoc->ChangeSelectionIndent( bIncrement, rMark );
3656
3657 rDocShell.PostPaint( aMarkRange, PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
3658 aModificator.SetDocumentModified();
3659
3660 SfxBindings* pBindings = rDocShell.GetViewBindings();
3661 if (pBindings)
3662 {
3663 pBindings->Invalidate( SID_ALIGNLEFT ); // ChangeIndent setzt auf links
3664 pBindings->Invalidate( SID_ALIGNRIGHT );
3665 pBindings->Invalidate( SID_ALIGNBLOCK );
3666 pBindings->Invalidate( SID_ALIGNCENTERHOR );
3667 pBindings->Invalidate( SID_ATTR_LRSPACE );
3668 pBindings->Invalidate( SID_ATTR_PARA_ADJUST_LEFT );
3669 pBindings->Invalidate( SID_ATTR_PARA_ADJUST_RIGHT );
3670 pBindings->Invalidate( SID_ATTR_PARA_ADJUST_BLOCK );
3671 pBindings->Invalidate( SID_ATTR_PARA_ADJUST_CENTER);
3672 // pseudo slots for Format menu
3673 pBindings->Invalidate( SID_ALIGN_ANY_HDEFAULT );
3674 pBindings->Invalidate( SID_ALIGN_ANY_LEFT );
3675 pBindings->Invalidate( SID_ALIGN_ANY_HCENTER );
3676 pBindings->Invalidate( SID_ALIGN_ANY_RIGHT );
3677 pBindings->Invalidate( SID_ALIGN_ANY_JUSTIFIED );
3678 }
3679
3680 return sal_True;
3681 }
3682
AutoFormat(const ScRange & rRange,const ScMarkData * pTabMark,sal_uInt16 nFormatNo,sal_Bool bRecord,sal_Bool bApi)3683 sal_Bool ScDocFunc::AutoFormat( const ScRange& rRange, const ScMarkData* pTabMark,
3684 sal_uInt16 nFormatNo, sal_Bool bRecord, sal_Bool bApi )
3685 {
3686 ScDocShellModificator aModificator( rDocShell );
3687
3688 sal_Bool bSuccess = sal_False;
3689 ScDocument* pDoc = rDocShell.GetDocument();
3690 SCCOL nStartCol = rRange.aStart.Col();
3691 SCROW nStartRow = rRange.aStart.Row();
3692 SCTAB nStartTab = rRange.aStart.Tab();
3693 SCCOL nEndCol = rRange.aEnd.Col();
3694 SCROW nEndRow = rRange.aEnd.Row();
3695 SCTAB nEndTab = rRange.aEnd.Tab();
3696
3697 if (bRecord && !pDoc->IsUndoEnabled())
3698 bRecord = sal_False;
3699 ScMarkData aMark;
3700 if (pTabMark)
3701 aMark = *pTabMark;
3702 else
3703 {
3704 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
3705 aMark.SelectTable( nTab, sal_True );
3706 }
3707
3708 ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat();
3709 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
3710 if ( pAutoFormat && nFormatNo < pAutoFormat->GetCount() && aTester.IsEditable() )
3711 {
3712 WaitObject aWait( rDocShell.GetActiveDialogParent() );
3713
3714 sal_Bool bSize = (*pAutoFormat)[nFormatNo]->GetIncludeWidthHeight();
3715
3716 SCTAB nTabCount = pDoc->GetTableCount();
3717 ScDocument* pUndoDoc = NULL;
3718 if ( bRecord )
3719 {
3720 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3721 pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab, bSize, bSize );
3722 for (SCTAB i=0; i<nTabCount; i++)
3723 if (i != nStartTab && aMark.GetTableSelect(i))
3724 pUndoDoc->AddUndoTab( i, i, bSize, bSize );
3725
3726 ScRange aCopyRange = rRange;
3727 aCopyRange.aStart.SetTab(0);
3728 aCopyRange.aStart.SetTab(nTabCount-1);
3729 pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_False, pUndoDoc, &aMark );
3730 if (bSize)
3731 {
3732 pDoc->CopyToDocument( nStartCol,0,0, nEndCol,MAXROW,nTabCount-1,
3733 IDF_NONE, sal_False, pUndoDoc, &aMark );
3734 pDoc->CopyToDocument( 0,nStartRow,0, MAXCOL,nEndRow,nTabCount-1,
3735 IDF_NONE, sal_False, pUndoDoc, &aMark );
3736 }
3737 pDoc->BeginDrawUndo();
3738 }
3739
3740 pDoc->AutoFormat( nStartCol, nStartRow, nEndCol, nEndRow, nFormatNo, aMark );
3741
3742 if (bSize)
3743 {
3744 /* SCCOL nCols[2];
3745 nCols[0] = nStartCol;
3746 nCols[1] = nEndCol;
3747 SCROW nRows[2];
3748 nRows[0] = nStartRow;
3749 nRows[1] = nEndRow;
3750 */
3751 SCCOLROW nCols[2] = { nStartCol, nEndCol };
3752 SCCOLROW nRows[2] = { nStartRow, nEndRow };
3753
3754 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
3755 if (aMark.GetTableSelect(nTab))
3756 {
3757 SetWidthOrHeight( sal_True, 1,nCols, nTab, SC_SIZE_VISOPT, STD_EXTRA_WIDTH, sal_False, sal_True);
3758 SetWidthOrHeight( sal_False,1,nRows, nTab, SC_SIZE_VISOPT, 0, sal_False, sal_False);
3759 rDocShell.PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab,
3760 PAINT_GRID | PAINT_LEFT | PAINT_TOP );
3761 }
3762 }
3763 else
3764 {
3765 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
3766 if (aMark.GetTableSelect(nTab))
3767 {
3768 sal_Bool bAdj = AdjustRowHeight( ScRange(nStartCol, nStartRow, nTab,
3769 nEndCol, nEndRow, nTab), sal_False );
3770 if (bAdj)
3771 rDocShell.PostPaint( 0,nStartRow,nTab, MAXCOL,MAXROW,nTab,
3772 PAINT_GRID | PAINT_LEFT );
3773 else
3774 rDocShell.PostPaint( nStartCol, nStartRow, nTab,
3775 nEndCol, nEndRow, nTab, PAINT_GRID );
3776 }
3777 }
3778
3779 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
3780 {
3781 rDocShell.GetUndoManager()->AddUndoAction(
3782 new ScUndoAutoFormat( &rDocShell, rRange, pUndoDoc, aMark, bSize, nFormatNo ) );
3783 }
3784
3785 aModificator.SetDocumentModified();
3786 }
3787 else if (!bApi)
3788 rDocShell.ErrorMessage(aTester.GetMessageId());
3789
3790 return bSuccess;
3791 }
3792
3793 //------------------------------------------------------------------------
3794
EnterMatrix(const ScRange & rRange,const ScMarkData * pTabMark,const ScTokenArray * pTokenArray,const String & rString,sal_Bool bApi,sal_Bool bEnglish,const String & rFormulaNmsp,const formula::FormulaGrammar::Grammar eGrammar)3795 sal_Bool ScDocFunc::EnterMatrix( const ScRange& rRange, const ScMarkData* pTabMark,
3796 const ScTokenArray* pTokenArray, const String& rString, sal_Bool bApi, sal_Bool bEnglish,
3797 const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar )
3798 {
3799 ScDocShellModificator aModificator( rDocShell );
3800
3801 sal_Bool bSuccess = sal_False;
3802 ScDocument* pDoc = rDocShell.GetDocument();
3803 SCCOL nStartCol = rRange.aStart.Col();
3804 SCROW nStartRow = rRange.aStart.Row();
3805 SCTAB nStartTab = rRange.aStart.Tab();
3806 SCCOL nEndCol = rRange.aEnd.Col();
3807 SCROW nEndRow = rRange.aEnd.Row();
3808 SCTAB nEndTab = rRange.aEnd.Tab();
3809
3810 sal_Bool bUndo(pDoc->IsUndoEnabled());
3811
3812 ScMarkData aMark;
3813 if (pTabMark)
3814 aMark = *pTabMark;
3815 else
3816 {
3817 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
3818 aMark.SelectTable( nTab, sal_True );
3819 }
3820
3821 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
3822 if ( aTester.IsEditable() )
3823 {
3824 WaitObject aWait( rDocShell.GetActiveDialogParent() );
3825
3826 ScDocument* pUndoDoc = NULL;
3827 // if (bRecord) // immer
3828 if (bUndo)
3829 {
3830 //! auch bei Undo selektierte Tabellen beruecksichtigen
3831 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3832 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
3833 pDoc->CopyToDocument( rRange, IDF_ALL & ~IDF_NOTE, sal_False, pUndoDoc );
3834 }
3835
3836 // use TokenArray if given, string (and flags) otherwise
3837 if ( pTokenArray )
3838 {
3839 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
3840 aMark, EMPTY_STRING, pTokenArray, eGrammar);
3841 }
3842 else if ( pDoc->IsImportingXML() )
3843 {
3844 ScTokenArray* pCode = lcl_ScDocFunc_CreateTokenArrayXML( rString, rFormulaNmsp, eGrammar );
3845 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
3846 aMark, EMPTY_STRING, pCode, eGrammar);
3847 delete pCode;
3848 pDoc->IncXMLImportedFormulaCount( rString.Len() );
3849 }
3850 else if (bEnglish)
3851 {
3852 ScCompiler aComp( pDoc, rRange.aStart);
3853 aComp.SetGrammar(eGrammar);
3854 ScTokenArray* pCode = aComp.CompileString( rString );
3855 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
3856 aMark, EMPTY_STRING, pCode, eGrammar);
3857 delete pCode;
3858 }
3859 else
3860 pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow,
3861 aMark, rString, NULL, eGrammar);
3862
3863 // if (bRecord) // immer
3864 if (bUndo)
3865 {
3866 //! auch bei Undo selektierte Tabellen beruecksichtigen
3867 rDocShell.GetUndoManager()->AddUndoAction(
3868 new ScUndoEnterMatrix( &rDocShell, rRange, pUndoDoc, rString ) );
3869 }
3870
3871 // Err522 beim Paint von DDE-Formeln werden jetzt beim Interpretieren abgefangen
3872 rDocShell.PostPaint( nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab, PAINT_GRID );
3873 aModificator.SetDocumentModified();
3874
3875 bSuccess = sal_True;
3876 }
3877 else if (!bApi)
3878 rDocShell.ErrorMessage(aTester.GetMessageId());
3879
3880 return bSuccess;
3881 }
3882
3883 //------------------------------------------------------------------------
3884
TabOp(const ScRange & rRange,const ScMarkData * pTabMark,const ScTabOpParam & rParam,sal_Bool bRecord,sal_Bool bApi)3885 sal_Bool ScDocFunc::TabOp( const ScRange& rRange, const ScMarkData* pTabMark,
3886 const ScTabOpParam& rParam, sal_Bool bRecord, sal_Bool bApi )
3887 {
3888 ScDocShellModificator aModificator( rDocShell );
3889
3890 sal_Bool bSuccess = sal_False;
3891 ScDocument* pDoc = rDocShell.GetDocument();
3892 SCCOL nStartCol = rRange.aStart.Col();
3893 SCROW nStartRow = rRange.aStart.Row();
3894 SCTAB nStartTab = rRange.aStart.Tab();
3895 SCCOL nEndCol = rRange.aEnd.Col();
3896 SCROW nEndRow = rRange.aEnd.Row();
3897 SCTAB nEndTab = rRange.aEnd.Tab();
3898
3899 if (bRecord && !pDoc->IsUndoEnabled())
3900 bRecord = sal_False;
3901
3902 ScMarkData aMark;
3903 if (pTabMark)
3904 aMark = *pTabMark;
3905 else
3906 {
3907 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
3908 aMark.SelectTable( nTab, sal_True );
3909 }
3910
3911 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
3912 if ( aTester.IsEditable() )
3913 {
3914 WaitObject aWait( rDocShell.GetActiveDialogParent() );
3915 pDoc->SetDirty( rRange );
3916 if ( bRecord )
3917 {
3918 //! auch bei Undo selektierte Tabellen beruecksichtigen
3919 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
3920 pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
3921 pDoc->CopyToDocument( rRange, IDF_ALL & ~IDF_NOTE, sal_False, pUndoDoc );
3922
3923 rDocShell.GetUndoManager()->AddUndoAction(
3924 new ScUndoTabOp( &rDocShell,
3925 nStartCol, nStartRow, nStartTab,
3926 nEndCol, nEndRow, nEndTab, pUndoDoc,
3927 rParam.aRefFormulaCell,
3928 rParam.aRefFormulaEnd,
3929 rParam.aRefRowCell,
3930 rParam.aRefColCell,
3931 rParam.nMode) );
3932 }
3933 pDoc->InsertTableOp(rParam, nStartCol, nStartRow, nEndCol, nEndRow, aMark);
3934 rDocShell.PostPaintGridAll();
3935 aModificator.SetDocumentModified();
3936 bSuccess = sal_True;
3937 }
3938 else if (!bApi)
3939 rDocShell.ErrorMessage(aTester.GetMessageId());
3940
3941 return bSuccess;
3942 }
3943
3944 //------------------------------------------------------------------------
3945
DirFromFillDir(FillDir eDir)3946 inline ScDirection DirFromFillDir( FillDir eDir )
3947 {
3948 if (eDir==FILL_TO_BOTTOM)
3949 return DIR_BOTTOM;
3950 else if (eDir==FILL_TO_RIGHT)
3951 return DIR_RIGHT;
3952 else if (eDir==FILL_TO_TOP)
3953 return DIR_TOP;
3954 else // if (eDir==FILL_TO_LEFT)
3955 return DIR_LEFT;
3956 }
3957
FillSimple(const ScRange & rRange,const ScMarkData * pTabMark,FillDir eDir,sal_Bool bRecord,sal_Bool bApi)3958 sal_Bool ScDocFunc::FillSimple( const ScRange& rRange, const ScMarkData* pTabMark,
3959 FillDir eDir, sal_Bool bRecord, sal_Bool bApi )
3960 {
3961 ScDocShellModificator aModificator( rDocShell );
3962
3963 sal_Bool bSuccess = sal_False;
3964 ScDocument* pDoc = rDocShell.GetDocument();
3965 SCCOL nStartCol = rRange.aStart.Col();
3966 SCROW nStartRow = rRange.aStart.Row();
3967 SCTAB nStartTab = rRange.aStart.Tab();
3968 SCCOL nEndCol = rRange.aEnd.Col();
3969 SCROW nEndRow = rRange.aEnd.Row();
3970 SCTAB nEndTab = rRange.aEnd.Tab();
3971
3972 if (bRecord && !pDoc->IsUndoEnabled())
3973 bRecord = sal_False;
3974
3975 ScMarkData aMark;
3976 if (pTabMark)
3977 aMark = *pTabMark;
3978 else
3979 {
3980 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
3981 aMark.SelectTable( nTab, sal_True );
3982 }
3983
3984 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
3985 if ( aTester.IsEditable() )
3986 {
3987 WaitObject aWait( rDocShell.GetActiveDialogParent() );
3988
3989 ScRange aSourceArea = rRange;
3990 ScRange aDestArea = rRange;
3991
3992 SCCOLROW nCount = 0;
3993 switch (eDir)
3994 {
3995 case FILL_TO_BOTTOM:
3996 nCount = aSourceArea.aEnd.Row()-aSourceArea.aStart.Row();
3997 aSourceArea.aEnd.SetRow( aSourceArea.aStart.Row() );
3998 break;
3999 case FILL_TO_RIGHT:
4000 nCount = aSourceArea.aEnd.Col()-aSourceArea.aStart.Col();
4001 aSourceArea.aEnd.SetCol( aSourceArea.aStart.Col() );
4002 break;
4003 case FILL_TO_TOP:
4004 nCount = aSourceArea.aEnd.Row()-aSourceArea.aStart.Row();
4005 aSourceArea.aStart.SetRow( aSourceArea.aEnd.Row() );
4006 break;
4007 case FILL_TO_LEFT:
4008 nCount = aSourceArea.aEnd.Col()-aSourceArea.aStart.Col();
4009 aSourceArea.aStart.SetCol( aSourceArea.aEnd.Col() );
4010 break;
4011 }
4012
4013 ScDocument* pUndoDoc = NULL;
4014 if ( bRecord )
4015 {
4016 SCTAB nTabCount = pDoc->GetTableCount();
4017 SCTAB nDestStartTab = aDestArea.aStart.Tab();
4018
4019 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4020 pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab );
4021 for (SCTAB i=0; i<nTabCount; i++)
4022 if (i != nDestStartTab && aMark.GetTableSelect(i))
4023 pUndoDoc->AddUndoTab( i, i );
4024
4025 ScRange aCopyRange = aDestArea;
4026 aCopyRange.aStart.SetTab(0);
4027 aCopyRange.aEnd.SetTab(nTabCount-1);
4028 pDoc->CopyToDocument( aCopyRange, IDF_AUTOFILL, sal_False, pUndoDoc, &aMark );
4029 }
4030
4031 pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(),
4032 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark,
4033 nCount, eDir, FILL_SIMPLE );
4034 AdjustRowHeight(rRange);
4035
4036 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
4037 {
4038 rDocShell.GetUndoManager()->AddUndoAction(
4039 new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
4040 eDir, FILL_SIMPLE, FILL_DAY, MAXDOUBLE, 1.0, 1e307,
4041 pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) );
4042 }
4043
4044 rDocShell.PostPaintGridAll();
4045 // rDocShell.PostPaintDataChanged();
4046 aModificator.SetDocumentModified();
4047
4048 bSuccess = sal_True;
4049 }
4050 else if (!bApi)
4051 rDocShell.ErrorMessage(aTester.GetMessageId());
4052
4053 return bSuccess;
4054 }
4055
FillSeries(const ScRange & rRange,const ScMarkData * pTabMark,FillDir eDir,FillCmd eCmd,FillDateCmd eDateCmd,double fStart,double fStep,double fMax,sal_Bool bRecord,sal_Bool bApi)4056 sal_Bool ScDocFunc::FillSeries( const ScRange& rRange, const ScMarkData* pTabMark,
4057 FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd,
4058 double fStart, double fStep, double fMax,
4059 sal_Bool bRecord, sal_Bool bApi )
4060 {
4061 ScDocShellModificator aModificator( rDocShell );
4062
4063 sal_Bool bSuccess = sal_False;
4064 ScDocument* pDoc = rDocShell.GetDocument();
4065 SCCOL nStartCol = rRange.aStart.Col();
4066 SCROW nStartRow = rRange.aStart.Row();
4067 SCTAB nStartTab = rRange.aStart.Tab();
4068 SCCOL nEndCol = rRange.aEnd.Col();
4069 SCROW nEndRow = rRange.aEnd.Row();
4070 SCTAB nEndTab = rRange.aEnd.Tab();
4071
4072 if (bRecord && !pDoc->IsUndoEnabled())
4073 bRecord = sal_False;
4074
4075 ScMarkData aMark;
4076 if (pTabMark)
4077 aMark = *pTabMark;
4078 else
4079 {
4080 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
4081 aMark.SelectTable( nTab, sal_True );
4082 }
4083
4084 ScEditableTester aTester( pDoc, nStartCol,nStartRow, nEndCol,nEndRow, aMark );
4085 if ( aTester.IsEditable() )
4086 {
4087 WaitObject aWait( rDocShell.GetActiveDialogParent() );
4088
4089 ScRange aSourceArea = rRange;
4090 ScRange aDestArea = rRange;
4091
4092 SCSIZE nCount = pDoc->GetEmptyLinesInBlock(
4093 aSourceArea.aStart.Col(), aSourceArea.aStart.Row(), aSourceArea.aStart.Tab(),
4094 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aSourceArea.aEnd.Tab(),
4095 DirFromFillDir(eDir) );
4096
4097 // #27665# mindestens eine Zeile/Spalte als Quellbereich behalten:
4098 SCSIZE nTotLines = ( eDir == FILL_TO_BOTTOM || eDir == FILL_TO_TOP ) ?
4099 static_cast<SCSIZE>( aSourceArea.aEnd.Row() - aSourceArea.aStart.Row() + 1 ) :
4100 static_cast<SCSIZE>( aSourceArea.aEnd.Col() - aSourceArea.aStart.Col() + 1 );
4101 if ( nCount >= nTotLines )
4102 nCount = nTotLines - 1;
4103
4104 switch (eDir)
4105 {
4106 case FILL_TO_BOTTOM:
4107 aSourceArea.aEnd.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aEnd.Row() - nCount ) );
4108 break;
4109 case FILL_TO_RIGHT:
4110 aSourceArea.aEnd.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aEnd.Col() - nCount ) );
4111 break;
4112 case FILL_TO_TOP:
4113 aSourceArea.aStart.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aStart.Row() + nCount ) );
4114 break;
4115 case FILL_TO_LEFT:
4116 aSourceArea.aStart.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aStart.Col() + nCount ) );
4117 break;
4118 }
4119
4120 ScDocument* pUndoDoc = NULL;
4121 if ( bRecord )
4122 {
4123 SCTAB nTabCount = pDoc->GetTableCount();
4124 SCTAB nDestStartTab = aDestArea.aStart.Tab();
4125
4126 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4127 pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab );
4128 for (SCTAB i=0; i<nTabCount; i++)
4129 if (i != nDestStartTab && aMark.GetTableSelect(i))
4130 pUndoDoc->AddUndoTab( i, i );
4131
4132 pDoc->CopyToDocument(
4133 aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0,
4134 aDestArea.aEnd.Col(), aDestArea.aEnd.Row(), nTabCount-1,
4135 IDF_AUTOFILL, sal_False, pUndoDoc, &aMark );
4136 }
4137
4138 if (aDestArea.aStart.Col() <= aDestArea.aEnd.Col() &&
4139 aDestArea.aStart.Row() <= aDestArea.aEnd.Row())
4140 {
4141 if ( fStart != MAXDOUBLE )
4142 {
4143 SCCOL nValX = (eDir == FILL_TO_LEFT) ? aDestArea.aEnd.Col() : aDestArea.aStart.Col();
4144 SCROW nValY = (eDir == FILL_TO_TOP ) ? aDestArea.aEnd.Row() : aDestArea.aStart.Row();
4145 SCTAB nTab = aDestArea.aStart.Tab();
4146 pDoc->SetValue( nValX, nValY, nTab, fStart );
4147 }
4148 pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(),
4149 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark,
4150 nCount, eDir, eCmd, eDateCmd, fStep, fMax );
4151 AdjustRowHeight(rRange);
4152
4153 rDocShell.PostPaintGridAll();
4154 // rDocShell.PostPaintDataChanged();
4155 aModificator.SetDocumentModified();
4156 }
4157
4158 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
4159 {
4160 rDocShell.GetUndoManager()->AddUndoAction(
4161 new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
4162 eDir, eCmd, eDateCmd, fStart, fStep, fMax,
4163 pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) );
4164 }
4165
4166 bSuccess = sal_True;
4167 }
4168 else if (!bApi)
4169 rDocShell.ErrorMessage(aTester.GetMessageId());
4170
4171 return bSuccess;
4172 }
4173
FillAuto(ScRange & rRange,const ScMarkData * pTabMark,FillDir eDir,sal_uLong nCount,sal_Bool bRecord,sal_Bool bApi)4174 sal_Bool ScDocFunc::FillAuto( ScRange& rRange, const ScMarkData* pTabMark,
4175 FillDir eDir, sal_uLong nCount, sal_Bool bRecord, sal_Bool bApi )
4176 {
4177 ScDocShellModificator aModificator( rDocShell );
4178
4179 ScDocument* pDoc = rDocShell.GetDocument();
4180 SCCOL nStartCol = rRange.aStart.Col();
4181 SCROW nStartRow = rRange.aStart.Row();
4182 SCTAB nStartTab = rRange.aStart.Tab();
4183 SCCOL nEndCol = rRange.aEnd.Col();
4184 SCROW nEndRow = rRange.aEnd.Row();
4185 SCTAB nEndTab = rRange.aEnd.Tab();
4186
4187 if (bRecord && !pDoc->IsUndoEnabled())
4188 bRecord = sal_False;
4189
4190 ScMarkData aMark;
4191 if (pTabMark)
4192 aMark = *pTabMark;
4193 else
4194 {
4195 for (SCTAB nTab=nStartTab; nTab<=nEndTab; nTab++)
4196 aMark.SelectTable( nTab, sal_True );
4197 }
4198
4199 ScRange aSourceArea = rRange;
4200 ScRange aDestArea = rRange;
4201
4202 FillCmd eCmd = FILL_AUTO;
4203 FillDateCmd eDateCmd = FILL_DAY;
4204 double fStep = 1.0;
4205 double fMax = MAXDOUBLE;
4206
4207 switch (eDir)
4208 {
4209 case FILL_TO_BOTTOM:
4210 aDestArea.aEnd.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aEnd.Row() + nCount ) );
4211 break;
4212 case FILL_TO_TOP:
4213 if (nCount > sal::static_int_cast<sal_uLong>( aSourceArea.aStart.Row() ))
4214 {
4215 DBG_ERROR("FillAuto: Row < 0");
4216 nCount = aSourceArea.aStart.Row();
4217 }
4218 aDestArea.aStart.SetRow( sal::static_int_cast<SCROW>( aSourceArea.aStart.Row() - nCount ) );
4219 break;
4220 case FILL_TO_RIGHT:
4221 aDestArea.aEnd.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aEnd.Col() + nCount ) );
4222 break;
4223 case FILL_TO_LEFT:
4224 if (nCount > sal::static_int_cast<sal_uLong>( aSourceArea.aStart.Col() ))
4225 {
4226 DBG_ERROR("FillAuto: Col < 0");
4227 nCount = aSourceArea.aStart.Col();
4228 }
4229 aDestArea.aStart.SetCol( sal::static_int_cast<SCCOL>( aSourceArea.aStart.Col() - nCount ) );
4230 break;
4231 default:
4232 DBG_ERROR("Falsche Richtung bei FillAuto");
4233 break;
4234 }
4235
4236 // Zellschutz testen
4237 //! Quellbereich darf geschuetzt sein !!!
4238 //! aber kein Matrixfragment enthalten !!!
4239
4240 ScEditableTester aTester( pDoc, aDestArea );
4241 if ( !aTester.IsEditable() )
4242 {
4243 if (!bApi)
4244 rDocShell.ErrorMessage(aTester.GetMessageId());
4245 return sal_False;
4246 }
4247
4248 if ( pDoc->HasSelectedBlockMatrixFragment( nStartCol, nStartRow,
4249 nEndCol, nEndRow, aMark ) )
4250 {
4251 if (!bApi)
4252 rDocShell.ErrorMessage(STR_MATRIXFRAGMENTERR);
4253 return sal_False;
4254 }
4255
4256 WaitObject aWait( rDocShell.GetActiveDialogParent() );
4257
4258 ScDocument* pUndoDoc = NULL;
4259 if ( bRecord )
4260 {
4261 SCTAB nTabCount = pDoc->GetTableCount();
4262 SCTAB nDestStartTab = aDestArea.aStart.Tab();
4263
4264 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4265 pUndoDoc->InitUndo( pDoc, nDestStartTab, nDestStartTab );
4266 for (SCTAB i=0; i<nTabCount; i++)
4267 if (i != nDestStartTab && aMark.GetTableSelect(i))
4268 pUndoDoc->AddUndoTab( i, i );
4269
4270 // do not clone note captions in undo document
4271 pDoc->CopyToDocument(
4272 aDestArea.aStart.Col(), aDestArea.aStart.Row(), 0,
4273 aDestArea.aEnd.Col(), aDestArea.aEnd.Row(), nTabCount-1,
4274 IDF_AUTOFILL, sal_False, pUndoDoc, &aMark );
4275 }
4276
4277 pDoc->Fill( aSourceArea.aStart.Col(), aSourceArea.aStart.Row(),
4278 aSourceArea.aEnd.Col(), aSourceArea.aEnd.Row(), aMark,
4279 nCount, eDir, eCmd, eDateCmd, fStep, fMax );
4280
4281 AdjustRowHeight(aDestArea);
4282
4283 if ( bRecord ) // Draw-Undo erst jetzt verfuegbar
4284 {
4285 rDocShell.GetUndoManager()->AddUndoAction(
4286 new ScUndoAutoFill( &rDocShell, aDestArea, aSourceArea, pUndoDoc, aMark,
4287 eDir, eCmd, eDateCmd, MAXDOUBLE, fStep, fMax,
4288 pDoc->GetRangeName()->GetSharedMaxIndex()+1 ) );
4289 }
4290
4291 rDocShell.PostPaintGridAll();
4292 // rDocShell.PostPaintDataChanged();
4293 aModificator.SetDocumentModified();
4294
4295 rRange = aDestArea; // Zielbereich zurueckgeben (zum Markieren)
4296 return sal_True;
4297 }
4298
4299 //------------------------------------------------------------------------
4300
MergeCells(const ScRange & rRange,sal_Bool bContents,sal_Bool bRecord,sal_Bool bApi)4301 sal_Bool ScDocFunc::MergeCells( const ScRange& rRange, sal_Bool bContents, sal_Bool bRecord, sal_Bool bApi )
4302 {
4303 ScDocShellModificator aModificator( rDocShell );
4304
4305 ScDocument* pDoc = rDocShell.GetDocument();
4306 SCCOL nStartCol = rRange.aStart.Col();
4307 SCROW nStartRow = rRange.aStart.Row();
4308 SCCOL nEndCol = rRange.aEnd.Col();
4309 SCROW nEndRow = rRange.aEnd.Row();
4310 SCTAB nTab = rRange.aStart.Tab();
4311
4312 if (bRecord && !pDoc->IsUndoEnabled())
4313 bRecord = sal_False;
4314
4315 ScEditableTester aTester( pDoc, nTab, nStartCol, nStartRow, nEndCol, nEndRow );
4316 if (!aTester.IsEditable())
4317 {
4318 if (!bApi)
4319 rDocShell.ErrorMessage(aTester.GetMessageId());
4320 return sal_False;
4321 }
4322
4323 if ( nStartCol == nEndCol && nStartRow == nEndRow )
4324 {
4325 // nichts zu tun
4326 return sal_True;
4327 }
4328
4329 if ( pDoc->HasAttrib( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab,
4330 HASATTR_MERGED | HASATTR_OVERLAPPED ) )
4331 {
4332 // "Zusammenfassen nicht verschachteln !"
4333 if (!bApi)
4334 rDocShell.ErrorMessage(STR_MSSG_MERGECELLS_0);
4335 return sal_False;
4336 }
4337
4338 sal_Bool bNeedContents = bContents &&
4339 ( !pDoc->IsBlockEmpty( nTab, nStartCol,nStartRow+1, nStartCol,nEndRow, true ) ||
4340 !pDoc->IsBlockEmpty( nTab, nStartCol+1,nStartRow, nEndCol,nEndRow, true ) );
4341
4342 ScDocument* pUndoDoc = 0;
4343 if (bRecord)
4344 {
4345 // test if the range contains other notes which also implies that we need an undo document
4346 bool bHasNotes = false;
4347 for( ScAddress aPos( nStartCol, nStartRow, nTab ); !bHasNotes && (aPos.Col() <= nEndCol); aPos.IncCol() )
4348 for( aPos.SetRow( nStartRow ); !bHasNotes && (aPos.Row() <= nEndRow); aPos.IncRow() )
4349 bHasNotes = ((aPos.Col() != nStartCol) || (aPos.Row() != nStartRow)) && (pDoc->GetNote( aPos ) != 0);
4350
4351 if (bNeedContents || bHasNotes)
4352 {
4353 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4354 pUndoDoc->InitUndo( pDoc, nTab, nTab );
4355 // note captions are collected by drawing undo
4356 pDoc->CopyToDocument( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab,
4357 IDF_ALL|IDF_NOCAPTIONS, sal_False, pUndoDoc );
4358 }
4359 if( bHasNotes )
4360 pDoc->BeginDrawUndo();
4361 }
4362
4363 if (bNeedContents)
4364 pDoc->DoMergeContents( nTab, nStartCol,nStartRow, nEndCol,nEndRow );
4365 pDoc->DoMerge( nTab, nStartCol,nStartRow, nEndCol,nEndRow );
4366
4367 if( bRecord )
4368 {
4369 SdrUndoGroup* pDrawUndo = pDoc->GetDrawLayer() ? pDoc->GetDrawLayer()->GetCalcUndo() : 0;
4370 rDocShell.GetUndoManager()->AddUndoAction(
4371 new ScUndoMerge( &rDocShell,
4372 nStartCol, nStartRow, nTab,
4373 nEndCol, nEndRow, nTab, bNeedContents, pUndoDoc, pDrawUndo ) );
4374 }
4375
4376 if ( !AdjustRowHeight( ScRange( 0,nStartRow,nTab, MAXCOL,nEndRow,nTab ) ) )
4377 rDocShell.PostPaint( nStartCol, nStartRow, nTab,
4378 nEndCol, nEndRow, nTab, PAINT_GRID );
4379 if (bNeedContents)
4380 pDoc->SetDirty( rRange );
4381 aModificator.SetDocumentModified();
4382
4383 SfxBindings* pBindings = rDocShell.GetViewBindings();
4384 if (pBindings)
4385 {
4386 pBindings->Invalidate( FID_MERGE_ON );
4387 pBindings->Invalidate( FID_MERGE_OFF );
4388 pBindings->Invalidate( FID_MERGE_TOGGLE );
4389 }
4390
4391 return sal_True;
4392 }
4393
UnmergeCells(const ScRange & rRange,sal_Bool bRecord,sal_Bool bApi)4394 sal_Bool ScDocFunc::UnmergeCells( const ScRange& rRange, sal_Bool bRecord, sal_Bool bApi )
4395 {
4396 ScDocShellModificator aModificator( rDocShell );
4397
4398 ScDocument* pDoc = rDocShell.GetDocument();
4399 SCTAB nTab = rRange.aStart.Tab();
4400
4401 if (bRecord && !pDoc->IsUndoEnabled())
4402 bRecord = sal_False;
4403
4404 if ( pDoc->HasAttrib( rRange, HASATTR_MERGED ) )
4405 {
4406 ScRange aExtended = rRange;
4407 pDoc->ExtendMerge( aExtended );
4408 ScRange aRefresh = aExtended;
4409 pDoc->ExtendOverlapped( aRefresh );
4410
4411 if (bRecord)
4412 {
4413 ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4414 pUndoDoc->InitUndo( pDoc, nTab, nTab );
4415 pDoc->CopyToDocument( aExtended, IDF_ATTRIB, sal_False, pUndoDoc );
4416 rDocShell.GetUndoManager()->AddUndoAction(
4417 new ScUndoRemoveMerge( &rDocShell, rRange, pUndoDoc ) );
4418 }
4419
4420 const SfxPoolItem& rDefAttr = pDoc->GetPool()->GetDefaultItem( ATTR_MERGE );
4421 ScPatternAttr aPattern( pDoc->GetPool() );
4422 aPattern.GetItemSet().Put( rDefAttr );
4423 pDoc->ApplyPatternAreaTab( rRange.aStart.Col(), rRange.aStart.Row(),
4424 rRange.aEnd.Col(), rRange.aEnd.Row(), nTab,
4425 aPattern );
4426
4427 pDoc->RemoveFlagsTab( aExtended.aStart.Col(), aExtended.aStart.Row(),
4428 aExtended.aEnd.Col(), aExtended.aEnd.Row(), nTab,
4429 SC_MF_HOR | SC_MF_VER );
4430
4431 pDoc->ExtendMerge( aRefresh, sal_True, sal_False );
4432
4433 if ( !AdjustRowHeight( aExtended ) )
4434 rDocShell.PostPaint( aExtended, PAINT_GRID );
4435 aModificator.SetDocumentModified();
4436 }
4437 else if (!bApi)
4438 Sound::Beep(); //! sal_False zurueck???
4439
4440 return sal_True;
4441 }
4442
4443 //------------------------------------------------------------------------
4444
ModifyRangeNames(const ScRangeName & rNewRanges,sal_Bool bApi)4445 sal_Bool ScDocFunc::ModifyRangeNames( const ScRangeName& rNewRanges, sal_Bool bApi )
4446 {
4447 return SetNewRangeNames( new ScRangeName( rNewRanges ), bApi );
4448 }
4449
SetNewRangeNames(ScRangeName * pNewRanges,sal_Bool)4450 sal_Bool ScDocFunc::SetNewRangeNames( ScRangeName* pNewRanges, sal_Bool /* bApi */ ) // takes ownership of pNewRanges
4451 {
4452 ScDocShellModificator aModificator( rDocShell );
4453
4454 DBG_ASSERT( pNewRanges, "pNewRanges is 0" );
4455 ScDocument* pDoc = rDocShell.GetDocument();
4456 sal_Bool bUndo(pDoc->IsUndoEnabled());
4457
4458 if (bUndo)
4459 {
4460 ScRangeName* pOld = pDoc->GetRangeName();
4461 ScRangeName* pUndoRanges = new ScRangeName(*pOld);
4462 ScRangeName* pRedoRanges = new ScRangeName(*pNewRanges);
4463 rDocShell.GetUndoManager()->AddUndoAction(
4464 new ScUndoRangeNames( &rDocShell, pUndoRanges, pRedoRanges ) );
4465 }
4466
4467 // #i55926# While loading XML, formula cells only have a single string token,
4468 // so CompileNameFormula would never find any name (index) tokens, and would
4469 // unnecessarily loop through all cells.
4470 sal_Bool bCompile = ( !pDoc->IsImportingXML() && pDoc->GetNamedRangesLockCount() == 0 );
4471
4472 if ( bCompile )
4473 pDoc->CompileNameFormula( sal_True ); // CreateFormulaString
4474 pDoc->SetRangeName( pNewRanges ); // takes ownership
4475 if ( bCompile )
4476 pDoc->CompileNameFormula( sal_False ); // CompileFormulaString
4477
4478 aModificator.SetDocumentModified();
4479
4480 // #i114072# don't broadcast while loading a file
4481 // (navigator and input line for other open documents would be notified)
4482 if ( bCompile )
4483 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
4484
4485 return sal_True;
4486 }
4487
4488 //------------------------------------------------------------------------
4489
CreateOneName(ScRangeName & rList,SCCOL nPosX,SCROW nPosY,SCTAB nTab,SCCOL nX1,SCROW nY1,SCCOL nX2,SCROW nY2,sal_Bool & rCancel,sal_Bool bApi)4490 void ScDocFunc::CreateOneName( ScRangeName& rList,
4491 SCCOL nPosX, SCROW nPosY, SCTAB nTab,
4492 SCCOL nX1, SCROW nY1, SCCOL nX2, SCROW nY2,
4493 sal_Bool& rCancel, sal_Bool bApi )
4494 {
4495 if (rCancel)
4496 return;
4497
4498 ScDocument* pDoc = rDocShell.GetDocument();
4499 if (!pDoc->HasValueData( nPosX, nPosY, nTab ))
4500 {
4501 String aName;
4502 pDoc->GetString( nPosX, nPosY, nTab, aName );
4503 ScRangeData::MakeValidName(aName);
4504 if (aName.Len())
4505 {
4506 String aContent;
4507 ScRange( nX1, nY1, nTab, nX2, nY2, nTab ).Format( aContent, SCR_ABS_3D, pDoc );
4508
4509 sal_Bool bInsert = sal_False;
4510 sal_uInt16 nOldPos;
4511 if (rList.SearchName( aName, nOldPos )) // vorhanden ?
4512 {
4513 ScRangeData* pOld = rList[nOldPos];
4514 String aOldStr;
4515 pOld->GetSymbol( aOldStr );
4516 if (aOldStr != aContent)
4517 {
4518 if (bApi)
4519 bInsert = sal_True; // per API nicht nachfragen
4520 else
4521 {
4522 String aTemplate = ScGlobal::GetRscString( STR_CREATENAME_REPLACE );
4523
4524 String aMessage = aTemplate.GetToken( 0, '#' );
4525 aMessage += aName;
4526 aMessage += aTemplate.GetToken( 1, '#' );
4527
4528 short nResult = QueryBox( rDocShell.GetActiveDialogParent(),
4529 WinBits(WB_YES_NO_CANCEL | WB_DEF_YES),
4530 aMessage ).Execute();
4531 if ( nResult == RET_YES )
4532 {
4533 rList.AtFree(nOldPos);
4534 bInsert = sal_True;
4535 }
4536 else if ( nResult == RET_CANCEL )
4537 rCancel = sal_True;
4538 }
4539 }
4540 }
4541 else
4542 bInsert = sal_True;
4543
4544 if (bInsert)
4545 {
4546 ScRangeData* pData = new ScRangeData( pDoc, aName, aContent,
4547 ScAddress( nPosX, nPosY, nTab));
4548 if (!rList.Insert(pData))
4549 {
4550 DBG_ERROR("nanu?");
4551 delete pData;
4552 }
4553 }
4554 }
4555 }
4556 }
4557
CreateNames(const ScRange & rRange,sal_uInt16 nFlags,sal_Bool bApi)4558 sal_Bool ScDocFunc::CreateNames( const ScRange& rRange, sal_uInt16 nFlags, sal_Bool bApi )
4559 {
4560 if (!nFlags)
4561 return sal_False; // war nix
4562
4563 ScDocShellModificator aModificator( rDocShell );
4564
4565 sal_Bool bDone = sal_False;
4566 SCCOL nStartCol = rRange.aStart.Col();
4567 SCROW nStartRow = rRange.aStart.Row();
4568 SCCOL nEndCol = rRange.aEnd.Col();
4569 SCROW nEndRow = rRange.aEnd.Row();
4570 SCTAB nTab = rRange.aStart.Tab();
4571 DBG_ASSERT(rRange.aEnd.Tab() == nTab, "CreateNames: mehrere Tabellen geht nicht");
4572
4573 sal_Bool bValid = sal_True;
4574 if ( nFlags & ( NAME_TOP | NAME_BOTTOM ) )
4575 if ( nStartRow == nEndRow )
4576 bValid = sal_False;
4577 if ( nFlags & ( NAME_LEFT | NAME_RIGHT ) )
4578 if ( nStartCol == nEndCol )
4579 bValid = sal_False;
4580
4581 if (bValid)
4582 {
4583 ScDocument* pDoc = rDocShell.GetDocument();
4584 ScRangeName* pNames = pDoc->GetRangeName();
4585 if (!pNames)
4586 return sal_False; // soll nicht sein
4587 ScRangeName aNewRanges( *pNames );
4588
4589 sal_Bool bTop = ( ( nFlags & NAME_TOP ) != 0 );
4590 sal_Bool bLeft = ( ( nFlags & NAME_LEFT ) != 0 );
4591 sal_Bool bBottom = ( ( nFlags & NAME_BOTTOM ) != 0 );
4592 sal_Bool bRight = ( ( nFlags & NAME_RIGHT ) != 0 );
4593
4594 SCCOL nContX1 = nStartCol;
4595 SCROW nContY1 = nStartRow;
4596 SCCOL nContX2 = nEndCol;
4597 SCROW nContY2 = nEndRow;
4598
4599 if ( bTop )
4600 ++nContY1;
4601 if ( bLeft )
4602 ++nContX1;
4603 if ( bBottom )
4604 --nContY2;
4605 if ( bRight )
4606 --nContX2;
4607
4608 sal_Bool bCancel = sal_False;
4609 SCCOL i;
4610 SCROW j;
4611
4612 if ( bTop )
4613 for (i=nContX1; i<=nContX2; i++)
4614 CreateOneName( aNewRanges, i,nStartRow,nTab, i,nContY1,i,nContY2, bCancel, bApi );
4615 if ( bLeft )
4616 for (j=nContY1; j<=nContY2; j++)
4617 CreateOneName( aNewRanges, nStartCol,j,nTab, nContX1,j,nContX2,j, bCancel, bApi );
4618 if ( bBottom )
4619 for (i=nContX1; i<=nContX2; i++)
4620 CreateOneName( aNewRanges, i,nEndRow,nTab, i,nContY1,i,nContY2, bCancel, bApi );
4621 if ( bRight )
4622 for (j=nContY1; j<=nContY2; j++)
4623 CreateOneName( aNewRanges, nEndCol,j,nTab, nContX1,j,nContX2,j, bCancel, bApi );
4624
4625 if ( bTop && bLeft )
4626 CreateOneName( aNewRanges, nStartCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
4627 if ( bTop && bRight )
4628 CreateOneName( aNewRanges, nEndCol,nStartRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
4629 if ( bBottom && bLeft )
4630 CreateOneName( aNewRanges, nStartCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
4631 if ( bBottom && bRight )
4632 CreateOneName( aNewRanges, nEndCol,nEndRow,nTab, nContX1,nContY1,nContX2,nContY2, bCancel, bApi );
4633
4634 bDone = ModifyRangeNames( aNewRanges, bApi );
4635
4636 aModificator.SetDocumentModified();
4637 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
4638 }
4639
4640 return bDone;
4641 }
4642
4643 //------------------------------------------------------------------------
4644
InsertNameList(const ScAddress & rStartPos,sal_Bool bApi)4645 sal_Bool ScDocFunc::InsertNameList( const ScAddress& rStartPos, sal_Bool bApi )
4646 {
4647 ScDocShellModificator aModificator( rDocShell );
4648
4649
4650 sal_Bool bDone = sal_False;
4651 ScDocument* pDoc = rDocShell.GetDocument();
4652 const sal_Bool bRecord = pDoc->IsUndoEnabled();
4653 SCTAB nTab = rStartPos.Tab();
4654 ScDocument* pUndoDoc = NULL;
4655
4656 ScRangeName* pList = pDoc->GetRangeName();
4657 sal_uInt16 nCount = pList->GetCount();
4658 sal_uInt16 nValidCount = 0;
4659 sal_uInt16 i;
4660 for (i=0; i<nCount; i++)
4661 {
4662 ScRangeData* pData = (*pList)[i];
4663 if ( !pData->HasType( RT_DATABASE ) && !pData->HasType( RT_SHARED ) )
4664 ++nValidCount;
4665 }
4666
4667 if (nValidCount)
4668 {
4669 SCCOL nStartCol = rStartPos.Col();
4670 SCROW nStartRow = rStartPos.Row();
4671 SCCOL nEndCol = nStartCol + 1;
4672 SCROW nEndRow = nStartRow + static_cast<SCROW>(nValidCount) - 1;
4673
4674 ScEditableTester aTester( pDoc, nTab, nStartCol,nStartRow, nEndCol,nEndRow );
4675 if (aTester.IsEditable())
4676 {
4677 if (bRecord)
4678 {
4679 pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
4680 pUndoDoc->InitUndo( pDoc, nTab, nTab );
4681 pDoc->CopyToDocument( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab,
4682 IDF_ALL, sal_False, pUndoDoc );
4683
4684 pDoc->BeginDrawUndo(); // wegen Hoehenanpassung
4685 }
4686
4687 ScRangeData** ppSortArray = new ScRangeData* [ nValidCount ];
4688 sal_uInt16 j = 0;
4689 for (i=0; i<nCount; i++)
4690 {
4691 ScRangeData* pData = (*pList)[i];
4692 if ( !pData->HasType( RT_DATABASE ) && !pData->HasType( RT_SHARED ) )
4693 ppSortArray[j++] = pData;
4694 }
4695 #ifndef ICC
4696 qsort( (void*)ppSortArray, nValidCount, sizeof(ScRangeData*),
4697 &ScRangeData_QsortNameCompare );
4698 #else
4699 qsort( (void*)ppSortArray, nValidCount, sizeof(ScRangeData*),
4700 ICCQsortNameCompare );
4701 #endif
4702 String aName;
4703 rtl::OUStringBuffer aContent;
4704 String aFormula;
4705 SCROW nOutRow = nStartRow;
4706 for (j=0; j<nValidCount; j++)
4707 {
4708 ScRangeData* pData = ppSortArray[j];
4709 pData->GetName(aName);
4710 // relative Referenzen Excel-konform auf die linke Spalte anpassen:
4711 pData->UpdateSymbol(aContent, ScAddress( nStartCol, nOutRow, nTab ));
4712 aFormula = '=';
4713 aFormula += aContent;
4714 pDoc->PutCell( nStartCol,nOutRow,nTab, new ScStringCell( aName ) );
4715 pDoc->PutCell( nEndCol ,nOutRow,nTab, new ScStringCell( aFormula ) );
4716 ++nOutRow;
4717 }
4718
4719 delete [] ppSortArray;
4720
4721 if (bRecord)
4722 {
4723 ScDocument* pRedoDoc = new ScDocument( SCDOCMODE_UNDO );
4724 pRedoDoc->InitUndo( pDoc, nTab, nTab );
4725 pDoc->CopyToDocument( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab,
4726 IDF_ALL, sal_False, pRedoDoc );
4727
4728 rDocShell.GetUndoManager()->AddUndoAction(
4729 new ScUndoListNames( &rDocShell,
4730 ScRange( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab ),
4731 pUndoDoc, pRedoDoc ) );
4732 }
4733
4734 if (!AdjustRowHeight(ScRange(0,nStartRow,nTab,MAXCOL,nEndRow,nTab)))
4735 rDocShell.PostPaint( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab, PAINT_GRID );
4736 //! rDocShell.UpdateOle(GetViewData());
4737 aModificator.SetDocumentModified();
4738 bDone = sal_True;
4739 }
4740 else if (!bApi)
4741 rDocShell.ErrorMessage(aTester.GetMessageId());
4742 }
4743 return bDone;
4744 }
4745
4746 //------------------------------------------------------------------------
4747
ResizeMatrix(const ScRange & rOldRange,const ScAddress & rNewEnd,sal_Bool bApi)4748 sal_Bool ScDocFunc::ResizeMatrix( const ScRange& rOldRange, const ScAddress& rNewEnd, sal_Bool bApi )
4749 {
4750 ScDocument* pDoc = rDocShell.GetDocument();
4751 SCCOL nStartCol = rOldRange.aStart.Col();
4752 SCROW nStartRow = rOldRange.aStart.Row();
4753 SCTAB nTab = rOldRange.aStart.Tab();
4754
4755 sal_Bool bUndo(pDoc->IsUndoEnabled());
4756
4757 sal_Bool bRet = sal_False;
4758
4759 String aFormula;
4760 pDoc->GetFormula( nStartCol, nStartRow, nTab, aFormula );
4761 if ( aFormula.GetChar(0) == '{' && aFormula.GetChar(aFormula.Len()-1) == '}' )
4762 {
4763 String aUndo = ScGlobal::GetRscString( STR_UNDO_RESIZEMATRIX );
4764 if (bUndo)
4765 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
4766
4767 aFormula.Erase(0,1);
4768 aFormula.Erase(aFormula.Len()-1,1);
4769
4770 ScMarkData aMark;
4771 aMark.SetMarkArea( rOldRange );
4772 aMark.SelectTable( nTab, sal_True );
4773 ScRange aNewRange( rOldRange.aStart, rNewEnd );
4774
4775 if ( DeleteContents( aMark, IDF_CONTENTS, sal_True, bApi ) )
4776 {
4777 // GRAM_PODF_A1 for API compatibility.
4778 bRet = EnterMatrix( aNewRange, &aMark, NULL, aFormula, bApi, sal_False, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 );
4779 if (!bRet)
4780 {
4781 // versuchen, alten Zustand wiederherzustellen
4782 EnterMatrix( rOldRange, &aMark, NULL, aFormula, bApi, sal_False, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 );
4783 }
4784 }
4785
4786 if (bUndo)
4787 rDocShell.GetUndoManager()->LeaveListAction();
4788 }
4789
4790 return bRet;
4791 }
4792
4793 //------------------------------------------------------------------------
4794
InsertAreaLink(const String & rFile,const String & rFilter,const String & rOptions,const String & rSource,const ScRange & rDestRange,sal_uLong nRefresh,sal_Bool bFitBlock,sal_Bool bApi)4795 sal_Bool ScDocFunc::InsertAreaLink( const String& rFile, const String& rFilter,
4796 const String& rOptions, const String& rSource,
4797 const ScRange& rDestRange, sal_uLong nRefresh,
4798 sal_Bool bFitBlock, sal_Bool bApi )
4799 {
4800 //! auch fuer ScViewFunc::InsertAreaLink benutzen!
4801
4802 ScDocument* pDoc = rDocShell.GetDocument();
4803 sal_Bool bUndo (pDoc->IsUndoEnabled());
4804
4805 sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
4806
4807 // #i52120# if other area links exist at the same start position,
4808 // remove them first (file format specifies only one link definition
4809 // for a cell)
4810
4811 sal_uInt16 nLinkCount = pLinkManager->GetLinks().Count();
4812 sal_uInt16 nRemoved = 0;
4813 sal_uInt16 nLinkPos = 0;
4814 while (nLinkPos<nLinkCount)
4815 {
4816 ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[nLinkPos];
4817 if ( pBase->ISA(ScAreaLink) &&
4818 static_cast<ScAreaLink*>(pBase)->GetDestArea().aStart == rDestRange.aStart )
4819 {
4820 if ( bUndo )
4821 {
4822 if ( !nRemoved )
4823 {
4824 // group all remove and the insert action
4825 String aUndo = ScGlobal::GetRscString( STR_UNDO_INSERTAREALINK );
4826 rDocShell.GetUndoManager()->EnterListAction( aUndo, aUndo );
4827 }
4828
4829 ScAreaLink* pOldArea = static_cast<ScAreaLink*>(pBase);
4830 rDocShell.GetUndoManager()->AddUndoAction(
4831 new ScUndoRemoveAreaLink( &rDocShell,
4832 pOldArea->GetFile(), pOldArea->GetFilter(), pOldArea->GetOptions(),
4833 pOldArea->GetSource(), pOldArea->GetDestArea(), pOldArea->GetRefreshDelay() ) );
4834 }
4835 pLinkManager->Remove( pBase );
4836 nLinkCount = pLinkManager->GetLinks().Count();
4837 ++nRemoved;
4838 }
4839 else
4840 ++nLinkPos;
4841 }
4842
4843 String aFilterName = rFilter;
4844 String aNewOptions = rOptions;
4845 if (!aFilterName.Len())
4846 ScDocumentLoader::GetFilterName( rFile, aFilterName, aNewOptions, sal_True, !bApi );
4847
4848 // remove application prefix from filter name here, so the filter options
4849 // aren't reset when the filter name is changed in ScAreaLink::DataChanged
4850 ScDocumentLoader::RemoveAppPrefix( aFilterName );
4851
4852 ScAreaLink* pLink = new ScAreaLink( &rDocShell, rFile, aFilterName,
4853 aNewOptions, rSource, rDestRange, nRefresh );
4854 pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, rFile, &aFilterName, &rSource );
4855
4856 // Undo fuer den leeren Link
4857
4858 if (bUndo)
4859 {
4860 rDocShell.GetUndoManager()->AddUndoAction( new ScUndoInsertAreaLink( &rDocShell,
4861 rFile, aFilterName, aNewOptions,
4862 rSource, rDestRange, nRefresh ) );
4863 if ( nRemoved )
4864 rDocShell.GetUndoManager()->LeaveListAction(); // undo for link update is still separate
4865 }
4866
4867 // Update hat sein eigenes Undo
4868 if (pDoc->IsExecuteLinkEnabled())
4869 {
4870 pLink->SetDoInsert(bFitBlock); // beim ersten Update ggf. nichts einfuegen
4871 pLink->Update(); // kein SetInCreate -> Update ausfuehren
4872 }
4873 pLink->SetDoInsert(sal_True); // Default = sal_True
4874
4875 SfxBindings* pBindings = rDocShell.GetViewBindings();
4876 if (pBindings)
4877 pBindings->Invalidate( SID_LINKS );
4878
4879 SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) ); // Navigator
4880
4881 return sal_True;
4882 }
4883
4884 /* vim: set noet sw=4 ts=4: */
4885