xref: /trunk/main/sc/source/ui/view/viewfun2.cxx (revision 1ecadb572e7010ff3b3382ad9bf179dbc6efadbb)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_sc.hxx"
30 
31 // INCLUDE ---------------------------------------------------------------
32 
33 #include "scitems.hxx"
34 #include <editeng/eeitem.hxx>
35 
36 #include <sfx2/app.hxx>
37 #define _SVSTDARR_STRINGS
38 #include <editeng/boxitem.hxx>
39 #include <editeng/fontitem.hxx>
40 #include <editeng/scripttypeitem.hxx>
41 #include <svl/srchitem.hxx>
42 #include <sfx2/linkmgr.hxx>
43 #include <sfx2/dispatch.hxx>
44 #include <sfx2/docfilt.hxx>
45 #include <sfx2/docfile.hxx>
46 #include <sfx2/objitem.hxx>
47 #include <sfx2/viewfrm.hxx>
48 #include <svl/stritem.hxx>
49 #include <svl/zforlist.hxx>
50 #include <svl/svstdarr.hxx>
51 #include <vcl/msgbox.hxx>
52 #include <vcl/sound.hxx>
53 #include <vcl/waitobj.hxx>
54 
55 #include "viewfunc.hxx"
56 
57 #include "sc.hrc"
58 #include "globstr.hrc"
59 
60 #include "attrib.hxx"
61 #include "autoform.hxx"
62 #include "cell.hxx"                 // EnterAutoSum
63 #include "compiler.hxx"
64 #include "docfunc.hxx"
65 #include "docpool.hxx"
66 #include "docsh.hxx"
67 #include "global.hxx"
68 #include "patattr.hxx"
69 #include "printfun.hxx"
70 #include "rangenam.hxx"
71 #include "rangeutl.hxx"
72 #include "refundo.hxx"
73 #include "tablink.hxx"
74 #include "tabvwsh.hxx"
75 #include "uiitems.hxx"
76 #include "undoblk.hxx"
77 #include "undocell.hxx"
78 #include "undotab.hxx"
79 #include "sizedev.hxx"
80 #include "editable.hxx"
81 #include "scmod.hxx"
82 #include "inputhdl.hxx"
83 #include "inputwin.hxx"
84 #include "funcdesc.hxx"
85 #include "docuno.hxx"
86 #include "charthelper.hxx"
87 #include "tabbgcolor.hxx"
88 
89 #include <basic/sbstar.hxx>
90 #include <com/sun/star/container/XNameContainer.hpp>
91 #include <com/sun/star/script/XLibraryContainer.hpp>
92 using namespace com::sun::star;
93 
94 // helper func defined in docfunc.cxx
95 void VBA_DeleteModule( ScDocShell& rDocSh, String& sModuleName );
96 
97 // STATIC DATA ---------------------------------------------------------------
98 
99 
100 //----------------------------------------------------------------------------
101 
102 sal_Bool ScViewFunc::AdjustBlockHeight( sal_Bool bPaint, ScMarkData* pMarkData )
103 {
104     ScDocShell* pDocSh = GetViewData()->GetDocShell();
105     if (!pMarkData)
106         pMarkData = &GetViewData()->GetMarkData();
107 
108     ScDocument* pDoc = pDocSh->GetDocument();
109     SCCOLROW* pRanges = new SCCOLROW[MAXCOLROWCOUNT];
110     SCCOLROW nRangeCnt = pMarkData->GetMarkRowRanges( pRanges );
111     if (nRangeCnt == 0)
112     {
113         pRanges[0] = pRanges[1] = GetViewData()->GetCurY();
114         nRangeCnt = 1;
115     }
116 
117     double nPPTX = GetViewData()->GetPPTX();
118     double nPPTY = GetViewData()->GetPPTY();
119     Fraction aZoomX = GetViewData()->GetZoomX();
120     Fraction aZoomY = GetViewData()->GetZoomY();
121 
122     ScSizeDeviceProvider aProv(pDocSh);
123     if (aProv.IsPrinter())
124     {
125         nPPTX = aProv.GetPPTX();
126         nPPTY = aProv.GetPPTY();
127         aZoomX = aZoomY = Fraction( 1, 1 );
128     }
129 
130     sal_Bool bAnyChanged = sal_False;
131     SCTAB nTabCount = pDoc->GetTableCount();
132     for (SCTAB nTab=0; nTab<nTabCount; nTab++)
133     {
134         if (pMarkData->GetTableSelect(nTab))
135         {
136             SCCOLROW* pOneRange = pRanges;
137             sal_Bool bChanged = sal_False;
138             SCROW nPaintY = 0;
139             for (SCROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
140             {
141                 SCROW nStartNo = *(pOneRange++);
142                 SCROW nEndNo = *(pOneRange++);
143                 if (pDoc->SetOptimalHeight( nStartNo, nEndNo, nTab, 0, aProv.GetDevice(),
144                                             nPPTX, nPPTY, aZoomX, aZoomY, sal_False ))
145                 {
146                     if (!bChanged)
147                         nPaintY = nStartNo;
148                     bAnyChanged = bChanged = sal_True;
149                 }
150             }
151             if ( bPaint && bChanged )
152                 pDocSh->PostPaint( 0, nPaintY, nTab, MAXCOL, MAXROW, nTab,
153                                                     PAINT_GRID | PAINT_LEFT );
154         }
155     }
156     delete[] pRanges;
157 
158     if ( bPaint && bAnyChanged )
159         pDocSh->UpdateOle(GetViewData());
160 
161     return bAnyChanged;
162 }
163 
164 
165 //----------------------------------------------------------------------------
166 
167 sal_Bool ScViewFunc::AdjustRowHeight( SCROW nStartRow, SCROW nEndRow, sal_Bool bPaint )
168 {
169     ScDocShell* pDocSh = GetViewData()->GetDocShell();
170     ScDocument* pDoc = pDocSh->GetDocument();
171     SCTAB nTab = GetViewData()->GetTabNo();
172     double nPPTX = GetViewData()->GetPPTX();
173     double nPPTY = GetViewData()->GetPPTY();
174     Fraction aZoomX = GetViewData()->GetZoomX();
175     Fraction aZoomY = GetViewData()->GetZoomY();
176     sal_uInt16 nOldPixel = 0;
177     if (nStartRow == nEndRow)
178         nOldPixel = (sal_uInt16) (pDoc->GetRowHeight(nStartRow,nTab) * nPPTY);
179 
180     ScSizeDeviceProvider aProv(pDocSh);
181     if (aProv.IsPrinter())
182     {
183         nPPTX = aProv.GetPPTX();
184         nPPTY = aProv.GetPPTY();
185         aZoomX = aZoomY = Fraction( 1, 1 );
186     }
187     sal_Bool bChanged = pDoc->SetOptimalHeight( nStartRow, nEndRow, nTab, 0, aProv.GetDevice(),
188                                             nPPTX, nPPTY, aZoomX, aZoomY, sal_False );
189 
190     if (bChanged && ( nStartRow == nEndRow ))
191     {
192         sal_uInt16 nNewPixel = (sal_uInt16) (pDoc->GetRowHeight(nStartRow,nTab) * nPPTY);
193         if ( nNewPixel == nOldPixel )
194             bChanged = sal_False;
195     }
196 
197     if ( bPaint && bChanged )
198         pDocSh->PostPaint( 0, nStartRow, nTab, MAXCOL, MAXROW, nTab,
199                                             PAINT_GRID | PAINT_LEFT );
200 
201     return bChanged;
202 }
203 
204 
205 //----------------------------------------------------------------------------
206 
207 enum ScAutoSum
208 {
209     ScAutoSumNone = 0,
210     ScAutoSumData,
211     ScAutoSumSum
212 };
213 
214 
215 ScAutoSum lcl_IsAutoSumData( ScDocument* pDoc, SCCOL nCol, SCROW nRow,
216         SCTAB nTab, ScDirection eDir, SCCOLROW& nExtend )
217 {
218     ScBaseCell* pCell;
219     pDoc->GetCell( nCol, nRow, nTab, pCell );
220     if ( pCell && pCell->HasValueData() )
221     {
222         if ( pCell->GetCellType() == CELLTYPE_FORMULA )
223         {
224             ScTokenArray* pCode = ((ScFormulaCell*)pCell)->GetCode();
225             if ( pCode && pCode->GetOuterFuncOpCode() == ocSum )
226             {
227                 if ( pCode->GetAdjacentExtendOfOuterFuncRefs( nExtend,
228                         ScAddress( nCol, nRow, nTab ), eDir ) )
229                     return ScAutoSumSum;
230             }
231         }
232         return ScAutoSumData;
233     }
234     return ScAutoSumNone;
235 }
236 
237 
238 //----------------------------------------------------------------------------
239 
240 #define SC_AUTOSUM_MAXCOUNT     20
241 
242 ScAutoSum lcl_SeekAutoSumData( ScDocument* pDoc, SCCOL& nCol, SCROW& nRow,
243         SCTAB nTab, ScDirection eDir, SCCOLROW& nExtend )
244 {
245     sal_uInt16 nCount = 0;
246     while (nCount < SC_AUTOSUM_MAXCOUNT)
247     {
248         if ( eDir == DIR_TOP )
249         {
250             if (nRow > 0)
251                 --nRow;
252             else
253                 return ScAutoSumNone;
254         }
255         else
256         {
257             if (nCol > 0)
258                 --nCol;
259             else
260                 return ScAutoSumNone;
261         }
262         ScAutoSum eSum;
263         if ( (eSum = lcl_IsAutoSumData(
264                 pDoc, nCol, nRow, nTab, eDir, nExtend )) != ScAutoSumNone )
265             return eSum;
266         ++nCount;
267     }
268     return ScAutoSumNone;
269 }
270 
271 #undef SC_AUTOSUM_MAXCOUNT
272 
273 //----------------------------------------------------------------------------
274 
275 bool lcl_FindNextSumEntryInColumn( ScDocument* pDoc, SCCOL nCol, SCROW& nRow,
276                                    SCTAB nTab, SCCOLROW& nExtend, SCROW nMinRow )
277 {
278     const SCROW nTmp = nRow;
279     ScAutoSum eSkip = ScAutoSumNone;
280     while ( ( eSkip = lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_TOP, nExtend ) ) == ScAutoSumData &&
281             nRow > nMinRow )
282     {
283         --nRow;
284     }
285     if ( eSkip == ScAutoSumSum && nRow < nTmp )
286     {
287         return true;
288     }
289     return false;
290 }
291 
292 //----------------------------------------------------------------------------
293 
294 bool lcl_FindNextSumEntryInRow( ScDocument* pDoc, SCCOL& nCol, SCROW nRow,
295                                 SCTAB nTab, SCCOLROW& nExtend, SCROW nMinCol )
296 {
297     const SCCOL nTmp = nCol;
298     ScAutoSum eSkip = ScAutoSumNone;
299     while ( ( eSkip = lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_LEFT, nExtend ) ) == ScAutoSumData &&
300             nCol > nMinCol )
301     {
302         --nCol;
303     }
304     if ( eSkip == ScAutoSumSum && nCol < nTmp )
305     {
306         return true;
307     }
308     return false;
309 }
310 
311 //----------------------------------------------------------------------------
312 
313 bool lcl_GetAutoSumForColumnRange( ScDocument* pDoc, ScRangeList& rRangeList, const ScRange& rRange )
314 {
315     const ScAddress aStart = rRange.aStart;
316     const ScAddress aEnd = rRange.aEnd;
317     if ( aStart.Col() != aEnd.Col() )
318     {
319         return false;
320     }
321 
322     const SCTAB nTab = aEnd.Tab();
323     const SCCOL nCol = aEnd.Col();
324     SCROW nEndRow = aEnd.Row();
325     SCROW nStartRow = nEndRow;
326     SCCOLROW nExtend = 0;
327     const ScAutoSum eSum = lcl_IsAutoSumData( pDoc, nCol, nEndRow, nTab, DIR_TOP, nExtend /*out*/ );
328 
329     if ( eSum == ScAutoSumSum )
330     {
331         bool bContinue = false;
332         do
333         {
334             rRangeList.Append( ScRange( nCol, nStartRow, nTab, nCol, nEndRow, nTab ) );
335             nEndRow = static_cast< SCROW >( nExtend );
336             if ( ( bContinue = lcl_FindNextSumEntryInColumn( pDoc, nCol, nEndRow /*inout*/, nTab, nExtend /*out*/, aStart.Row() ) ) == true )
337             {
338                 nStartRow = nEndRow;
339             }
340         } while ( bContinue );
341     }
342     else
343     {
344         while ( nStartRow > aStart.Row() &&
345                 lcl_IsAutoSumData( pDoc, nCol, nStartRow-1, nTab, DIR_TOP, nExtend /*out*/ ) != ScAutoSumSum )
346         {
347             --nStartRow;
348         }
349         rRangeList.Append( ScRange( nCol, nStartRow, nTab, nCol, nEndRow, nTab ) );
350     }
351 
352     return true;
353 }
354 
355 //----------------------------------------------------------------------------
356 
357 bool lcl_GetAutoSumForRowRange( ScDocument* pDoc, ScRangeList& rRangeList, const ScRange& rRange )
358 {
359     const ScAddress aStart = rRange.aStart;
360     const ScAddress aEnd = rRange.aEnd;
361     if ( aStart.Row() != aEnd.Row() )
362     {
363         return false;
364     }
365 
366     const SCTAB nTab = aEnd.Tab();
367     const SCROW nRow = aEnd.Row();
368     SCCOL nEndCol = aEnd.Col();
369     SCCOL nStartCol = nEndCol;
370     SCCOLROW nExtend = 0;
371     const ScAutoSum eSum = lcl_IsAutoSumData( pDoc, nEndCol, nRow, nTab, DIR_LEFT, nExtend /*out*/ );
372 
373     if ( eSum == ScAutoSumSum )
374     {
375         bool bContinue = false;
376         do
377         {
378             rRangeList.Append( ScRange( nStartCol, nRow, nTab, nEndCol, nRow, nTab ) );
379             nEndCol = static_cast< SCCOL >( nExtend );
380             if ( ( bContinue = lcl_FindNextSumEntryInRow( pDoc, nEndCol /*inout*/, nRow, nTab, nExtend /*out*/, aStart.Col() ) ) == true )
381             {
382                 nStartCol = nEndCol;
383             }
384         } while ( bContinue );
385     }
386     else
387     {
388         while ( nStartCol > aStart.Col() &&
389                 lcl_IsAutoSumData( pDoc, nStartCol-1, nRow, nTab, DIR_LEFT, nExtend /*out*/ ) != ScAutoSumSum )
390         {
391             --nStartCol;
392         }
393         rRangeList.Append( ScRange( nStartCol, nRow, nTab, nEndCol, nRow, nTab ) );
394     }
395 
396     return true;
397 }
398 
399 //----------------------------------------------------------------------------
400 
401 sal_Bool ScViewFunc::GetAutoSumArea( ScRangeList& rRangeList )
402 {
403     ScDocument* pDoc = GetViewData()->GetDocument();
404     SCTAB nTab = GetViewData()->GetTabNo();
405 
406     SCCOL nCol = GetViewData()->GetCurX();
407     SCROW nRow = GetViewData()->GetCurY();
408 
409     SCCOL nStartCol = nCol;
410     SCROW nStartRow = nRow;
411     SCCOL nEndCol    = nCol;
412     SCROW nEndRow    = nRow;
413     SCCOL nSeekCol   = nCol;
414     SCROW nSeekRow   = nRow;
415     SCCOLROW nExtend;       // wird per Reference gueltig bei ScAutoSumSum
416 
417     sal_Bool bCol = sal_False;
418     sal_Bool bRow = sal_False;
419 
420     ScAutoSum eSum;
421     if ( nRow != 0
422             && ((eSum = lcl_IsAutoSumData( pDoc, nCol, nRow-1, nTab,
423                 DIR_TOP, nExtend /*out*/ )) == ScAutoSumData )
424             && ((eSum = lcl_IsAutoSumData( pDoc, nCol, nRow-1, nTab,
425                 DIR_LEFT, nExtend /*out*/ )) == ScAutoSumData )
426         )
427     {
428         bRow = sal_True;
429         nSeekRow = nRow - 1;
430     }
431     else if ( nCol != 0 && (eSum = lcl_IsAutoSumData( pDoc, nCol-1, nRow, nTab,
432             DIR_LEFT, nExtend /*out*/ )) == ScAutoSumData )
433     {
434         bCol = sal_True;
435         nSeekCol = nCol - 1;
436     }
437     else if ( (eSum = lcl_SeekAutoSumData( pDoc, nCol, nSeekRow, nTab, DIR_TOP, nExtend /*out*/ )) != ScAutoSumNone )
438         bRow = sal_True;
439     else if (( eSum = lcl_SeekAutoSumData( pDoc, nSeekCol, nRow, nTab, DIR_LEFT, nExtend /*out*/ )) != ScAutoSumNone )
440         bCol = sal_True;
441 
442     if ( bCol || bRow )
443     {
444         if ( bRow )
445         {
446             nStartRow = nSeekRow;       // nSeekRow evtl. per Reference angepasst
447             if ( eSum == ScAutoSumSum )
448                 nEndRow = nStartRow;        // nur Summen summieren
449             else
450                 nEndRow = nRow - 1;     // Datenbereich evtl. nach unten erweitern
451         }
452         else
453         {
454             nStartCol = nSeekCol;       // nSeekCol evtl. per Reference angepasst
455             if ( eSum == ScAutoSumSum )
456                 nEndCol = nStartCol;        // nur Summen summieren
457             else
458                 nEndCol = nCol - 1;     // Datenbereich evtl. nach rechts erweitern
459         }
460         sal_Bool bContinue = sal_False;
461         do
462         {
463             if ( eSum == ScAutoSumData )
464             {
465                 if ( bRow )
466                 {
467                     while ( nStartRow != 0 && lcl_IsAutoSumData(    pDoc, nCol,
468                             nStartRow-1, nTab, DIR_TOP, nExtend /*out*/ ) == eSum )
469                         --nStartRow;
470                 }
471                 else
472                 {
473                     while ( nStartCol != 0 && lcl_IsAutoSumData( pDoc, nStartCol-1,
474                             nRow, nTab, DIR_LEFT, nExtend /*out*/ ) == eSum )
475                         --nStartCol;
476                 }
477             }
478             rRangeList.Append(
479                 ScRange( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab ) );
480             if ( eSum == ScAutoSumSum )
481             {
482                 if ( bRow )
483                 {
484                     nEndRow = static_cast< SCROW >( nExtend );
485                     if ( ( bContinue = lcl_FindNextSumEntryInColumn( pDoc, nCol, nEndRow /*inout*/, nTab, nExtend /*out*/, 0 ) ) == true )
486                     {
487                         nStartRow = nEndRow;
488                     }
489                 }
490                 else
491                 {
492                     nEndCol = static_cast< SCCOL >( nExtend );
493                     if ( ( bContinue = lcl_FindNextSumEntryInRow( pDoc, nEndCol /*inout*/, nRow, nTab, nExtend /*out*/, 0 ) ) == true )
494                     {
495                         nStartCol = nEndCol;
496                     }
497                 }
498             }
499         } while ( bContinue );
500         return sal_True;
501     }
502     return sal_False;
503 }
504 
505 //----------------------------------------------------------------------------
506 
507 void ScViewFunc::EnterAutoSum(const ScRangeList& rRangeList, sal_Bool bSubTotal)        // Block mit Summen fuellen
508 {
509     String aFormula = GetAutoSumFormula( rRangeList, bSubTotal );
510     EnterBlock( aFormula, NULL );
511 }
512 
513 //----------------------------------------------------------------------------
514 
515 bool ScViewFunc::AutoSum( const ScRange& rRange, bool bSubTotal, bool bSetCursor, bool bContinue )
516 {
517     ScDocument* pDoc = GetViewData()->GetDocument();
518     const SCTAB nTab = rRange.aStart.Tab();
519     SCCOL nStartCol = rRange.aStart.Col();
520     SCROW nStartRow = rRange.aStart.Row();
521     const SCCOL nEndCol = rRange.aEnd.Col();
522     const SCROW nEndRow = rRange.aEnd.Row();
523     SCCOLROW nExtend = 0; // out parameter for lcl_IsAutoSumData
524 
525     // ignore rows at the top of the given range which don't contain autosum data
526     bool bRowData = false;
527     for ( SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow )
528     {
529         for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol )
530         {
531             if ( lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_TOP, nExtend ) != ScAutoSumNone )
532             {
533                 bRowData = true;
534                 break;
535             }
536         }
537         if ( bRowData )
538         {
539             nStartRow = nRow;
540             break;
541         }
542     }
543     if ( !bRowData )
544     {
545         return false;
546     }
547 
548     // ignore columns at the left of the given range which don't contain autosum data
549     bool bColData = false;
550     for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol )
551     {
552         for ( SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow )
553         {
554             if ( lcl_IsAutoSumData( pDoc, nCol, nRow, nTab, DIR_LEFT, nExtend ) != ScAutoSumNone )
555             {
556                 bColData = true;
557                 break;
558             }
559         }
560         if ( bColData )
561         {
562             nStartCol = nCol;
563             break;
564         }
565     }
566     if ( !bColData )
567     {
568         return false;
569     }
570 
571     const bool bEndRowEmpty = pDoc->IsBlockEmpty( nTab, nStartCol, nEndRow, nEndCol, nEndRow );
572     const bool bEndColEmpty = pDoc->IsBlockEmpty( nTab, nEndCol, nStartRow, nEndCol, nEndRow );
573     bool bRow = ( ( nStartRow != nEndRow ) && ( bEndRowEmpty || ( !bEndRowEmpty && !bEndColEmpty ) ) );
574     bool bCol = ( ( nStartCol != nEndCol ) && ( bEndColEmpty || nStartRow == nEndRow ) );
575 
576     // find an empty row for entering the result
577     SCROW nInsRow = nEndRow;
578     if ( bRow && !bEndRowEmpty )
579     {
580         if ( nInsRow < MAXROW )
581         {
582             ++nInsRow;
583             while ( !pDoc->IsBlockEmpty( nTab, nStartCol, nInsRow, nEndCol, nInsRow ) )
584             {
585                 if ( nInsRow < MAXROW )
586                 {
587                     ++nInsRow;
588                 }
589                 else
590                 {
591                     bRow = false;
592                     break;
593                 }
594             }
595         }
596         else
597         {
598             bRow = false;
599         }
600     }
601 
602     // find an empty column for entering the result
603     SCCOL nInsCol = nEndCol;
604     if ( bCol && !bEndColEmpty )
605     {
606         if ( nInsCol < MAXCOL )
607         {
608             ++nInsCol;
609             while ( !pDoc->IsBlockEmpty( nTab, nInsCol, nStartRow, nInsCol, nEndRow ) )
610             {
611                 if ( nInsCol < MAXCOL )
612                 {
613                     ++nInsCol;
614                 }
615                 else
616                 {
617                     bCol = false;
618                     break;
619                 }
620             }
621         }
622         else
623         {
624             bCol = false;
625         }
626     }
627 
628     if ( !bRow && !bCol )
629     {
630         return false;
631     }
632 
633     SCCOL nMarkEndCol = nEndCol;
634     SCROW nMarkEndRow = nEndRow;
635 
636     if ( bRow )
637     {
638         // calculate the row sums for all columns of the given range
639 
640         SCROW nSumEndRow = nEndRow;
641 
642         if ( bEndRowEmpty )
643         {
644             // the last row of the given range is empty;
645             // don't take into account for calculating the autosum
646             --nSumEndRow;
647         }
648         else
649         {
650             // increase mark range
651             ++nMarkEndRow;
652         }
653 
654         for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol )
655         {
656             if ( !pDoc->IsBlockEmpty( nTab, nCol, nStartRow, nCol, nSumEndRow ) )
657             {
658                 ScRangeList aRangeList;
659                 const ScRange aRange( nCol, nStartRow, nTab, nCol, nSumEndRow, nTab );
660                 if ( lcl_GetAutoSumForColumnRange( pDoc, aRangeList, aRange ) )
661                 {
662                     const String aFormula = GetAutoSumFormula( aRangeList, bSubTotal );
663                     EnterData( nCol, nInsRow, nTab, aFormula );
664                 }
665             }
666         }
667     }
668 
669     if ( bCol )
670     {
671         // calculate the column sums for all rows of the given range
672 
673         SCCOL nSumEndCol = nEndCol;
674 
675         if ( bEndColEmpty )
676         {
677             // the last column of the given range is empty;
678             // don't take into account for calculating the autosum
679             --nSumEndCol;
680         }
681         else
682         {
683             // increase mark range
684             ++nMarkEndCol;
685         }
686 
687         for ( SCROW nRow = nStartRow; nRow <= nEndRow; ++nRow )
688         {
689             if ( !pDoc->IsBlockEmpty( nTab, nStartCol, nRow, nSumEndCol, nRow ) )
690             {
691                 ScRangeList aRangeList;
692                 const ScRange aRange( nStartCol, nRow, nTab, nSumEndCol, nRow, nTab );
693                 if ( lcl_GetAutoSumForRowRange( pDoc, aRangeList, aRange ) )
694                 {
695                     const String aFormula = GetAutoSumFormula( aRangeList, bSubTotal );
696                     EnterData( nInsCol, nRow, nTab, aFormula );
697                 }
698             }
699         }
700     }
701 
702     // set new mark range and cursor position
703     const ScRange aMarkRange( nStartCol, nStartRow, nTab, nMarkEndCol, nMarkEndRow, nTab );
704     MarkRange( aMarkRange, sal_False, bContinue );
705     if ( bSetCursor )
706     {
707         SetCursor( nMarkEndCol, nMarkEndRow );
708     }
709 
710     return true;
711 }
712 
713 //----------------------------------------------------------------------------
714 
715 String ScViewFunc::GetAutoSumFormula( const ScRangeList& rRangeList, bool bSubTotal )
716 {
717     String aFormula = '=';
718     ScFunctionMgr* pFuncMgr = ScGlobal::GetStarCalcFunctionMgr();
719     const ScFuncDesc* pDesc = NULL;
720     if ( bSubTotal )
721     {
722         pDesc = pFuncMgr->Get( SC_OPCODE_SUB_TOTAL );
723     }
724     else
725     {
726         pDesc = pFuncMgr->Get( SC_OPCODE_SUM );
727     }
728     if ( pDesc && pDesc->pFuncName )
729     {
730         aFormula += *pDesc->pFuncName;
731         if ( bSubTotal )
732         {
733             aFormula.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "(9;" ) );
734         }
735         else
736         {
737             aFormula += '(';
738         }
739         ScDocument* pDoc = GetViewData()->GetDocument();
740         String aRef;
741         rRangeList.Format( aRef, SCA_VALID, pDoc );
742         aFormula += aRef;
743         aFormula += ')';
744     }
745     return aFormula;
746 }
747 
748 //----------------------------------------------------------------------------
749 
750 void ScViewFunc::EnterBlock( const String& rString, const EditTextObject* pData )
751 {
752     //  Mehrfachselektion vorher abfragen...
753 
754     SCCOL nCol = GetViewData()->GetCurX();
755     SCROW nRow = GetViewData()->GetCurY();
756     SCTAB nTab = GetViewData()->GetTabNo();
757     ScMarkData& rMark = GetViewData()->GetMarkData();
758     if ( rMark.IsMultiMarked() )
759     {
760         rMark.MarkToSimple();
761         if ( rMark.IsMultiMarked() )
762         {       // "Einfuegen auf Mehrfachselektion nicht moeglich"
763             ErrorMessage(STR_MSSG_PASTEFROMCLIP_0);
764 
765             //  insert into single cell
766             if ( pData )
767                 EnterData( nCol, nRow, nTab, pData );
768             else
769                 EnterData( nCol, nRow, nTab, rString );
770             return;
771         }
772     }
773 
774     ScDocument* pDoc = GetViewData()->GetDocument();
775     String aNewStr = rString;
776     if ( pData )
777     {
778         const ScPatternAttr* pOldPattern = pDoc->GetPattern( nCol, nRow, nTab );
779         ScTabEditEngine aEngine( *pOldPattern, pDoc->GetEnginePool() );
780         aEngine.SetText(*pData);
781 
782         ScEditAttrTester aTester( &aEngine );
783         if (!aTester.NeedsObject())
784         {
785             aNewStr = aEngine.GetText();
786             pData = NULL;
787         }
788     }
789 
790     //  Einfuegen per PasteFromClip
791 
792     WaitObject aWait( GetFrameWin() );
793 
794     ScAddress aPos( nCol, nRow, nTab );
795 
796     ScDocument* pInsDoc = new ScDocument( SCDOCMODE_CLIP );
797     pInsDoc->ResetClip( pDoc, nTab );
798 
799     if (aNewStr.GetChar(0) == '=')                      // Formel ?
800     {
801         //  SetString geht nicht, weil in Clipboard-Dokumenten nicht kompiliert wird!
802         ScFormulaCell* pFCell = new ScFormulaCell( pDoc, aPos, aNewStr );
803         pInsDoc->PutCell( nCol, nRow, nTab, pFCell );
804     }
805     else if ( pData )
806         pInsDoc->PutCell( nCol, nRow, nTab, new ScEditCell( pData, pDoc, NULL ) );
807     else
808         pInsDoc->SetString( nCol, nRow, nTab, aNewStr );
809 
810     pInsDoc->SetClipArea( ScRange(aPos) );
811     // auf Block einfuegen, mit Undo etc.
812     if ( PasteFromClip( IDF_CONTENTS, pInsDoc, PASTE_NOFUNC, sal_False, sal_False,
813             sal_False, INS_NONE, IDF_ATTRIB ) )
814     {
815         const SfxUInt32Item* pItem = (SfxUInt32Item*) pInsDoc->GetAttr(
816             nCol, nRow, nTab, ATTR_VALUE_FORMAT );
817         if ( pItem )
818         {   // Numberformat setzen wenn inkompatibel
819             // MarkData wurde bereits in PasteFromClip MarkToSimple'ed
820             ScRange aRange;
821             rMark.GetMarkArea( aRange );
822             ScPatternAttr* pPattern = new ScPatternAttr( pDoc->GetPool() );
823             pPattern->GetItemSet().Put( *pItem );
824             short nNewType = pDoc->GetFormatTable()->GetType( pItem->GetValue() );
825             pDoc->ApplyPatternIfNumberformatIncompatible( aRange, rMark,
826                 *pPattern, nNewType );
827             delete pPattern;
828         }
829     }
830 
831     delete pInsDoc;
832 }
833 
834 
835 //----------------------------------------------------------------------------
836 
837 //UNUSED2008-05  void ScViewFunc::PaintWidthHeight( sal_Bool bColumns, SCCOLROW nStart, SCCOLROW nEnd )
838 //UNUSED2008-05  {
839 //UNUSED2008-05      SCTAB nTab = GetViewData()->GetTabNo();
840 //UNUSED2008-05      ScDocument* pDoc = GetViewData()->GetDocument();
841 //UNUSED2008-05
842 //UNUSED2008-05      sal_uInt16 nParts = PAINT_GRID;
843 //UNUSED2008-05      SCCOL nStartCol = 0;
844 //UNUSED2008-05      SCROW nStartRow = 0;
845 //UNUSED2008-05      SCCOL nEndCol = MAXCOL;         // fuer Test auf Merge
846 //UNUSED2008-05      SCROW nEndRow = MAXROW;
847 //UNUSED2008-05      if ( bColumns )
848 //UNUSED2008-05      {
849 //UNUSED2008-05          nParts |= PAINT_TOP;
850 //UNUSED2008-05          nStartCol = static_cast<SCCOL>(nStart);
851 //UNUSED2008-05          nEndCol = static_cast<SCCOL>(nEnd);
852 //UNUSED2008-05      }
853 //UNUSED2008-05      else
854 //UNUSED2008-05      {
855 //UNUSED2008-05          nParts |= PAINT_LEFT;
856 //UNUSED2008-05          nStartRow = nStart;
857 //UNUSED2008-05          nEndRow = nEnd;
858 //UNUSED2008-05      }
859 //UNUSED2008-05      if (pDoc->HasAttrib( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab,
860 //UNUSED2008-05                           HASATTR_MERGED | HASATTR_OVERLAPPED ))
861 //UNUSED2008-05      {
862 //UNUSED2008-05          nStartCol = 0;
863 //UNUSED2008-05          nStartRow = 0;
864 //UNUSED2008-05      }
865 //UNUSED2008-05      GetViewData()->GetDocShell()->PostPaint( nStartCol,nStartRow,nTab, MAXCOL,MAXROW,nTab, nParts );
866 //UNUSED2008-05  }
867 
868 
869 //----------------------------------------------------------------------------
870 //  manueller Seitenumbruch
871 
872 void ScViewFunc::InsertPageBreak( sal_Bool bColumn, sal_Bool bRecord, const ScAddress* pPos,
873                                     sal_Bool bSetModified )
874 {
875     SCTAB nTab = GetViewData()->GetTabNo();
876     ScAddress aCursor;
877     if (pPos)
878         aCursor = *pPos;
879     else
880         aCursor = ScAddress( GetViewData()->GetCurX(), GetViewData()->GetCurY(), nTab );
881 
882     sal_Bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().
883                         InsertPageBreak( bColumn, aCursor, bRecord, bSetModified, sal_False );
884 
885     if ( bSuccess && bSetModified )
886         UpdatePageBreakData( sal_True );    // fuer PageBreak-Modus
887 }
888 
889 
890 //----------------------------------------------------------------------------
891 
892 void ScViewFunc::DeletePageBreak( sal_Bool bColumn, sal_Bool bRecord, const ScAddress* pPos,
893                                     sal_Bool bSetModified )
894 {
895     SCTAB nTab = GetViewData()->GetTabNo();
896     ScAddress aCursor;
897     if (pPos)
898         aCursor = *pPos;
899     else
900         aCursor = ScAddress( GetViewData()->GetCurX(), GetViewData()->GetCurY(), nTab );
901 
902     sal_Bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().
903                         RemovePageBreak( bColumn, aCursor, bRecord, bSetModified, sal_False );
904 
905     if ( bSuccess && bSetModified )
906         UpdatePageBreakData( sal_True );    // fuer PageBreak-Modus
907 }
908 
909 //----------------------------------------------------------------------------
910 
911 void ScViewFunc::RemoveManualBreaks()
912 {
913     ScDocShell* pDocSh = GetViewData()->GetDocShell();
914     ScDocument* pDoc = pDocSh->GetDocument();
915     SCTAB nTab = GetViewData()->GetTabNo();
916     sal_Bool bUndo(pDoc->IsUndoEnabled());
917 
918     if (bUndo)
919     {
920         ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
921         pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_True );
922         pDoc->CopyToDocument( 0,0,nTab, MAXCOL,MAXROW,nTab, IDF_NONE, sal_False, pUndoDoc );
923         pDocSh->GetUndoManager()->AddUndoAction(
924                                 new ScUndoRemoveBreaks( pDocSh, nTab, pUndoDoc ) );
925     }
926 
927     pDoc->RemoveManualBreaks(nTab);
928     pDoc->UpdatePageBreaks(nTab);
929 
930     UpdatePageBreakData( sal_True );
931     pDocSh->SetDocumentModified();
932     pDocSh->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID );
933 }
934 
935 //----------------------------------------------------------------------------
936 
937 void ScViewFunc::SetPrintZoom(sal_uInt16 nScale, sal_uInt16 nPages)
938 {
939     ScDocShell* pDocSh = GetViewData()->GetDocShell();
940     SCTAB nTab = GetViewData()->GetTabNo();
941     pDocSh->SetPrintZoom( nTab, nScale, nPages );
942 }
943 
944 void ScViewFunc::AdjustPrintZoom()
945 {
946     ScRange aRange;
947     if ( GetViewData()->GetSimpleArea( aRange ) != SC_MARK_SIMPLE )
948         GetViewData()->GetMarkData().GetMultiMarkArea( aRange );
949     GetViewData()->GetDocShell()->AdjustPrintZoom( aRange );
950 }
951 
952 //----------------------------------------------------------------------------
953 
954 void ScViewFunc::SetPrintRanges( sal_Bool bEntireSheet, const String* pPrint,
955                                 const String* pRepCol, const String* pRepRow,
956                                 sal_Bool bAddPrint )
957 {
958     //  on all selected tables
959 
960     ScDocShell* pDocSh  = GetViewData()->GetDocShell();
961     ScDocument* pDoc    = pDocSh->GetDocument();
962     SCTAB nTabCount = pDoc->GetTableCount();
963     ScMarkData& rMark   = GetViewData()->GetMarkData();
964     SCTAB nTab;
965     sal_Bool bUndo (pDoc->IsUndoEnabled());
966 
967     ScPrintRangeSaver* pOldRanges = pDoc->CreatePrintRangeSaver();
968 
969     ScAddress::Details aDetails(pDoc->GetAddressConvention(), 0, 0);
970 
971     for (nTab=0; nTab<nTabCount; nTab++)
972         if (rMark.GetTableSelect(nTab))
973         {
974             ScRange aRange( 0,0,nTab );
975 
976             //  print ranges
977 
978             if( !bAddPrint )
979                 pDoc->ClearPrintRanges( nTab );
980 
981             if( bEntireSheet )
982             {
983                 pDoc->SetPrintEntireSheet( nTab );
984             }
985             else if ( pPrint )
986             {
987                 if ( pPrint->Len() )
988                 {
989                     const sal_Unicode sep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0);
990                     sal_uInt16 nTCount = pPrint->GetTokenCount(sep);
991                     for (sal_uInt16 i=0; i<nTCount; i++)
992                     {
993                         String aToken = pPrint->GetToken(i, sep);
994                         if ( aRange.ParseAny( aToken, pDoc, aDetails ) & SCA_VALID )
995                             pDoc->AddPrintRange( nTab, aRange );
996                     }
997                 }
998             }
999             else    // NULL = use selection (print range is always set), use empty string to delete all ranges
1000             {
1001                 if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
1002                 {
1003                     pDoc->AddPrintRange( nTab, aRange );
1004                 }
1005                 else if ( rMark.IsMultiMarked() )
1006                 {
1007                     rMark.MarkToMulti();
1008                     ScRangeListRef aList( new ScRangeList );
1009                     rMark.FillRangeListWithMarks( aList, sal_False );
1010                     sal_uInt16 nCnt = (sal_uInt16) aList->Count();
1011                     if ( nCnt )
1012                     {
1013                         ScRangePtr pR;
1014                         sal_uInt16 i;
1015                         for ( pR = aList->First(), i=0; i < nCnt;
1016                               pR = aList->Next(), i++ )
1017                         {
1018                             pDoc->AddPrintRange( nTab, *pR );
1019                         }
1020                     }
1021                 }
1022             }
1023 
1024             //  repeat columns
1025 
1026             if ( pRepCol )
1027             {
1028                 if ( !pRepCol->Len() )
1029                     pDoc->SetRepeatColRange( nTab, NULL );
1030                 else
1031                     if ( aRange.ParseAny( *pRepCol, pDoc, aDetails ) & SCA_VALID )
1032                         pDoc->SetRepeatColRange( nTab, &aRange );
1033             }
1034 
1035             //  repeat rows
1036 
1037             if ( pRepRow )
1038             {
1039                 if ( !pRepRow->Len() )
1040                     pDoc->SetRepeatRowRange( nTab, NULL );
1041                 else
1042                     if ( aRange.ParseAny( *pRepRow, pDoc, aDetails ) & SCA_VALID )
1043                         pDoc->SetRepeatRowRange( nTab, &aRange );
1044             }
1045         }
1046 
1047     //  undo (for all tables)
1048     if (bUndo)
1049     {
1050         SCTAB nCurTab = GetViewData()->GetTabNo();
1051         ScPrintRangeSaver* pNewRanges = pDoc->CreatePrintRangeSaver();
1052         pDocSh->GetUndoManager()->AddUndoAction(
1053                     new ScUndoPrintRange( pDocSh, nCurTab, pOldRanges, pNewRanges ) );
1054     }
1055 
1056     //  update page breaks
1057 
1058     for (nTab=0; nTab<nTabCount; nTab++)
1059         if (rMark.GetTableSelect(nTab))
1060             ScPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab ).UpdatePages();
1061 
1062     SfxBindings& rBindings = GetViewData()->GetBindings();
1063     rBindings.Invalidate( SID_DELETE_PRINTAREA );
1064 
1065     pDocSh->SetDocumentModified();
1066 }
1067 
1068 //----------------------------------------------------------------------------
1069 //  Zellen zusammenfassen
1070 
1071 sal_Bool ScViewFunc::TestMergeCells()           // Vorab-Test (fuer Menue)
1072 {
1073     //  simple test: sal_True if there's a selection but no multi selection and not filtered
1074 
1075     const ScMarkData& rMark = GetViewData()->GetMarkData();
1076     if ( rMark.IsMarked() || rMark.IsMultiMarked() )
1077     {
1078         ScRange aDummy;
1079         return GetViewData()->GetSimpleArea( aDummy) == SC_MARK_SIMPLE;
1080     }
1081     else
1082         return sal_False;
1083 }
1084 
1085 
1086 //----------------------------------------------------------------------------
1087 
1088 sal_Bool ScViewFunc::MergeCells( sal_Bool bApi, sal_Bool& rDoContents, sal_Bool bRecord )
1089 {
1090     //  Editable- und Verschachtelungs-Abfrage muss vorneweg sein (auch in DocFunc),
1091     //  damit dann nicht die Inhalte-QueryBox kommt
1092     ScEditableTester aTester( this );
1093     if (!aTester.IsEditable())
1094     {
1095         ErrorMessage(aTester.GetMessageId());
1096         return sal_False;
1097     }
1098 
1099     ScMarkData& rMark = GetViewData()->GetMarkData();
1100     rMark.MarkToSimple();
1101     if (!rMark.IsMarked())
1102     {
1103         ErrorMessage(STR_NOMULTISELECT);
1104         return sal_False;
1105     }
1106 
1107     ScDocShell* pDocSh = GetViewData()->GetDocShell();
1108     ScDocument* pDoc = pDocSh->GetDocument();
1109 
1110     ScRange aMarkRange;
1111     rMark.GetMarkArea( aMarkRange );
1112     SCCOL nStartCol = aMarkRange.aStart.Col();
1113     SCROW nStartRow = aMarkRange.aStart.Row();
1114     SCTAB nStartTab = aMarkRange.aStart.Tab();
1115     SCCOL nEndCol = aMarkRange.aEnd.Col();
1116     SCROW nEndRow = aMarkRange.aEnd.Row();
1117     SCTAB nEndTab = aMarkRange.aEnd.Tab();
1118     if ( nStartCol == nEndCol && nStartRow == nEndRow )
1119     {
1120         // nichts zu tun
1121         return sal_True;
1122     }
1123 
1124     if ( pDoc->HasAttrib( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab,
1125                             HASATTR_MERGED | HASATTR_OVERLAPPED ) )
1126     {       // "Zusammenfassen nicht verschachteln !"
1127         ErrorMessage(STR_MSSG_MERGECELLS_0);
1128         return sal_False;
1129     }
1130 
1131     sal_Bool bOk = sal_True;
1132 
1133     if ( !pDoc->IsBlockEmpty( nStartTab, nStartCol,nStartRow+1, nStartCol,nEndRow, true ) ||
1134          !pDoc->IsBlockEmpty( nStartTab, nStartCol+1,nStartRow, nEndCol,nEndRow, true ) )
1135     {
1136         if (!bApi)
1137         {
1138             MessBox aBox( GetViewData()->GetDialogParent(),
1139                             WinBits(WB_YES_NO_CANCEL | WB_DEF_NO),
1140                             ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ),
1141                             ScGlobal::GetRscString( STR_MERGE_NOTEMPTY ) );
1142             sal_uInt16 nRetVal = aBox.Execute();
1143 
1144             if ( nRetVal == RET_YES )
1145                 rDoContents = sal_True;
1146             else if ( nRetVal == RET_CANCEL )
1147                 bOk = sal_False;
1148         }
1149     }
1150 
1151     if (bOk)
1152     {
1153         HideCursor();
1154         bOk = pDocSh->GetDocFunc().MergeCells( aMarkRange, rDoContents, bRecord, bApi );
1155         ShowCursor();
1156 
1157         if (bOk)
1158         {
1159             SetCursor( nStartCol, nStartRow );
1160             //DoneBlockMode( sal_False);
1161             Unmark();
1162 
1163             pDocSh->UpdateOle(GetViewData());
1164             UpdateInputLine();
1165         }
1166     }
1167 
1168     return bOk;
1169 }
1170 
1171 
1172 //----------------------------------------------------------------------------
1173 
1174 sal_Bool ScViewFunc::TestRemoveMerge()
1175 {
1176     sal_Bool bMerged = sal_False;
1177     ScRange aRange;
1178     if (GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE)
1179     {
1180         ScDocument* pDoc = GetViewData()->GetDocument();
1181         if ( pDoc->HasAttrib( aRange, HASATTR_MERGED ) )
1182             bMerged = sal_True;
1183     }
1184     return bMerged;
1185 }
1186 
1187 
1188 //----------------------------------------------------------------------------
1189 
1190 sal_Bool ScViewFunc::RemoveMerge( sal_Bool bRecord )
1191 {
1192     ScRange aRange;
1193     ScEditableTester aTester( this );
1194     if (!aTester.IsEditable())
1195     {
1196         ErrorMessage(aTester.GetMessageId());
1197         return sal_False;
1198     }
1199     else if (GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE)
1200     {
1201         ScRange aExtended( aRange );
1202         GetViewData()->GetDocument()->ExtendMerge( aExtended );
1203         ScDocShell* pDocSh = GetViewData()->GetDocShell();
1204 
1205         HideCursor();
1206         sal_Bool bOk = pDocSh->GetDocFunc().UnmergeCells( aRange, bRecord, sal_False );
1207         MarkRange( aExtended );
1208         ShowCursor();
1209 
1210         if (bOk)
1211             pDocSh->UpdateOle(GetViewData());
1212     }
1213     return sal_True;        //! bOk ??
1214 }
1215 
1216 //----------------------------------------------------------------------------
1217 
1218 void ScViewFunc::FillSimple( FillDir eDir, sal_Bool bRecord )
1219 {
1220     ScRange aRange;
1221     if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
1222     {
1223         ScDocShell* pDocSh = GetViewData()->GetDocShell();
1224         const ScMarkData& rMark = GetViewData()->GetMarkData();
1225         sal_Bool bSuccess = pDocSh->GetDocFunc().FillSimple( aRange, &rMark, eDir, bRecord, sal_False );
1226         if (bSuccess)
1227         {
1228             pDocSh->UpdateOle(GetViewData());
1229             UpdateScrollBars();
1230         }
1231     }
1232     else
1233         ErrorMessage(STR_NOMULTISELECT);
1234 }
1235 
1236 //----------------------------------------------------------------------------
1237 
1238 void ScViewFunc::FillSeries( FillDir eDir, FillCmd eCmd, FillDateCmd eDateCmd,
1239                              double fStart, double fStep, double fMax, sal_Bool bRecord )
1240 {
1241     ScRange aRange;
1242     if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
1243     {
1244         ScDocShell* pDocSh = GetViewData()->GetDocShell();
1245         const ScMarkData& rMark = GetViewData()->GetMarkData();
1246         sal_Bool bSuccess = pDocSh->GetDocFunc().
1247                         FillSeries( aRange, &rMark, eDir, eCmd, eDateCmd,
1248                                     fStart, fStep, fMax, bRecord, sal_False );
1249         if (bSuccess)
1250         {
1251             pDocSh->UpdateOle(GetViewData());
1252             UpdateScrollBars();
1253 
1254             // #i97876# Spreadsheet data changes are not notified
1255             ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
1256             if ( pModelObj && pModelObj->HasChangesListeners() )
1257             {
1258                 ScRangeList aChangeRanges;
1259                 aChangeRanges.Append( aRange );
1260                 pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges );
1261             }
1262         }
1263     }
1264     else
1265         ErrorMessage(STR_NOMULTISELECT);
1266 }
1267 
1268 //----------------------------------------------------------------------------
1269 
1270 void ScViewFunc::FillAuto( FillDir eDir, SCCOL nStartCol, SCROW nStartRow,
1271                             SCCOL nEndCol, SCROW nEndRow, sal_uLong nCount, sal_Bool bRecord )
1272 {
1273     SCTAB nTab = GetViewData()->GetTabNo();
1274     ScRange aRange( nStartCol,nStartRow,nTab, nEndCol,nEndRow,nTab );
1275     ScRange aSourceRange( aRange );
1276     ScDocShell* pDocSh = GetViewData()->GetDocShell();
1277     const ScMarkData& rMark = GetViewData()->GetMarkData();
1278     sal_Bool bSuccess = pDocSh->GetDocFunc().
1279                     FillAuto( aRange, &rMark, eDir, nCount, bRecord, sal_False );
1280     if (bSuccess)
1281     {
1282         MarkRange( aRange, sal_False );         // aRange ist in FillAuto veraendert worden
1283         pDocSh->UpdateOle(GetViewData());
1284         UpdateScrollBars();
1285 
1286         // #i97876# Spreadsheet data changes are not notified
1287         ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
1288         if ( pModelObj && pModelObj->HasChangesListeners() )
1289         {
1290             ScRangeList aChangeRanges;
1291             ScRange aChangeRange( aRange );
1292             switch ( eDir )
1293             {
1294                 case FILL_TO_BOTTOM:
1295                     {
1296                         aChangeRange.aStart.SetRow( aSourceRange.aEnd.Row() + 1 );
1297                     }
1298                     break;
1299                 case FILL_TO_TOP:
1300                     {
1301                         aChangeRange.aEnd.SetRow( aSourceRange.aStart.Row() - 1 );
1302                     }
1303                     break;
1304                 case FILL_TO_RIGHT:
1305                     {
1306                         aChangeRange.aStart.SetCol( aSourceRange.aEnd.Col() + 1 );
1307                     }
1308                     break;
1309                 case FILL_TO_LEFT:
1310                     {
1311                         aChangeRange.aEnd.SetCol( aSourceRange.aStart.Col() - 1 );
1312                     }
1313                     break;
1314                 default:
1315                     {
1316 
1317                     }
1318                     break;
1319             }
1320             aChangeRanges.Append( aChangeRange );
1321             pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges );
1322         }
1323     }
1324 }
1325 
1326 //----------------------------------------------------------------------------
1327 
1328 void ScViewFunc::FillTab( sal_uInt16 nFlags, sal_uInt16 nFunction, sal_Bool bSkipEmpty, sal_Bool bAsLink )
1329 {
1330     //! allow source sheet to be protected
1331     ScEditableTester aTester( this );
1332     if (!aTester.IsEditable())
1333     {
1334         ErrorMessage(aTester.GetMessageId());
1335         return;
1336     }
1337 
1338     ScDocShell* pDocSh = GetViewData()->GetDocShell();
1339     ScDocument* pDoc = pDocSh->GetDocument();
1340     ScMarkData& rMark = GetViewData()->GetMarkData();
1341     SCTAB nTab = GetViewData()->GetTabNo();
1342     sal_Bool bUndo(pDoc->IsUndoEnabled());
1343 
1344     ScRange aMarkRange;
1345     rMark.MarkToSimple();
1346     sal_Bool bMulti = rMark.IsMultiMarked();
1347     if (bMulti)
1348         rMark.GetMultiMarkArea( aMarkRange );
1349     else if (rMark.IsMarked())
1350         rMark.GetMarkArea( aMarkRange );
1351     else
1352         aMarkRange = ScRange( GetViewData()->GetCurX(), GetViewData()->GetCurY(), nTab );
1353 
1354     ScDocument* pUndoDoc = NULL;
1355 //  if ( bRecord )
1356     if (bUndo)
1357     {
1358         pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1359         pUndoDoc->InitUndo( pDoc, nTab, nTab );
1360 //      pUndoDoc->SelectTable( nTab, sal_True );        // nur fuer Markierung
1361 
1362         SCTAB nTabCount = pDoc->GetTableCount();
1363         for (SCTAB i=0; i<nTabCount; i++)
1364             if (i != nTab && rMark.GetTableSelect(i))
1365             {
1366                 pUndoDoc->AddUndoTab( i, i );
1367                 aMarkRange.aStart.SetTab( i );
1368                 aMarkRange.aEnd.SetTab( i );
1369                 pDoc->CopyToDocument( aMarkRange, IDF_ALL, bMulti, pUndoDoc );
1370 //              pUndoDoc->SelectTable( i, sal_True );
1371             }
1372     }
1373 
1374     if (bMulti)
1375         pDoc->FillTabMarked( nTab, rMark, nFlags, nFunction, bSkipEmpty, bAsLink );
1376     else
1377     {
1378         aMarkRange.aStart.SetTab( nTab );
1379         aMarkRange.aEnd.SetTab( nTab );
1380         pDoc->FillTab( aMarkRange, rMark, nFlags, nFunction, bSkipEmpty, bAsLink );
1381     }
1382 
1383 //  if ( bRecord )
1384     if (bUndo)
1385     {   //! fuer ChangeTrack erst zum Schluss
1386         pDocSh->GetUndoManager()->AddUndoAction(
1387             new ScUndoFillTable( pDocSh, rMark,
1388                                 aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), nTab,
1389                                 aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), nTab,
1390                                 pUndoDoc, bMulti, nTab, nFlags, nFunction, bSkipEmpty, bAsLink ) );
1391     }
1392 
1393     pDocSh->PostPaintGridAll();
1394     pDocSh->PostDataChanged();
1395 }
1396 
1397 //----------------------------------------------------------------------------
1398 
1399 /** Downward fill of selected cell(s) by double-clicking cross-hair cursor
1400 
1401     Extends a current selection down to the last non-empty cell of an adjacent
1402     column when the lower-right corner of the selection is double-clicked.  It
1403     uses a left-adjoining non-empty column as a guide if such is available,
1404     otherwise a right-adjoining non-empty column is used.
1405 
1406     @author Kohei Yoshida (kohei@openoffice.org)
1407 
1408     @return No return value
1409 
1410     @see #i12313#
1411 */
1412 void ScViewFunc::FillCrossDblClick()
1413 {
1414     ScRange aRange;
1415     GetViewData()->GetSimpleArea( aRange );
1416     aRange.Justify();
1417 
1418     SCTAB nTab = GetViewData()->GetCurPos().Tab();
1419     SCCOL nStartX = aRange.aStart.Col();
1420     SCROW nStartY = aRange.aStart.Row();
1421     SCCOL nEndX   = aRange.aEnd.Col();
1422     SCROW nEndY   = aRange.aEnd.Row();
1423 
1424     ScDocument* pDoc = GetViewData()->GetDocument();
1425 
1426     // Make sure the selection is not empty
1427     if ( pDoc->IsBlockEmpty( nTab, nStartX, nStartY, nEndX, nEndY ) )
1428         return;
1429 
1430     if ( nEndY < MAXROW )
1431     {
1432         if ( nStartX > 0 )
1433         {
1434             SCCOL nMovX = nStartX - 1;
1435             SCROW nMovY = nStartY;
1436 
1437             if ( pDoc->HasData( nMovX, nStartY, nTab ) &&
1438                  pDoc->HasData( nMovX, nStartY + 1, nTab ) )
1439             {
1440                 pDoc->FindAreaPos( nMovX, nMovY, nTab, 0, 1 );
1441 
1442                 if ( nMovY > nEndY )
1443                 {
1444                     FillAuto( FILL_TO_BOTTOM, nStartX, nStartY, nEndX, nEndY,
1445                               nMovY - nEndY );
1446                     return;
1447                 }
1448             }
1449         }
1450 
1451         if ( nEndX < MAXCOL )
1452         {
1453             SCCOL nMovX = nEndX + 1;
1454             SCROW nMovY = nStartY;
1455 
1456             if ( pDoc->HasData( nMovX, nStartY, nTab ) &&
1457                  pDoc->HasData( nMovX, nStartY + 1, nTab ) )
1458             {
1459                 pDoc->FindAreaPos( nMovX, nMovY, nTab, 0, 1 );
1460 
1461                 if ( nMovY > nEndY )
1462                 {
1463                     FillAuto( FILL_TO_BOTTOM, nStartX, nStartY, nEndX, nEndY,
1464                               nMovY - nEndY );
1465                     return;
1466                 }
1467             }
1468         }
1469     }
1470 }
1471 
1472 //----------------------------------------------------------------------------
1473 
1474 void ScViewFunc::TransliterateText( sal_Int32 nType )
1475 {
1476     ScMarkData aFuncMark = GetViewData()->GetMarkData();
1477     if ( !aFuncMark.IsMarked() && !aFuncMark.IsMultiMarked() )
1478     {
1479         //  no selection -> use cursor position
1480 
1481         ScAddress aCursor( GetViewData()->GetCurX(), GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
1482         aFuncMark.SetMarkArea( ScRange( aCursor ) );
1483     }
1484 
1485     sal_Bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().
1486                         TransliterateText( aFuncMark, nType, sal_True, sal_False );
1487     if (bSuccess)
1488     {
1489         GetViewData()->GetViewShell()->UpdateInputHandler();
1490     }
1491 }
1492 
1493 //----------------------------------------------------------------------------
1494 //  AutoFormat
1495 
1496 ScAutoFormatData* ScViewFunc::CreateAutoFormatData()
1497 {
1498     ScAutoFormatData* pData = NULL;
1499     SCCOL nStartCol;
1500     SCROW nStartRow;
1501     SCTAB nStartTab;
1502     SCCOL nEndCol;
1503     SCROW nEndRow;
1504     SCTAB nEndTab;
1505     if (GetViewData()->GetSimpleArea(nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab) == SC_MARK_SIMPLE)
1506     {
1507         if ( nEndCol-nStartCol >= 3 && nEndRow-nStartRow >= 3 )
1508         {
1509             ScDocument* pDoc = GetViewData()->GetDocument();
1510             pData = new ScAutoFormatData;
1511             pDoc->GetAutoFormatData( nStartTab, nStartCol,nStartRow,nEndCol,nEndRow, *pData );
1512         }
1513     }
1514     return pData;
1515 }
1516 
1517 
1518 //----------------------------------------------------------------------------
1519 
1520 void ScViewFunc::AutoFormat( sal_uInt16 nFormatNo, sal_Bool bRecord )
1521 {
1522 #if 1
1523 
1524     ScRange aRange;
1525     if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
1526     {
1527         ScDocShell* pDocSh = GetViewData()->GetDocShell();
1528         ScMarkData& rMark = GetViewData()->GetMarkData();
1529 
1530         sal_Bool bSuccess = pDocSh->GetDocFunc().AutoFormat( aRange, &rMark, nFormatNo, bRecord, sal_False );
1531         if (bSuccess)
1532             pDocSh->UpdateOle(GetViewData());
1533     }
1534     else
1535         ErrorMessage(STR_NOMULTISELECT);
1536 
1537 #else
1538 
1539     // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
1540     sal_Bool bOnlyNotBecauseOfMatrix;
1541     if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
1542     {
1543         ErrorMessage(STR_PROTECTIONERR);
1544         return;
1545     }
1546 
1547     SCCOL nStartCol;
1548     SCROW nStartRow;
1549     SCTAB nStartTab;
1550     SCCOL nEndCol;
1551     SCROW nEndRow;
1552     SCTAB nEndTab;
1553 
1554     if (GetViewData()->GetSimpleArea(nStartCol,nStartRow,nStartTab,nEndCol,nEndRow,nEndTab) == SC_MARK_SIMPLE)
1555     {
1556         ScDocShell* pDocSh = GetViewData()->GetDocShell();
1557         ScDocument* pDoc = pDocSh->GetDocument();
1558         ScMarkData& rMark = GetViewData()->GetMarkData();
1559         sal_Bool bSize = (*ScGlobal::GetAutoFormat())[nFormatNo]->GetIncludeWidthHeight();
1560         if (bRecord && !pDoc->IsUndoEnabled())
1561             bRecord = sal_False;
1562 
1563         ScDocument* pUndoDoc = NULL;
1564         if ( bRecord )
1565         {
1566             pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1567             pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab, bSize, bSize );
1568             pDoc->CopyToDocument( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab,
1569                                     IDF_ATTRIB, sal_False, pUndoDoc );
1570             if (bSize)
1571             {
1572                 pDoc->CopyToDocument( nStartCol,0,nStartTab, nEndCol,MAXROW,nEndTab,
1573                                                             IDF_NONE, sal_False, pUndoDoc );
1574                 pDoc->CopyToDocument( 0,nStartRow,nStartTab, MAXCOL,nEndRow,nEndTab,
1575                                                             IDF_NONE, sal_False, pUndoDoc );
1576             }
1577             pDoc->BeginDrawUndo();
1578         }
1579 
1580         GetFrameWin()->EnterWait();
1581         pDoc->AutoFormat( nStartCol, nStartRow, nEndCol, nEndRow, nFormatNo, rMark );
1582         GetFrameWin()->LeaveWait();
1583 
1584         if (bSize)
1585         {
1586             SetMarkedWidthOrHeight( sal_True, SC_SIZE_VISOPT, STD_EXTRA_WIDTH, sal_False, sal_False );
1587             SetMarkedWidthOrHeight( sal_False, SC_SIZE_VISOPT, 0, sal_False, sal_False );
1588             pDocSh->PostPaint( 0,0,nStartTab, MAXCOL,MAXROW,nStartTab,
1589                                     PAINT_GRID | PAINT_LEFT | PAINT_TOP );
1590         }
1591         else
1592         {
1593             sal_Bool bAdj = AdjustBlockHeight( sal_False );
1594             if (bAdj)
1595                 pDocSh->PostPaint( 0,nStartRow,nStartTab, MAXCOL,MAXROW,nStartTab,
1596                                     PAINT_GRID | PAINT_LEFT );
1597             else
1598                 pDocSh->PostPaint( nStartCol, nStartRow, nStartTab,
1599                                     nEndCol, nEndRow, nEndTab, PAINT_GRID );
1600         }
1601 
1602         if ( bRecord )      // Draw-Undo erst jetzt verfuegbar
1603         {
1604             pDocSh->GetUndoManager()->AddUndoAction(
1605                 new ScUndoAutoFormat( pDocSh,
1606                         ScRange(nStartCol,nStartRow,nStartTab, nEndCol,nEndRow,nEndTab),
1607                         pUndoDoc, rMark, bSize, nFormatNo ) );
1608         }
1609 
1610         pDocSh->UpdateOle(GetViewData());
1611         pDocSh->SetDocumentModified();
1612     }
1613     else
1614         ErrorMessage(STR_NOMULTISELECT);
1615 
1616 #endif
1617 }
1618 
1619 
1620 //----------------------------------------------------------------------------
1621 //  Suchen & Ersetzen
1622 
1623 void ScViewFunc::SearchAndReplace( const SvxSearchItem* pSearchItem,
1624                                         sal_Bool bAddUndo, sal_Bool bIsApi )
1625 {
1626     ScDocShell* pDocSh = GetViewData()->GetDocShell();
1627     ScDocument* pDoc = pDocSh->GetDocument();
1628     ScMarkData& rMark = GetViewData()->GetMarkData();
1629     if (bAddUndo && !pDoc->IsUndoEnabled())
1630         bAddUndo = sal_False;
1631 
1632     SCCOL nCol = GetViewData()->GetCurX();
1633     SCROW nRow = GetViewData()->GetCurY();
1634     SCTAB nTab = GetViewData()->GetTabNo();
1635 //    sal_Bool bAttrib = pSearchItem->GetPattern();
1636     sal_uInt16 nCommand = pSearchItem->GetCommand();
1637     sal_Bool bAllTables = pSearchItem->IsAllTables();
1638     sal_Bool* pOldSelectedTables = NULL;
1639     sal_uInt16 nOldSelectedCount = 0;
1640     SCTAB nOldTab = nTab;
1641     SCTAB nLastTab = pDoc->GetTableCount() - 1;
1642     SCTAB nStartTab, nEndTab;
1643     if ( bAllTables )
1644     {
1645         nStartTab = 0;
1646         nEndTab = nLastTab;
1647         pOldSelectedTables = new sal_Bool [ nEndTab + 1 ];
1648         for ( SCTAB j = 0; j <= nEndTab; j++ )
1649         {
1650             pOldSelectedTables[j] = rMark.GetTableSelect( j );
1651             if ( pOldSelectedTables[j] )
1652                 ++nOldSelectedCount;
1653         }
1654     }
1655     else
1656     {   //! mindestens eine ist immer selektiert
1657         nStartTab = nEndTab = rMark.GetFirstSelected();
1658         for ( SCTAB j = nStartTab + 1; j <= nLastTab; j++ )
1659         {
1660             if ( rMark.GetTableSelect( j ) )
1661                 nEndTab = j;
1662         }
1663     }
1664 
1665     if (   nCommand == SVX_SEARCHCMD_REPLACE
1666         || nCommand == SVX_SEARCHCMD_REPLACE_ALL )
1667     {
1668         for ( SCTAB j = nStartTab; j <= nEndTab; j++ )
1669         {
1670             if ( (bAllTables || rMark.GetTableSelect( j )) &&
1671                     pDoc->IsTabProtected( j ) )
1672             {
1673                 if ( pOldSelectedTables )
1674                     delete [] pOldSelectedTables;
1675                 ErrorMessage(STR_PROTECTIONERR);
1676                 return;
1677             }
1678         }
1679     }
1680 
1681     if (   nCommand == SVX_SEARCHCMD_FIND
1682         || nCommand == SVX_SEARCHCMD_FIND_ALL)
1683         bAddUndo = sal_False;
1684 
1685     //!     bAttrib bei Undo beruecksichtigen !!!
1686 
1687     ScDocument* pUndoDoc = NULL;
1688     ScMarkData* pUndoMark = NULL;
1689     String aUndoStr;
1690     if (bAddUndo)
1691     {
1692         pUndoMark = new ScMarkData( rMark );                // Markierung wird veraendert
1693         if ( nCommand == SVX_SEARCHCMD_REPLACE_ALL )
1694         {
1695             pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1696             pUndoDoc->InitUndo( pDoc, nStartTab, nEndTab );
1697         }
1698     }
1699 
1700     if ( bAllTables )
1701     {   //! alles selektieren, erst nachdem pUndoMark erzeugt wurde
1702         for ( SCTAB j = nStartTab; j <= nEndTab; j++ )
1703         {
1704             rMark.SelectTable( j, sal_True );
1705         }
1706     }
1707 
1708     DoneBlockMode(sal_True);                // Markierung nicht loeschen!
1709     InitOwnBlockMode();
1710 
1711     //  wenn vom Anfang an gesucht wird, nicht nochmal fragen ob vom Anfang gesucht werden soll
1712     sal_Bool bFirst = sal_True;
1713     if ( nCol == 0 && nRow == 0 && nTab == nStartTab && !pSearchItem->GetBackward()  )
1714         bFirst = sal_False;
1715 
1716     sal_Bool bFound = sal_False;
1717     while (sal_True)
1718     {
1719         GetFrameWin()->EnterWait();
1720         if (pDoc->SearchAndReplace( *pSearchItem, nCol, nRow, nTab, rMark, aUndoStr, pUndoDoc ) )
1721         {
1722             bFound = sal_True;
1723             bFirst = sal_True;
1724             if (bAddUndo)
1725             {
1726                 GetViewData()->GetDocShell()->GetUndoManager()->AddUndoAction(
1727                     new ScUndoReplace( GetViewData()->GetDocShell(), *pUndoMark,
1728                                         nCol, nRow, nTab,
1729                                         aUndoStr, pUndoDoc, pSearchItem ) );
1730                 pUndoDoc = NULL;
1731             }
1732 
1733             break;                  // Abbruch while True
1734         }
1735         else if ( bFirst && (nCommand == SVX_SEARCHCMD_FIND ||
1736                 nCommand == SVX_SEARCHCMD_REPLACE) )
1737         {
1738             bFirst = sal_False;
1739             sal_uInt16 nRetVal;
1740             GetFrameWin()->LeaveWait();
1741             if ( bIsApi )
1742                 nRetVal = RET_NO;
1743             else
1744             {
1745                 //  Suchen-Dialog als Parent, wenn vorhanden
1746                 Window* pParent = GetParentOrChild(SID_SEARCH_DLG);
1747                 sal_uInt16 nStrId;
1748                 if ( pSearchItem->GetBackward() )
1749                 {
1750                     if ( nStartTab == nEndTab )
1751                         nStrId = STR_MSSG_SEARCHANDREPLACE_1;
1752                     else
1753                         nStrId = STR_MSSG_SEARCHANDREPLACE_4;
1754                 }
1755                 else
1756                 {
1757                     if ( nStartTab == nEndTab )
1758                         nStrId = STR_MSSG_SEARCHANDREPLACE_2;
1759                     else
1760                         nStrId = STR_MSSG_SEARCHANDREPLACE_5;
1761                 }
1762                 MessBox aBox( pParent, WinBits(WB_YES_NO | WB_DEF_YES),
1763                                 ScGlobal::GetRscString( STR_MSSG_SEARCHANDREPLACE_3 ),
1764                                 ScGlobal::GetRscString( nStrId ) );
1765                 nRetVal = aBox.Execute();
1766             }
1767 
1768             if ( nRetVal == RET_YES )
1769             {
1770                 ScDocument::GetSearchAndReplaceStart( *pSearchItem, nCol, nRow );
1771                 if (pSearchItem->GetBackward())
1772                     nTab = nEndTab;
1773                 else
1774                     nTab = nStartTab;
1775             }
1776             else
1777             {
1778                 break;                  // Abbruch while True
1779             }
1780         }
1781         else                            // nichts gefunden
1782         {
1783             if ( nCommand == SVX_SEARCHCMD_FIND_ALL || nCommand == SVX_SEARCHCMD_REPLACE_ALL )
1784             {
1785                 pDocSh->PostPaintGridAll();                             // Markierung
1786             }
1787 
1788             GetFrameWin()->LeaveWait();
1789             if (!bIsApi)
1790             {
1791                 //  Suchen-Dialog als Parent, wenn vorhanden
1792                 Window* pParent = GetParentOrChild(SID_SEARCH_DLG);
1793                 // "nichts gefunden"
1794                 InfoBox aBox( pParent, ScGlobal::GetRscString( STR_MSSG_SEARCHANDREPLACE_0 ) );
1795                 aBox.Execute();
1796             }
1797 
1798             break;                      // Abbruch while True
1799         }
1800     }                               // of while sal_True
1801 
1802     if ( pOldSelectedTables )
1803     {   // urspruenglich selektierte Tabellen wiederherstellen
1804         for ( SCTAB j = nStartTab; j <= nEndTab; j++ )
1805         {
1806             rMark.SelectTable( j, pOldSelectedTables[j] );
1807         }
1808         if ( bFound )
1809         {   // durch Fundstelle neu selektierte Tabelle bleibt
1810             rMark.SelectTable( nTab, sal_True );
1811             // wenn vorher nur eine selektiert war, ist es ein Tausch
1812             //! wenn nicht, ist jetzt evtl. eine mehr selektiert
1813             if ( nOldSelectedCount == 1 && nTab != nOldTab )
1814                 rMark.SelectTable( nOldTab, sal_False );
1815         }
1816         delete [] pOldSelectedTables;
1817     }
1818 
1819     MarkDataChanged();
1820 
1821     if ( bFound )
1822     {
1823         if ( nTab != GetViewData()->GetTabNo() )
1824             SetTabNo( nTab );
1825 
1826         //  wenn nichts markiert ist, DoneBlockMode, damit von hier aus
1827         //  direkt per Shift-Cursor markiert werden kann:
1828         if (!rMark.IsMarked() && !rMark.IsMultiMarked())
1829             DoneBlockMode(sal_True);
1830 
1831         AlignToCursor( nCol, nRow, SC_FOLLOW_JUMP );
1832         SetCursor( nCol, nRow, sal_True );
1833 
1834         if (   nCommand == SVX_SEARCHCMD_REPLACE
1835             || nCommand == SVX_SEARCHCMD_REPLACE_ALL )
1836         {
1837             if ( nCommand == SVX_SEARCHCMD_REPLACE )
1838                 pDocSh->PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PAINT_GRID );
1839             else
1840                 pDocSh->PostPaintGridAll();
1841             pDocSh->SetDocumentModified();
1842         }
1843         else if ( nCommand == SVX_SEARCHCMD_FIND_ALL )
1844             pDocSh->PostPaintGridAll();                             // Markierung
1845         GetFrameWin()->LeaveWait();
1846     }
1847 
1848     delete pUndoDoc;            // loeschen wenn nicht benutzt
1849     delete pUndoMark;           // kann immer geloescht werden
1850 }
1851 
1852 
1853 //----------------------------------------------------------------------------
1854 //  Zielwertsuche
1855 
1856 void ScViewFunc::Solve( const ScSolveParam& rParam )
1857 {
1858     ScDocument* pDoc = GetViewData()->GetDocument();
1859 
1860     SCCOL nDestCol = rParam.aRefVariableCell.Col();
1861     SCROW nDestRow = rParam.aRefVariableCell.Row();
1862     SCTAB nDestTab = rParam.aRefVariableCell.Tab();
1863 
1864     ScEditableTester aTester( pDoc, nDestTab, nDestCol,nDestRow, nDestCol,nDestRow );
1865     if (!aTester.IsEditable())
1866     {
1867         ErrorMessage(aTester.GetMessageId());
1868         return;
1869     }
1870 
1871     if ( pDoc )
1872     {
1873         String  aTargetValStr;
1874         if ( rParam.pStrTargetVal != NULL )
1875             aTargetValStr = *(rParam.pStrTargetVal);
1876 
1877         String  aMsgStr;
1878         String  aResStr;
1879         double  nSolveResult;
1880 
1881         GetFrameWin()->EnterWait();
1882 
1883         sal_Bool    bExact =
1884                     pDoc->Solver(
1885                         rParam.aRefFormulaCell.Col(),
1886                         rParam.aRefFormulaCell.Row(),
1887                         rParam.aRefFormulaCell.Tab(),
1888                         nDestCol, nDestRow, nDestTab,
1889                         aTargetValStr,
1890                         nSolveResult );
1891 
1892         GetFrameWin()->LeaveWait();
1893 
1894         SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
1895         sal_uLong nFormat = 0;
1896         const ScPatternAttr* pPattern = pDoc->GetPattern( nDestCol, nDestRow, nDestTab );
1897         if ( pPattern )
1898             nFormat = pPattern->GetNumberFormat( pFormatter );
1899         Color* p;
1900         pFormatter->GetOutputString( nSolveResult, nFormat, aResStr, &p );
1901 
1902         if ( bExact )
1903         {
1904             aMsgStr  = ScGlobal::GetRscString( STR_MSSG_SOLVE_0 );
1905             aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_1 );
1906             aMsgStr += String( aResStr );
1907             aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_2 );
1908         }
1909         else
1910         {
1911             aMsgStr  = ScGlobal::GetRscString( STR_MSSG_SOLVE_3 );
1912             aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_4 );
1913             aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_5 );
1914             aMsgStr += String( aResStr );
1915             aMsgStr += ScGlobal::GetRscString( STR_MSSG_SOLVE_6 );
1916         }
1917 
1918         MessBox aBox( GetViewData()->GetDialogParent(),
1919                         WinBits(WB_YES_NO | WB_DEF_NO),
1920                         ScGlobal::GetRscString( STR_MSSG_DOSUBTOTALS_0 ), aMsgStr );
1921         sal_uInt16 nRetVal = aBox.Execute();
1922 
1923         if ( RET_YES == nRetVal )
1924             EnterValue( nDestCol, nDestRow, nDestTab, nSolveResult );
1925 
1926         GetViewData()->GetViewShell()->UpdateInputHandler( sal_True );
1927     }
1928 }
1929 
1930 
1931 //----------------------------------------------------------------------------
1932 //  Mehrfachoperation
1933 
1934 void ScViewFunc::TabOp( const ScTabOpParam& rParam, sal_Bool bRecord )
1935 {
1936     ScRange aRange;
1937     if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
1938     {
1939         ScDocShell* pDocSh = GetViewData()->GetDocShell();
1940         ScMarkData& rMark = GetViewData()->GetMarkData();
1941         pDocSh->GetDocFunc().TabOp( aRange, &rMark, rParam, bRecord, sal_False );
1942     }
1943     else
1944         ErrorMessage(STR_NOMULTISELECT);
1945 }
1946 
1947 
1948 //----------------------------------------------------------------------------
1949 
1950 void ScViewFunc::MakeScenario( const String& rName, const String& rComment,
1951                                     const Color& rColor, sal_uInt16 nFlags )
1952 {
1953     ScDocShell* pDocSh  = GetViewData()->GetDocShell();
1954     ScMarkData& rMark   = GetViewData()->GetMarkData();
1955     SCTAB       nTab    = GetViewData()->GetTabNo();
1956 
1957     SCTAB nNewTab = pDocSh->MakeScenario( nTab, rName, rComment, rColor, nFlags, rMark );
1958     if (nFlags & SC_SCENARIO_COPYALL)
1959         SetTabNo( nNewTab, sal_True );          // SC_SCENARIO_COPYALL -> sichtbar
1960     else
1961     {
1962         SfxBindings& rBindings = GetViewData()->GetBindings();
1963         rBindings.Invalidate( SID_STATUS_DOCPOS );      // Statusbar
1964         rBindings.Invalidate( SID_TABLES_COUNT );
1965         rBindings.Invalidate( SID_SELECT_SCENARIO );
1966         rBindings.Invalidate( FID_TABLE_SHOW );
1967     }
1968 }
1969 
1970 
1971 //----------------------------------------------------------------------------
1972 
1973 void ScViewFunc::ExtendScenario()
1974 {
1975     ScEditableTester aTester( this );
1976     if (!aTester.IsEditable())
1977     {
1978         ErrorMessage(aTester.GetMessageId());
1979         return;
1980     }
1981 
1982         //  Undo: Attribute anwenden
1983 
1984     ScDocument* pDoc = GetViewData()->GetDocument();
1985     ScPatternAttr aPattern( pDoc->GetPool() );
1986     aPattern.GetItemSet().Put( ScMergeFlagAttr( SC_MF_SCENARIO ) );
1987     aPattern.GetItemSet().Put( ScProtectionAttr( sal_True ) );
1988     ApplySelectionPattern(aPattern);
1989 }
1990 
1991 
1992 //----------------------------------------------------------------------------
1993 
1994 void ScViewFunc::UseScenario( const String& rName )
1995 {
1996     ScDocShell* pDocSh  = GetViewData()->GetDocShell();
1997     SCTAB       nTab    = GetViewData()->GetTabNo();
1998 
1999     DoneBlockMode();
2000     InitOwnBlockMode();
2001     pDocSh->UseScenario( nTab, rName );
2002 }
2003 
2004 
2005 //----------------------------------------------------------------------------
2006 //  Tabelle einfuegen
2007 
2008 sal_Bool ScViewFunc::InsertTable( const String& rName, SCTAB nTab, sal_Bool bRecord )
2009 {
2010     //  Reihenfolge Tabelle/Name ist bei DocFunc umgekehrt
2011     sal_Bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().
2012                         InsertTable( nTab, rName, bRecord, sal_False );
2013     if (bSuccess)
2014         SetTabNo( nTab, sal_True );
2015 
2016     return bSuccess;
2017 }
2018 
2019 //----------------------------------------------------------------------------
2020 //  Tabellen einfuegen
2021 
2022 sal_Bool ScViewFunc::InsertTables(SvStrings *pNames, SCTAB nTab,
2023                                             SCTAB nCount, sal_Bool bRecord )
2024 {
2025     ScDocShell* pDocSh  = GetViewData()->GetDocShell();
2026     ScDocument* pDoc    = pDocSh->GetDocument();
2027     if (bRecord && !pDoc->IsUndoEnabled())
2028         bRecord = sal_False;
2029 
2030     SvStrings *pNameList= NULL;
2031 
2032     WaitObject aWait( GetFrameWin() );
2033 
2034     if (bRecord)
2035     {
2036         pNameList= new SvStrings;
2037         pDoc->BeginDrawUndo();                          //  InsertTab erzeugt ein SdrUndoNewPage
2038     }
2039 
2040     sal_Bool bFlag=sal_False;
2041 
2042     String aValTabName;
2043     String *pStr;
2044 
2045     for(SCTAB i=0;i<nCount;i++)
2046     {
2047         if(pNames!=NULL)
2048         {
2049             pStr=pNames->GetObject(static_cast<sal_uInt16>(i));
2050         }
2051         else
2052         {
2053             aValTabName.Erase();
2054             pDoc->CreateValidTabName( aValTabName);
2055             pStr=&aValTabName;
2056         }
2057 
2058         if(pDoc->InsertTab( nTab+i,*pStr))
2059         {
2060             bFlag=sal_True;
2061             pDocSh->Broadcast( ScTablesHint( SC_TAB_INSERTED, nTab+i ) );
2062         }
2063         else
2064         {
2065             break;
2066         }
2067 
2068         if(pNameList!=NULL)
2069             pNameList->Insert(new String(*pStr),pNameList->Count());
2070 
2071     }
2072 
2073     if (bFlag)
2074     {
2075         if (bRecord)
2076             pDocSh->GetUndoManager()->AddUndoAction(
2077                         new ScUndoInsertTables( pDocSh, nTab, sal_False, pNameList));
2078 
2079         //  Views updaten:
2080 
2081         SetTabNo( nTab, sal_True );
2082         pDocSh->PostPaintExtras();
2083         pDocSh->SetDocumentModified();
2084         SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2085         return sal_True;
2086     }
2087     else
2088     {
2089         return sal_False;
2090     }
2091 }
2092 
2093 
2094 //----------------------------------------------------------------------------
2095 
2096 sal_Bool ScViewFunc::AppendTable( const String& rName, sal_Bool bRecord )
2097 {
2098     ScDocShell* pDocSh = GetViewData()->GetDocShell();
2099     ScDocument* pDoc   = pDocSh->GetDocument();
2100     if (bRecord && !pDoc->IsUndoEnabled())
2101         bRecord = sal_False;
2102 
2103     WaitObject aWait( GetFrameWin() );
2104 
2105     if (bRecord)
2106         pDoc->BeginDrawUndo();                          //  InsertTab erzeugt ein SdrUndoNewPage
2107 
2108     if (pDoc->InsertTab( SC_TAB_APPEND, rName ))
2109     {
2110         SCTAB nTab = pDoc->GetTableCount()-1;
2111         if (bRecord)
2112             pDocSh->GetUndoManager()->AddUndoAction(
2113                         new ScUndoInsertTab( pDocSh, nTab, sal_True, rName));
2114         GetViewData()->InsertTab( nTab );
2115         SetTabNo( nTab, sal_True );
2116         pDocSh->PostPaintExtras();
2117         pDocSh->SetDocumentModified();
2118         SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2119         return sal_True;
2120     }
2121     else
2122     {
2123         return sal_False;
2124     }
2125 }
2126 
2127 
2128 //----------------------------------------------------------------------------
2129 
2130 sal_Bool ScViewFunc::DeleteTable( SCTAB nTab, sal_Bool bRecord )
2131 {
2132     ScDocShell* pDocSh  = GetViewData()->GetDocShell();
2133     ScDocument* pDoc    = pDocSh->GetDocument();
2134 
2135     sal_Bool bSuccess = pDocSh->GetDocFunc().DeleteTable( nTab, bRecord, sal_False );
2136     if (bSuccess)
2137     {
2138         SCTAB nNewTab = nTab;
2139         if ( nNewTab >= pDoc->GetTableCount() )
2140             --nNewTab;
2141         SetTabNo( nNewTab, sal_True );
2142     }
2143     return bSuccess;
2144 }
2145 
2146 sal_Bool ScViewFunc::DeleteTables(const SvShorts &TheTabs, sal_Bool bRecord )
2147 {
2148     ScDocShell* pDocSh  = GetViewData()->GetDocShell();
2149     ScDocument* pDoc    = pDocSh->GetDocument();
2150     sal_Bool bVbaEnabled = pDoc ? pDoc->IsInVBAMode() : sal_False;
2151     SCTAB       nNewTab = TheTabs.front();
2152     WaitObject aWait( GetFrameWin() );
2153     if (bRecord && !pDoc->IsUndoEnabled())
2154         bRecord = sal_False;
2155 
2156     while ( nNewTab > 0 && !pDoc->IsVisible( nNewTab ) )
2157         --nNewTab;
2158 
2159     sal_Bool bWasLinked = sal_False;
2160     ScDocument* pUndoDoc = NULL;
2161     ScRefUndoData* pUndoData = NULL;
2162     if (bRecord)
2163     {
2164         pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2165 //      pUndoDoc->InitDrawLayer( pDocSh );
2166         SCTAB nCount = pDoc->GetTableCount();
2167 
2168 //      pUndoDoc->InitUndo( pDoc, 0, nCount-1 );        // incl. Ref.
2169 
2170         String aOldName;
2171         for (size_t i = 0; i < TheTabs.size(); i++)
2172         {
2173             SCTAB nTab = TheTabs[i];
2174             if (i==0)
2175                 pUndoDoc->InitUndo( pDoc, nTab,nTab, sal_True,sal_True );   // incl. Spalten/Zeilenflags
2176             else
2177                 pUndoDoc->AddUndoTab( nTab,nTab, sal_True,sal_True );       // incl. Spalten/Zeilenflags
2178 
2179             pDoc->CopyToDocument(0,0,nTab, MAXCOL,MAXROW,nTab, IDF_ALL,sal_False, pUndoDoc );
2180             pDoc->GetName( nTab, aOldName );
2181             pUndoDoc->RenameTab( nTab, aOldName, sal_False );
2182             if (pDoc->IsLinked(nTab))
2183             {
2184                 bWasLinked = sal_True;
2185                 pUndoDoc->SetLink( nTab, pDoc->GetLinkMode(nTab), pDoc->GetLinkDoc(nTab),
2186                                     pDoc->GetLinkFlt(nTab), pDoc->GetLinkOpt(nTab),
2187                                     pDoc->GetLinkTab(nTab),
2188                                     pDoc->GetLinkRefreshDelay(nTab) );
2189             }
2190             if ( pDoc->IsScenario(nTab) )
2191             {
2192                 pUndoDoc->SetScenario( nTab, sal_True );
2193                 String aComment;
2194                 Color  aColor;
2195                 sal_uInt16 nScenFlags;
2196                 pDoc->GetScenarioData( nTab, aComment, aColor, nScenFlags );
2197                 pUndoDoc->SetScenarioData( nTab, aComment, aColor, nScenFlags );
2198                 sal_Bool bActive = pDoc->IsActiveScenario( nTab );
2199                 pUndoDoc->SetActiveScenario( nTab, bActive );
2200             }
2201             pUndoDoc->SetVisible( nTab, pDoc->IsVisible( nTab ) );
2202             pUndoDoc->SetTabBgColor( nTab, pDoc->GetTabBgColor(nTab) );
2203             pUndoDoc->SetSheetEvents( nTab, pDoc->GetSheetEvents( nTab ) );
2204 
2205             if ( pDoc->IsTabProtected( nTab ) )
2206                 pUndoDoc->SetTabProtection(nTab, pDoc->GetTabProtection(nTab));
2207 
2208             //  Drawing-Layer muss sein Undo selbst in der Hand behalten !!!
2209             //      pUndoDoc->TransferDrawPage(pDoc, nTab,nTab);
2210         }
2211 
2212         pUndoDoc->AddUndoTab( 0, nCount-1 );            //  alle Tabs fuer Referenzen
2213 
2214         pDoc->BeginDrawUndo();                          //  DeleteTab erzeugt ein SdrUndoDelPage
2215 
2216         pUndoData = new ScRefUndoData( pDoc );
2217     }
2218 
2219     sal_Bool bDelDone = sal_False;
2220 
2221     for (size_t i = TheTabs.size(); i > 0; i--)
2222     {
2223         String sCodeName;
2224         sal_Bool bHasCodeName = pDoc->GetCodeName( TheTabs[i-1], sCodeName );
2225         if (pDoc->DeleteTab( TheTabs[i-1], pUndoDoc ))
2226         {
2227             bDelDone = sal_True;
2228             if( bVbaEnabled )
2229             {
2230                 if( bHasCodeName )
2231                 {
2232                     VBA_DeleteModule( *pDocSh, sCodeName );
2233                 }
2234             }
2235             pDocSh->Broadcast( ScTablesHint( SC_TAB_DELETED, TheTabs[i-1] ) );
2236         }
2237     }
2238     if (bRecord)
2239     {
2240         pDocSh->GetUndoManager()->AddUndoAction(
2241                     new ScUndoDeleteTab( GetViewData()->GetDocShell(), TheTabs,
2242                                             pUndoDoc, pUndoData ));
2243     }
2244 
2245 
2246     if (bDelDone)
2247     {
2248         if ( nNewTab >= pDoc->GetTableCount() )
2249             nNewTab = pDoc->GetTableCount() - 1;
2250 
2251         SetTabNo( nNewTab, sal_True );
2252 
2253         if (bWasLinked)
2254         {
2255             pDocSh->UpdateLinks();              // Link-Manager updaten
2256             GetViewData()->GetBindings().Invalidate(SID_LINKS);
2257         }
2258 
2259         pDocSh->PostPaintExtras();
2260         pDocSh->SetDocumentModified();
2261 
2262         SfxApplication* pSfxApp = SFX_APP();                                // Navigator
2263         pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2264         pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_DBAREAS_CHANGED ) );
2265         pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
2266     }
2267     else
2268     {
2269         delete pUndoDoc;
2270         delete pUndoData;
2271     }
2272     return bDelDone;
2273 }
2274 
2275 
2276 //----------------------------------------------------------------------------
2277 
2278 sal_Bool ScViewFunc::RenameTable( const String& rName, SCTAB nTab )
2279 {
2280     //  Reihenfolge Tabelle/Name ist bei DocFunc umgekehrt
2281     sal_Bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().
2282                         RenameTable( nTab, rName, sal_True, sal_False );
2283     if (bSuccess)
2284     {
2285         //  Der Tabellenname koennte in einer Formel vorkommen...
2286         GetViewData()->GetViewShell()->UpdateInputHandler();
2287     }
2288     return bSuccess;
2289 }
2290 
2291 
2292 //----------------------------------------------------------------------------
2293 
2294 bool ScViewFunc::SetTabBgColor( const Color& rColor, SCTAB nTab )
2295 {
2296     bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().SetTabBgColor( nTab, rColor, sal_True, sal_False );
2297     if (bSuccess)
2298     {
2299         GetViewData()->GetViewShell()->UpdateInputHandler();
2300     }
2301     return bSuccess;
2302 }
2303 
2304 bool ScViewFunc::SetTabBgColor( ScUndoTabColorInfo::List& rUndoSetTabBgColorInfoList )
2305 {
2306     bool bSuccess = GetViewData()->GetDocShell()->GetDocFunc().SetTabBgColor( rUndoSetTabBgColorInfoList, sal_True, sal_False );
2307     if (bSuccess)
2308     {
2309         GetViewData()->GetViewShell()->UpdateInputHandler();
2310     }
2311     return bSuccess;
2312 }
2313 
2314 //----------------------------------------------------------------------------
2315 
2316 void ScViewFunc::InsertAreaLink( const String& rFile,
2317                                     const String& rFilter, const String& rOptions,
2318                                     const String& rSource, sal_uLong nRefresh )
2319 {
2320     ScDocShell* pDocSh = GetViewData()->GetDocShell();
2321     SCCOL nPosX = GetViewData()->GetCurX();
2322     SCROW nPosY = GetViewData()->GetCurY();
2323     SCTAB nTab = GetViewData()->GetTabNo();
2324     ScAddress aPos( nPosX, nPosY, nTab );
2325 
2326     pDocSh->GetDocFunc().InsertAreaLink( rFile, rFilter, rOptions, rSource, aPos, nRefresh, sal_False, sal_False );
2327 }
2328 
2329 
2330 //----------------------------------------------------------------------------
2331 
2332 void ScViewFunc::InsertTableLink( const String& rFile,
2333                                     const String& rFilter, const String& rOptions,
2334                                     const String& rTabName )
2335 {
2336     String aFilterName = rFilter;
2337     String aOpt = rOptions;
2338     ScDocumentLoader aLoader( rFile, aFilterName, aOpt );
2339     if (!aLoader.IsError())
2340     {
2341         ScDocShell* pSrcSh = aLoader.GetDocShell();
2342         ScDocument* pSrcDoc = pSrcSh->GetDocument();
2343         SCTAB nTab = MAXTAB+1;
2344         if (!rTabName.Len())                // kein Name angegeben -> erste Tabelle
2345             nTab = 0;
2346         else
2347         {
2348             String aTemp;
2349             SCTAB nCount = pSrcDoc->GetTableCount();
2350             for (SCTAB i=0; i<nCount; i++)
2351             {
2352                 pSrcDoc->GetName( i, aTemp );
2353                 if ( aTemp == rTabName )
2354                     nTab = i;
2355             }
2356         }
2357 
2358         if ( nTab <= MAXTAB )
2359             ImportTables( pSrcSh, 1, &nTab, sal_True,
2360                         GetViewData()->GetTabNo() );
2361     }
2362 }
2363 
2364 
2365 //----------------------------------------------------------------------------
2366 //  Tabellen aus anderem Dokument kopieren / linken
2367 
2368 void ScViewFunc::ImportTables( ScDocShell* pSrcShell,
2369                                 SCTAB nCount, const SCTAB* pSrcTabs, sal_Bool bLink,SCTAB nTab )
2370 {
2371     ScDocument* pSrcDoc = pSrcShell->GetDocument();
2372 
2373     ScDocShell* pDocSh = GetViewData()->GetDocShell();
2374     ScDocument* pDoc = pDocSh->GetDocument();
2375     sal_Bool bUndo(pDoc->IsUndoEnabled());
2376     //SCTAB nTab = GetViewData()->GetTabNo();
2377 
2378     sal_Bool bError = sal_False;
2379     sal_Bool bRefs = sal_False;
2380     sal_Bool bName = sal_False;
2381 
2382     if (pSrcDoc->GetDrawLayer())
2383         pDocSh->MakeDrawLayer();
2384 
2385     if (bUndo)
2386         pDoc->BeginDrawUndo();          // drawing layer must do its own undo actions
2387 
2388     SCTAB nInsCount = 0;
2389     SCTAB i;
2390     for( i=0; i<nCount; i++ )
2391     {   // #63304# insert sheets first and update all references
2392         String aName;
2393         pSrcDoc->GetName( pSrcTabs[i], aName );
2394         pDoc->CreateValidTabName( aName );
2395         if ( !pDoc->InsertTab( nTab+i, aName ) )
2396         {
2397             bError = sal_True;      // total error
2398             break;  // for
2399         }
2400         ++nInsCount;
2401     }
2402     for (i=0; i<nCount && !bError; i++)
2403     {
2404         SCTAB nSrcTab = pSrcTabs[i];
2405         SCTAB nDestTab1=nTab+i;
2406         sal_uLong nErrVal = pDoc->TransferTab( pSrcDoc, nSrcTab, nDestTab1,
2407             sal_False );        // no insert
2408 
2409         switch (nErrVal)
2410         {
2411             case 0:                     // interner Fehler oder voll Fehler
2412                 bError = sal_True;
2413                 break;
2414             case 2:
2415                 bRefs = sal_True;
2416                 break;
2417             case 3:
2418                 bName = sal_True;
2419                 break;
2420             case 4:
2421                 bRefs = bName = sal_True;
2422                 break;
2423         }
2424 
2425         // TransferTab doesn't copy drawing objects with bInsertNew=FALSE
2426         if ( !bError )
2427             pDoc->TransferDrawPage( pSrcDoc, nSrcTab, nDestTab1 );
2428 
2429         if(!bError &&pSrcDoc->IsScenario(nSrcTab))
2430         {
2431             String aComment;
2432             Color  aColor;
2433             sal_uInt16 nFlags;
2434 
2435             pSrcDoc->GetScenarioData(nSrcTab, aComment,aColor, nFlags);
2436             pDoc->SetScenario( nDestTab1,sal_True);
2437             pDoc->SetScenarioData( nTab+i,aComment,aColor,nFlags);
2438             sal_Bool bActive = pSrcDoc->IsActiveScenario(nSrcTab );
2439             pDoc->SetActiveScenario( nDestTab1, bActive );
2440             sal_Bool bVisible=pSrcDoc->IsVisible(nSrcTab);
2441             pDoc->SetVisible(nDestTab1,bVisible );
2442 
2443         }
2444     }
2445 
2446     if (bLink)
2447     {
2448         sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager();
2449 
2450         SfxMedium* pMed = pSrcShell->GetMedium();
2451         String aFileName = pMed->GetName();
2452         String aFilterName;
2453         if (pMed->GetFilter())
2454             aFilterName = pMed->GetFilter()->GetFilterName();
2455         String aOptions = ScDocumentLoader::GetOptions(*pMed);
2456 
2457         sal_Bool bWasThere = pDoc->HasLink( aFileName, aFilterName, aOptions );
2458 
2459         sal_uLong nRefresh = 0;
2460         String aTabStr;
2461         for (i=0; i<nInsCount; i++)
2462         {
2463             pSrcDoc->GetName( pSrcTabs[i], aTabStr );
2464             pDoc->SetLink( nTab+i, SC_LINK_NORMAL,
2465                         aFileName, aFilterName, aOptions, aTabStr, nRefresh );
2466         }
2467 
2468         if (!bWasThere)         // Link pro Quelldokument nur einmal eintragen
2469         {
2470             ScTableLink* pLink = new ScTableLink( pDocSh, aFileName, aFilterName, aOptions, nRefresh );
2471             pLink->SetInCreate( sal_True );
2472             pLinkManager->InsertFileLink( *pLink, OBJECT_CLIENT_FILE, aFileName, &aFilterName );
2473             pLink->Update();
2474             pLink->SetInCreate( sal_False );
2475 
2476             SfxBindings& rBindings = GetViewData()->GetBindings();
2477             rBindings.Invalidate( SID_LINKS );
2478         }
2479     }
2480 
2481 
2482     if (bUndo)
2483     {
2484         pDocSh->GetUndoManager()->AddUndoAction(
2485                 new ScUndoImportTab( pDocSh, nTab, nCount, bLink ) );
2486     }
2487 
2488     for (i=0; i<nInsCount; i++)
2489         GetViewData()->InsertTab(nTab);
2490     SetTabNo(nTab,sal_True);
2491     pDocSh->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB,
2492                                 PAINT_GRID | PAINT_TOP | PAINT_LEFT | PAINT_EXTRAS );
2493 
2494     SfxApplication* pSfxApp = SFX_APP();
2495     pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2496     pSfxApp->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
2497 
2498     pDocSh->PostPaintExtras();
2499     pDocSh->PostPaintGridAll();
2500     pDocSh->SetDocumentModified();
2501 
2502     if (bRefs)
2503         ErrorMessage(STR_ABSREFLOST);
2504     if (bName)
2505         ErrorMessage(STR_NAMECONFLICT);
2506 }
2507 
2508 
2509 //----------------------------------------------------------------------------
2510 //  Tabelle in anderes Dokument verschieben / kopieren
2511 
2512 void ScViewFunc::MoveTable( sal_uInt16 nDestDocNo, SCTAB nDestTab, sal_Bool bCopy )
2513 {
2514     ScDocument* pDoc       = GetViewData()->GetDocument();
2515     ScDocShell* pDocShell  = GetViewData()->GetDocShell();
2516     ScDocument* pDestDoc   = NULL;
2517     ScDocShell* pDestShell = NULL;
2518     ScTabViewShell* pDestViewSh = NULL;
2519     sal_Bool bUndo (pDoc->IsUndoEnabled());
2520 
2521     sal_Bool bNewDoc = ( nDestDocNo == SC_DOC_NEW );
2522     if ( bNewDoc )
2523     {
2524         nDestTab = 0;           // als erstes einfuegen
2525 
2526         //  ohne SFX_CALLMODE_RECORD ausfuehren, weil schon im Move-Befehl enthalten:
2527 
2528         String aUrl = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("private:factory/"));
2529         aUrl.AppendAscii(RTL_CONSTASCII_STRINGPARAM( STRING_SCAPP ));               // "scalc"
2530         SfxStringItem aItem( SID_FILE_NAME, aUrl );
2531         SfxStringItem aTarget( SID_TARGETNAME, String::CreateFromAscii("_blank") );
2532 
2533         const SfxPoolItem* pRetItem = GetViewData()->GetDispatcher().Execute(
2534                     SID_OPENDOC, SFX_CALLMODE_API|SFX_CALLMODE_SYNCHRON, &aItem, &aTarget, 0L );
2535         if ( pRetItem )
2536         {
2537             if ( pRetItem->ISA( SfxObjectItem ) )
2538                 pDestShell = PTR_CAST( ScDocShell, ((const SfxObjectItem*)pRetItem)->GetShell() );
2539             else if ( pRetItem->ISA( SfxViewFrameItem ) )
2540             {
2541                 SfxViewFrame* pFrm = ((const SfxViewFrameItem*)pRetItem)->GetFrame();
2542                 if (pFrm)
2543                     pDestShell = PTR_CAST( ScDocShell, pFrm->GetObjectShell() );
2544             }
2545             if (pDestShell)
2546                 pDestViewSh = pDestShell->GetBestViewShell();
2547         }
2548     }
2549     else
2550         pDestShell = ScDocShell::GetShellByNum( nDestDocNo );
2551 
2552     if (!pDestShell)
2553     {
2554         DBG_ERROR("Dest-Doc nicht gefunden !!!");
2555         return;
2556     }
2557 
2558     pDestDoc = pDestShell->GetDocument();
2559 
2560     SCTAB nTab = GetViewData()->GetTabNo();
2561 
2562     if (pDestDoc != pDoc)
2563     {
2564         if (bNewDoc)
2565         {
2566             while (pDestDoc->GetTableCount() > 1)
2567                 pDestDoc->DeleteTab(0);
2568             pDestDoc->RenameTab( 0,
2569                         String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("______42_____")),
2570                         sal_False );
2571         }
2572 
2573         ScMarkData& rMark       = GetViewData()->GetMarkData();
2574         SCTAB       nTabCount   = pDoc->GetTableCount();
2575         SCTAB       nTabSelCount = rMark.GetSelectCount();
2576 
2577         SvShorts    TheTabs;
2578 
2579         for(SCTAB i=0;i<nTabCount;i++)
2580         {
2581             if(rMark.GetTableSelect(i))
2582             {
2583                 String aTabName;
2584                 pDoc->GetName( i, aTabName);
2585                 TheTabs.push_back(i);
2586                 for(SCTAB j=i+1;j<nTabCount;j++)
2587                 {
2588                     if((!pDoc->IsVisible(j))&&(pDoc->IsScenario(j)))
2589                     {
2590                         pDoc->GetName( j, aTabName);
2591                         TheTabs.push_back(j);
2592                         i=j;
2593                     }
2594                     else break;
2595                 }
2596             }
2597         }
2598 
2599         GetFrameWin()->EnterWait();
2600 
2601         if (pDoc->GetDrawLayer())
2602             pDestShell->MakeDrawLayer();
2603 
2604         if (!bNewDoc && bUndo)
2605             pDestDoc->BeginDrawUndo();      // drawing layer must do its own undo actions
2606 
2607         sal_uLong nErrVal =1;
2608         if(nDestTab==SC_TAB_APPEND)
2609             nDestTab=pDestDoc->GetTableCount();
2610         SCTAB nDestTab1=nDestTab;
2611         for( size_t j=0; j<TheTabs.size(); j++, nDestTab1++ )
2612         {   // #63304# insert sheets first and update all references
2613             String aName;
2614             pDoc->GetName( TheTabs[j], aName );
2615             pDestDoc->CreateValidTabName( aName );
2616             if ( !pDestDoc->InsertTab( nDestTab1, aName ) )
2617             {
2618                 nErrVal = 0;        // total error
2619                 break;  // for
2620             }
2621         }
2622         if ( nErrVal > 0 )
2623         {
2624             nDestTab1 = nDestTab;
2625             for(size_t i=0;i<TheTabs.size();i++)
2626             {
2627                 nErrVal = pDestDoc->TransferTab( pDoc, TheTabs[i], nDestTab1,
2628                     sal_False );        // no insert
2629 
2630                 // TransferTab doesn't copy drawing objects with bInsertNew=FALSE
2631                 if ( nErrVal > 0 )
2632                     pDestDoc->TransferDrawPage( pDoc, TheTabs[i], nDestTab1 );
2633 
2634                 if(nErrVal>0 && pDoc->IsScenario(TheTabs[i]))
2635                 {
2636                     String aComment;
2637                     Color  aColor;
2638                     sal_uInt16 nFlags;
2639 
2640                     pDoc->GetScenarioData(TheTabs[i], aComment,aColor, nFlags);
2641                     pDestDoc->SetScenario(nDestTab1,sal_True);
2642                     pDestDoc->SetScenarioData(nDestTab1,aComment,aColor,nFlags);
2643                     sal_Bool bActive = pDoc->IsActiveScenario(TheTabs[i]);
2644                     pDestDoc->SetActiveScenario(nDestTab1, bActive );
2645 
2646                     sal_Bool bVisible=pDoc->IsVisible(TheTabs[i]);
2647                     pDestDoc->SetVisible(nDestTab1,bVisible );
2648 
2649                 }
2650 
2651                 if ( nErrVal > 0 && pDoc->IsTabProtected( TheTabs[i] ) )
2652                     pDestDoc->SetTabProtection(nDestTab1, pDoc->GetTabProtection(TheTabs[i]));
2653 
2654                 nDestTab1++;
2655             }
2656         }
2657         String sName;
2658         if (!bNewDoc && bUndo)
2659         {
2660             pDestDoc->GetName(nDestTab, sName);
2661             pDestShell->GetUndoManager()->AddUndoAction(
2662                             new ScUndoImportTab( pDestShell, nDestTab,
2663                                 static_cast<SCTAB>(TheTabs.size()), sal_False));
2664 
2665         }
2666         else
2667         {
2668             pDestShell->GetUndoManager()->Clear();
2669         }
2670 
2671         GetFrameWin()->LeaveWait();
2672         switch (nErrVal)
2673         {
2674             case 0:                     // interner Fehler oder voll Fehler
2675             {
2676                 ErrorMessage(STR_TABINSERT_ERROR);
2677                 return;
2678             }
2679             //break;
2680             case 2:
2681                 ErrorMessage(STR_ABSREFLOST);
2682             break;
2683             case 3:
2684                 ErrorMessage(STR_NAMECONFLICT);
2685             break;
2686             case 4:
2687             {
2688                 ErrorMessage(STR_ABSREFLOST);
2689                 ErrorMessage(STR_NAMECONFLICT);
2690             }
2691             break;
2692             default:
2693             break;
2694         }
2695         //pDestShell->GetUndoManager()->Clear();        //! Undo implementieren !!!
2696 /*
2697         String sName;
2698         pDestDoc->GetName(nDestTab, sName);
2699         pDestShell->GetUndoManager()->AddUndoAction(
2700                         new ScUndoInsertTab( pDestShell, nDestTab, sal_True, sName ) );
2701 */
2702         if (!bCopy)
2703         {
2704             if(nTabCount!=nTabSelCount)
2705                 DeleteTables(TheTabs);// incl. Paint & Undo
2706             else
2707                 ErrorMessage(STR_TABREMOVE_ERROR);
2708         }
2709 
2710         if (bNewDoc)
2711         {
2712             //  ChartListenerCollection must be updated before DeleteTab
2713             if ( pDestDoc->IsChartListenerCollectionNeedsUpdate() )
2714                 pDestDoc->UpdateChartListenerCollection();
2715 
2716             pDestDoc->DeleteTab(static_cast<SCTAB>(TheTabs.size()));   // first old table
2717 //?         pDestDoc->SelectTable(0, sal_True);     // neue erste Tabelle selektieren
2718             if (pDestViewSh)
2719                 pDestViewSh->TabChanged();      // Pages auf dem Drawing-Layer
2720             pDestShell->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB,
2721                                     PAINT_GRID | PAINT_TOP | PAINT_LEFT |
2722                                     PAINT_EXTRAS | PAINT_SIZE );
2723             //  PAINT_SIZE fuer Gliederung
2724         }
2725         else
2726         {
2727             pDestShell->Broadcast( ScTablesHint( SC_TAB_INSERTED, nDestTab ) );
2728             pDestShell->PostPaintExtras();
2729             pDestShell->PostPaintGridAll();
2730         }
2731 
2732         TheTabs.clear();
2733 
2734         pDestShell->SetDocumentModified();
2735         SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2736     }
2737     else                    // within the documents
2738     {
2739 
2740         ScMarkData& rMark       = GetViewData()->GetMarkData();
2741         SCTAB       nTabCount   = pDoc->GetTableCount();
2742 
2743         SvShorts    TheTabs;
2744         SvShorts    TheDestTabs;
2745         SvStrings   TheTabNames;
2746         String      aDestName;
2747         String      *pString;
2748 
2749         for(SCTAB i=0;i<nTabCount;i++)
2750         {
2751             if(rMark.GetTableSelect(i))
2752             {
2753                 String aTabName;
2754                 pDoc->GetName( i, aTabName);
2755                 TheTabNames.Insert(new String(aTabName),TheTabNames.Count());
2756 
2757                 for(SCTAB j=i+1;j<nTabCount;j++)
2758                 {
2759                     if((!pDoc->IsVisible(j))&&(pDoc->IsScenario(j)))
2760                     {
2761                         pDoc->GetName( j, aTabName);
2762                         TheTabNames.Insert(new String(aTabName),TheTabNames.Count());
2763                         i=j;
2764                     }
2765                     else break;
2766                 }
2767 
2768             }
2769         }
2770 
2771         if (bCopy && bUndo)
2772             pDoc->BeginDrawUndo();          // drawing layer must do its own undo actions
2773 
2774         pDoc->GetName( nDestTab, aDestName);
2775         SCTAB nDestTab1=nDestTab;
2776         SCTAB nMovTab=0;
2777         for(int j=0;j<TheTabNames.Count();j++)
2778         {
2779             nTabCount   = pDoc->GetTableCount();
2780             pString=TheTabNames[sal::static_int_cast<sal_uInt16>(j)];
2781             if(!pDoc->GetTable(*pString,nMovTab))
2782             {
2783                 nMovTab=nTabCount;
2784             }
2785             if(!pDoc->GetTable(aDestName,nDestTab1))
2786             {
2787                 nDestTab1=nTabCount;
2788             }
2789             pDocShell->MoveTable( nMovTab, nDestTab1, bCopy, sal_False );   // Undo ist hier
2790 
2791             if(bCopy && pDoc->IsScenario(nMovTab))
2792             {
2793                 String aComment;
2794                 Color  aColor;
2795                 sal_uInt16 nFlags;
2796 
2797                 pDoc->GetScenarioData(nMovTab, aComment,aColor, nFlags);
2798                 pDoc->SetScenario(nDestTab1,sal_True);
2799                 pDoc->SetScenarioData(nDestTab1,aComment,aColor,nFlags);
2800                 sal_Bool bActive = pDoc->IsActiveScenario(nMovTab );
2801                 pDoc->SetActiveScenario( nDestTab1, bActive );
2802                 sal_Bool bVisible=pDoc->IsVisible(nMovTab);
2803                 pDoc->SetVisible(nDestTab1,bVisible );
2804             }
2805 
2806             TheTabs.push_back(nMovTab);
2807 
2808             if(!bCopy)
2809             {
2810                 if(!pDoc->GetTable(*pString,nDestTab1))
2811                 {
2812                     nDestTab1=nTabCount;
2813                 }
2814             }
2815 
2816             TheDestTabs.push_back(nDestTab1);
2817             delete pString;
2818         }
2819 
2820         nTab = GetViewData()->GetTabNo();
2821 
2822         if (bUndo)
2823         {
2824             if (bCopy)
2825             {
2826                 pDocShell->GetUndoManager()->AddUndoAction(
2827                         new ScUndoCopyTab( pDocShell, TheTabs, TheDestTabs));
2828             }
2829             else
2830             {
2831                 pDocShell->GetUndoManager()->AddUndoAction(
2832                         new ScUndoMoveTab( pDocShell, TheTabs, TheDestTabs));
2833             }
2834         }
2835 
2836         SCTAB nNewTab = nDestTab;
2837         if (nNewTab == SC_TAB_APPEND)
2838             nNewTab = pDoc->GetTableCount()-1;
2839         else if (!bCopy && nTab<nDestTab)
2840             nNewTab--;
2841 
2842         SetTabNo( nNewTab, sal_True );
2843 
2844         //#i29848# adjust references to data on the copied sheet
2845         if( bCopy )
2846             ScChartHelper::AdjustRangesOfChartsOnDestinationPage( pDoc, pDestDoc, nTab, nNewTab );
2847     }
2848 }
2849 
2850 
2851 //----------------------------------------------------------------------------
2852 
2853 void ScViewFunc::ShowTable( const String& rName )
2854 {
2855     ScDocShell* pDocSh = GetViewData()->GetDocShell();
2856     ScDocument* pDoc = pDocSh->GetDocument();
2857     sal_Bool bUndo(pDoc->IsUndoEnabled());
2858     sal_Bool bFound = sal_False;
2859     SCTAB nPos = 0;
2860     String aTabName;
2861     SCTAB nCount = pDoc->GetTableCount();
2862     for (SCTAB i=0; i<nCount; i++)
2863     {
2864         pDoc->GetName( i, aTabName );
2865         if ( aTabName == rName )
2866         {
2867             nPos = i;
2868             bFound = sal_True;
2869         }
2870     }
2871 
2872     if (bFound)
2873     {
2874         pDoc->SetVisible( nPos, sal_True );
2875         if (bUndo)
2876         {
2877             pDocSh->GetUndoManager()->AddUndoAction( new ScUndoShowHideTab( pDocSh, nPos, sal_True ) );
2878         }
2879         SetTabNo( nPos, sal_True );
2880         SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2881         pDocSh->PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS);
2882         pDocSh->SetDocumentModified();
2883     }
2884     else
2885         Sound::Beep();
2886 }
2887 
2888 
2889 //----------------------------------------------------------------------------
2890 
2891 void ScViewFunc::HideTable( SCTAB nTab )
2892 {
2893     ScDocShell* pDocSh = GetViewData()->GetDocShell();
2894     ScDocument* pDoc = pDocSh->GetDocument();
2895     sal_Bool bUndo(pDoc->IsUndoEnabled());
2896     SCTAB nVisible = 0;
2897     SCTAB nCount = pDoc->GetTableCount();
2898     for (SCTAB i=0; i<nCount; i++)
2899     {
2900         if (pDoc->IsVisible(i))
2901             ++nVisible;
2902     }
2903 
2904     if (nVisible > 1)
2905     {
2906         pDoc->SetVisible( nTab, sal_False );
2907         if (bUndo)
2908         {
2909             pDocSh->GetUndoManager()->AddUndoAction( new ScUndoShowHideTab( pDocSh, nTab, sal_False ) );
2910         }
2911 
2912         //  Views updaten:
2913         pDocSh->Broadcast( ScTablesHint( SC_TAB_HIDDEN, nTab ) );
2914 
2915         SetTabNo( nTab, sal_True );
2916         SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) );
2917         pDocSh->PostPaint(0,0,0,MAXCOL,MAXROW,MAXTAB, PAINT_EXTRAS);
2918         pDocSh->SetDocumentModified();
2919     }
2920     else
2921         Sound::Beep();
2922 }
2923 
2924 
2925 //----------------------------------------------------------------------------
2926 
2927 void ScViewFunc::InsertSpecialChar( const String& rStr, const Font& rFont )
2928 {
2929     ScEditableTester aTester( this );
2930     if (!aTester.IsEditable())
2931     {
2932         ErrorMessage(aTester.GetMessageId());
2933         return;
2934     }
2935 
2936     const sal_Unicode* pChar    = rStr.GetBuffer();
2937     ScTabViewShell* pViewShell  = GetViewData()->GetViewShell();
2938     SvxFontItem     aFontItem( rFont.GetFamily(),
2939                                rFont.GetName(),
2940                                rFont.GetStyleName(),
2941                                rFont.GetPitch(),
2942                                rFont.GetCharSet(),
2943                                ATTR_FONT );
2944 
2945     //  if string contains WEAK characters, set all fonts
2946     sal_uInt8 nScript;
2947     ScDocument* pDoc = GetViewData()->GetDocument();
2948     if ( pDoc->HasStringWeakCharacters( rStr ) )
2949         nScript = SCRIPTTYPE_LATIN | SCRIPTTYPE_ASIAN | SCRIPTTYPE_COMPLEX;
2950     else
2951         nScript = pDoc->GetStringScriptType( rStr );
2952 
2953     SvxScriptSetItem aSetItem( SID_ATTR_CHAR_FONT, pViewShell->GetPool() );
2954     aSetItem.PutItemForScriptType( nScript, aFontItem );
2955     ApplyUserItemSet( aSetItem.GetItemSet() );
2956 
2957     while ( *pChar )
2958         pViewShell->TabKeyInput( KeyEvent( *(pChar++), KeyCode() ) );
2959 }
2960 
2961 
2962 //----------------------------------------------------------------------------
2963 
2964 void ScViewFunc::UpdateLineAttrs( SvxBorderLine&       rLine,
2965                                   const SvxBorderLine* pDestLine,
2966                                   const SvxBorderLine* pSrcLine,
2967                                   sal_Bool                 bColor )
2968 {
2969     if ( pSrcLine && pDestLine )
2970     {
2971         if ( bColor )
2972         {
2973             rLine.SetColor      ( pSrcLine->GetColor() );
2974             rLine.SetOutWidth   ( pDestLine->GetOutWidth() );
2975             rLine.SetInWidth    ( pDestLine->GetInWidth() );
2976             rLine.SetDistance   ( pDestLine->GetDistance() );
2977         }
2978         else
2979         {
2980             rLine.SetColor      ( pDestLine->GetColor() );
2981             rLine.SetOutWidth   ( pSrcLine->GetOutWidth() );
2982             rLine.SetInWidth    ( pSrcLine->GetInWidth() );
2983             rLine.SetDistance   ( pSrcLine->GetDistance() );
2984         }
2985     }
2986 }
2987 
2988 
2989 #define SET_LINE_ATTRIBUTES(LINE,BOXLINE) \
2990     pBoxLine = aBoxItem.Get##LINE();                                \
2991     if ( pBoxLine )                                                 \
2992     {                                                               \
2993         if ( pLine )                                                \
2994         {                                                           \
2995             UpdateLineAttrs( aLine, pBoxLine, pLine, bColorOnly );  \
2996             aBoxItem.SetLine( &aLine, BOXLINE );                    \
2997         }                                                           \
2998         else                                                        \
2999             aBoxItem.SetLine( NULL, BOXLINE );                      \
3000     }
3001 
3002 
3003 //----------------------------------------------------------------------------
3004 
3005 void ScViewFunc::SetSelectionFrameLines( const SvxBorderLine* pLine,
3006                                          sal_Bool bColorOnly )
3007 {
3008     // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
3009     sal_Bool bOnlyNotBecauseOfMatrix;
3010     if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
3011     {
3012         ErrorMessage(STR_PROTECTIONERR);
3013         return;
3014     }
3015 
3016     ScDocument*             pDoc = GetViewData()->GetDocument();
3017     ScMarkData aFuncMark( GetViewData()->GetMarkData() );       // local copy for UnmarkFiltered
3018     ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
3019     ScDocShell*             pDocSh = GetViewData()->GetDocShell();
3020     const ScPatternAttr*    pSelAttrs = GetSelectionPattern();
3021     const SfxItemSet&       rSelItemSet = pSelAttrs->GetItemSet();
3022 
3023     const SfxPoolItem*      pBorderAttr = NULL;
3024     SfxItemState            eItemState = rSelItemSet.GetItemState( ATTR_BORDER, sal_True, &pBorderAttr );
3025 
3026     const SfxPoolItem*      pTLBRItem = 0;
3027     SfxItemState            eTLBRState = rSelItemSet.GetItemState( ATTR_BORDER_TLBR, sal_True, &pTLBRItem );
3028 
3029     const SfxPoolItem*      pBLTRItem = 0;
3030     SfxItemState            eBLTRState = rSelItemSet.GetItemState( ATTR_BORDER_BLTR, sal_True, &pBLTRItem );
3031 
3032     // any of the lines visible?
3033     if( (eItemState != SFX_ITEM_DEFAULT) || (eTLBRState != SFX_ITEM_DEFAULT) || (eBLTRState != SFX_ITEM_DEFAULT) )
3034     {
3035         // none of the lines don't care?
3036         if( (eItemState != SFX_ITEM_DONTCARE) && (eTLBRState != SFX_ITEM_DONTCARE) && (eBLTRState != SFX_ITEM_DONTCARE) )
3037         {
3038             SfxItemSet*     pOldSet = new SfxItemSet(
3039                                             *(pDoc->GetPool()),
3040                                             ATTR_PATTERN_START,
3041                                             ATTR_PATTERN_END );
3042             SfxItemSet*     pNewSet = new SfxItemSet(
3043                                             *(pDoc->GetPool()),
3044                                             ATTR_PATTERN_START,
3045                                             ATTR_PATTERN_END );
3046 
3047             //------------------------------------------------------------
3048             const SvxBorderLine*    pBoxLine = NULL;
3049             SvxBorderLine           aLine;
3050 
3051             // hier wird die pBoxLine benutzt:
3052 
3053             if( pBorderAttr )
3054             {
3055                 SvxBoxItem      aBoxItem( *(const SvxBoxItem*)pBorderAttr );
3056                 SvxBoxInfoItem  aBoxInfoItem( ATTR_BORDER_INNER );
3057 
3058                 SET_LINE_ATTRIBUTES(Top,BOX_LINE_TOP)
3059                 SET_LINE_ATTRIBUTES(Bottom,BOX_LINE_BOTTOM)
3060                 SET_LINE_ATTRIBUTES(Left,BOX_LINE_LEFT)
3061                 SET_LINE_ATTRIBUTES(Right,BOX_LINE_RIGHT)
3062 
3063                 aBoxInfoItem.SetLine( aBoxItem.GetTop(), BOXINFO_LINE_HORI );
3064                 aBoxInfoItem.SetLine( aBoxItem.GetLeft(), BOXINFO_LINE_VERT );
3065                 aBoxInfoItem.ResetFlags(); // Lines auf Valid setzen
3066 
3067                 pOldSet->Put( *pBorderAttr );
3068                 pNewSet->Put( aBoxItem );
3069                 pNewSet->Put( aBoxInfoItem );
3070             }
3071 
3072             if( pTLBRItem && ((const SvxLineItem*)pTLBRItem)->GetLine() )
3073             {
3074                 SvxLineItem aTLBRItem( *(const SvxLineItem*)pTLBRItem );
3075                 UpdateLineAttrs( aLine, aTLBRItem.GetLine(), pLine, bColorOnly );
3076                 aTLBRItem.SetLine( &aLine );
3077                 pOldSet->Put( *pTLBRItem );
3078                 pNewSet->Put( aTLBRItem );
3079             }
3080 
3081             if( pBLTRItem && ((const SvxLineItem*)pBLTRItem)->GetLine() )
3082             {
3083                 SvxLineItem aBLTRItem( *(const SvxLineItem*)pBLTRItem );
3084                 UpdateLineAttrs( aLine, aBLTRItem.GetLine(), pLine, bColorOnly );
3085                 aBLTRItem.SetLine( &aLine );
3086                 pOldSet->Put( *pBLTRItem );
3087                 pNewSet->Put( aBLTRItem );
3088             }
3089 
3090             ApplyAttributes( pNewSet, pOldSet );
3091 
3092             delete pOldSet;
3093             delete pNewSet;
3094         }
3095         else // if ( eItemState == SFX_ITEM_DONTCARE )
3096         {
3097             aFuncMark.MarkToMulti();
3098             pDoc->ApplySelectionLineStyle( aFuncMark, pLine, bColorOnly );
3099         }
3100 
3101         ScRange aMarkRange;
3102         aFuncMark.GetMultiMarkArea( aMarkRange );
3103         SCCOL nStartCol = aMarkRange.aStart.Col();
3104         SCROW nStartRow = aMarkRange.aStart.Row();
3105         SCTAB nStartTab = aMarkRange.aStart.Tab();
3106         SCCOL nEndCol = aMarkRange.aEnd.Col();
3107         SCROW nEndRow = aMarkRange.aEnd.Row();
3108         SCTAB nEndTab = aMarkRange.aEnd.Tab();
3109         pDocSh->PostPaint( nStartCol, nStartRow, nStartTab,
3110                            nEndCol, nEndRow, nEndTab,
3111                            PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE );
3112 
3113         pDocSh->UpdateOle( GetViewData() );
3114         pDocSh->SetDocumentModified();
3115     }
3116 }
3117 
3118 #undef SET_LINE_ATTRIBUTES
3119 
3120 
3121 //----------------------------------------------------------------------------
3122 
3123 void ScViewFunc::SetConditionalFormat( const ScConditionalFormat& rNew )
3124 {
3125     ScDocument* pDoc = GetViewData()->GetDocument();
3126     sal_uLong nIndex = pDoc->AddCondFormat(rNew);           // dafuer gibt's kein Undo
3127     SfxUInt32Item aItem( ATTR_CONDITIONAL, nIndex );
3128 
3129     ApplyAttr( aItem );         // mit Paint und Undo...
3130 }
3131 
3132 
3133 //----------------------------------------------------------------------------
3134 
3135 void ScViewFunc::SetValidation( const ScValidationData& rNew )
3136 {
3137     ScDocument* pDoc = GetViewData()->GetDocument();
3138     sal_uLong nIndex = pDoc->AddValidationEntry(rNew);      // dafuer gibt's kein Undo
3139     SfxUInt32Item aItem( ATTR_VALIDDATA, nIndex );
3140 
3141     ApplyAttr( aItem );         // mit Paint und Undo...
3142 }
3143 
3144 
3145