xref: /AOO41X/main/sc/source/ui/view/viewfunc.cxx (revision ca62e2c2083b5d0995f1245bad6c2edfb455fbec)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_sc.hxx"
26 
27 
28 
29 //------------------------------------------------------------------
30 
31 // INCLUDE ---------------------------------------------------------------
32 
33 #include "scitems.hxx"
34 #include <editeng/eeitem.hxx>
35 
36 #include <sfx2/app.hxx>
37 #include <svx/algitem.hxx>
38 #include <editeng/boxitem.hxx>
39 #include <editeng/editobj.hxx>
40 #include <editeng/editview.hxx>
41 #include <editeng/langitem.hxx>
42 #include <editeng/scripttypeitem.hxx>
43 #include <sfx2/bindings.hxx>
44 #include <svl/zforlist.hxx>
45 #include <svl/zformat.hxx>
46 #include <vcl/msgbox.hxx>
47 #include <vcl/sound.hxx>
48 #include <vcl/virdev.hxx>
49 #include <vcl/waitobj.hxx>
50 #include <vcl/wrkwin.hxx>
51 #include <stdlib.h>             // qsort
52 
53 #include "viewfunc.hxx"
54 #include "tabvwsh.hxx"
55 #include "docsh.hxx"
56 #include "attrib.hxx"
57 #include "patattr.hxx"
58 #include "docpool.hxx"
59 #include "uiitems.hxx"
60 #include "sc.hrc"
61 #include "undocell.hxx"
62 #include "undoblk.hxx"
63 #include "undotab.hxx"
64 #include "refundo.hxx"
65 #include "dbcolect.hxx"
66 #include "olinetab.hxx"
67 #include "rangeutl.hxx"
68 #include "rangenam.hxx"
69 #include "globstr.hrc"
70 #include "global.hxx"
71 #include "stlsheet.hxx"
72 #include "editutil.hxx"
73 //CHINA001 #include "namecrea.hxx"          // wegen Flags
74 #include "cell.hxx"
75 #include "scresid.hxx"
76 #include "inputhdl.hxx"
77 #include "scmod.hxx"
78 #include "inputopt.hxx"
79 #include "compiler.hxx"
80 #include "docfunc.hxx"
81 #include "appoptio.hxx"
82 #include "dociter.hxx"
83 #include "sizedev.hxx"
84 #include "editable.hxx"
85 #include "scui_def.hxx" //CHINA001
86 #include "funcdesc.hxx"
87 #include "docuno.hxx"
88 #include "cellsuno.hxx"
89 //==================================================================
90 
ScViewFunc(Window * pParent,ScDocShell & rDocSh,ScTabViewShell * pViewShell)91 ScViewFunc::ScViewFunc( Window* pParent, ScDocShell& rDocSh, ScTabViewShell* pViewShell ) :
92     ScTabView( pParent, rDocSh, pViewShell ),
93     bFormatValid( sal_False )
94 {
95 }
96 
97 //UNUSED2008-05  ScViewFunc::ScViewFunc( Window* pParent, const ScViewFunc& rViewFunc, ScTabViewShell* pViewShell ) :
98 //UNUSED2008-05      ScTabView( pParent, rViewFunc, pViewShell ),
99 //UNUSED2008-05      bFormatValid( sal_False )
100 //UNUSED2008-05  {
101 //UNUSED2008-05  }
102 
~ScViewFunc()103 ScViewFunc::~ScViewFunc()
104 {
105 }
106 
107 //------------------------------------------------------------------------------------
108 
StartFormatArea()109 void ScViewFunc::StartFormatArea()
110 {
111     //  ueberhaupt aktiviert?
112     if ( !SC_MOD()->GetInputOptions().GetExtendFormat() )
113         return;
114 
115     //  start only with single cell (marked or cursor position)
116     ScRange aMarkRange;
117     sal_Bool bOk = (GetViewData()->GetSimpleArea( aMarkRange ) == SC_MARK_SIMPLE);
118     if ( bOk && aMarkRange.aStart != aMarkRange.aEnd )
119         bOk = sal_False;
120 
121     if (bOk)
122     {
123         bFormatValid = sal_True;
124         aFormatSource = aMarkRange.aStart;
125         aFormatArea = ScRange( aFormatSource );
126     }
127     else
128         bFormatValid = sal_False;       // keinen alten Bereich behalten
129 }
130 
TestFormatArea(SCCOL nCol,SCROW nRow,SCTAB nTab,sal_Bool bAttrChanged)131 sal_Bool ScViewFunc::TestFormatArea( SCCOL nCol, SCROW nRow, SCTAB nTab, sal_Bool bAttrChanged )
132 {
133     //  ueberhaupt aktiviert?
134     if ( !SC_MOD()->GetInputOptions().GetExtendFormat() )
135         return sal_False;
136 
137     //  Test: Eingabe mit Zahlformat (bAttrChanged) immer als neue Attributierung behandeln
138     //  (alte Area verwerfen). Wenn das nicht gewollt ist, den if-Teil weglassen:
139     if ( bAttrChanged )
140     {
141         StartFormatArea();
142         return sal_False;
143     }
144 
145     //! Abfrage, ob Zelle leer war ???
146 
147     sal_Bool bFound = sal_False;
148     ScRange aNewRange = aFormatArea;
149     if ( bFormatValid && nTab == aFormatSource.Tab() )
150     {
151         if ( nRow >= aFormatArea.aStart.Row() && nRow <= aFormatArea.aEnd.Row() )
152         {
153             //  innerhalb ?
154             if ( nCol >= aFormatArea.aStart.Col() && nCol <= aFormatArea.aEnd.Col() )
155             {
156                 bFound = sal_True;          // Bereich nicht aendern
157             }
158             //  links ?
159             if ( nCol+1 == aFormatArea.aStart.Col() )
160             {
161                 bFound = sal_True;
162                 aNewRange.aStart.SetCol( nCol );
163             }
164             //  rechts ?
165             if ( nCol == aFormatArea.aEnd.Col()+1 )
166             {
167                 bFound = sal_True;
168                 aNewRange.aEnd.SetCol( nCol );
169             }
170         }
171         if ( nCol >= aFormatArea.aStart.Col() && nCol <= aFormatArea.aEnd.Col() )
172         {
173             //  oben ?
174             if ( nRow+1 == aFormatArea.aStart.Row() )
175             {
176                 bFound = sal_True;
177                 aNewRange.aStart.SetRow( nRow );
178             }
179             //  unten ?
180             if ( nRow == aFormatArea.aEnd.Row()+1 )
181             {
182                 bFound = sal_True;
183                 aNewRange.aEnd.SetRow( nRow );
184             }
185         }
186     }
187 
188     if (bFound)
189         aFormatArea = aNewRange;    // erweitern
190     else
191     {
192         bFormatValid = sal_False;       // ausserhalb -> abbrechen
193         if ( bAttrChanged )         // Wert mit Zahlformat eingegeben?
194             StartFormatArea();      // dann ggf. neu starten
195     }
196 
197     return bFound;
198 }
199 
DoAutoAttributes(SCCOL nCol,SCROW nRow,SCTAB nTab,sal_Bool bAttrChanged,sal_Bool bAddUndo)200 void ScViewFunc::DoAutoAttributes( SCCOL nCol, SCROW nRow, SCTAB nTab,
201                                     sal_Bool bAttrChanged, sal_Bool bAddUndo )
202 {
203     ScDocShell* pDocSh = GetViewData()->GetDocShell();
204     ScDocument* pDoc = pDocSh->GetDocument();
205     if (bAddUndo && !pDoc->IsUndoEnabled())
206         bAddUndo = sal_False;
207 
208     const ScPatternAttr* pSource = pDoc->GetPattern(
209                             aFormatSource.Col(), aFormatSource.Row(), nTab );
210     if ( !((const ScMergeAttr&)pSource->GetItem(ATTR_MERGE)).IsMerged() )
211     {
212         const ScPatternAttr* pDocOld = pDoc->GetPattern( nCol, nRow, nTab );
213         //  pDocOld ist nur bis zum Apply... gueltig!
214 
215         ScPatternAttr* pOldPattern = NULL;
216         if ( bAddUndo )
217             pOldPattern = new ScPatternAttr( *pDocOld );
218 
219         const ScStyleSheet* pSrcStyle = pSource->GetStyleSheet();
220         if ( pSrcStyle && pSrcStyle != pDocOld->GetStyleSheet() )
221             pDoc->ApplyStyle( nCol, nRow, nTab, *pSrcStyle );
222         pDoc->ApplyPattern( nCol, nRow, nTab, *pSource );
223         AdjustRowHeight( nRow, nRow, sal_True );                //! nicht doppelt ?
224 
225         if ( bAddUndo )
226         {
227             const ScPatternAttr* pNewPattern = pDoc->GetPattern( nCol, nRow, nTab );
228 
229             pDocSh->GetUndoManager()->AddUndoAction(
230                         new ScUndoCursorAttr( pDocSh, nCol, nRow, nTab,
231                                               pOldPattern, pNewPattern, pSource,
232                                               sal_True ) );
233 
234             delete pOldPattern;     // wird im Undo kopiert (Pool)
235         }
236     }
237 
238     if ( bAttrChanged )                             // Wert mit Zahlformat eingegeben?
239         aFormatSource.Set( nCol, nRow, nTab );      // dann als neue Quelle
240 }
241 
242 //------------------------------------------------------------------------------------
243 
244 //      Hilfsroutinen
245 
GetOptimalColWidth(SCCOL nCol,SCTAB nTab,sal_Bool bFormula)246 sal_uInt16 ScViewFunc::GetOptimalColWidth( SCCOL nCol, SCTAB nTab, sal_Bool bFormula )
247 {
248     ScDocShell* pDocSh = GetViewData()->GetDocShell();
249     ScDocument* pDoc = pDocSh->GetDocument();
250     ScMarkData& rMark = GetViewData()->GetMarkData();
251 
252     double nPPTX = GetViewData()->GetPPTX();
253     double nPPTY = GetViewData()->GetPPTY();
254     Fraction aZoomX = GetViewData()->GetZoomX();
255     Fraction aZoomY = GetViewData()->GetZoomY();
256 
257     ScSizeDeviceProvider aProv(pDocSh);
258     if (aProv.IsPrinter())
259     {
260         nPPTX = aProv.GetPPTX();
261         nPPTY = aProv.GetPPTY();
262         aZoomX = aZoomY = Fraction( 1, 1 );
263     }
264 
265     sal_uInt16 nTwips = pDoc->GetOptimalColWidth( nCol, nTab, aProv.GetDevice(),
266                                 nPPTX, nPPTY, aZoomX, aZoomY, bFormula, &rMark );
267     return nTwips;
268 }
269 
SelectionEditable(sal_Bool * pOnlyNotBecauseOfMatrix)270 sal_Bool ScViewFunc::SelectionEditable( sal_Bool* pOnlyNotBecauseOfMatrix /* = NULL */ )
271 {
272     sal_Bool bRet;
273     ScDocument* pDoc = GetViewData()->GetDocument();
274     ScMarkData& rMark = GetViewData()->GetMarkData();
275     if (rMark.IsMarked() || rMark.IsMultiMarked())
276         bRet = pDoc->IsSelectionEditable( rMark, pOnlyNotBecauseOfMatrix );
277     else
278     {
279         SCCOL nCol = GetViewData()->GetCurX();
280         SCROW nRow = GetViewData()->GetCurY();
281         SCTAB nTab = GetViewData()->GetTabNo();
282         bRet = pDoc->IsBlockEditable( nTab, nCol, nRow, nCol, nRow,
283             pOnlyNotBecauseOfMatrix );
284     }
285     return bRet;
286 }
287 
288 #ifndef LRU_MAX
289 #define LRU_MAX 10
290 #endif
291 
lcl_FunctionKnown(sal_uInt16 nOpCode)292 sal_Bool lcl_FunctionKnown( sal_uInt16 nOpCode )
293 {
294     const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList();
295     if ( pFuncList )
296     {
297         sal_uLong nCount = pFuncList->GetCount();
298         for (sal_uLong i=0; i<nCount; i++)
299             if ( pFuncList->GetFunction(i)->nFIndex == nOpCode )
300                 return sal_True;
301     }
302     return sal_False;
303 }
304 
lcl_AddFunction(ScAppOptions & rAppOpt,sal_uInt16 nOpCode)305 sal_Bool lcl_AddFunction( ScAppOptions& rAppOpt, sal_uInt16 nOpCode )
306 {
307     sal_uInt16 nOldCount = rAppOpt.GetLRUFuncListCount();
308     sal_uInt16* pOldList = rAppOpt.GetLRUFuncList();
309     sal_uInt16 nPos;
310     for (nPos=0; nPos<nOldCount; nPos++)
311         if (pOldList[nPos] == nOpCode)          // is the function already in the list?
312         {
313             if ( nPos == 0 )
314                 return sal_False;                   // already at the top -> no change
315 
316             //  count doesn't change, so the original array is modified
317 
318             for (sal_uInt16 nCopy=nPos; nCopy>0; nCopy--)
319                 pOldList[nCopy] = pOldList[nCopy-1];
320             pOldList[0] = nOpCode;
321 
322             return sal_True;                        // list has changed
323         }
324 
325     if ( !lcl_FunctionKnown( nOpCode ) )
326         return sal_False;                           // not in function list -> no change
327 
328     sal_uInt16 nNewCount = Min( (sal_uInt16)(nOldCount + 1), (sal_uInt16)LRU_MAX );
329     sal_uInt16 nNewList[LRU_MAX];
330     nNewList[0] = nOpCode;
331     for (nPos=1; nPos<nNewCount; nPos++)
332         nNewList[nPos] = pOldList[nPos-1];
333     rAppOpt.SetLRUFuncList( nNewList, nNewCount );
334 
335     return sal_True;                                // list has changed
336 }
337 
338 //      eigentliche Funktionen
339 
340 //  Eingabe - Undo OK
341 
EnterData(SCCOL nCol,SCROW nRow,SCTAB nTab,const String & rString,sal_Bool bRecord,const EditTextObject * pData)342 void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rString,
343                             sal_Bool bRecord, const EditTextObject* pData )
344 {
345     ScDocument* pDoc = GetViewData()->GetDocument();
346     ScMarkData& rMark = GetViewData()->GetMarkData();
347     SCTAB nTabCount = pDoc->GetTableCount();
348     SCTAB nSelCount = rMark.GetSelectCount();
349     SCTAB i;
350     if (bRecord && !pDoc->IsUndoEnabled())
351         bRecord = sal_False;
352 
353     ScDocShell* pDocSh = GetViewData()->GetDocShell();
354     ScDocShellModificator aModificator( *pDocSh );
355 
356     ScEditableTester aTester( pDoc, nCol,nRow, nCol,nRow, rMark );
357     if (aTester.IsEditable())
358     {
359         sal_Bool bEditDeleted = sal_False;
360         sal_uInt8 nOldScript = 0;
361 
362         ScBaseCell** ppOldCells = NULL;
363         sal_Bool* pHasFormat        = NULL;
364         sal_uLong* pOldFormats      = NULL;
365         SCTAB* pTabs            = NULL;
366         SCTAB nUndoPos = 0;
367         EditTextObject* pUndoData = NULL;
368         if ( bRecord )
369         {
370             ppOldCells      = new ScBaseCell*[nSelCount];
371             pHasFormat      = new sal_Bool[nSelCount];
372             pOldFormats     = new sal_uLong[nSelCount];
373             pTabs           = new SCTAB[nSelCount];
374             nUndoPos = 0;
375 
376             for (i=0; i<nTabCount; i++)
377                 if (rMark.GetTableSelect(i))
378                 {
379                     pTabs[nUndoPos] = i;
380                     ScBaseCell* pDocCell;
381                     pDoc->GetCell( nCol, nRow, i, pDocCell );
382                     if ( pDocCell )
383                     {
384                         ppOldCells[nUndoPos] = pDocCell->CloneWithoutNote( *pDoc );
385                         if ( pDocCell->GetCellType() == CELLTYPE_EDIT )
386                             bEditDeleted = sal_True;
387 
388                         sal_uInt8 nDocScript = pDoc->GetScriptType( nCol, nRow, i, pDocCell );
389                         if ( nOldScript == 0 )
390                             nOldScript = nDocScript;
391                         else if ( nDocScript != nOldScript )
392                             bEditDeleted = sal_True;
393                     }
394                     else
395                     {
396                         ppOldCells[nUndoPos] = NULL;
397                     }
398 
399                     const SfxPoolItem* pItem;
400                     const ScPatternAttr* pPattern = pDoc->GetPattern(nCol, nRow, i);
401                     if ( SFX_ITEM_SET == pPattern->GetItemSet().GetItemState(
402                                             ATTR_VALUE_FORMAT,sal_False,&pItem) )
403                     {
404                         pHasFormat[nUndoPos] = sal_True;
405                         pOldFormats[nUndoPos] = ((const SfxUInt32Item*)pItem)->GetValue();
406                     }
407                     else
408                         pHasFormat[nUndoPos] = sal_False;
409 
410                     ++nUndoPos;
411                 }
412 
413             DBG_ASSERT( nUndoPos==nSelCount, "nUndoPos!=nSelCount" );
414 
415             pUndoData = ( pData ? pData->Clone() : NULL );
416         }
417 
418         bool bFormula = false;
419 
420         // a single '=' character is handled as string (needed for special filters)
421         if ( rString.Len() > 1 )
422         {
423             if ( rString.GetChar(0) == '=' )
424             {
425                 // handle as formula
426                 bFormula = true;
427             }
428             else if ( rString.GetChar(0) == '+' || rString.GetChar(0) == '-' )
429             {
430                 // if there is more than one leading '+' or '-' character, remove the additional ones
431                 String aString( rString );
432                 xub_StrLen nIndex = 1;
433                 xub_StrLen nLen = aString.Len();
434                 while ( nIndex < nLen && ( aString.GetChar( nIndex ) == '+' || aString.GetChar( nIndex ) == '-' ) )
435                 {
436                     ++nIndex;
437                 }
438                 aString.Erase( 1, nIndex - 1 );
439 
440                 // if the remaining part without the leading '+' or '-' character
441                 // is non-empty and not a number, handle as formula
442                 if ( aString.Len() > 1 )
443                 {
444                     sal_uInt32 nFormat = 0;
445                     pDoc->GetNumberFormat( nCol, nRow, nTab, nFormat );
446                     SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
447                     double fNumber = 0;
448                     if ( !pFormatter->IsNumberFormat( aString, nFormat, fNumber ) )
449                     {
450                         bFormula = true;
451                     }
452                 }
453             }
454         }
455 
456         sal_Bool bNumFmtChanged = sal_False;
457         if ( bFormula )
458         {   // Formel, compile mit AutoCorrection
459             for (i=0; i<nTabCount; i++)
460                 if (rMark.GetTableSelect(i))
461                     break;
462             ScAddress aPos( nCol, nRow, i );
463             ScCompiler aComp( pDoc, aPos);
464             aComp.SetGrammar(pDoc->GetGrammar());
465 //2do: AutoCorrection via CalcOptions abschaltbar machen
466             aComp.SetAutoCorrection( sal_True );
467             if ( rString.GetChar(0) == '+' || rString.GetChar(0) == '-' )
468             {
469                 aComp.SetExtendedErrorDetection( true );
470             }
471             String aFormula( rString );
472             ScTokenArray* pArr;
473             sal_Bool bAgain;
474             do
475             {
476                 bAgain = sal_False;
477                 sal_Bool bAddEqual = sal_False;
478                 ScTokenArray* pArrFirst = pArr = aComp.CompileString( aFormula );
479                 sal_Bool bCorrected = aComp.IsCorrected();
480                 if ( bCorrected )
481                 {   // probieren, mit erster Parser-Korrektur neu zu parsen
482                     pArr = aComp.CompileString( aComp.GetCorrectedFormula() );
483                 }
484                 if ( !pArr->GetCodeError() )
485                 {
486                     bAddEqual = sal_True;
487                     aComp.CompileTokenArray();
488                     bCorrected |= aComp.IsCorrected();
489                 }
490                 if ( bCorrected )
491                 {
492                     String aCorrectedFormula;
493                     if ( bAddEqual )
494                     {
495                         aCorrectedFormula = '=';
496                         aCorrectedFormula += aComp.GetCorrectedFormula();
497                     }
498                     else
499                         aCorrectedFormula = aComp.GetCorrectedFormula();
500                     short nResult;
501                     if ( aCorrectedFormula.Len() == 1 )
502                         nResult = RET_NO;   // leere Formel, nur '='
503                     else
504                     {
505                         String aMessage( ScResId( SCSTR_FORMULA_AUTOCORRECTION ) );
506                         aMessage += aCorrectedFormula;
507                         nResult = QueryBox( GetViewData()->GetDialogParent(),
508                                                 WinBits(WB_YES_NO | WB_DEF_YES),
509                                                 aMessage ).Execute();
510                     }
511                     if ( nResult == RET_YES )
512                     {
513                         aFormula = aCorrectedFormula;
514                         if ( pArr != pArrFirst )
515                             delete pArrFirst;
516                         bAgain = sal_True;
517                     }
518                     else
519                     {
520                         if ( pArr != pArrFirst )
521                         {
522                             delete pArr;
523                             pArr = pArrFirst;
524                         }
525                     }
526                 }
527             } while ( bAgain );
528             // um in mehreren Tabellen eingesetzt zu werden, muss die Formel
529             // via ScFormulaCell copy-ctor evtl. wegen RangeNames neu kompiliert
530             // werden, gleiches Code-Array fuer alle Zellen geht nicht.
531             // Wenn das Array einen Fehler enthaelt, muss in den neu erzeugten
532             // Zellen RPN geloescht und der Fehler explizit gesetzt werden, da
533             // via FormulaCell copy-ctor und Interpreter das, wenn moeglich,
534             // wieder glattgebuegelt wird, zu intelligent.. z.B.: =1))
535             sal_uInt16 nError = pArr->GetCodeError();
536             if ( !nError )
537             {
538                 //  #68693# update list of recent functions with all functions that
539                 //  are not within parentheses
540 
541                 ScModule* pScMod = SC_MOD();
542                 ScAppOptions aAppOpt = pScMod->GetAppOptions();
543                 sal_Bool bOptChanged = sal_False;
544 
545                 formula::FormulaToken** ppToken = pArr->GetArray();
546                 sal_uInt16 nTokens = pArr->GetLen();
547                 sal_uInt16 nLevel = 0;
548                 for (sal_uInt16 nTP=0; nTP<nTokens; nTP++)
549                 {
550                     formula::FormulaToken* pTok = ppToken[nTP];
551                     OpCode eOp = pTok->GetOpCode();
552                     if ( eOp == ocOpen )
553                         ++nLevel;
554                     else if ( eOp == ocClose && nLevel )
555                         --nLevel;
556                     if ( nLevel == 0 && pTok->IsFunction() &&
557                             lcl_AddFunction( aAppOpt, sal::static_int_cast<sal_uInt16>( eOp ) ) )
558                         bOptChanged = sal_True;
559                 }
560 
561                 if ( bOptChanged )
562                 {
563                     pScMod->SetAppOptions(aAppOpt);
564                     pScMod->RecentFunctionsChanged();
565                 }
566             }
567 
568             ScFormulaCell aCell( pDoc, aPos, pArr,formula::FormulaGrammar::GRAM_DEFAULT, MM_NONE );
569             delete pArr;
570             sal_Bool bAutoCalc = pDoc->GetAutoCalc();
571             SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
572             for ( ; i<nTabCount; i++)
573             {
574                 if (rMark.GetTableSelect(i))
575                 {
576                     aPos.SetTab( i );
577                     sal_uLong nIndex = (sal_uLong) ((SfxUInt32Item*) pDoc->GetAttr(
578                         nCol, nRow, i, ATTR_VALUE_FORMAT ))->GetValue();
579                     if ( pFormatter->GetType( nIndex ) == NUMBERFORMAT_TEXT ||
580                          ( ( rString.GetChar(0) == '+' || rString.GetChar(0) == '-' ) && nError && rString.Equals( aFormula ) ) )
581                     {
582                         if ( pData )
583                         {
584                             ScEditCell* pCell = new ScEditCell( pData, pDoc, NULL );
585                             pDoc->PutCell( aPos, pCell );
586                         }
587                         else
588                         {
589                             ScStringCell* pCell = new ScStringCell( aFormula );
590                             pDoc->PutCell( aPos, pCell );
591                         }
592                     }
593                     else
594                     {
595                         DELETEZ(pUndoData);
596                         ScFormulaCell* pCell = new ScFormulaCell( aCell, *pDoc, aPos );
597                         if ( nError )
598                         {
599                             pCell->GetCode()->DelRPN();
600                             pCell->SetErrCode( nError );
601                             if(pCell->GetCode()->IsHyperLink())
602                                 pCell->GetCode()->SetHyperLink(sal_False);
603                         }
604                         pDoc->PutCell( aPos, pCell );
605                         if ( !bAutoCalc )
606                         {   // einmal nur die Zelle berechnen und wieder dirty setzen
607                             pCell->Interpret();
608                             pCell->SetDirtyVar();
609                             pDoc->PutInFormulaTree( pCell );
610                         }
611                     }
612 
613                 }
614             }
615         }
616         else
617         {
618             for (i=0; i<nTabCount; i++)
619                 if (rMark.GetTableSelect(i))
620                     if (pDoc->SetString( nCol, nRow, i, rString ))
621                         bNumFmtChanged = sal_True;
622         }
623 
624         //  row height must be changed if new text has a different script type
625         for (i=0; i<nTabCount && !bEditDeleted; i++)
626             if (rMark.GetTableSelect(i))
627                 if ( pDoc->GetScriptType( nCol, nRow, i ) != nOldScript )
628                     bEditDeleted = sal_True;
629 
630         HideAllCursors();
631 
632         if (bEditDeleted || pDoc->HasAttrib( nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_NEEDHEIGHT ))
633             AdjustRowHeight(nRow,nRow);
634 
635         sal_Bool bAutoFormat = TestFormatArea(nCol, nRow, nTab, bNumFmtChanged);
636         if (bAutoFormat)
637             DoAutoAttributes(nCol, nRow, nTab, bNumFmtChanged, bRecord);
638 
639         if ( bRecord )
640         {   // wg. ChangeTrack erst jetzt
641             pDocSh->GetUndoManager()->AddUndoAction(
642                 new ScUndoEnterData( pDocSh, nCol, nRow, nTab, nUndoPos, pTabs,
643                                      ppOldCells, pHasFormat, pOldFormats,
644                                      rString, pUndoData ) );
645         }
646 
647         for (i=0; i<nTabCount; i++)
648             if (rMark.GetTableSelect(i))
649                 pDocSh->PostPaintCell( nCol, nRow, i );
650 
651         ShowAllCursors();
652 
653         pDocSh->UpdateOle(GetViewData());
654 
655         // #i97876# Spreadsheet data changes are not notified
656         ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
657         if ( pModelObj && pModelObj->HasChangesListeners() )
658         {
659             ScRangeList aChangeRanges;
660             for ( i = 0; i < nTabCount; ++i )
661             {
662                 if ( rMark.GetTableSelect( i ) )
663                 {
664                     aChangeRanges.Append( ScRange( nCol, nRow, i ) );
665                 }
666             }
667             pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges );
668         }
669 
670         aModificator.SetDocumentModified();
671     }
672     else
673     {
674         ErrorMessage(aTester.GetMessageId());
675         PaintArea( nCol, nRow, nCol, nRow );        // da steht evtl. noch die Edit-Engine
676     }
677 }
678 
679 //  Wert in einzele Zelle eintragen (nur auf nTab)
680 
EnterValue(SCCOL nCol,SCROW nRow,SCTAB nTab,const double & rValue)681 void ScViewFunc::EnterValue( SCCOL nCol, SCROW nRow, SCTAB nTab, const double& rValue )
682 {
683     ScDocument* pDoc = GetViewData()->GetDocument();
684     ScDocShell* pDocSh = GetViewData()->GetDocShell();
685     sal_Bool bUndo (pDoc->IsUndoEnabled());
686 
687     if ( pDoc && pDocSh )
688     {
689         ScDocShellModificator aModificator( *pDocSh );
690 
691         ScEditableTester aTester( pDoc, nTab, nCol,nRow, nCol,nRow );
692         if (aTester.IsEditable())
693         {
694             ScAddress aPos( nCol, nRow, nTab );
695             ScBaseCell* pOldCell = pDoc->GetCell( aPos );
696             sal_Bool bNeedHeight = ( pOldCell && pOldCell->GetCellType() == CELLTYPE_EDIT )
697                                 || pDoc->HasAttrib(
698                                     nCol,nRow,nTab, nCol,nRow,nTab, HASATTR_NEEDHEIGHT );
699 
700             //  Undo
701             ScBaseCell* pUndoCell = (bUndo && pOldCell) ? pOldCell->CloneWithoutNote( *pDoc ) : 0;
702 
703             pDoc->SetValue( nCol, nRow, nTab, rValue );
704 
705             // wg. ChangeTrack nach Aenderung im Dokument
706             if (bUndo)
707             {
708                 pDocSh->GetUndoManager()->AddUndoAction(
709                     new ScUndoEnterValue( pDocSh, aPos, pUndoCell, rValue, bNeedHeight ) );
710             }
711 
712 /*!             Zeilenhoehe anpassen? Dann auch bei Undo...
713             if (bNeedHeight)
714                 AdjustRowHeight(nRow,nRow);
715 */
716 
717             pDocSh->PostPaintCell( aPos );
718             pDocSh->UpdateOle(GetViewData());
719             aModificator.SetDocumentModified();
720         }
721         else
722             ErrorMessage(aTester.GetMessageId());
723     }
724 }
725 
EnterData(SCCOL nCol,SCROW nRow,SCTAB nTab,const EditTextObject * pData,sal_Bool bRecord,sal_Bool bTestSimple)726 void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const EditTextObject* pData,
727                             sal_Bool bRecord, sal_Bool bTestSimple )
728 {
729     ScDocShell* pDocSh = GetViewData()->GetDocShell();
730     ScMarkData& rMark = GetViewData()->GetMarkData();
731     ScDocument* pDoc = pDocSh->GetDocument();
732     if (bRecord && !pDoc->IsUndoEnabled())
733         bRecord = sal_False;
734 
735     ScDocShellModificator aModificator( *pDocSh );
736 
737     ScEditableTester aTester( pDoc, nTab, nCol,nRow, nCol,nRow );
738     if (aTester.IsEditable())
739     {
740         //
741         //      Test auf Attribute
742         //
743         sal_Bool bSimple = sal_False;
744         sal_Bool bCommon = sal_False;
745         ScPatternAttr* pCellAttrs = NULL;
746         EditTextObject* pNewData = NULL;
747         String aString;
748 
749         const ScPatternAttr* pOldPattern = pDoc->GetPattern( nCol, nRow, nTab );
750         ScTabEditEngine aEngine( *pOldPattern, pDoc->GetEnginePool() );
751         aEngine.SetText(*pData);
752 
753         if (bTestSimple)                    // Testen, ob einfacher String ohne Attribute
754         {
755             ScEditAttrTester aAttrTester( &aEngine );
756             bSimple = !aAttrTester.NeedsObject();
757             bCommon = aAttrTester.NeedsCellAttr();
758 
759             // formulas have to be recognized even if they're formatted
760             // (but commmon attributes are still collected)
761 
762             if ( !bSimple && aEngine.GetParagraphCount() == 1 )
763             {
764                 String aParStr = aEngine.GetText( (sal_uInt16) 0 );
765                 if ( aParStr.GetChar(0) == '=' )
766                     bSimple = sal_True;
767             }
768 
769             if (bCommon)                // Attribute fuer Tabelle
770             {
771                 pCellAttrs = new ScPatternAttr( *pOldPattern );
772                 pCellAttrs->GetFromEditItemSet( &aAttrTester.GetAttribs() );
773                 //! remove common attributes from EditEngine?
774             }
775         }
776 
777         // #i97726# always get text for "repeat" of undo action
778         aString = ScEditUtil::GetSpaceDelimitedString(aEngine);
779 
780         //
781         //      Undo
782         //
783 
784         SCTAB nTabCount = pDoc->GetTableCount();
785         SCTAB nSelCount = rMark.GetSelectCount();
786         SCTAB i;
787         ScBaseCell** ppOldCells = NULL;
788         SCTAB* pTabs            = NULL;
789         SCTAB nPos = 0;
790         EditTextObject* pUndoData = NULL;
791         if (bRecord && !bSimple)
792         {
793             ppOldCells  = new ScBaseCell*[nSelCount];
794             pTabs       = new SCTAB[nSelCount];
795             nPos = 0;
796 
797             for (i=0; i<nTabCount; i++)
798                 if (rMark.GetTableSelect(i))
799                 {
800                     pTabs[nPos] = i;
801                     ScBaseCell* pDocCell;
802                     pDoc->GetCell( nCol, nRow, i, pDocCell );
803                     ppOldCells[nPos] = pDocCell ? pDocCell->CloneWithoutNote( *pDoc ) : 0;
804                     ++nPos;
805                 }
806 
807             DBG_ASSERT( nPos==nSelCount, "nPos!=nSelCount" );
808 
809             pUndoData = pData->Clone();
810         }
811 
812         //
813         //      Daten eintragen
814         //
815 
816         if (bCommon)
817             pDoc->ApplyPattern(nCol,nRow,nTab,*pCellAttrs);         //! Undo
818 
819         if (bSimple)
820         {
821             if (bCommon)
822                 AdjustRowHeight(nRow,nRow);
823 
824             EnterData(nCol,nRow,nTab,aString,bRecord);
825         }
826         else
827         {
828             for (i=0; i<nTabCount; i++)
829                 if (rMark.GetTableSelect(i))
830                     pDoc->PutCell( nCol, nRow, i, new ScEditCell( pData, pDoc, NULL ) );
831 
832             if ( bRecord )
833             {   // wg. ChangeTrack erst jetzt
834                 pDocSh->GetUndoManager()->AddUndoAction(
835                     new ScUndoEnterData( pDocSh, nCol, nRow, nTab, nPos, pTabs,
836                                         ppOldCells, NULL, NULL, aString,
837                                         pUndoData ) );
838             }
839 
840             HideAllCursors();
841 
842             AdjustRowHeight(nRow,nRow);
843 
844             for (i=0; i<nTabCount; i++)
845                 if (rMark.GetTableSelect(i))
846                     pDocSh->PostPaintCell( nCol, nRow, i );
847 
848             ShowAllCursors();
849 
850             pDocSh->UpdateOle(GetViewData());
851 
852             // #i97876# Spreadsheet data changes are not notified
853             ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
854             if ( pModelObj && pModelObj->HasChangesListeners() )
855             {
856                 ScRangeList aChangeRanges;
857                 for ( i = 0; i < nTabCount; ++i )
858                 {
859                     if ( rMark.GetTableSelect( i ) )
860                     {
861                         aChangeRanges.Append( ScRange( nCol, nRow, i ) );
862                     }
863                 }
864                 pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges );
865             }
866 
867             aModificator.SetDocumentModified();
868         }
869 
870         delete pCellAttrs;
871         delete pNewData;
872     }
873     else
874     {
875         ErrorMessage(aTester.GetMessageId());
876         PaintArea( nCol, nRow, nCol, nRow );        // da steht evtl. noch die Edit-Engine
877     }
878 }
879 
EnterDataAtCursor(const String & rString)880 void ScViewFunc::EnterDataAtCursor( const String& rString )
881 {
882     SCCOL nPosX = GetViewData()->GetCurX();
883     SCROW nPosY = GetViewData()->GetCurY();
884     SCTAB nTab = GetViewData()->GetTabNo();
885 
886     EnterData( nPosX, nPosY, nTab, rString );
887 }
888 
EnterMatrix(const String & rString)889 void ScViewFunc::EnterMatrix( const String& rString )
890 {
891     ScViewData* pData = GetViewData();
892     const ScMarkData& rMark = pData->GetMarkData();
893     if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
894     {
895         //  nichts markiert -> automatisch Block mit Groesse des Ergebnisses
896         //  Formel temporaer berechnen, um an die Groesse heranzukommen
897 
898         ScDocument* pDoc = pData->GetDocument();
899         SCCOL nCol = pData->GetCurX();
900         SCROW nRow = pData->GetCurY();
901         SCTAB nTab = pData->GetTabNo();
902         ScFormulaCell aFormCell( pDoc, ScAddress(nCol,nRow,nTab), rString,formula::FormulaGrammar::GRAM_DEFAULT, MM_FORMULA );
903 
904         SCSIZE nSizeX;
905         SCSIZE nSizeY;
906         aFormCell.GetResultDimensions( nSizeX, nSizeY );
907         if ( nSizeX != 0 && nSizeY != 0 &&
908              nCol+nSizeX-1 <= sal::static_int_cast<SCSIZE>(MAXCOL) &&
909              nRow+nSizeY-1 <= sal::static_int_cast<SCSIZE>(MAXROW) )
910         {
911             ScRange aResult( nCol, nRow, nTab,
912                              sal::static_int_cast<SCCOL>(nCol+nSizeX-1),
913                              sal::static_int_cast<SCROW>(nRow+nSizeY-1), nTab );
914             MarkRange( aResult, sal_False );
915         }
916     }
917 
918     ScRange aRange;
919     if (pData->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
920     {
921         ScDocShell* pDocSh = pData->GetDocShell();
922         sal_Bool bSuccess = pDocSh->GetDocFunc().EnterMatrix( aRange, &rMark, NULL, rString, sal_False, sal_False, EMPTY_STRING, formula::FormulaGrammar::GRAM_DEFAULT );
923         if (bSuccess)
924             pDocSh->UpdateOle(GetViewData());
925     }
926     else
927         ErrorMessage(STR_NOMULTISELECT);
928 }
929 
GetSelectionScriptType()930 sal_uInt8 ScViewFunc::GetSelectionScriptType()
931 {
932     sal_uInt8 nScript = 0;
933 
934     ScDocument* pDoc = GetViewData()->GetDocument();
935     const ScMarkData& rMark = GetViewData()->GetMarkData();
936     if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
937     {
938         // no selection -> cursor
939 
940         nScript = pDoc->GetScriptType( GetViewData()->GetCurX(),
941                             GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
942     }
943     else
944     {
945         ScRangeList aRanges;
946         rMark.FillRangeListWithMarks( &aRanges, sal_False );
947         sal_uLong nCount = aRanges.Count();
948         for (sal_uLong i=0; i<nCount; i++)
949         {
950             ScRange aRange = *aRanges.GetObject(i);
951             ScCellIterator aIter( pDoc, aRange );
952             ScBaseCell* pCell = aIter.GetFirst();
953             while ( pCell )
954             {
955                 nScript |= pDoc->GetScriptType( aIter.GetCol(), aIter.GetRow(), aIter.GetTab(), pCell );
956                 pCell = aIter.GetNext();
957             }
958         }
959     }
960 
961     if (nScript == 0)
962         nScript = ScGlobal::GetDefaultScriptType();
963 
964     return nScript;
965 }
966 
GetSelectionPattern()967 const ScPatternAttr* ScViewFunc::GetSelectionPattern()
968 {
969     // Don't use UnmarkFiltered in slot state functions, for performance reasons.
970     // The displayed state is always that of the whole selection including filtered rows.
971 
972     const ScMarkData& rMark = GetViewData()->GetMarkData();
973     ScDocument* pDoc = GetViewData()->GetDocument();
974     if ( rMark.IsMarked() || rMark.IsMultiMarked() )
975     {
976         //  MarkToMulti is no longer necessary for pDoc->GetSelectionPattern
977         const ScPatternAttr* pAttr = pDoc->GetSelectionPattern( rMark );
978         return pAttr;
979     }
980     else
981     {
982         SCCOL  nCol = GetViewData()->GetCurX();
983         SCROW  nRow = GetViewData()->GetCurY();
984         SCTAB  nTab = GetViewData()->GetTabNo();
985 
986         ScMarkData aTempMark( rMark );      // copy sheet selection
987         aTempMark.SetMarkArea( ScRange( nCol, nRow, nTab ) );
988         const ScPatternAttr* pAttr = pDoc->GetSelectionPattern( aTempMark );
989         return pAttr;
990     }
991 }
992 
GetSelectionFrame(SvxBoxItem & rLineOuter,SvxBoxInfoItem & rLineInner)993 void ScViewFunc::GetSelectionFrame( SvxBoxItem&     rLineOuter,
994                                     SvxBoxInfoItem& rLineInner )
995 {
996     ScDocument* pDoc = GetViewData()->GetDocument();
997     const ScMarkData& rMark = GetViewData()->GetMarkData();
998 
999     if ( rMark.IsMarked() || rMark.IsMultiMarked() )
1000     {
1001         if ( rMark.IsMultiMarked() )
1002         {
1003             ScMarkData aNewMark( rMark );   // use local copy for MarkToSimple
1004             aNewMark.MarkToSimple();        // simple block is needed for GetSelectionFrame
1005             pDoc->GetSelectionFrame( aNewMark, rLineOuter, rLineInner );
1006         }
1007         else
1008             pDoc->GetSelectionFrame( rMark, rLineOuter, rLineInner );
1009     }
1010     else
1011     {
1012         const ScPatternAttr* pAttrs =
1013                     pDoc->GetPattern( GetViewData()->GetCurX(),
1014                                       GetViewData()->GetCurY(),
1015                                       GetViewData()->GetTabNo() );
1016 
1017         rLineOuter = (const SvxBoxItem&)    (pAttrs->GetItem( ATTR_BORDER ));
1018         rLineInner = (const SvxBoxInfoItem&)(pAttrs->GetItem( ATTR_BORDER_INNER ));
1019         rLineInner.SetTable(sal_False);
1020         rLineInner.SetDist(sal_True);
1021         rLineInner.SetMinDist(sal_False);
1022     }
1023 }
1024 
1025 //
1026 //  Attribute anwenden - Undo OK
1027 //
1028 //  kompletter Set ( ATTR_STARTINDEX, ATTR_ENDINDEX )
1029 //
1030 
ApplyAttributes(const SfxItemSet * pDialogSet,const SfxItemSet * pOldSet,sal_Bool bRecord)1031 void ScViewFunc::ApplyAttributes( const SfxItemSet* pDialogSet,
1032                                   const SfxItemSet* pOldSet,
1033                                   sal_Bool              bRecord )
1034 {
1035     // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
1036     sal_Bool bOnlyNotBecauseOfMatrix;
1037     if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
1038     {
1039         ErrorMessage(STR_PROTECTIONERR);
1040         return;
1041     }
1042 
1043     ScPatternAttr aOldAttrs( new SfxItemSet(*pOldSet) );
1044     ScPatternAttr aNewAttrs( new SfxItemSet(*pDialogSet) );
1045     aNewAttrs.DeleteUnchanged( &aOldAttrs );
1046 
1047     if ( pDialogSet->GetItemState( ATTR_VALUE_FORMAT ) == SFX_ITEM_SET )
1048     {   // #82521# don't reset to default SYSTEM GENERAL if not intended
1049         sal_uInt32 nOldFormat =
1050             ((const SfxUInt32Item&)pOldSet->Get( ATTR_VALUE_FORMAT )).GetValue();
1051         sal_uInt32 nNewFormat =
1052             ((const SfxUInt32Item&)pDialogSet->Get( ATTR_VALUE_FORMAT )).GetValue();
1053         if ( nNewFormat != nOldFormat )
1054         {
1055             SvNumberFormatter* pFormatter =
1056                 GetViewData()->GetDocument()->GetFormatTable();
1057             const SvNumberformat* pOldEntry = pFormatter->GetEntry( nOldFormat );
1058             LanguageType eOldLang =
1059                 pOldEntry ? pOldEntry->GetLanguage() : LANGUAGE_DONTKNOW;
1060             const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewFormat );
1061             LanguageType eNewLang =
1062                 pNewEntry ? pNewEntry->GetLanguage() : LANGUAGE_DONTKNOW;
1063             if ( eNewLang != eOldLang )
1064             {
1065                 aNewAttrs.GetItemSet().Put(
1066                     SvxLanguageItem( eNewLang, ATTR_LANGUAGE_FORMAT ) );
1067 
1068                 //  #40606# nur die Sprache geaendert -> Zahlformat-Attribut nicht anfassen
1069                 sal_uInt32 nNewMod = nNewFormat % SV_COUNTRY_LANGUAGE_OFFSET;
1070                 if ( nNewMod == ( nOldFormat % SV_COUNTRY_LANGUAGE_OFFSET ) &&
1071                     nNewMod <= SV_MAX_ANZ_STANDARD_FORMATE )
1072                     aNewAttrs.GetItemSet().ClearItem( ATTR_VALUE_FORMAT );
1073             }
1074         }
1075     }
1076 
1077     const SvxBoxItem*     pOldOuter = (const SvxBoxItem*)     &pOldSet->Get( ATTR_BORDER );
1078     const SvxBoxItem*     pNewOuter = (const SvxBoxItem*)     &pDialogSet->Get( ATTR_BORDER );
1079     const SvxBoxInfoItem* pOldInner = (const SvxBoxInfoItem*) &pOldSet->Get( ATTR_BORDER_INNER );
1080     const SvxBoxInfoItem* pNewInner = (const SvxBoxInfoItem*) &pDialogSet->Get( ATTR_BORDER_INNER );
1081     SfxItemSet&           rNewSet   = aNewAttrs.GetItemSet();
1082     SfxItemPool*          pNewPool  = rNewSet.GetPool();
1083 
1084     pNewPool->Put( *pNewOuter );        // noch nicht loeschen
1085     pNewPool->Put( *pNewInner );
1086     rNewSet.ClearItem( ATTR_BORDER );
1087     rNewSet.ClearItem( ATTR_BORDER_INNER );
1088 
1089     /*
1090      * Feststellen, ob Rahmenattribute zu setzen sind:
1091      * 1. Neu != Alt
1092      * 2. Ist eine der Linien nicht-DontCare (seit 238.f: IsxxValid())
1093      *
1094      */
1095 
1096     sal_Bool bFrame =    (pDialogSet->GetItemState( ATTR_BORDER ) != SFX_ITEM_DEFAULT)
1097                   || (pDialogSet->GetItemState( ATTR_BORDER_INNER ) != SFX_ITEM_DEFAULT);
1098 
1099     if ( pNewOuter==pOldOuter && pNewInner==pOldInner )
1100         bFrame = sal_False;
1101 
1102     //  das sollte doch der Pool abfangen: ?!??!??
1103 
1104     if ( bFrame && pNewOuter && pNewInner )
1105         if ( *pNewOuter == *pOldOuter && *pNewInner == *pOldInner )
1106             bFrame = sal_False;
1107 
1108     if ( pNewInner )
1109     {
1110         bFrame =   bFrame
1111                 && (   pNewInner->IsValid(VALID_LEFT)
1112                     || pNewInner->IsValid(VALID_RIGHT)
1113                     || pNewInner->IsValid(VALID_TOP)
1114                     || pNewInner->IsValid(VALID_BOTTOM)
1115                     || pNewInner->IsValid(VALID_HORI)
1116                     || pNewInner->IsValid(VALID_VERT) );
1117     }
1118     else
1119         bFrame = sal_False;
1120 
1121     if (!bFrame)
1122         ApplySelectionPattern( aNewAttrs, bRecord );                // nur normale
1123     else
1124     {
1125         // wenn neue Items Default-Items sind, so muessen die
1126         // alten Items geputtet werden:
1127 
1128         sal_Bool bDefNewOuter = ( SFX_ITEMS_STATICDEFAULT == pNewOuter->GetKind() );
1129         sal_Bool bDefNewInner = ( SFX_ITEMS_STATICDEFAULT == pNewInner->GetKind() );
1130 
1131         ApplyPatternLines( aNewAttrs,
1132                            bDefNewOuter ? pOldOuter : pNewOuter,
1133                            bDefNewInner ? pOldInner : pNewInner,
1134                            bRecord );
1135     }
1136 
1137     pNewPool->Remove( *pNewOuter );         // freigeben
1138     pNewPool->Remove( *pNewInner );
1139 
1140     //  Hoehen anpassen
1141     AdjustBlockHeight();
1142 
1143     // CellContentChanged wird von ApplySelectionPattern / ApplyPatternLines gerufen
1144 }
1145 
ApplyAttr(const SfxPoolItem & rAttrItem)1146 void ScViewFunc::ApplyAttr( const SfxPoolItem& rAttrItem )
1147 {
1148     // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
1149     sal_Bool bOnlyNotBecauseOfMatrix;
1150     if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
1151     {
1152         ErrorMessage(STR_PROTECTIONERR);
1153         return;
1154     }
1155 
1156     ScPatternAttr aNewAttrs( new SfxItemSet( *GetViewData()->GetDocument()->GetPool(),
1157                                             ATTR_PATTERN_START, ATTR_PATTERN_END ) );
1158 
1159     aNewAttrs.GetItemSet().Put( rAttrItem );
1160     //  Wenn Ausrichtung eingestellt wird (ueber Buttons), immer Einzug 0
1161     if ( rAttrItem.Which() == ATTR_HOR_JUSTIFY )
1162         aNewAttrs.GetItemSet().Put( SfxUInt16Item( ATTR_INDENT, 0 ) );
1163     ApplySelectionPattern( aNewAttrs );
1164 
1165     AdjustBlockHeight();
1166 
1167     // CellContentChanged wird von ApplySelectionPattern gerufen
1168 }
1169 
1170 
1171 //  Pattern und Rahmen
1172 
ApplyPatternLines(const ScPatternAttr & rAttr,const SvxBoxItem * pNewOuter,const SvxBoxInfoItem * pNewInner,sal_Bool bRecord)1173 void ScViewFunc::ApplyPatternLines( const ScPatternAttr& rAttr, const SvxBoxItem* pNewOuter,
1174                                     const SvxBoxInfoItem* pNewInner, sal_Bool bRecord )
1175 {
1176     ScDocument* pDoc = GetViewData()->GetDocument();
1177     ScMarkData aFuncMark( GetViewData()->GetMarkData() );       // local copy for UnmarkFiltered
1178     ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
1179     if (bRecord && !pDoc->IsUndoEnabled())
1180         bRecord = sal_False;
1181 
1182     ScRange aMarkRange;
1183     aFuncMark.MarkToSimple();
1184     sal_Bool bMulti = aFuncMark.IsMultiMarked();
1185     if (bMulti)
1186         aFuncMark.GetMultiMarkArea( aMarkRange );
1187     else if (aFuncMark.IsMarked())
1188         aFuncMark.GetMarkArea( aMarkRange );
1189     else
1190     {
1191         aMarkRange = ScRange( GetViewData()->GetCurX(),
1192                             GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
1193         DoneBlockMode();
1194         InitOwnBlockMode();
1195         aFuncMark.SetMarkArea(aMarkRange);
1196         MarkDataChanged();
1197     }
1198 
1199     ScDocShell* pDocSh = GetViewData()->GetDocShell();
1200 
1201     ScDocShellModificator aModificator( *pDocSh );
1202 
1203     if (bRecord)
1204     {
1205         ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1206         SCTAB nStartTab = aMarkRange.aStart.Tab();
1207         SCTAB nTabCount = pDoc->GetTableCount();
1208         pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
1209         for (SCTAB i=0; i<nTabCount; i++)
1210             if (i != nStartTab && aFuncMark.GetTableSelect(i))
1211                 pUndoDoc->AddUndoTab( i, i );
1212 
1213         ScRange aCopyRange = aMarkRange;
1214         aCopyRange.aStart.SetTab(0);
1215         aCopyRange.aEnd.SetTab(nTabCount-1);
1216         pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &aFuncMark );
1217 
1218         pDocSh->GetUndoManager()->AddUndoAction(
1219             new ScUndoSelectionAttr(
1220             pDocSh, aFuncMark,
1221             aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), aMarkRange.aStart.Tab(),
1222             aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), aMarkRange.aEnd.Tab(),
1223             pUndoDoc, bMulti, &rAttr, pNewOuter, pNewInner ) );
1224     }
1225 
1226     sal_uInt16 nExt = SC_PF_TESTMERGE;
1227     pDocSh->UpdatePaintExt( nExt, aMarkRange ); // content before the change
1228 
1229     pDoc->ApplySelectionFrame( aFuncMark, pNewOuter, pNewInner );
1230 
1231     pDocSh->UpdatePaintExt( nExt, aMarkRange ); // content after the change
1232 
1233     aFuncMark.MarkToMulti();
1234     pDoc->ApplySelectionPattern( rAttr, aFuncMark );
1235 
1236     pDocSh->PostPaint( aMarkRange, PAINT_GRID, nExt );
1237     pDocSh->UpdateOle(GetViewData());
1238     aModificator.SetDocumentModified();
1239     CellContentChanged();
1240 
1241     StartFormatArea();
1242 }
1243 
1244 //  nur Pattern
1245 
ApplySelectionPattern(const ScPatternAttr & rAttr,sal_Bool bRecord,sal_Bool bCursorOnly)1246 void ScViewFunc::ApplySelectionPattern( const ScPatternAttr& rAttr,
1247                                             sal_Bool bRecord, sal_Bool bCursorOnly )
1248 {
1249     ScViewData* pViewData   = GetViewData();
1250     ScDocShell* pDocSh      = pViewData->GetDocShell();
1251     ScDocument* pDoc        = pDocSh->GetDocument();
1252     ScMarkData aFuncMark( pViewData->GetMarkData() );       // local copy for UnmarkFiltered
1253     ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
1254 
1255     if (bRecord && !pDoc->IsUndoEnabled())
1256         bRecord = sal_False;
1257 
1258     //  State from old ItemSet doesn't matter for paint flags, as any change will be
1259     //  from SFX_ITEM_SET in the new ItemSet (default is ignored in ApplyPattern).
1260     //  New alignment is checked (check in PostPaint isn't enough) in case a right
1261     //  alignment is changed to left.
1262     const SfxItemSet& rNewSet = rAttr.GetItemSet();
1263     sal_Bool bSetLines = rNewSet.GetItemState( ATTR_BORDER, sal_True ) == SFX_ITEM_SET ||
1264                      rNewSet.GetItemState( ATTR_SHADOW, sal_True ) == SFX_ITEM_SET;
1265     sal_Bool bSetAlign = rNewSet.GetItemState( ATTR_HOR_JUSTIFY, sal_True ) == SFX_ITEM_SET;
1266 
1267     sal_uInt16 nExtFlags = 0;
1268     if ( bSetLines )
1269         nExtFlags |= SC_PF_LINES;
1270     if ( bSetAlign )
1271         nExtFlags |= SC_PF_WHOLEROWS;
1272 
1273     ScDocShellModificator aModificator( *pDocSh );
1274 
1275     sal_Bool bMulti = aFuncMark.IsMultiMarked();
1276     aFuncMark.MarkToMulti();
1277     sal_Bool bOnlyTab = (!aFuncMark.IsMultiMarked() && !bCursorOnly && aFuncMark.GetSelectCount() > 1);
1278     if (bOnlyTab)
1279     {
1280         SCCOL nCol = pViewData->GetCurX();
1281         SCROW nRow = pViewData->GetCurY();
1282         SCTAB nTab = pViewData->GetTabNo();
1283         aFuncMark.SetMarkArea(ScRange(nCol,nRow,nTab));
1284         aFuncMark.MarkToMulti();
1285     }
1286 
1287     ScRangeList aChangeRanges;
1288 
1289     if (aFuncMark.IsMultiMarked() && !bCursorOnly)
1290     {
1291         ScRange aMarkRange;
1292         aFuncMark.GetMultiMarkArea( aMarkRange );
1293         SCTAB nTabCount = pDoc->GetTableCount();
1294         for ( SCTAB i = 0; i < nTabCount; ++i )
1295         {
1296             if ( aFuncMark.GetTableSelect( i ) )
1297             {
1298                 ScRange aChangeRange( aMarkRange );
1299                 aChangeRange.aStart.SetTab( i );
1300                 aChangeRange.aEnd.SetTab( i );
1301                 aChangeRanges.Append( aChangeRange );
1302             }
1303         }
1304 
1305         SCCOL nStartCol = aMarkRange.aStart.Col();
1306         SCROW nStartRow = aMarkRange.aStart.Row();
1307         SCTAB nStartTab = aMarkRange.aStart.Tab();
1308         SCCOL nEndCol = aMarkRange.aEnd.Col();
1309         SCROW nEndRow = aMarkRange.aEnd.Row();
1310         SCTAB nEndTab = aMarkRange.aEnd.Tab();
1311 
1312         if (bRecord)
1313         {
1314             ScRange aCopyRange = aMarkRange;
1315             aCopyRange.aStart.SetTab(0);
1316             aCopyRange.aEnd.SetTab(nTabCount-1);
1317 
1318             ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1319             pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab );
1320             for (SCTAB i=0; i<nTabCount; i++)
1321                 if (i != nStartTab && aFuncMark.GetTableSelect(i))
1322                     pUndoDoc->AddUndoTab( i, i );
1323             pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &aFuncMark );
1324 
1325             aFuncMark.MarkToMulti();
1326 
1327             pDocSh->GetUndoManager()->AddUndoAction(
1328                 new ScUndoSelectionAttr(
1329                             pDocSh, aFuncMark,
1330                             nStartCol, nStartRow, nStartTab,
1331                             nEndCol, nEndRow, nEndTab,
1332                             pUndoDoc, bMulti, &rAttr ) );
1333         }
1334 
1335         pDoc->ApplySelectionPattern( rAttr, aFuncMark );
1336 
1337         pDocSh->PostPaint( nStartCol, nStartRow, nStartTab,
1338                            nEndCol,   nEndRow,   nEndTab,
1339                            PAINT_GRID, nExtFlags | SC_PF_TESTMERGE );
1340         pDocSh->UpdateOle(GetViewData());
1341         aModificator.SetDocumentModified();
1342         CellContentChanged();
1343     }
1344     else                            // einzelne Zelle - Undo einfacher
1345     {
1346         SCCOL nCol = pViewData->GetCurX();
1347         SCROW nRow = pViewData->GetCurY();
1348         SCTAB nTab = pViewData->GetTabNo();
1349         aChangeRanges.Append( ScRange( nCol, nRow, nTab ) );
1350         ScPatternAttr* pOldPat = new ScPatternAttr(*pDoc->GetPattern( nCol, nRow, nTab ));
1351 
1352         pDoc->ApplyPattern( nCol, nRow, nTab, rAttr );
1353 
1354         const ScPatternAttr* pNewPat = pDoc->GetPattern( nCol, nRow, nTab );
1355 
1356         if (bRecord)
1357         {
1358             pDocSh->GetUndoManager()->AddUndoAction(
1359                         new ScUndoCursorAttr( pDocSh,
1360                                               nCol, nRow, nTab,
1361                                               pOldPat, pNewPat, &rAttr,
1362                                               sal_False ) );    // sal_False = nicht automatisch
1363         }
1364         delete pOldPat;     // wird im Undo kopiert (Pool)
1365 
1366         pDocSh->PostPaint( nCol,nRow,nTab, nCol,nRow,nTab, PAINT_GRID, nExtFlags | SC_PF_TESTMERGE );
1367         pDocSh->UpdateOle(GetViewData());
1368         aModificator.SetDocumentModified();
1369         CellContentChanged();
1370     }
1371 
1372     // #i97876# Spreadsheet data changes are not notified
1373     ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
1374     if ( pModelObj && pModelObj->HasChangesListeners() )
1375     {
1376         ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue > aProperties;
1377         sal_Int32 nCount = 0;
1378         const SfxItemPropertyMap* pMap = ScCellObj::GetCellPropertyMap();
1379         PropertyEntryVector_t aPropVector = pMap->getPropertyEntries();
1380         for ( sal_uInt16 nWhich = ATTR_PATTERN_START; nWhich <= ATTR_PATTERN_END; ++nWhich )
1381         {
1382             const SfxPoolItem* pItem = 0;
1383             if ( rNewSet.GetItemState( nWhich, sal_True, &pItem ) == SFX_ITEM_SET && pItem )
1384             {
1385                 PropertyEntryVector_t::const_iterator aIt = aPropVector.begin();
1386                 while ( aIt != aPropVector.end())
1387                 {
1388                     if ( aIt->nWID == nWhich )
1389                     {
1390                         ::com::sun::star::uno::Any aVal;
1391                         pItem->QueryValue( aVal, aIt->nMemberId );
1392                         aProperties.realloc( nCount + 1 );
1393                         aProperties[ nCount ].Name = aIt->sName;
1394                         aProperties[ nCount ].Value <<= aVal;
1395                         ++nCount;
1396                     }
1397                     ++aIt;
1398                 }
1399             }
1400         }
1401         pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "attribute" ) ), aChangeRanges, aProperties );
1402     }
1403 
1404     StartFormatArea();
1405 }
1406 
ApplyUserItemSet(const SfxItemSet & rItemSet)1407 void ScViewFunc::ApplyUserItemSet( const SfxItemSet& rItemSet )
1408 {
1409     //  ItemSet from UI, may have different pool
1410 
1411     sal_Bool bOnlyNotBecauseOfMatrix;
1412     if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
1413     {
1414         ErrorMessage(STR_PROTECTIONERR);
1415         return;
1416     }
1417 
1418     ScPatternAttr aNewAttrs( GetViewData()->GetDocument()->GetPool() );
1419     SfxItemSet& rNewSet = aNewAttrs.GetItemSet();
1420     rNewSet.Put( rItemSet, sal_False );
1421     ApplySelectionPattern( aNewAttrs );
1422 
1423     AdjustBlockHeight();
1424 }
1425 
GetStyleSheetFromMarked()1426 const SfxStyleSheet* ScViewFunc::GetStyleSheetFromMarked()
1427 {
1428     // Don't use UnmarkFiltered in slot state functions, for performance reasons.
1429     // The displayed state is always that of the whole selection including filtered rows.
1430 
1431     const ScStyleSheet* pSheet      = NULL;
1432     ScViewData*         pViewData   = GetViewData();
1433     ScDocument*         pDoc        = pViewData->GetDocument();
1434     ScMarkData&         rMark       = pViewData->GetMarkData();
1435 
1436     if ( rMark.IsMarked() || rMark.IsMultiMarked() )
1437         pSheet = pDoc->GetSelectionStyle( rMark );                  // MarkToMulti isn't necessary
1438     else
1439         pSheet = pDoc->GetStyle( pViewData->GetCurX(),
1440                                  pViewData->GetCurY(),
1441                                  pViewData->GetTabNo() );
1442 
1443     return pSheet;
1444 }
1445 
SetStyleSheetToMarked(SfxStyleSheet * pStyleSheet,sal_Bool bRecord)1446 void ScViewFunc::SetStyleSheetToMarked( SfxStyleSheet* pStyleSheet, sal_Bool bRecord )
1447 {
1448     // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
1449     sal_Bool bOnlyNotBecauseOfMatrix;
1450     if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
1451     {
1452         ErrorMessage(STR_PROTECTIONERR);
1453         return;
1454     }
1455 
1456     if ( !pStyleSheet) return;
1457     // -------------------------------------------------------------------
1458 
1459     ScViewData* pViewData   = GetViewData();
1460     ScDocShell* pDocSh      = pViewData->GetDocShell();
1461     ScDocument* pDoc        = pDocSh->GetDocument();
1462     ScMarkData aFuncMark( pViewData->GetMarkData() );       // local copy for UnmarkFiltered
1463     ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
1464     SCTAB nTabCount     = pDoc->GetTableCount();
1465     if (bRecord && !pDoc->IsUndoEnabled())
1466         bRecord = sal_False;
1467 
1468     ScDocShellModificator aModificator( *pDocSh );
1469 
1470     if ( aFuncMark.IsMarked() || aFuncMark.IsMultiMarked() )
1471     {
1472         ScRange aMarkRange;
1473         aFuncMark.MarkToMulti();
1474         aFuncMark.GetMultiMarkArea( aMarkRange );
1475 
1476         if ( bRecord )
1477         {
1478             SCTAB nTab = pViewData->GetTabNo();
1479             ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1480             pUndoDoc->InitUndo( pDoc, nTab, nTab );
1481             for (SCTAB i=0; i<nTabCount; i++)
1482                 if (i != nTab && aFuncMark.GetTableSelect(i))
1483                     pUndoDoc->AddUndoTab( i, i );
1484 
1485             ScRange aCopyRange = aMarkRange;
1486             aCopyRange.aStart.SetTab(0);
1487             aCopyRange.aEnd.SetTab(nTabCount-1);
1488             pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_True, pUndoDoc, &aFuncMark );
1489             aFuncMark.MarkToMulti();
1490 
1491             String aName = pStyleSheet->GetName();
1492             pDocSh->GetUndoManager()->AddUndoAction(
1493                 new ScUndoSelectionStyle( pDocSh, aFuncMark, aMarkRange, aName, pUndoDoc ) );
1494         }
1495 
1496         pDoc->ApplySelectionStyle( (ScStyleSheet&)*pStyleSheet, aFuncMark );
1497 
1498         if (!AdjustBlockHeight())
1499             pViewData->GetDocShell()->PostPaint( aMarkRange, PAINT_GRID );
1500 
1501         aFuncMark.MarkToSimple();
1502     }
1503     else
1504     {
1505         SCCOL nCol = pViewData->GetCurX();
1506         SCROW nRow = pViewData->GetCurY();
1507         SCTAB nTab = pViewData->GetTabNo();
1508 
1509         if ( bRecord )
1510         {
1511             ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1512             pUndoDoc->InitUndo( pDoc, nTab, nTab );
1513             for (SCTAB i=0; i<nTabCount; i++)
1514                 if (i != nTab && aFuncMark.GetTableSelect(i))
1515                     pUndoDoc->AddUndoTab( i, i );
1516 
1517             ScRange aCopyRange( nCol, nRow, 0, nCol, nRow, nTabCount-1 );
1518             pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, sal_False, pUndoDoc );
1519 
1520             ScRange aMarkRange ( nCol, nRow, nTab );
1521             ScMarkData aUndoMark = aFuncMark;
1522             aUndoMark.SetMultiMarkArea( aMarkRange );
1523 
1524             String aName = pStyleSheet->GetName();
1525             pDocSh->GetUndoManager()->AddUndoAction(
1526                 new ScUndoSelectionStyle( pDocSh, aUndoMark, aMarkRange, aName, pUndoDoc ) );
1527         }
1528 
1529         for (SCTAB i=0; i<nTabCount; i++)
1530             if (aFuncMark.GetTableSelect(i))
1531                 pDoc->ApplyStyle( nCol, nRow, i, (ScStyleSheet&)*pStyleSheet );
1532 
1533         if (!AdjustBlockHeight())
1534             pViewData->GetDocShell()->PostPaintCell( nCol, nRow, nTab );
1535 
1536     }
1537 
1538     aModificator.SetDocumentModified();
1539 
1540     StartFormatArea();
1541 }
1542 
1543 
RemoveStyleSheetInUse(const SfxStyleSheetBase * pStyleSheet)1544 void ScViewFunc::RemoveStyleSheetInUse( const SfxStyleSheetBase* pStyleSheet )
1545 {
1546     if ( !pStyleSheet) return;
1547     // -------------------------------------------------------------------
1548 
1549     ScViewData* pViewData   = GetViewData();
1550     ScDocument* pDoc        = pViewData->GetDocument();
1551     ScDocShell* pDocSh      = pViewData->GetDocShell();
1552 
1553     ScDocShellModificator aModificator( *pDocSh );
1554 
1555     VirtualDevice aVirtDev;
1556     aVirtDev.SetMapMode(MAP_PIXEL);
1557     pDoc->StyleSheetChanged( pStyleSheet, sal_True, &aVirtDev,
1558                                 pViewData->GetPPTX(),
1559                                 pViewData->GetPPTY(),
1560                                 pViewData->GetZoomX(),
1561                                 pViewData->GetZoomY() );
1562 
1563     pDocSh->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID|PAINT_LEFT );
1564     aModificator.SetDocumentModified();
1565 
1566     ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1567     if (pHdl)
1568         pHdl->ForgetLastPattern();
1569 }
1570 
UpdateStyleSheetInUse(const SfxStyleSheetBase * pStyleSheet)1571 void ScViewFunc::UpdateStyleSheetInUse( const SfxStyleSheetBase* pStyleSheet )
1572 {
1573     if ( !pStyleSheet) return;
1574     // -------------------------------------------------------------------
1575 
1576     ScViewData* pViewData   = GetViewData();
1577     ScDocument* pDoc        = pViewData->GetDocument();
1578     ScDocShell* pDocSh      = pViewData->GetDocShell();
1579 
1580     ScDocShellModificator aModificator( *pDocSh );
1581 
1582     VirtualDevice aVirtDev;
1583     aVirtDev.SetMapMode(MAP_PIXEL);
1584     pDoc->StyleSheetChanged( pStyleSheet, sal_False, &aVirtDev,
1585                                 pViewData->GetPPTX(),
1586                                 pViewData->GetPPTY(),
1587                                 pViewData->GetZoomX(),
1588                                 pViewData->GetZoomY() );
1589 
1590     pDocSh->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID|PAINT_LEFT );
1591     aModificator.SetDocumentModified();
1592 
1593     ScInputHandler* pHdl = SC_MOD()->GetInputHdl();
1594     if (pHdl)
1595         pHdl->ForgetLastPattern();
1596 }
1597 
1598 //  Zellen einfuegen - Undo OK
1599 
InsertCells(InsCellCmd eCmd,sal_Bool bRecord,sal_Bool bPartOfPaste)1600 sal_Bool ScViewFunc::InsertCells( InsCellCmd eCmd, sal_Bool bRecord, sal_Bool bPartOfPaste )
1601 {
1602     ScRange aRange;
1603     if (GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE)
1604     {
1605         ScDocShell* pDocSh = GetViewData()->GetDocShell();
1606         const ScMarkData& rMark = GetViewData()->GetMarkData();
1607         sal_Bool bSuccess = pDocSh->GetDocFunc().InsertCells( aRange, &rMark, eCmd, bRecord, sal_False, bPartOfPaste );
1608         if (bSuccess)
1609         {
1610             pDocSh->UpdateOle(GetViewData());
1611             CellContentChanged();
1612 
1613             // #i97876# Spreadsheet data changes are not notified
1614             ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
1615             if ( pModelObj && pModelObj->HasChangesListeners() )
1616             {
1617                 if ( eCmd == INS_INSROWS || eCmd == INS_INSCOLS )
1618                 {
1619                     ScRangeList aChangeRanges;
1620                     aChangeRanges.Append( aRange );
1621                     ::rtl::OUString aOperation = ( eCmd == INS_INSROWS ?
1622                         ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert-rows" ) ) :
1623                         ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "insert-columns" ) ) );
1624                     pModelObj->NotifyChanges( aOperation, aChangeRanges );
1625                 }
1626             }
1627         }
1628         return bSuccess;
1629     }
1630     else
1631     {
1632         ErrorMessage(STR_NOMULTISELECT);
1633         return sal_False;
1634     }
1635 }
1636 
1637 //  Zellen loeschen - Undo OK
1638 
DeleteCells(DelCellCmd eCmd,sal_Bool bRecord)1639 void ScViewFunc::DeleteCells( DelCellCmd eCmd, sal_Bool bRecord )
1640 {
1641     ScRange aRange;
1642     if ( GetViewData()->GetSimpleArea( aRange ) == SC_MARK_SIMPLE )
1643     {
1644         ScDocShell* pDocSh = GetViewData()->GetDocShell();
1645         const ScMarkData& rMark = GetViewData()->GetMarkData();
1646 
1647         // #i94841# [Collaboration] When deleting rows is rejected, the content is sometimes wrong
1648         if ( pDocSh->IsDocShared() && ( eCmd == DEL_DELROWS || eCmd == DEL_DELCOLS ) )
1649         {
1650             ScRange aDelRange( aRange.aStart );
1651             SCCOLROW nCount = 0;
1652             if ( eCmd == DEL_DELROWS )
1653             {
1654                 nCount = sal::static_int_cast< SCCOLROW >( aRange.aEnd.Row() - aRange.aStart.Row() + 1 );
1655             }
1656             else
1657             {
1658                 nCount = sal::static_int_cast< SCCOLROW >( aRange.aEnd.Col() - aRange.aStart.Col() + 1 );
1659             }
1660             while ( nCount > 0 )
1661             {
1662                 pDocSh->GetDocFunc().DeleteCells( aDelRange, &rMark, eCmd, bRecord, sal_False );
1663                 --nCount;
1664             }
1665         }
1666         else
1667         {
1668             pDocSh->GetDocFunc().DeleteCells( aRange, &rMark, eCmd, bRecord, sal_False );
1669         }
1670 
1671         pDocSh->UpdateOle(GetViewData());
1672         CellContentChanged();
1673 
1674         // #i97876# Spreadsheet data changes are not notified
1675         ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
1676         if ( pModelObj && pModelObj->HasChangesListeners() )
1677         {
1678             if ( eCmd == DEL_DELROWS || eCmd == DEL_DELCOLS )
1679             {
1680                 ScRangeList aChangeRanges;
1681                 aChangeRanges.Append( aRange );
1682                 ::rtl::OUString aOperation = ( eCmd == DEL_DELROWS ?
1683                     ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete-rows" ) ) :
1684                     ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "delete-columns" ) ) );
1685                 pModelObj->NotifyChanges( aOperation, aChangeRanges );
1686             }
1687         }
1688 
1689         //  #58106# Cursor direkt hinter den geloeschten Bereich setzen
1690         SCCOL nCurX = GetViewData()->GetCurX();
1691         SCROW nCurY = GetViewData()->GetCurY();
1692         if ( eCmd==DEL_CELLSLEFT || eCmd==DEL_DELCOLS )
1693             nCurX = aRange.aStart.Col();
1694         else
1695             nCurY = aRange.aStart.Row();
1696         SetCursor( nCurX, nCurY );
1697     }
1698     else
1699     {
1700         if (eCmd == DEL_DELCOLS)
1701             DeleteMulti( sal_False, bRecord );
1702         else if (eCmd == DEL_DELROWS)
1703             DeleteMulti( sal_True, bRecord );
1704         else
1705             ErrorMessage(STR_NOMULTISELECT);
1706     }
1707 
1708     Unmark();
1709 }
1710 
DeleteMulti(sal_Bool bRows,sal_Bool bRecord)1711 void ScViewFunc::DeleteMulti( sal_Bool bRows, sal_Bool bRecord )
1712 {
1713     ScDocShell* pDocSh = GetViewData()->GetDocShell();
1714     ScDocShellModificator aModificator( *pDocSh );
1715     SCTAB nTab = GetViewData()->GetTabNo();
1716     ScDocument* pDoc = pDocSh->GetDocument();
1717     ScMarkData aFuncMark( GetViewData()->GetMarkData() );       // local copy for UnmarkFiltered
1718     ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
1719 
1720     if (bRecord && !pDoc->IsUndoEnabled())
1721         bRecord = sal_False;
1722     SCCOLROW* pRanges = new SCCOLROW[MAXCOLROWCOUNT];
1723     SCCOLROW nRangeCnt = bRows ? aFuncMark.GetMarkRowRanges( pRanges ) :
1724                                 aFuncMark.GetMarkColumnRanges( pRanges );
1725     if (nRangeCnt == 0)
1726     {
1727         pRanges[0] = pRanges[1] = bRows ? static_cast<SCCOLROW>(GetViewData()->GetCurY()) : static_cast<SCCOLROW>(GetViewData()->GetCurX());
1728         nRangeCnt = 1;
1729     }
1730 
1731     //  Test ob erlaubt
1732 
1733     SCCOLROW* pOneRange = pRanges;
1734     sal_uInt16 nErrorId = 0;
1735     sal_Bool bNeedRefresh = sal_False;
1736     SCCOLROW nRangeNo;
1737     for (nRangeNo=0; nRangeNo<nRangeCnt && !nErrorId; nRangeNo++)
1738     {
1739         SCCOLROW nStart = *(pOneRange++);
1740         SCCOLROW nEnd = *(pOneRange++);
1741 
1742         SCCOL nStartCol, nEndCol;
1743         SCROW nStartRow, nEndRow;
1744         if ( bRows )
1745         {
1746             nStartCol = 0;
1747             nEndCol   = MAXCOL;
1748             nStartRow = static_cast<SCROW>(nStart);
1749             nEndRow   = static_cast<SCROW>(nEnd);
1750         }
1751         else
1752         {
1753             nStartCol = static_cast<SCCOL>(nStart);
1754             nEndCol   = static_cast<SCCOL>(nEnd);
1755             nStartRow = 0;
1756             nEndRow   = MAXROW;
1757         }
1758 
1759         // cell protection (only needed for first range, as all following cells are moved)
1760         if ( nRangeNo == 0 )
1761         {
1762             // test to the end of the sheet
1763             ScEditableTester aTester( pDoc, nTab, nStartCol, nStartRow, MAXCOL, MAXROW );
1764             if (!aTester.IsEditable())
1765                 nErrorId = aTester.GetMessageId();
1766         }
1767 
1768         // merged cells
1769         SCCOL nMergeStartX = nStartCol;
1770         SCROW nMergeStartY = nStartRow;
1771         SCCOL nMergeEndX   = nEndCol;
1772         SCROW nMergeEndY   = nEndRow;
1773         pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, nTab );
1774         pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, nTab );
1775 
1776         if ( nMergeStartX != nStartCol || nMergeStartY != nStartRow )
1777         {
1778             // Disallow deleting parts of a merged cell.
1779             // Deleting the start is allowed (merge is removed), so the end doesn't have to be checked.
1780 
1781             nErrorId = STR_MSSG_DELETECELLS_0;
1782         }
1783         if ( nMergeEndX != nEndCol || nMergeEndY != nEndRow )
1784         {
1785             // detect if the start of a merged cell is deleted, so the merge flags can be refreshed
1786 
1787             bNeedRefresh = sal_True;
1788         }
1789     }
1790 
1791     if ( nErrorId )
1792     {
1793         ErrorMessage( nErrorId );
1794         delete[] pRanges;
1795         return;
1796     }
1797 
1798     //  ausfuehren
1799 
1800     WaitObject aWait( GetFrameWin() );      // wichtig wegen TrackFormulas bei UpdateReference
1801 
1802     ScDocument* pUndoDoc = NULL;
1803     ScRefUndoData* pUndoData = NULL;
1804     if (bRecord)
1805     {
1806         pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1807         pUndoDoc->InitUndo( pDoc, nTab, nTab, !bRows, bRows );      // Zeilenhoehen
1808 
1809         pOneRange = pRanges;
1810         for (nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
1811         {
1812             SCCOLROW nStart = *(pOneRange++);
1813             SCCOLROW nEnd = *(pOneRange++);
1814             if (bRows)
1815                 pDoc->CopyToDocument( 0,nStart,nTab, MAXCOL,nEnd,nTab, IDF_ALL,sal_False,pUndoDoc );
1816             else
1817                 pDoc->CopyToDocument( static_cast<SCCOL>(nStart),0,nTab,
1818                         static_cast<SCCOL>(nEnd),MAXROW,nTab,
1819                         IDF_ALL,sal_False,pUndoDoc );
1820         }
1821 
1822                 //  alle Formeln wegen Referenzen
1823         SCTAB nTabCount = pDoc->GetTableCount();
1824         pUndoDoc->AddUndoTab( 0, nTabCount-1, sal_False, sal_False );
1825         pDoc->CopyToDocument( 0,0,0, MAXCOL,MAXROW,MAXTAB, IDF_FORMULA,sal_False,pUndoDoc );
1826 
1827         pUndoData = new ScRefUndoData( pDoc );
1828 
1829         pDoc->BeginDrawUndo();
1830     }
1831 
1832     pOneRange = &pRanges[2*nRangeCnt];      // rueckwaerts
1833     for (nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
1834     {
1835         SCCOLROW nEnd = *(--pOneRange);
1836         SCCOLROW nStart = *(--pOneRange);
1837 
1838         if (bRows)
1839             pDoc->DeleteRow( 0,nTab, MAXCOL,nTab, nStart, static_cast<SCSIZE>(nEnd-nStart+1) );
1840         else
1841             pDoc->DeleteCol( 0,nTab, MAXROW,nTab, static_cast<SCCOL>(nStart), static_cast<SCSIZE>(nEnd-nStart+1) );
1842     }
1843 
1844     if (bNeedRefresh)
1845     {
1846         SCCOLROW nFirstStart = pRanges[0];
1847         SCCOL nStartCol = bRows ? 0 : static_cast<SCCOL>(nFirstStart);
1848         SCROW nStartRow = bRows ? static_cast<SCROW>(nFirstStart) : 0;
1849         SCCOL nEndCol = MAXCOL;
1850         SCROW nEndRow = MAXROW;
1851 
1852         pDoc->RemoveFlagsTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, SC_MF_HOR | SC_MF_VER );
1853         pDoc->ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, nTab, sal_True );
1854     }
1855 
1856     if (bRecord)
1857     {
1858         pDocSh->GetUndoManager()->AddUndoAction(
1859             new ScUndoDeleteMulti( pDocSh, bRows, bNeedRefresh, nTab, pRanges, nRangeCnt,
1860                                     pUndoDoc, pUndoData ) );
1861     }
1862 
1863     if (!AdjustRowHeight(0, MAXROW))
1864     {
1865         if (bRows)
1866             pDocSh->PostPaint( 0,pRanges[0],nTab, MAXCOL,MAXROW,nTab, PAINT_GRID | PAINT_LEFT );
1867         else
1868             pDocSh->PostPaint( static_cast<SCCOL>(pRanges[0]),0,nTab,
1869                     MAXCOL,MAXROW,nTab, PAINT_GRID | PAINT_TOP );
1870     }
1871     aModificator.SetDocumentModified();
1872 
1873     CellContentChanged();
1874 
1875     //  #58106# Cursor direkt hinter den ersten geloeschten Bereich setzen
1876     SCCOL nCurX = GetViewData()->GetCurX();
1877     SCROW nCurY = GetViewData()->GetCurY();
1878     if ( bRows )
1879         nCurY = pRanges[0];
1880     else
1881         nCurX = static_cast<SCCOL>(pRanges[0]);
1882     SetCursor( nCurX, nCurY );
1883 
1884     delete[] pRanges;
1885 
1886     SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREALINKS_CHANGED ) );
1887 }
1888 
1889 //  Inhalte loeschen
1890 
DeleteContents(sal_uInt16 nFlags,sal_Bool bRecord)1891 void ScViewFunc::DeleteContents( sal_uInt16 nFlags, sal_Bool bRecord )
1892 {
1893     // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
1894     sal_Bool bOnlyNotBecauseOfMatrix;
1895     sal_Bool bEditable = SelectionEditable( &bOnlyNotBecauseOfMatrix );
1896     if ( !bEditable )
1897     {
1898         if ( !(bOnlyNotBecauseOfMatrix &&
1899                 ((nFlags & (IDF_ATTRIB | IDF_EDITATTR)) == nFlags)) )
1900         {
1901             ErrorMessage(bOnlyNotBecauseOfMatrix ? STR_MATRIXFRAGMENTERR : STR_PROTECTIONERR);
1902             return;
1903         }
1904     }
1905 
1906     ScRange aMarkRange;
1907     sal_Bool bSimple = sal_False;
1908 
1909     ScDocument* pDoc = GetViewData()->GetDocument();
1910     ScDocShell* pDocSh = GetViewData()->GetDocShell();
1911     ScMarkData aFuncMark( GetViewData()->GetMarkData() );       // local copy for UnmarkFiltered
1912     ScViewUtil::UnmarkFiltered( aFuncMark, pDoc );
1913 
1914     if (bRecord && !pDoc->IsUndoEnabled())
1915         bRecord = sal_False;
1916 
1917     ScDocShellModificator aModificator( *pDocSh );
1918 
1919     if ( !aFuncMark.IsMarked() && !aFuncMark.IsMultiMarked() )
1920     {
1921         aMarkRange.aStart.SetCol(GetViewData()->GetCurX());
1922         aMarkRange.aStart.SetRow(GetViewData()->GetCurY());
1923         aMarkRange.aStart.SetTab(GetViewData()->GetTabNo());
1924         aMarkRange.aEnd = aMarkRange.aStart;
1925         if ( pDoc->HasAttrib( aMarkRange, HASATTR_MERGED ) )
1926         {
1927 //          InitOwnBlockMode();
1928             aFuncMark.SetMarkArea( aMarkRange );
1929         }
1930         else
1931             bSimple = sal_True;
1932     }
1933 
1934     aFuncMark.SetMarking(sal_False);        // for MarkToMulti
1935     aFuncMark.MarkToSimple();           // before bMulti test below
1936 
1937     DBG_ASSERT( aFuncMark.IsMarked() || aFuncMark.IsMultiMarked() || bSimple, "delete what?" );
1938 
1939     ScDocument* pUndoDoc = NULL;
1940     sal_Bool bMulti = !bSimple && aFuncMark.IsMultiMarked();
1941     if (!bSimple)
1942     {
1943         aFuncMark.MarkToMulti();
1944         aFuncMark.GetMultiMarkArea( aMarkRange );
1945     }
1946     ScRange aExtendedRange(aMarkRange);
1947     if (!bSimple)
1948     {
1949         if ( pDoc->ExtendMerge( aExtendedRange, sal_True ) )
1950             bMulti = sal_False;
1951     }
1952 
1953     // keine Objekte auf geschuetzten Tabellen
1954     sal_Bool bObjects = sal_False;
1955     if ( nFlags & IDF_OBJECTS )
1956     {
1957         bObjects = sal_True;
1958         SCTAB nTabCount = pDoc->GetTableCount();
1959         for (SCTAB nTab=0; nTab<nTabCount; nTab++)
1960             if (aFuncMark.GetTableSelect(nTab) && pDoc->IsTabProtected(nTab))
1961                 bObjects = sal_False;
1962     }
1963 
1964     sal_uInt16 nExtFlags = 0;       // extra flags are needed only if attributes are deleted
1965     if ( nFlags & IDF_ATTRIB )
1966         pDocSh->UpdatePaintExt( nExtFlags, aMarkRange );
1967 
1968     //  Reihenfolge:
1969     //  1) BeginDrawUndo
1970     //  2) Objekte loeschen (DrawUndo wird gefuellt)
1971     //  3) Inhalte fuer Undo kopieren
1972     //  4) Inhalte loeschen
1973     //  5) Undo-Aktion anlegen
1974 
1975     sal_Bool bDrawUndo = bObjects || ( nFlags & IDF_NOTE );     // needed for shown notes
1976     if ( bDrawUndo && bRecord )
1977         pDoc->BeginDrawUndo();
1978 
1979     if (bObjects)
1980     {
1981         if (bMulti)
1982             pDoc->DeleteObjectsInSelection( aFuncMark );
1983         else
1984             pDoc->DeleteObjectsInArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
1985 /*!*/                                  aMarkRange.aEnd.Col(),   aMarkRange.aEnd.Row(),
1986                                        aFuncMark );
1987     }
1988 
1989     if ( bRecord )
1990     {
1991         pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
1992         SCTAB nTab = aMarkRange.aStart.Tab();
1993         pUndoDoc->InitUndo( pDoc, nTab, nTab );
1994         SCTAB nTabCount = pDoc->GetTableCount();
1995         for (SCTAB i=0; i<nTabCount; i++)
1996             if (i != nTab && aFuncMark.GetTableSelect(i))
1997                 pUndoDoc->AddUndoTab( i, i );
1998         ScRange aCopyRange = aExtendedRange;
1999         aCopyRange.aStart.SetTab(0);
2000         aCopyRange.aEnd.SetTab(nTabCount-1);
2001 
2002         //  bei "Format/Standard" alle Attribute kopieren, weil CopyToDocument
2003         //  nur mit IDF_HARDATTR zu langsam ist:
2004         sal_uInt16 nUndoDocFlags = nFlags;
2005         if (nFlags & IDF_ATTRIB)
2006             nUndoDocFlags |= IDF_ATTRIB;
2007         if (nFlags & IDF_EDITATTR)          // Edit-Engine-Attribute
2008             nUndoDocFlags |= IDF_STRING;    // -> Zellen werden geaendert
2009         if (nFlags & IDF_NOTE)
2010             nUndoDocFlags |= IDF_CONTENTS;  // #68795# copy all cells with their notes
2011         // do not copy note captions to undo document
2012         nUndoDocFlags |= IDF_NOCAPTIONS;
2013         pDoc->CopyToDocument( aCopyRange, nUndoDocFlags, bMulti, pUndoDoc, &aFuncMark );
2014     }
2015 
2016     HideAllCursors();   // falls Zusammenfassung aufgehoben wird
2017     if (bSimple)
2018         pDoc->DeleteArea( aMarkRange.aStart.Col(), aMarkRange.aStart.Row(),
2019                           aMarkRange.aEnd.Col(),   aMarkRange.aEnd.Row(),
2020                           aFuncMark, nFlags );
2021     else
2022     {
2023         pDoc->DeleteSelection( nFlags, aFuncMark );
2024 //       aFuncMark.MarkToSimple();
2025     }
2026 
2027     if ( bRecord )
2028     {
2029         pDocSh->GetUndoManager()->AddUndoAction(
2030             new ScUndoDeleteContents( pDocSh, aFuncMark, aExtendedRange,
2031                                       pUndoDoc, bMulti, nFlags, bDrawUndo ) );
2032     }
2033 
2034     if (!AdjustRowHeight( aExtendedRange.aStart.Row(), aExtendedRange.aEnd.Row() ))
2035         pDocSh->PostPaint( aExtendedRange, PAINT_GRID, nExtFlags );
2036 
2037     pDocSh->UpdateOle(GetViewData());
2038 
2039     // #i97876# Spreadsheet data changes are not notified
2040     ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
2041     if ( pModelObj && pModelObj->HasChangesListeners() )
2042     {
2043         ScRangeList aChangeRanges;
2044         if ( bSimple )
2045         {
2046             aChangeRanges.Append( aMarkRange );
2047         }
2048         else
2049         {
2050             aFuncMark.FillRangeListWithMarks( &aChangeRanges, sal_False );
2051         }
2052         pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "cell-change" ) ), aChangeRanges );
2053     }
2054 
2055     aModificator.SetDocumentModified();
2056     CellContentChanged();
2057     ShowAllCursors();
2058 
2059     if ( nFlags & IDF_ATTRIB )
2060     {
2061         if ( nFlags & IDF_CONTENTS )
2062             ForgetFormatArea();
2063         else
2064             StartFormatArea();              // Attribute loeschen ist auch Attributierung
2065     }
2066 }
2067 
2068 //  Spaltenbreiten/Zeilenhoehen (ueber Header) - Undo OK
2069 
SetWidthOrHeight(sal_Bool bWidth,SCCOLROW nRangeCnt,SCCOLROW * pRanges,ScSizeMode eMode,sal_uInt16 nSizeTwips,sal_Bool bRecord,sal_Bool bPaint,ScMarkData * pMarkData)2070 void ScViewFunc::SetWidthOrHeight( sal_Bool bWidth, SCCOLROW nRangeCnt, SCCOLROW* pRanges,
2071                                     ScSizeMode eMode, sal_uInt16 nSizeTwips,
2072                                     sal_Bool bRecord, sal_Bool bPaint, ScMarkData* pMarkData )
2073 {
2074     if (nRangeCnt == 0)
2075         return;
2076 
2077     // use view's mark if none specified
2078     if ( !pMarkData )
2079         pMarkData = &GetViewData()->GetMarkData();
2080 
2081     ScDocShell* pDocSh = GetViewData()->GetDocShell();
2082     ScDocument* pDoc = pDocSh->GetDocument();
2083     SCTAB nTabCount = pDoc->GetTableCount();
2084     SCTAB nFirstTab = pMarkData->GetFirstSelected();
2085     SCTAB nCurTab = GetViewData()->GetTabNo();
2086     SCTAB nTab;
2087     if (bRecord && !pDoc->IsUndoEnabled())
2088         bRecord = sal_False;
2089 
2090     ScDocShellModificator aModificator( *pDocSh );
2091 
2092     sal_Bool bAllowed = sal_True;
2093     for (nTab=0; nTab<nTabCount && bAllowed; nTab++)
2094         if (pMarkData->GetTableSelect(nTab))
2095         {
2096             for ( SCCOLROW i=0; i<nRangeCnt && bAllowed; i++ )
2097             {
2098                 sal_Bool bOnlyMatrix;
2099                 if (bWidth)
2100                     bAllowed = pDoc->IsBlockEditable( nTab,
2101                             static_cast<SCCOL>(pRanges[2*i]),0,
2102                             static_cast<SCCOL>(pRanges[2*i+1]),MAXROW,
2103                             &bOnlyMatrix ) || bOnlyMatrix;
2104                 else
2105                     bAllowed = pDoc->IsBlockEditable( nTab, 0,pRanges[2*i],
2106                             MAXCOL,pRanges[2*i+1], &bOnlyMatrix ) ||
2107                         bOnlyMatrix;
2108             }
2109         }
2110     if ( !bAllowed )
2111     {
2112         ErrorMessage(STR_PROTECTIONERR);
2113         return;
2114     }
2115 
2116     SCCOLROW nStart = pRanges[0];
2117     SCCOLROW nEnd = pRanges[2*nRangeCnt-1];
2118 
2119     sal_Bool bFormula = sal_False;
2120     if ( eMode == SC_SIZE_OPTIMAL )
2121     {
2122         const ScViewOptions& rOpts = GetViewData()->GetOptions();
2123         bFormula = rOpts.GetOption( VOPT_FORMULAS );
2124     }
2125 
2126     ScDocument*     pUndoDoc = NULL;
2127     ScOutlineTable* pUndoTab = NULL;
2128     SCCOLROW*       pUndoRanges = NULL;
2129 
2130     if ( bRecord )
2131     {
2132         pDoc->BeginDrawUndo();                          // Drawing Updates
2133 
2134         pUndoDoc = new ScDocument( SCDOCMODE_UNDO );
2135         for (nTab=0; nTab<nTabCount; nTab++)
2136             if (pMarkData->GetTableSelect(nTab))
2137             {
2138                 if (bWidth)
2139                 {
2140                     if ( nTab == nFirstTab )
2141                         pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_True, sal_False );
2142                     else
2143                         pUndoDoc->AddUndoTab( nTab, nTab, sal_True, sal_False );
2144                     pDoc->CopyToDocument( static_cast<SCCOL>(nStart), 0, nTab,
2145                             static_cast<SCCOL>(nEnd), MAXROW, nTab, IDF_NONE,
2146                             sal_False, pUndoDoc );
2147                 }
2148                 else
2149                 {
2150                     if ( nTab == nFirstTab )
2151                         pUndoDoc->InitUndo( pDoc, nTab, nTab, sal_False, sal_True );
2152                     else
2153                         pUndoDoc->AddUndoTab( nTab, nTab, sal_False, sal_True );
2154                     pDoc->CopyToDocument( 0, nStart, nTab, MAXCOL, nEnd, nTab, IDF_NONE, sal_False, pUndoDoc );
2155                 }
2156             }
2157 
2158         pUndoRanges = new SCCOLROW[ 2*nRangeCnt ];
2159         memmove( pUndoRanges, pRanges, 2*nRangeCnt*sizeof(SCCOLROW) );
2160 
2161         //! outlines from all tables?
2162         ScOutlineTable* pTable = pDoc->GetOutlineTable( nCurTab );
2163         if (pTable)
2164             pUndoTab = new ScOutlineTable( *pTable );
2165     }
2166 
2167     if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
2168         pMarkData->MarkToMulti();
2169 
2170     sal_Bool bShow = nSizeTwips > 0 || eMode != SC_SIZE_DIRECT;
2171     sal_Bool bOutline = sal_False;
2172 
2173     for (nTab=0; nTab<nTabCount; nTab++)
2174         if (pMarkData->GetTableSelect(nTab))
2175         {
2176             const SCCOLROW* pTabRanges = pRanges;
2177 
2178             pDoc->IncSizeRecalcLevel( nTab );       // nicht fuer jede Spalte einzeln
2179             pDoc->InitializeNoteCaptions( nTab );
2180             for (SCCOLROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++)
2181             {
2182                 SCCOLROW nStartNo = *(pTabRanges++);
2183                 SCCOLROW nEndNo = *(pTabRanges++);
2184 
2185                 if ( !bWidth )                      // Hoehen immer blockweise
2186                 {
2187                     if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
2188                     {
2189                         sal_Bool bAll = ( eMode==SC_SIZE_OPTIMAL );
2190                         if (!bAll)
2191                         {
2192                             //  fuer alle eingeblendeten CR_MANUALSIZE loeschen,
2193                             //  dann SetOptimalHeight mit bShrink = FALSE
2194                             for (SCROW nRow = nStartNo; nRow <= nEndNo; ++nRow)
2195                             {
2196                                 SCROW nLastRow = nRow;
2197                                 if (pDoc->RowHidden(nRow, nTab, NULL, &nLastRow))
2198                                 {
2199                                     nRow = nLastRow;
2200                                     continue;
2201                                 }
2202 
2203                                 sal_uInt8 nOld = pDoc->GetRowFlags(nRow, nTab);
2204                                 if (nOld & CR_MANUALSIZE)
2205                                     pDoc->SetRowFlags(nRow, nTab, nOld & ~CR_MANUALSIZE);
2206                             }
2207                         }
2208 
2209                         double nPPTX = GetViewData()->GetPPTX();
2210                         double nPPTY = GetViewData()->GetPPTY();
2211                         Fraction aZoomX = GetViewData()->GetZoomX();
2212                         Fraction aZoomY = GetViewData()->GetZoomY();
2213 
2214                         ScSizeDeviceProvider aProv(pDocSh);
2215                         if (aProv.IsPrinter())
2216                         {
2217                             nPPTX = aProv.GetPPTX();
2218                             nPPTY = aProv.GetPPTY();
2219                             aZoomX = aZoomY = Fraction( 1, 1 );
2220                         }
2221 
2222                         pDoc->SetOptimalHeight( nStartNo, nEndNo, nTab, nSizeTwips, aProv.GetDevice(),
2223                                                     nPPTX, nPPTY, aZoomX, aZoomY, bAll );
2224                         if (bAll)
2225                             pDoc->ShowRows( nStartNo, nEndNo, nTab, sal_True );
2226 
2227                         //  Manual-Flag wird bei bAll=sal_True schon in SetOptimalHeight gesetzt
2228                         //  (an bei Extra-Height, sonst aus).
2229                     }
2230                     else if ( eMode==SC_SIZE_DIRECT )
2231                     {
2232                         if (nSizeTwips)
2233                         {
2234                             pDoc->SetRowHeightRange( nStartNo, nEndNo, nTab, nSizeTwips );
2235                             pDoc->SetManualHeight( nStartNo, nEndNo, nTab, sal_True );          // height was set manually
2236                         }
2237                         pDoc->ShowRows( nStartNo, nEndNo, nTab, nSizeTwips != 0 );
2238                     }
2239                     else if ( eMode==SC_SIZE_SHOW )
2240                     {
2241                         pDoc->ShowRows( nStartNo, nEndNo, nTab, sal_True );
2242                     }
2243                 }
2244                 else                                // Spaltenbreiten
2245                 {
2246                     for (SCCOL nCol=static_cast<SCCOL>(nStartNo); nCol<=static_cast<SCCOL>(nEndNo); nCol++)
2247                     {
2248                         if ( eMode != SC_SIZE_VISOPT || !pDoc->ColHidden(nCol, nTab) )
2249                         {
2250                             sal_uInt16 nThisSize = nSizeTwips;
2251 
2252                             if ( eMode==SC_SIZE_OPTIMAL || eMode==SC_SIZE_VISOPT )
2253                                 nThisSize = nSizeTwips + GetOptimalColWidth( nCol, nTab, bFormula );
2254                             if ( nThisSize )
2255                                 pDoc->SetColWidth( nCol, nTab, nThisSize );
2256 
2257                             pDoc->ShowCol( nCol, nTab, bShow );
2258                         }
2259                     }
2260                 }
2261 
2262                                     //  Outline anpassen
2263 
2264                 if (bWidth)
2265                 {
2266                     if ( pDoc->UpdateOutlineCol( static_cast<SCCOL>(nStartNo),
2267                                 static_cast<SCCOL>(nEndNo), nTab, bShow ) )
2268                         bOutline = sal_True;
2269                 }
2270                 else
2271                 {
2272                     if ( pDoc->UpdateOutlineRow( nStartNo, nEndNo, nTab, bShow ) )
2273                         bOutline = sal_True;
2274                 }
2275             }
2276             pDoc->DecSizeRecalcLevel( nTab );       // nicht fuer jede Spalte einzeln
2277         }
2278 
2279 
2280     if (!bOutline)
2281         DELETEZ(pUndoTab);
2282 
2283     if (bRecord)
2284     {
2285         pDocSh->GetUndoManager()->AddUndoAction(
2286             new ScUndoWidthOrHeight( pDocSh, *pMarkData,
2287                                      nStart, nCurTab, nEnd, nCurTab,
2288                                      pUndoDoc, nRangeCnt, pUndoRanges,
2289                                      pUndoTab, eMode, nSizeTwips, bWidth ) );
2290     }
2291 
2292     for (nTab=0; nTab<nTabCount; nTab++)
2293         if (pMarkData->GetTableSelect(nTab))
2294             pDoc->UpdatePageBreaks( nTab );
2295 
2296     GetViewData()->GetView()->UpdateScrollBars();
2297 
2298     if (bPaint)
2299     {
2300         HideCursor();
2301 
2302         for (nTab=0; nTab<nTabCount; nTab++)
2303             if (pMarkData->GetTableSelect(nTab))
2304             {
2305                 if (bWidth)
2306                 {
2307                     if (pDoc->HasAttrib( static_cast<SCCOL>(nStart),0,nTab,
2308                                 static_cast<SCCOL>(nEnd),MAXROW,nTab,
2309                                 HASATTR_MERGED | HASATTR_OVERLAPPED ))
2310                         nStart = 0;
2311                     if (nStart > 0)             // weiter oben anfangen wegen Linien und Cursor
2312                         --nStart;
2313                     pDocSh->PostPaint( static_cast<SCCOL>(nStart), 0, nTab,
2314                             MAXCOL, MAXROW, nTab, PAINT_GRID | PAINT_TOP );
2315                 }
2316                 else
2317                 {
2318                     if (pDoc->HasAttrib( 0,nStart,nTab, MAXCOL,nEnd,nTab, HASATTR_MERGED | HASATTR_OVERLAPPED ))
2319                         nStart = 0;
2320                     if (nStart != 0)
2321                         --nStart;
2322                     pDocSh->PostPaint( 0, nStart, nTab, MAXCOL, MAXROW, nTab, PAINT_GRID | PAINT_LEFT );
2323                 }
2324             }
2325 
2326         pDocSh->UpdateOle(GetViewData());
2327         aModificator.SetDocumentModified();
2328 
2329         ShowCursor();
2330     }
2331 
2332     // #i97876# Spreadsheet data changes are not notified
2333     if ( bWidth )
2334     {
2335         ScModelObj* pModelObj = ScModelObj::getImplementation( pDocSh->GetModel() );
2336         if ( pModelObj && pModelObj->HasChangesListeners() )
2337         {
2338             ScRangeList aChangeRanges;
2339             for ( nTab = 0; nTab < nTabCount; ++nTab )
2340             {
2341                 if ( pMarkData->GetTableSelect( nTab ) )
2342                 {
2343                     const SCCOLROW* pTabRanges = pRanges;
2344                     for ( SCCOLROW nRange = 0; nRange < nRangeCnt; ++nRange )
2345                     {
2346                         SCCOL nStartCol = static_cast< SCCOL >( *(pTabRanges++) );
2347                         SCCOL nEndCol = static_cast< SCCOL >( *(pTabRanges++) );
2348                         for ( SCCOL nCol = nStartCol; nCol <= nEndCol; ++nCol )
2349                         {
2350                             aChangeRanges.Append( ScRange( nCol, 0, nTab ) );
2351                         }
2352                     }
2353                 }
2354             }
2355             pModelObj->NotifyChanges( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "column-resize" ) ), aChangeRanges );
2356         }
2357     }
2358 }
2359 
2360 //  Spaltenbreiten/Zeilenhoehen (ueber Blockmarken)
2361 
SetMarkedWidthOrHeight(sal_Bool bWidth,ScSizeMode eMode,sal_uInt16 nSizeTwips,sal_Bool bRecord,sal_Bool bPaint)2362 void ScViewFunc::SetMarkedWidthOrHeight( sal_Bool bWidth, ScSizeMode eMode, sal_uInt16 nSizeTwips,
2363                                         sal_Bool bRecord, sal_Bool bPaint )
2364 {
2365     ScMarkData& rMark = GetViewData()->GetMarkData();
2366 
2367     rMark.MarkToMulti();
2368     if (!rMark.IsMultiMarked())
2369     {
2370         SCCOL nCol = GetViewData()->GetCurX();
2371         SCROW nRow = GetViewData()->GetCurY();
2372         SCTAB nTab = GetViewData()->GetTabNo();
2373         DoneBlockMode();
2374         InitOwnBlockMode();
2375         rMark.SetMultiMarkArea( ScRange( nCol,nRow,nTab ), sal_True );
2376         MarkDataChanged();
2377     }
2378 
2379     SCCOLROW* pRanges = new SCCOLROW[MAXCOLROWCOUNT];
2380     SCCOLROW nRangeCnt = 0;
2381 
2382     if ( bWidth )
2383         nRangeCnt = rMark.GetMarkColumnRanges( pRanges );
2384     else
2385         nRangeCnt = rMark.GetMarkRowRanges( pRanges );
2386 
2387     SetWidthOrHeight( bWidth, nRangeCnt, pRanges, eMode, nSizeTwips, bRecord, bPaint );
2388 
2389     delete[] pRanges;
2390     rMark.MarkToSimple();
2391 }
2392 
ModifyCellSize(ScDirection eDir,sal_Bool bOptimal)2393 void ScViewFunc::ModifyCellSize( ScDirection eDir, sal_Bool bOptimal )
2394 {
2395     //! Schrittweiten einstellbar
2396     //  Schrittweite ist auch Minimum
2397     sal_uInt16 nStepX = STD_COL_WIDTH / 5;
2398     sal_uInt16 nStepY = ScGlobal::nStdRowHeight;
2399 
2400     ScModule* pScMod = SC_MOD();
2401     sal_Bool bAnyEdit = pScMod->IsInputMode();
2402     SCCOL nCol = GetViewData()->GetCurX();
2403     SCROW nRow = GetViewData()->GetCurY();
2404     SCTAB nTab = GetViewData()->GetTabNo();
2405     ScDocShell* pDocSh = GetViewData()->GetDocShell();
2406     ScDocument* pDoc = pDocSh->GetDocument();
2407 
2408     sal_Bool bAllowed, bOnlyMatrix;
2409     if ( eDir == DIR_LEFT || eDir == DIR_RIGHT )
2410         bAllowed = pDoc->IsBlockEditable( nTab, nCol,0, nCol,MAXROW, &bOnlyMatrix );
2411     else
2412         bAllowed = pDoc->IsBlockEditable( nTab, 0,nRow, MAXCOL,nRow, &bOnlyMatrix );
2413     if ( !bAllowed && !bOnlyMatrix )
2414     {
2415         ErrorMessage(STR_PROTECTIONERR);
2416         return;
2417     }
2418 
2419     HideAllCursors();
2420 
2421     sal_uInt16 nWidth = pDoc->GetColWidth( nCol, nTab );
2422     sal_uInt16 nHeight = pDoc->GetRowHeight( nRow, nTab );
2423     SCCOLROW nRange[2];
2424     if ( eDir == DIR_LEFT || eDir == DIR_RIGHT )
2425     {
2426         if (bOptimal)               // Breite dieser einen Zelle
2427         {
2428             if ( bAnyEdit )
2429             {
2430                 //  beim Editieren die aktuelle Breite der Eingabe
2431                 ScInputHandler* pHdl = pScMod->GetInputHdl( GetViewData()->GetViewShell() );
2432                 if (pHdl)
2433                 {
2434                     long nEdit = pHdl->GetTextSize().Width();       // in 1/100mm
2435 
2436                     const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
2437                     const SvxMarginItem& rMItem =
2438                             (const SvxMarginItem&)pPattern->GetItem(ATTR_MARGIN);
2439                     sal_uInt16 nMargin = rMItem.GetLeftMargin() + rMItem.GetRightMargin();
2440                     if ( ((const SvxHorJustifyItem&) pPattern->
2441                             GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_LEFT )
2442                         nMargin = sal::static_int_cast<sal_uInt16>(
2443                             nMargin + ((const SfxUInt16Item&)pPattern->GetItem(ATTR_INDENT)).GetValue() );
2444 
2445                     nWidth = (sal_uInt16)(nEdit * pDocSh->GetOutputFactor() / HMM_PER_TWIPS)
2446                                 + nMargin + STD_EXTRA_WIDTH;
2447                 }
2448             }
2449             else
2450             {
2451                 double nPPTX = GetViewData()->GetPPTX();
2452                 double nPPTY = GetViewData()->GetPPTY();
2453                 Fraction aZoomX = GetViewData()->GetZoomX();
2454                 Fraction aZoomY = GetViewData()->GetZoomY();
2455 
2456                 ScSizeDeviceProvider aProv(pDocSh);
2457                 if (aProv.IsPrinter())
2458                 {
2459                     nPPTX = aProv.GetPPTX();
2460                     nPPTY = aProv.GetPPTY();
2461                     aZoomX = aZoomY = Fraction( 1, 1 );
2462                 }
2463 
2464                 long nPixel = pDoc->GetNeededSize( nCol, nRow, nTab, aProv.GetDevice(),
2465                                             nPPTX, nPPTY, aZoomX, aZoomY, sal_True );
2466                 sal_uInt16 nTwips = (sal_uInt16)( nPixel / nPPTX );
2467                 if (nTwips != 0)
2468                     nWidth = nTwips + STD_EXTRA_WIDTH;
2469                 else
2470                     nWidth = STD_COL_WIDTH;
2471             }
2472         }
2473         else                        // vergroessern / verkleinern
2474         {
2475             if ( eDir == DIR_RIGHT )
2476                 nWidth = sal::static_int_cast<sal_uInt16>( nWidth + nStepX );
2477             else if ( nWidth > nStepX )
2478                 nWidth = sal::static_int_cast<sal_uInt16>( nWidth - nStepX );
2479             if ( nWidth < nStepX ) nWidth = nStepX;
2480             if ( nWidth > MAX_COL_WIDTH ) nWidth = MAX_COL_WIDTH;
2481         }
2482         nRange[0] = nRange[1] = nCol;
2483         SetWidthOrHeight( sal_True, 1, nRange, SC_SIZE_DIRECT, nWidth );
2484 
2485         //  hier bei Breite auch Hoehe anpassen (nur die eine Zeile)
2486 
2487         if (!bAnyEdit)
2488         {
2489             const ScPatternAttr* pPattern = pDoc->GetPattern( nCol, nRow, nTab );
2490             sal_Bool bNeedHeight =
2491                     ((const SfxBoolItem&)pPattern->GetItem( ATTR_LINEBREAK )).GetValue() ||
2492                     ((const SvxHorJustifyItem&)pPattern->
2493                         GetItem( ATTR_HOR_JUSTIFY )).GetValue() == SVX_HOR_JUSTIFY_BLOCK;
2494             if (bNeedHeight)
2495                 AdjustRowHeight( nRow, nRow );
2496         }
2497     }
2498     else
2499     {
2500         ScSizeMode eMode;
2501         if (bOptimal)
2502         {
2503             eMode = SC_SIZE_OPTIMAL;
2504             nHeight = 0;
2505         }
2506         else
2507         {
2508             eMode = SC_SIZE_DIRECT;
2509             if ( eDir == DIR_BOTTOM )
2510                 nHeight = sal::static_int_cast<sal_uInt16>( nHeight + nStepY );
2511             else if ( nHeight > nStepY )
2512                 nHeight = sal::static_int_cast<sal_uInt16>( nHeight - nStepY );
2513             if ( nHeight < nStepY ) nHeight = nStepY;
2514             if ( nHeight > MAX_COL_HEIGHT ) nHeight = MAX_COL_HEIGHT;
2515             //! MAX_COL_HEIGHT umbenennen in MAX_ROW_HEIGHT in global.hxx !!!!!!
2516         }
2517         nRange[0] = nRange[1] = nRow;
2518         SetWidthOrHeight( sal_False, 1, nRange, eMode, nHeight );
2519     }
2520 
2521     if ( bAnyEdit )
2522     {
2523         UpdateEditView();
2524         if ( pDoc->HasAttrib( nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_NEEDHEIGHT ) )
2525         {
2526             ScInputHandler* pHdl = pScMod->GetInputHdl( GetViewData()->GetViewShell() );
2527             if (pHdl)
2528                 pHdl->SetModified();    // damit bei Enter die Hoehe angepasst wird
2529         }
2530     }
2531 
2532     ShowAllCursors();
2533 }
2534 
ProtectSheet(SCTAB nTab,const ScTableProtection & rProtect)2535 void ScViewFunc::ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect )
2536 {
2537     if (nTab == TABLEID_DOC)
2538         return;
2539 
2540     ScMarkData& rMark = GetViewData()->GetMarkData();
2541     ScDocShell* pDocSh = GetViewData()->GetDocShell();
2542     ScDocument* pDoc = pDocSh->GetDocument();
2543     ScDocFunc aFunc(*pDocSh);
2544     bool bUndo(pDoc->IsUndoEnabled());
2545 
2546     //  modifying several tables is handled here
2547 
2548     if (bUndo)
2549     {
2550         String aUndo = ScGlobal::GetRscString( STR_UNDO_PROTECT_TAB );
2551         pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
2552     }
2553 
2554     SCTAB nCount = pDocSh->GetDocument()->GetTableCount();
2555     for ( SCTAB i=0; i<nCount; i++ )
2556         if ( rMark.GetTableSelect(i) )
2557             aFunc.ProtectSheet(i, rProtect);
2558 
2559     if (bUndo)
2560         pDocSh->GetUndoManager()->LeaveListAction();
2561 
2562     UpdateLayerLocks();         //! broadcast to all views
2563 }
2564 
Protect(SCTAB nTab,const String & rPassword)2565 void ScViewFunc::Protect( SCTAB nTab, const String& rPassword )
2566 {
2567     ScMarkData& rMark = GetViewData()->GetMarkData();
2568     ScDocShell* pDocSh = GetViewData()->GetDocShell();
2569     ScDocument* pDoc = pDocSh->GetDocument();
2570     ScDocFunc aFunc(*pDocSh);
2571     sal_Bool bUndo(pDoc->IsUndoEnabled());
2572 
2573     if ( nTab == TABLEID_DOC || rMark.GetSelectCount() <= 1 )
2574         aFunc.Protect( nTab, rPassword, sal_False );
2575     else
2576     {
2577         //  modifying several tables is handled here
2578 
2579         if (bUndo)
2580         {
2581             String aUndo = ScGlobal::GetRscString( STR_UNDO_PROTECT_TAB );
2582             pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
2583         }
2584 
2585         SCTAB nCount = pDocSh->GetDocument()->GetTableCount();
2586         for ( SCTAB i=0; i<nCount; i++ )
2587             if ( rMark.GetTableSelect(i) )
2588                 aFunc.Protect( i, rPassword, sal_False );
2589 
2590         if (bUndo)
2591             pDocSh->GetUndoManager()->LeaveListAction();
2592     }
2593 
2594     UpdateLayerLocks();         //! broadcast to all views
2595 }
2596 
Unprotect(SCTAB nTab,const String & rPassword)2597 sal_Bool ScViewFunc::Unprotect( SCTAB nTab, const String& rPassword )
2598 {
2599     ScMarkData& rMark = GetViewData()->GetMarkData();
2600     ScDocShell* pDocSh = GetViewData()->GetDocShell();
2601     ScDocument* pDoc = pDocSh->GetDocument();
2602     ScDocFunc aFunc(*pDocSh);
2603     sal_Bool bChanged = sal_False;
2604     sal_Bool bUndo (pDoc->IsUndoEnabled());
2605 
2606     if ( nTab == TABLEID_DOC || rMark.GetSelectCount() <= 1 )
2607         bChanged = aFunc.Unprotect( nTab, rPassword, sal_False );
2608     else
2609     {
2610         //  modifying several tables is handled here
2611 
2612         if (bUndo)
2613         {
2614             String aUndo = ScGlobal::GetRscString( STR_UNDO_UNPROTECT_TAB );
2615             pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo );
2616         }
2617 
2618         SCTAB nCount = pDocSh->GetDocument()->GetTableCount();
2619         for ( SCTAB i=0; i<nCount; i++ )
2620             if ( rMark.GetTableSelect(i) )
2621                 if ( aFunc.Unprotect( i, rPassword, sal_False ) )
2622                     bChanged = sal_True;
2623 
2624         if (bUndo)
2625             pDocSh->GetUndoManager()->LeaveListAction();
2626     }
2627 
2628     if (bChanged)
2629         UpdateLayerLocks();     //! broadcast to all views
2630 
2631     return bChanged;
2632 }
2633 
SetNoteText(const ScAddress & rPos,const String & rNoteText)2634 void ScViewFunc::SetNoteText( const ScAddress& rPos, const String& rNoteText )
2635 {
2636     GetViewData()->GetDocShell()->GetDocFunc().SetNoteText( rPos, rNoteText, sal_False );
2637 }
2638 
ReplaceNote(const ScAddress & rPos,const String & rNoteText,const String * pAuthor,const String * pDate)2639 void ScViewFunc::ReplaceNote( const ScAddress& rPos, const String& rNoteText, const String* pAuthor, const String* pDate )
2640 {
2641     GetViewData()->GetDocShell()->GetDocFunc().ReplaceNote( rPos, rNoteText, pAuthor, pDate, sal_False );
2642 }
2643 
SetNumberFormat(short nFormatType,sal_uLong nAdd)2644 void ScViewFunc::SetNumberFormat( short nFormatType, sal_uLong nAdd )
2645 {
2646     // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
2647     sal_Bool bOnlyNotBecauseOfMatrix;
2648     if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
2649     {
2650         ErrorMessage(STR_PROTECTIONERR);
2651         return;
2652     }
2653 
2654     sal_uInt32          nNumberFormat = 0;
2655     ScViewData*         pViewData = GetViewData();
2656     ScDocument*         pDoc = pViewData->GetDocument();
2657     SvNumberFormatter*  pNumberFormatter = pDoc->GetFormatTable();
2658     LanguageType        eLanguage = ScGlobal::eLnge;
2659     ScPatternAttr       aNewAttrs( pDoc->GetPool() );
2660 
2661     //  #67936# always take language from cursor position, even if there is a selection
2662 
2663     sal_uInt32 nCurrentNumberFormat;
2664     pDoc->GetNumberFormat( pViewData->GetCurX(),
2665                            pViewData->GetCurY(),
2666                            pViewData->GetTabNo(),
2667                            nCurrentNumberFormat );
2668     const SvNumberformat* pEntry = pNumberFormatter->GetEntry( nCurrentNumberFormat );
2669     if (pEntry)
2670         eLanguage = pEntry->GetLanguage();      // sonst ScGlobal::eLnge behalten
2671 
2672     nNumberFormat = pNumberFormatter->GetStandardFormat( nFormatType, eLanguage ) + nAdd;
2673 
2674     SfxItemSet& rSet = aNewAttrs.GetItemSet();
2675     rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNumberFormat ) );
2676     //  ATTR_LANGUAGE_FORMAT nicht
2677     ApplySelectionPattern( aNewAttrs, sal_True );
2678 }
2679 
SetNumFmtByStr(const String & rCode)2680 void ScViewFunc::SetNumFmtByStr( const String& rCode )
2681 {
2682     // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
2683     sal_Bool bOnlyNotBecauseOfMatrix;
2684     if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
2685     {
2686         ErrorMessage(STR_PROTECTIONERR);
2687         return;
2688     }
2689 
2690     ScViewData*         pViewData = GetViewData();
2691     ScDocument*         pDoc = pViewData->GetDocument();
2692     SvNumberFormatter*  pFormatter = pDoc->GetFormatTable();
2693 
2694     //  Sprache immer von Cursorposition
2695 
2696     sal_uInt32 nCurrentNumberFormat;
2697     pDoc->GetNumberFormat( pViewData->GetCurX(), pViewData->GetCurY(),
2698                            pViewData->GetTabNo(), nCurrentNumberFormat );
2699     const SvNumberformat* pEntry = pFormatter->GetEntry( nCurrentNumberFormat );
2700     LanguageType eLanguage = pEntry ? pEntry->GetLanguage() : ScGlobal::eLnge;
2701 
2702     //  Index fuer String bestimmen
2703 
2704     sal_Bool bOk = sal_True;
2705     sal_uInt32 nNumberFormat = pFormatter->GetEntryKey( rCode, eLanguage );
2706     if ( nNumberFormat == NUMBERFORMAT_ENTRY_NOT_FOUND )
2707     {
2708         //  neu eintragen
2709 
2710         String      aFormat = rCode;    // wird veraendert
2711         xub_StrLen  nErrPos = 0;
2712         short       nType   = 0;        //! ???
2713         bOk = pFormatter->PutEntry( aFormat, nErrPos, nType, nNumberFormat, eLanguage );
2714     }
2715 
2716     if ( bOk )          // gueltiges Format?
2717     {
2718         ScPatternAttr aNewAttrs( pDoc->GetPool() );
2719         SfxItemSet& rSet = aNewAttrs.GetItemSet();
2720         rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNumberFormat ) );
2721         rSet.Put( SvxLanguageItem( eLanguage, ATTR_LANGUAGE_FORMAT ) );
2722         ApplySelectionPattern( aNewAttrs, sal_True );
2723     }
2724 
2725     //! sonst Fehler zuerueckgeben / Meldung ausgeben ???
2726 }
2727 
ChangeNumFmtDecimals(sal_Bool bIncrement)2728 void ScViewFunc::ChangeNumFmtDecimals( sal_Bool bIncrement )
2729 {
2730     // nur wegen Matrix nicht editierbar? Attribute trotzdem ok
2731     sal_Bool bOnlyNotBecauseOfMatrix;
2732     if ( !SelectionEditable( &bOnlyNotBecauseOfMatrix ) && !bOnlyNotBecauseOfMatrix )
2733     {
2734         ErrorMessage(STR_PROTECTIONERR);
2735         return;
2736     }
2737 
2738     ScDocument*         pDoc = GetViewData()->GetDocument();
2739     SvNumberFormatter*  pFormatter = pDoc->GetFormatTable();
2740 
2741     SCCOL nCol = GetViewData()->GetCurX();
2742     SCROW nRow = GetViewData()->GetCurY();
2743     SCTAB nTab = GetViewData()->GetTabNo();
2744 
2745     sal_uInt32 nOldFormat;
2746     pDoc->GetNumberFormat( nCol, nRow, nTab, nOldFormat );
2747     const SvNumberformat* pOldEntry = pFormatter->GetEntry( nOldFormat );
2748     if (!pOldEntry)
2749     {
2750         DBG_ERROR("Zahlformat nicht gefunden !!!");
2751         return;
2752     }
2753 
2754     //  was haben wir denn da?
2755 
2756     sal_uInt32 nNewFormat = nOldFormat;
2757     sal_Bool bError = sal_False;
2758 
2759     LanguageType eLanguage = pOldEntry->GetLanguage();
2760     sal_Bool bThousand, bNegRed;
2761     sal_uInt16 nPrecision, nLeading;
2762     pOldEntry->GetFormatSpecialInfo( bThousand, bNegRed, nPrecision, nLeading );
2763 
2764     short nOldType = pOldEntry->GetType();
2765     if ( 0 == ( nOldType & (
2766                 NUMBERFORMAT_NUMBER |  NUMBERFORMAT_CURRENCY | NUMBERFORMAT_PERCENT ) ) )
2767     {
2768         //  Datum, Zeit, Bruch, logisch, Text kann nicht angepasst werden
2769         //! bei Wisssenschaftlich kann es der Numberformatter auch nicht
2770         bError = sal_True;
2771     }
2772 
2773     //! Das SvNumberformat hat einen Member bStandard, verraet ihn aber nicht
2774     sal_Bool bWasStandard = ( nOldFormat == pFormatter->GetStandardIndex( eLanguage ) );
2775     if (bWasStandard)
2776     {
2777         //  bei "Standard" die Nachkommastellen abhaengig vom Zellinhalt
2778         //  0 bei leer oder Text -> keine Nachkommastellen
2779         double nVal = pDoc->GetValue( ScAddress( nCol, nRow, nTab ) );
2780 
2781         //  Die Wege des Numberformatters sind unergruendlich, darum ausprobieren:
2782         String aOut;
2783         Color* pCol;
2784         ((SvNumberformat*)pOldEntry)->GetOutputString( nVal, aOut, &pCol );
2785 
2786         nPrecision = 0;
2787         // 'E' fuer Exponential ist fest im Numberformatter
2788         if ( aOut.Search('E') != STRING_NOTFOUND )
2789             bError = sal_True;                              // Exponential nicht veraendern
2790         else
2791         {
2792             String aDecSep( pFormatter->GetFormatDecimalSep( nOldFormat ) );
2793             xub_StrLen nPos = aOut.Search( aDecSep );
2794             if ( nPos != STRING_NOTFOUND )
2795                 nPrecision = aOut.Len() - nPos - aDecSep.Len();
2796             // sonst 0 behalten
2797         }
2798     }
2799 
2800     if (!bError)
2801     {
2802         if (bIncrement)
2803         {
2804             if (nPrecision<20)
2805                 ++nPrecision;           // erhoehen
2806             else
2807                 bError = sal_True;          // 20 ist Maximum
2808         }
2809         else
2810         {
2811             if (nPrecision)
2812                 --nPrecision;           // vermindern
2813             else
2814                 bError = sal_True;          // weniger als 0 geht nicht
2815         }
2816     }
2817 
2818     if (!bError)
2819     {
2820         String aNewPicture;
2821         pFormatter->GenerateFormat( aNewPicture, nOldFormat, eLanguage,
2822                                     bThousand, bNegRed, nPrecision, nLeading );
2823 
2824         nNewFormat = pFormatter->GetEntryKey( aNewPicture, eLanguage );
2825         if ( nNewFormat == NUMBERFORMAT_ENTRY_NOT_FOUND )
2826         {
2827             xub_StrLen nErrPos = 0;
2828             short nNewType = 0;
2829             sal_Bool bOk = pFormatter->PutEntry( aNewPicture, nErrPos,
2830                                                 nNewType, nNewFormat, eLanguage );
2831             DBG_ASSERT( bOk, "falsches Zahlformat generiert" );
2832             if (!bOk)
2833                 bError = sal_True;
2834         }
2835     }
2836 
2837     if (!bError)
2838     {
2839         ScPatternAttr aNewAttrs( pDoc->GetPool() );
2840         SfxItemSet& rSet = aNewAttrs.GetItemSet();
2841         rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) );
2842         //  ATTR_LANGUAGE_FORMAT nicht
2843         ApplySelectionPattern( aNewAttrs, sal_True );
2844     }
2845     else
2846         Sound::Beep();              // war nix
2847 }
2848 
ChangeIndent(sal_Bool bIncrement)2849 void ScViewFunc::ChangeIndent( sal_Bool bIncrement )
2850 {
2851     ScViewData* pViewData = GetViewData();
2852     ScDocShell* pDocSh  = pViewData->GetDocShell();
2853     ScMarkData& rMark   = pViewData->GetMarkData();
2854 
2855     ScMarkData aWorkMark = rMark;
2856     ScViewUtil::UnmarkFiltered( aWorkMark, pDocSh->GetDocument() );
2857     aWorkMark.MarkToMulti();
2858     if (!aWorkMark.IsMultiMarked())
2859     {
2860         SCCOL nCol = pViewData->GetCurX();
2861         SCROW nRow = pViewData->GetCurY();
2862         SCTAB nTab = pViewData->GetTabNo();
2863         aWorkMark.SetMultiMarkArea( ScRange(nCol,nRow,nTab) );
2864     }
2865 
2866     sal_Bool bSuccess = pDocSh->GetDocFunc().ChangeIndent( aWorkMark, bIncrement, sal_False );
2867     if (bSuccess)
2868     {
2869         pDocSh->UpdateOle(pViewData);
2870         StartFormatArea();
2871 
2872         // stuff for sidebar panels
2873         SfxBindings& rBindings = GetViewData()->GetBindings();
2874         rBindings.Invalidate( SID_H_ALIGNCELL );
2875         rBindings.Invalidate( SID_ATTR_ALIGN_INDENT );
2876     }
2877 }
2878 
InsertName(const String & rName,const String & rSymbol,const String & rType)2879 sal_Bool ScViewFunc::InsertName( const String& rName, const String& rSymbol,
2880                                 const String& rType )
2881 {
2882     //  Type = P,R,C,F (und Kombinationen)
2883     //! Undo...
2884 
2885     sal_Bool bOk = sal_False;
2886     ScDocShell* pDocSh = GetViewData()->GetDocShell();
2887     ScDocument* pDoc = pDocSh->GetDocument();
2888     SCTAB nTab = GetViewData()->GetTabNo();
2889     ScRangeName* pList = pDoc->GetRangeName();
2890 
2891     RangeType nType = RT_NAME;
2892     ScRangeData* pNewEntry = new ScRangeData( pDoc, rName, rSymbol,
2893             ScAddress( GetViewData()->GetCurX(), GetViewData()->GetCurY(),
2894                 nTab), nType );
2895     String aUpType = rType;
2896     aUpType.ToUpperAscii();
2897     if ( aUpType.Search( 'P' ) != STRING_NOTFOUND )
2898         nType |= RT_PRINTAREA;
2899     if ( aUpType.Search( 'R' ) != STRING_NOTFOUND )
2900         nType |= RT_ROWHEADER;
2901     if ( aUpType.Search( 'C' ) != STRING_NOTFOUND )
2902         nType |= RT_COLHEADER;
2903     if ( aUpType.Search( 'F' ) != STRING_NOTFOUND )
2904         nType |= RT_CRITERIA;
2905     pNewEntry->AddType(nType);
2906 
2907     if ( !pNewEntry->GetErrCode() )     //  Text gueltig?
2908     {
2909         ScDocShellModificator aModificator( *pDocSh );
2910 
2911         pDoc->CompileNameFormula( sal_True );   // CreateFormulaString
2912 
2913         // Eintrag bereits vorhanden? Dann vorher entfernen (=Aendern)
2914         sal_uInt16 nFoundAt;
2915         if ( pList->SearchName( rName, nFoundAt ) )
2916         {                                   // alten Index uebernehmen
2917             pNewEntry->SetIndex( ((ScRangeData*)pList->At(nFoundAt))->GetIndex() );
2918             pList->AtFree( nFoundAt );
2919         }
2920 
2921         if ( pList->Insert( pNewEntry ) )
2922         {
2923             pNewEntry = NULL;   // nicht loeschen
2924             bOk = sal_True;
2925         }
2926 
2927         pDoc->CompileNameFormula( sal_False );  // CompileFormulaString
2928         aModificator.SetDocumentModified();
2929         SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_AREAS_CHANGED ) );
2930     }
2931 
2932     delete pNewEntry;       // wenn er nicht eingefuegt wurde
2933     return bOk;
2934 }
2935 
CreateNames(sal_uInt16 nFlags)2936 void ScViewFunc::CreateNames( sal_uInt16 nFlags )
2937 {
2938     sal_Bool bDone = sal_False;
2939     ScRange aRange;
2940     if ( GetViewData()->GetSimpleArea(aRange) == SC_MARK_SIMPLE )
2941         bDone = GetViewData()->GetDocShell()->GetDocFunc().CreateNames( aRange, nFlags, sal_False );
2942 
2943     if (!bDone)
2944         ErrorMessage(STR_CREATENAME_MARKERR);
2945 }
2946 
GetCreateNameFlags()2947 sal_uInt16 ScViewFunc::GetCreateNameFlags()
2948 {
2949     sal_uInt16 nFlags = 0;
2950 
2951     SCCOL nStartCol, nEndCol;
2952     SCROW nStartRow, nEndRow;
2953     SCTAB nDummy;
2954     if (GetViewData()->GetSimpleArea(nStartCol,nStartRow,nDummy,nEndCol,nEndRow,nDummy) == SC_MARK_SIMPLE)
2955     {
2956         ScDocument* pDoc = GetViewData()->GetDocument();
2957         SCTAB nTab = GetViewData()->GetTabNo();
2958         sal_Bool bOk;
2959         SCCOL i;
2960         SCROW j;
2961 
2962         bOk = sal_True;
2963         SCCOL nFirstCol = nStartCol;
2964         SCCOL nLastCol  = nEndCol;
2965         if (nStartCol+1 < nEndCol) { ++nFirstCol; --nLastCol; }
2966         for (i=nFirstCol; i<=nLastCol && bOk; i++)
2967             if (!pDoc->HasStringData( i,nStartRow,nTab ))
2968                 bOk = sal_False;
2969         if (bOk)
2970             nFlags |= NAME_TOP;
2971         else                            // Bottom nur wenn nicht Top
2972         {
2973             bOk = sal_True;
2974             for (i=nFirstCol; i<=nLastCol && bOk; i++)
2975                 if (!pDoc->HasStringData( i,nEndRow,nTab ))
2976                     bOk = sal_False;
2977             if (bOk)
2978                 nFlags |= NAME_BOTTOM;
2979         }
2980 
2981         bOk = sal_True;
2982         SCROW nFirstRow = nStartRow;
2983         SCROW nLastRow  = nEndRow;
2984         if (nStartRow+1 < nEndRow) { ++nFirstRow; --nLastRow; }
2985         for (j=nFirstRow; j<=nLastRow && bOk; j++)
2986             if (!pDoc->HasStringData( nStartCol,j,nTab ))
2987                 bOk = sal_False;
2988         if (bOk)
2989             nFlags |= NAME_LEFT;
2990         else                            // Right nur wenn nicht Left
2991         {
2992             bOk = sal_True;
2993             for (j=nFirstRow; j<=nLastRow && bOk; j++)
2994                 if (!pDoc->HasStringData( nEndCol,j,nTab ))
2995                     bOk = sal_False;
2996             if (bOk)
2997                 nFlags |= NAME_RIGHT;
2998         }
2999     }
3000 
3001     if (nStartCol == nEndCol)
3002         nFlags &= ~( NAME_LEFT | NAME_RIGHT );
3003     if (nStartRow == nEndRow)
3004         nFlags &= ~( NAME_TOP | NAME_BOTTOM );
3005 
3006     return nFlags;
3007 }
3008 
InsertNameList()3009 void ScViewFunc::InsertNameList()
3010 {
3011     ScAddress aPos( GetViewData()->GetCurX(), GetViewData()->GetCurY(), GetViewData()->GetTabNo() );
3012     ScDocShell* pDocSh = GetViewData()->GetDocShell();
3013     if ( pDocSh->GetDocFunc().InsertNameList( aPos, sal_False ) )
3014         pDocSh->UpdateOle(GetViewData());
3015 }
3016 
3017 
3018 
3019 
3020