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