1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice project.
4  *
5  * This Source Code Form is subject to the terms of the Mozilla Public
6  * License, v. 2.0. If a copy of the MPL was not distributed with this
7  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8  *
9  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #include <com/sun/star/table/BorderLineStyle.hpp>
21 
22 #include <comphelper/lok.hxx>
23 #include <editeng/boxitem.hxx>
24 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
25 #include <o3tl/temporary.hxx>
26 #include <sfx2/bindings.hxx>
27 #include <sfx2/lokhelper.hxx>
28 #include <sfx2/request.hxx>
29 #include <sfx2/sfxdlg.hxx>
30 #include <sfx2/sidebar/Sidebar.hxx>
31 #include <sfx2/viewfrm.hxx>
32 #include <svl/ilstitem.hxx>
33 #include <svl/int64item.hxx>
34 #include <svl/srchitem.hxx>
35 #include <svl/srchdefs.hxx>
36 #include <svl/stritem.hxx>
37 #include <svl/whiter.hxx>
38 #include <svx/numinf.hxx>
39 #include <svx/zoomslideritem.hxx>
40 
41 #include <global.hxx>
42 #include <appoptio.hxx>
43 #include <attrib.hxx>
44 #include <cellform.hxx>
45 #include <cellvalue.hxx>
46 #include <compiler.hxx>
47 #include <docsh.hxx>
48 #include <document.hxx>
49 #include <formulacell.hxx>
50 #include <globstr.hrc>
51 #include <inputhdl.hxx>
52 #include <inputwin.hxx>
53 #include <markdata.hxx>
54 #include <patattr.hxx>
55 #include <sc.hrc>
56 #include <scabstdlg.hxx>
57 #include <scitems.hxx>
58 #include <scmod.hxx>
59 #include <scresid.hxx>
60 #include <stlpool.hxx>
61 #include <tabvwsh.hxx>
62 #include <tokenarray.hxx>
63 #include <viewdata.hxx>
64 
65 #include <memory>
66 
67 using namespace com::sun::star;
68 
GetFunction(OUString & rFuncStr,FormulaError nErrCode)69 bool ScTabViewShell::GetFunction( OUString& rFuncStr, FormulaError nErrCode )
70 {
71     sal_uInt32 nFuncs = SC_MOD()->GetAppOptions().GetStatusFunc();
72     ScViewData& rViewData   = GetViewData();
73     ScMarkData& rMark       = rViewData.GetMarkData();
74     bool bIgnoreError = (rMark.IsMarked() || rMark.IsMultiMarked());
75     bool bFirst = true;
76     for ( sal_uInt16 nFunc = 0; nFunc < 32; nFunc++ )
77     {
78         if ( !(nFuncs & (1 << nFunc)) )
79             continue;
80         ScSubTotalFunc eFunc = static_cast<ScSubTotalFunc>(nFunc);
81 
82         if (bIgnoreError && (eFunc == SUBTOTAL_FUNC_CNT || eFunc == SUBTOTAL_FUNC_CNT2))
83             nErrCode = FormulaError::NONE;
84 
85         if (nErrCode != FormulaError::NONE)
86         {
87             rFuncStr = ScGlobal::GetLongErrorString(nErrCode);
88             return true;
89         }
90 
91         const char* pGlobStrId = nullptr;
92         switch (eFunc)
93         {
94             case SUBTOTAL_FUNC_AVE:  pGlobStrId = STR_FUN_TEXT_AVG; break;
95             case SUBTOTAL_FUNC_CNT:  pGlobStrId = STR_FUN_TEXT_COUNT; break;
96             case SUBTOTAL_FUNC_CNT2: pGlobStrId = STR_FUN_TEXT_COUNT2; break;
97             case SUBTOTAL_FUNC_MAX:  pGlobStrId = STR_FUN_TEXT_MAX; break;
98             case SUBTOTAL_FUNC_MIN:  pGlobStrId = STR_FUN_TEXT_MIN; break;
99             case SUBTOTAL_FUNC_SUM:  pGlobStrId = STR_FUN_TEXT_SUM; break;
100             case SUBTOTAL_FUNC_SELECTION_COUNT: pGlobStrId = STR_FUN_TEXT_SELECTION_COUNT; break;
101 
102             default:
103             {
104                 // added to avoid warnings
105             }
106         }
107         if (pGlobStrId)
108         {
109             ScDocument* pDoc        = rViewData.GetDocument();
110             SCCOL       nPosX       = rViewData.GetCurX();
111             SCROW       nPosY       = rViewData.GetCurY();
112             SCTAB       nTab        = rViewData.GetTabNo();
113 
114             OUString aStr = ScResId(pGlobStrId) + ": ";
115 
116             ScAddress aCursor( nPosX, nPosY, nTab );
117             double nVal;
118             if ( pDoc->GetSelectionFunction( eFunc, aCursor, rMark, nVal ) )
119             {
120                 if ( nVal == 0.0 )
121                     aStr += "0";
122                 else
123                 {
124                     // Number in the standard format, the other on the cursor position
125                     SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
126                     sal_uInt32 nNumFmt = 0;
127                     if ( eFunc != SUBTOTAL_FUNC_CNT && eFunc != SUBTOTAL_FUNC_CNT2 && eFunc != SUBTOTAL_FUNC_SELECTION_COUNT)
128                     {
129                         // number format from attributes or formula
130                         pDoc->GetNumberFormat( nPosX, nPosY, nTab, nNumFmt );
131                     }
132 
133                     OUString aValStr;
134                     Color* pDummy;
135                     pFormatter->GetOutputString( nVal, nNumFmt, aValStr, &pDummy );
136                     aStr += aValStr;
137                 }
138             }
139             if ( bFirst )
140             {
141                 rFuncStr += aStr;
142                 bFirst = false;
143             }
144             else
145                 rFuncStr += "; " + aStr;
146         }
147     }
148 
149     return !rFuncStr.isEmpty();
150 }
151 
152 //  Functions that are disabled, depending on the selection
153 //  Default:
154 //      SID_DELETE,
155 //      SID_DELETE_CONTENTS,
156 //      FID_DELETE_CELL
157 //      FID_VALIDATION
158 
GetState(SfxItemSet & rSet)159 void ScTabViewShell::GetState( SfxItemSet& rSet )
160 {
161     ScViewData& rViewData   = GetViewData();
162     ScDocument* pDoc        = rViewData.GetDocument();
163     ScDocShell* pDocShell   = rViewData.GetDocShell();
164     ScMarkData& rMark       = rViewData.GetMarkData();
165     SCCOL       nPosX       = rViewData.GetCurX();
166     SCROW       nPosY       = rViewData.GetCurY();
167     SCTAB       nTab        = rViewData.GetTabNo();
168 
169     SfxViewFrame* pThisFrame = GetViewFrame();
170     bool bOle = GetViewFrame()->GetFrame().IsInPlace();
171 
172     SCTAB nTabSelCount = rMark.GetSelectCount();
173 
174     SfxWhichIter    aIter(rSet);
175     sal_uInt16          nWhich = aIter.FirstWhich();
176 
177     while ( nWhich )
178     {
179         switch ( nWhich )
180         {
181             case FID_CHG_COMMENT:
182                 {
183                     ScDocShell* pDocSh = GetViewData().GetDocShell();
184                     ScAddress aPos( nPosX, nPosY, nTab );
185                     if ( pDocSh->IsReadOnly() || !pDocSh->GetChangeAction(aPos) || pDocSh->IsDocShared() )
186                         rSet.DisableItem( nWhich );
187                 }
188                 break;
189 
190             case SID_OPENDLG_EDIT_PRINTAREA:
191             case SID_ADD_PRINTAREA:
192             case SID_DEFINE_PRINTAREA:
193                 {
194                     if ( pDocShell && pDocShell->IsDocShared() )
195                     {
196                         rSet.DisableItem( nWhich );
197                     }
198                 }
199                 break;
200 
201             case SID_DELETE_PRINTAREA:
202                 if ( pDocShell && pDocShell->IsDocShared() )
203                 {
204                     rSet.DisableItem( nWhich );
205                 }
206                 else if (pDoc->IsPrintEntireSheet(nTab))
207                     rSet.DisableItem(nWhich);
208                 break;
209 
210             case SID_STATUS_PAGESTYLE:
211             case SID_HFEDIT:
212                 GetViewData().GetDocShell()->GetStatePageStyle( rSet, nTab );
213                 break;
214 
215             case SID_SEARCH_ITEM:
216             {
217                 SvxSearchItem aItem(ScGlobal::GetSearchItem()); // make a copy.
218                 // Search on current selection if a range is marked.
219                 aItem.SetSelection(rMark.IsMarked());
220                 rSet.Put(aItem);
221                 break;
222             }
223 
224             case SID_SEARCH_OPTIONS:
225                 {
226                     // Anything goes
227                     SearchOptionFlags nOptions = SearchOptionFlags::ALL;
228 
229                     // No replacement if ReadOnly
230                     if (GetViewData().GetDocShell()->IsReadOnly())
231                         nOptions &= ~SearchOptionFlags( SearchOptionFlags::REPLACE | SearchOptionFlags::REPLACE_ALL );
232                     rSet.Put( SfxUInt16Item( nWhich, static_cast<sal_uInt16>(nOptions) ) );
233                 }
234                 break;
235 
236             case SID_CURRENTCELL:
237                 {
238                     ScAddress aScAddress( GetViewData().GetCurX(), GetViewData().GetCurY(), 0 );
239                     OUString  aAddr(aScAddress.Format(ScRefFlags::ADDR_ABS, nullptr, pDoc->GetAddressConvention()));
240                     SfxStringItem   aPosItem( SID_CURRENTCELL, aAddr );
241 
242                     rSet.Put( aPosItem );
243                 }
244                 break;
245 
246             case SID_CURRENTTAB:
247                 // Table for Basic is 1-based
248                 rSet.Put( SfxUInt16Item( nWhich, static_cast<sal_uInt16>(GetViewData().GetTabNo()) + 1 ) );
249                 break;
250 
251             case SID_CURRENTDOC:
252                 rSet.Put( SfxStringItem( nWhich, GetViewData().GetDocShell()->GetTitle() ) );
253                 break;
254 
255             case FID_TOGGLEINPUTLINE:
256                 {
257                     sal_uInt16 nId = ScInputWindowWrapper::GetChildWindowId();
258 
259                     if ( pThisFrame->KnowsChildWindow( nId ) )
260                     {
261                         SfxChildWindow* pWnd = pThisFrame->GetChildWindow( nId );
262                         rSet.Put( SfxBoolItem( nWhich, pWnd != nullptr ) );
263                     }
264                     else
265                         rSet.DisableItem( nWhich );
266                 }
267                 break;
268 
269             case FID_DEL_MANUALBREAKS:
270                 if (!pDoc->HasManualBreaks(nTab))
271                     rSet.DisableItem( nWhich );
272                 break;
273 
274             case FID_RESET_PRINTZOOM:
275                 {
276                     // disable if already set to default
277 
278                     OUString aStyleName = pDoc->GetPageStyle( nTab );
279                     ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool();
280                     SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName,
281                                                     SfxStyleFamily::Page );
282                     OSL_ENSURE( pStyleSheet, "PageStyle not found" );
283                     if ( pStyleSheet )
284                     {
285                         SfxItemSet& rStyleSet = pStyleSheet->GetItemSet();
286                         sal_uInt16 nScale = rStyleSet.Get(ATTR_PAGE_SCALE).GetValue();
287                         sal_uInt16 nPages = rStyleSet.Get(ATTR_PAGE_SCALETOPAGES).GetValue();
288                         if ( nScale == 100 && nPages == 0 )
289                             rSet.DisableItem( nWhich );
290                     }
291                 }
292                 break;
293 
294             case FID_SCALE:
295             case SID_ATTR_ZOOM:
296                 if ( bOle )
297                     rSet.DisableItem( nWhich );
298                 else
299                 {
300                     const Fraction& rOldY = GetViewData().GetZoomY();
301                     sal_uInt16 nZoom = static_cast<sal_uInt16>(long( rOldY * 100 ));
302                     rSet.Put( SvxZoomItem( SvxZoomType::PERCENT, nZoom, nWhich ) );
303                 }
304                 break;
305 
306             case SID_ATTR_ZOOMSLIDER:
307                 {
308                     if ( bOle )
309                         rSet.DisableItem( nWhich );
310                     else
311                     {
312                         const Fraction& rOldY = GetViewData().GetZoomY();
313                         sal_uInt16 nCurrentZoom = static_cast<sal_uInt16>(long( rOldY * 100 ));
314 
315                         if( nCurrentZoom )
316                         {
317                             SvxZoomSliderItem aZoomSliderItem( nCurrentZoom, MINZOOM, MAXZOOM, SID_ATTR_ZOOMSLIDER );
318                             aZoomSliderItem.AddSnappingPoint( 100 );
319                             rSet.Put( aZoomSliderItem );
320                         }
321                     }
322                 }
323                 break;
324 
325             case FID_FUNCTION_BOX:
326             {
327                 const bool bBoxOpen = ::sfx2::sidebar::Sidebar::IsPanelVisible("ScFunctionsPanel",
328                                                     pThisFrame->GetFrame().GetFrameInterface());
329                 rSet.Put(SfxBoolItem(nWhich, bBoxOpen));
330                 break;
331             }
332 
333             case FID_TOGGLESYNTAX:
334                 rSet.Put(SfxBoolItem(nWhich, GetViewData().IsSyntaxMode()));
335                 break;
336 
337             case FID_TOGGLEHEADERS:
338                 rSet.Put(SfxBoolItem(nWhich, GetViewData().IsHeaderMode()));
339                 break;
340 
341             case FID_TOGGLEFORMULA:
342                 {
343                     const ScViewOptions& rOpts = rViewData.GetOptions();
344                     bool bFormulaMode = rOpts.GetOption( VOPT_FORMULAS );
345                     rSet.Put(SfxBoolItem(nWhich, bFormulaMode ));
346                 }
347                 break;
348 
349             case FID_NORMALVIEWMODE:
350             case FID_PAGEBREAKMODE:
351                 // always handle both slots - they exclude each other
352                 if ( bOle )
353                 {
354                     rSet.DisableItem( FID_NORMALVIEWMODE );
355                     rSet.DisableItem( FID_PAGEBREAKMODE );
356                 }
357                 else
358                 {
359                     rSet.Put(SfxBoolItem(FID_NORMALVIEWMODE, !GetViewData().IsPagebreakMode()));
360                     rSet.Put(SfxBoolItem(FID_PAGEBREAKMODE, GetViewData().IsPagebreakMode()));
361                 }
362                 break;
363 
364             case FID_PROTECT_DOC:
365                 {
366                     if ( pDocShell && pDocShell->IsDocShared() )
367                     {
368                         rSet.DisableItem( nWhich );
369                     }
370                     else
371                     {
372                         rSet.Put( SfxBoolItem( nWhich, pDoc->IsDocProtected() ) );
373                     }
374                 }
375                 break;
376 
377             case FID_PROTECT_TABLE:
378                 {
379                     if ( pDocShell && pDocShell->IsDocShared() )
380                     {
381                         rSet.DisableItem( nWhich );
382                     }
383                     else
384                     {
385                         rSet.Put( SfxBoolItem( nWhich, pDoc->IsTabProtected( nTab ) ) );
386                     }
387                 }
388                 break;
389 
390             case SID_AUTO_OUTLINE:
391                 {
392                     if (pDoc->GetChangeTrack()!=nullptr || GetViewData().IsMultiMarked())
393                     {
394                         rSet.DisableItem( nWhich );
395                     }
396                 }
397                 break;
398 
399             case SID_OUTLINE_DELETEALL:
400                 {
401                     SCTAB nOlTab = GetViewData().GetTabNo();
402                     ScOutlineTable* pOlTable = pDoc->GetOutlineTable( nOlTab );
403                     if (pOlTable == nullptr)
404                         rSet.DisableItem( nWhich );
405                 }
406                 break;
407 
408             case SID_WINDOW_SPLIT:
409                 rSet.Put(SfxBoolItem(nWhich,
410                             rViewData.GetHSplitMode() == SC_SPLIT_NORMAL ||
411                             rViewData.GetVSplitMode() == SC_SPLIT_NORMAL ));
412                 break;
413 
414             case SID_WINDOW_FIX:
415                 rSet.Put(SfxBoolItem(nWhich,
416                             rViewData.GetHSplitMode() == SC_SPLIT_FIX ||
417                             rViewData.GetVSplitMode() == SC_SPLIT_FIX ));
418                 break;
419 
420             case FID_CHG_SHOW:
421                 {
422                     if ( pDoc->GetChangeTrack() == nullptr || ( pDocShell && pDocShell->IsDocShared() ) )
423                         rSet.DisableItem( nWhich );
424                 }
425                 break;
426             case FID_CHG_ACCEPT:
427                 {
428                     if(
429                        ( !pDoc->GetChangeTrack() &&  !pThisFrame->HasChildWindow(FID_CHG_ACCEPT) )
430                        ||
431                        ( pDocShell && pDocShell->IsDocShared() )
432                       )
433                     {
434                         rSet.DisableItem( nWhich);
435                     }
436                     else
437                     {
438                         rSet.Put(SfxBoolItem(FID_CHG_ACCEPT,
439                             pThisFrame->HasChildWindow(FID_CHG_ACCEPT)));
440                     }
441                 }
442                 break;
443 
444             case SID_FORMATPAGE:
445                 // in protected tables
446                 if ( pDocShell && ( pDocShell->IsReadOnly() || pDocShell->IsDocShared() ) )
447                     rSet.DisableItem( nWhich );
448                 break;
449 
450             case SID_PRINTPREVIEW:
451                 // Toggle slot needs a State
452                 rSet.Put( SfxBoolItem( nWhich, false ) );
453                 break;
454 
455             case SID_READONLY_MODE:
456                 rSet.Put( SfxBoolItem( nWhich, GetViewData().GetDocShell()->IsReadOnly() ) );
457                 break;
458 
459             case FID_TAB_DESELECTALL:
460                 if ( nTabSelCount == 1 )
461                     rSet.DisableItem( nWhich );     // enabled only if several sheets are selected
462                 break;
463 
464         } // switch ( nWitch )
465         nWhich = aIter.NextWhich();
466     } // while ( nWitch )
467 }
468 
ExecuteCellFormatDlg(SfxRequest & rReq,const OString & rName)469 void ScTabViewShell::ExecuteCellFormatDlg(SfxRequest& rReq, const OString &rName)
470 {
471     ScDocument*             pDoc    = GetViewData().GetDocument();
472 
473     std::shared_ptr<SvxBoxItem> aLineOuter(std::make_shared<SvxBoxItem>(ATTR_BORDER));
474     std::shared_ptr<SvxBoxInfoItem> aLineInner(std::make_shared<SvxBoxInfoItem>(ATTR_BORDER_INNER));
475 
476     const ScPatternAttr*    pOldAttrs       = GetSelectionPattern();
477 
478     std::shared_ptr<SfxItemSet> pOldSet(new SfxItemSet(pOldAttrs->GetItemSet()));
479     std::shared_ptr<SvxNumberInfoItem> pNumberInfoItem;
480 
481     pOldSet->MergeRange(XATTR_FILLSTYLE, XATTR_FILLCOLOR);
482 
483     pOldSet->MergeRange(SID_ATTR_BORDER_STYLES, SID_ATTR_BORDER_DEFAULT_WIDTH);
484 
485     // We only allow these border line types.
486     const std::vector<sal_Int32> aBorderStyles{
487         table::BorderLineStyle::SOLID,
488         table::BorderLineStyle::DOTTED,
489         table::BorderLineStyle::DASHED,
490         table::BorderLineStyle::FINE_DASHED,
491         table::BorderLineStyle::DASH_DOT,
492         table::BorderLineStyle::DASH_DOT_DOT,
493         table::BorderLineStyle::DOUBLE_THIN };
494 
495     SfxIntegerListItem aBorderStylesItem(SID_ATTR_BORDER_STYLES, aBorderStyles);
496     pOldSet->Put(aBorderStylesItem);
497 
498     // Set the default border width to 0.75 points.
499     SfxInt64Item aBorderWidthItem(SID_ATTR_BORDER_DEFAULT_WIDTH, 75);
500     pOldSet->Put(aBorderWidthItem);
501 
502     // Get border items and put them in the set:
503     GetSelectionFrame( aLineOuter, aLineInner );
504 
505     //Fix border incorrect for RTL fdo#62399
506     if( pDoc->IsLayoutRTL( GetViewData().GetTabNo() ) )
507     {
508         std::shared_ptr<SvxBoxItem> aNewFrame(static_cast<SvxBoxItem*>(aLineOuter->Clone()));
509         std::shared_ptr<SvxBoxInfoItem> aTempInfo(static_cast<SvxBoxInfoItem*>(aLineInner->Clone()));
510 
511         if ( aLineInner->IsValid(SvxBoxInfoItemValidFlags::LEFT) )
512             aNewFrame->SetLine( aLineOuter->GetLeft(), SvxBoxItemLine::RIGHT );
513         if ( aLineInner->IsValid(SvxBoxInfoItemValidFlags::RIGHT) )
514             aNewFrame->SetLine( aLineOuter->GetRight(), SvxBoxItemLine::LEFT );
515 
516         aLineInner->SetValid( SvxBoxInfoItemValidFlags::LEFT, aTempInfo->IsValid(SvxBoxInfoItemValidFlags::RIGHT));
517         aLineInner->SetValid( SvxBoxInfoItemValidFlags::RIGHT, aTempInfo->IsValid(SvxBoxInfoItemValidFlags::LEFT));
518 
519         pOldSet->Put( *aNewFrame );
520     }
521     else
522     {
523         pOldSet->Put( *aLineOuter );
524     }
525 
526     pOldSet->Put( *aLineInner );
527 
528     // Generate NumberFormat Value from Value and Language and box it.
529     pOldSet->Put( SfxUInt32Item( ATTR_VALUE_FORMAT,
530         pOldAttrs->GetNumberFormat( pDoc->GetFormatTable() ) ) );
531 
532     pNumberInfoItem = MakeNumberInfoItem(pDoc, &GetViewData());
533 
534     pOldSet->MergeRange( SID_ATTR_NUMBERFORMAT_INFO, SID_ATTR_NUMBERFORMAT_INFO );
535     pOldSet->Put(*pNumberInfoItem );
536 
537     bInFormatDialog = true;
538     ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
539 
540     VclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateScAttrDlg(GetFrameWeld(), pOldSet.get()));
541 
542     if (!rName.isEmpty())
543         pDlg->SetCurPageId(rName);
544 
545     std::shared_ptr<SfxRequest> pRequest(new SfxRequest(rReq));
546     rReq.Ignore(); // the 'old' request is not relevant any more
547 
548     pDlg->StartExecuteAsync([pDlg, pOldSet, pRequest, this](sal_Int32 nResult){
549         bInFormatDialog = false;
550 
551         if ( nResult == RET_OK )
552         {
553             const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
554 
555             const SfxPoolItem* pItem=nullptr;
556             if(pOutSet->GetItemState(SID_ATTR_NUMBERFORMAT_INFO,true,&pItem)==SfxItemState::SET)
557             {
558                 UpdateNumberFormatter(static_cast<const SvxNumberInfoItem&>(*pItem));
559             }
560 
561             ApplyAttributes(pOutSet, pOldSet.get());
562 
563             pRequest->Done(*pOutSet);
564         }
565 
566         pDlg->disposeOnce();
567     });
568 }
569 
IsRefInputMode() const570 bool ScTabViewShell::IsRefInputMode() const
571 {
572     ScModule* pScMod = SC_MOD();
573     if ( pScMod )
574     {
575         if( pScMod->IsRefDialogOpen() )
576             return pScMod->IsFormulaMode();
577         if( pScMod->IsFormulaMode() )
578         {
579             ScInputHandler* pHdl = pScMod->GetInputHdl();
580             if ( pHdl )
581             {
582                 OUString aString = pHdl->GetEditString();
583                 if ( !pHdl->GetSelIsRef() && aString.getLength() > 1 &&
584                      ( aString[0] == '+' || aString[0] == '-' ) )
585                 {
586                     const ScViewData& rViewData = GetViewData();
587                     ScDocument* pDoc = rViewData.GetDocument();
588                     if ( pDoc )
589                     {
590                         const ScAddress aPos( rViewData.GetCurPos() );
591                         ScCompiler aComp( pDoc, aPos, pDoc->GetGrammar() );
592                         aComp.SetCloseBrackets( false );
593                         std::unique_ptr<ScTokenArray> pArr(aComp.CompileString(aString));
594                         if ( pArr && pArr->MayReferenceFollow() )
595                         {
596                             return true;
597                         }
598                     }
599                 }
600                 else
601                 {
602                     return true;
603                 }
604             }
605         }
606     }
607 
608     return false;
609 }
610 
ExecuteInputDirect()611 void ScTabViewShell::ExecuteInputDirect()
612 {
613     if ( !IsRefInputMode() )
614     {
615         ScModule* pScMod = SC_MOD();
616         if ( pScMod )
617         {
618             pScMod->InputEnterHandler();
619         }
620     }
621 }
622 
UpdateInputHandler(bool bForce,bool bStopEditing)623 void ScTabViewShell::UpdateInputHandler( bool bForce /* = sal_False */, bool bStopEditing /* = sal_True */ )
624 {
625     ScInputHandler* pHdl = mpInputHandler ? mpInputHandler.get() : SC_MOD()->GetInputHdl();
626 
627     if ( pHdl )
628     {
629         OUString                aString;
630         const EditTextObject*   pObject     = nullptr;
631         ScViewData&             rViewData   = GetViewData();
632         ScDocument*             pDoc        = rViewData.GetDocument();
633         SCCOL                   nPosX       = rViewData.GetCurX();
634         SCROW                   nPosY       = rViewData.GetCurY();
635         SCTAB                   nTab        = rViewData.GetTabNo();
636         SCTAB                   nStartTab   = 0;
637         SCTAB                   nEndTab     = 0;
638         SCCOL                   nStartCol   = 0;
639         SCROW                   nStartRow   = 0;
640         SCCOL                   nEndCol     = 0;
641         SCROW                   nEndRow     = 0;
642         ScAddress aPos = rViewData.GetCurPos();
643 
644         rViewData.GetSimpleArea( nStartCol, nStartRow, nStartTab,
645                                   nEndCol,   nEndRow,   nEndTab );
646 
647         PutInOrder( nStartCol, nEndCol );
648         PutInOrder( nStartRow, nEndRow );
649         PutInOrder( nStartTab, nEndTab );
650 
651         bool bHideFormula = false;
652         bool bHideAll     = false;
653 
654         if (pDoc->IsTabProtected(nTab))
655         {
656             const ScProtectionAttr* pProt = pDoc->GetAttr( nPosX,nPosY,nTab,
657                                                            ATTR_PROTECTION);
658             bHideFormula = pProt->GetHideFormula();
659             bHideAll     = pProt->GetHideCell();
660         }
661 
662         if (!bHideAll)
663         {
664             ScRefCellValue rCell(*pDoc, aPos);
665             if (rCell.meType == CELLTYPE_FORMULA)
666             {
667                 if (!bHideFormula)
668                     rCell.mpFormula->GetFormula(aString);
669             }
670             else if (rCell.meType == CELLTYPE_EDIT)
671             {
672                 pObject = rCell.mpEditText;
673             }
674             else
675             {
676                 SvNumberFormatter* pFormatter = pDoc->GetFormatTable();
677                 sal_uInt32 nNumFmt = pDoc->GetNumberFormat( aPos );
678 
679                 ScCellFormat::GetInputString( rCell, nNumFmt, aString, *pFormatter, pDoc );
680                 if (rCell.meType == CELLTYPE_STRING)
681                 {
682                     // Put a ' in front if necessary, so that the string is not
683                     // unintentionally interpreted as a number, and to show the
684                     // user that it is a string (#35060#).
685                     //! also for numberformat "Text"? -> then remove when editing
686                     if ( pFormatter->IsNumberFormat(aString, nNumFmt, o3tl::temporary(double())) )
687                         aString = "'" + aString;
688                 }
689             }
690         }
691 
692         ScInputHdlState aState( ScAddress( nPosX,     nPosY,     nTab ),
693                                 ScAddress( nStartCol, nStartRow, nTab ),
694                                 ScAddress( nEndCol,   nEndRow,   nTab ),
695                                 aString,
696                                 pObject );
697 
698         //  if using the view's local input handler, this view can always be set
699         //  as current view inside NotifyChange.
700         ScTabViewShell* pSourceSh = mpInputHandler ? this : nullptr;
701 
702         pHdl->NotifyChange( &aState, bForce, pSourceSh, bStopEditing );
703     }
704 
705     SfxBindings& rBindings = GetViewFrame()->GetBindings();
706     rBindings.Invalidate( SID_STATUS_SUM );         // always together with the input row
707     rBindings.Invalidate( SID_ATTR_SIZE );
708     rBindings.Invalidate( SID_TABLE_CELL );
709 }
710 
UpdateInputHandlerCellAdjust(SvxCellHorJustify eJust)711 void ScTabViewShell::UpdateInputHandlerCellAdjust( SvxCellHorJustify eJust )
712 {
713     if( ScInputHandler* pHdl = mpInputHandler ? mpInputHandler.get() : SC_MOD()->GetInputHdl() )
714         pHdl->UpdateCellAdjust( eJust );
715 }
716 
ExecuteSave(SfxRequest & rReq)717 void ScTabViewShell::ExecuteSave( SfxRequest& rReq )
718 {
719     // only SID_SAVEDOC / SID_SAVEASDOC
720     bool bCommitChanges = true;
721     const SfxItemSet* pReqArgs = rReq.GetArgs();
722     const SfxPoolItem* pItem;
723 
724     if (pReqArgs && pReqArgs->HasItem(FN_PARAM_1, &pItem))
725         bCommitChanges = !static_cast<const SfxBoolItem*>(pItem)->GetValue();
726 
727     // Finish entering unless 'DontTerminateEdit' is specified, even if a formula is being processed
728     if (bCommitChanges)
729     {
730         if (comphelper::LibreOfficeKit::isActive())
731         {
732             // Normally this isn't needed, but in Calc when editing a cell formula
733             // and manually saving (without changing cells or hitting enter), while
734             // InputEnterHandler will mark the doc as modified (when it is), because
735             // we will save the doc immediately afterwards, the modified state event
736             // is clobbered. To avoid that, we notify all views immediately of the
737             // modified state, apply the modification, then save the document.
738             ScInputHandler* pHdl = GetInputHandler();
739             if (pHdl != nullptr && pHdl->GetModified())
740                 SfxLokHelper::notifyAllViews(LOK_CALLBACK_STATE_CHANGED, ".uno:ModifiedStatus=true");
741         }
742 
743         SC_MOD()->InputEnterHandler();
744     }
745 
746     if ( GetViewData().GetDocShell()->IsDocShared() )
747     {
748         GetViewData().GetDocShell()->SetDocumentModified();
749     }
750 
751     // otherwise as normal
752     GetViewData().GetDocShell()->ExecuteSlot( rReq );
753 }
754 
GetSaveState(SfxItemSet & rSet)755 void ScTabViewShell::GetSaveState( SfxItemSet& rSet )
756 {
757     SfxShell* pDocSh = GetViewData().GetDocShell();
758 
759     SfxWhichIter aIter(rSet);
760     sal_uInt16 nWhich = aIter.FirstWhich();
761     while( nWhich )
762     {
763         if ( nWhich != SID_SAVEDOC || !GetViewData().GetDocShell()->IsDocShared() )
764         {
765             // get state from DocShell
766             pDocSh->GetSlotState( nWhich, nullptr, &rSet );
767         }
768         nWhich = aIter.NextWhich();
769     }
770 }
771 
ExecDrawOpt(const SfxRequest & rReq)772 void ScTabViewShell::ExecDrawOpt( const SfxRequest& rReq )
773 {
774     ScViewOptions aViewOptions = GetViewData().GetOptions();
775     ScGridOptions aGridOptions = aViewOptions.GetGridOptions();
776 
777     SfxBindings& rBindings = GetViewFrame()->GetBindings();
778     const SfxItemSet* pArgs = rReq.GetArgs();
779     const SfxPoolItem* pItem;
780     sal_uInt16 nSlotId = rReq.GetSlot();
781     switch (nSlotId)
782     {
783         case SID_GRID_VISIBLE:
784             if ( pArgs && pArgs->GetItemState(nSlotId,true,&pItem) == SfxItemState::SET )
785             {
786                 aGridOptions.SetGridVisible( static_cast<const SfxBoolItem*>(pItem)->GetValue() );
787                 aViewOptions.SetGridOptions(aGridOptions);
788                 rBindings.Invalidate(SID_GRID_VISIBLE);
789             }
790             break;
791 
792         case SID_GRID_USE:
793             if ( pArgs && pArgs->GetItemState(nSlotId,true,&pItem) == SfxItemState::SET )
794             {
795                 aGridOptions.SetUseGridSnap( static_cast<const SfxBoolItem*>(pItem)->GetValue() );
796                 aViewOptions.SetGridOptions(aGridOptions);
797                 rBindings.Invalidate(SID_GRID_USE);
798             }
799             break;
800 
801         case SID_HELPLINES_MOVE:
802             if ( pArgs && pArgs->GetItemState(nSlotId,true,&pItem) == SfxItemState::SET )
803             {
804                 aViewOptions.SetOption( VOPT_HELPLINES, static_cast<const SfxBoolItem*>(pItem)->GetValue() );
805                 rBindings.Invalidate(SID_HELPLINES_MOVE);
806             }
807             break;
808     }
809 
810     GetViewData().SetOptions(aViewOptions);
811 }
812 
GetDrawOptState(SfxItemSet & rSet)813 void ScTabViewShell::GetDrawOptState( SfxItemSet& rSet )
814 {
815     SfxBoolItem aBool;
816 
817     const ScViewOptions& rViewOptions = GetViewData().GetOptions();
818     const ScGridOptions& rGridOptions = rViewOptions.GetGridOptions();
819 
820     aBool.SetValue(rGridOptions.GetGridVisible());
821     aBool.SetWhich( SID_GRID_VISIBLE );
822     rSet.Put( aBool );
823 
824     aBool.SetValue(rGridOptions.GetUseGridSnap());
825     aBool.SetWhich( SID_GRID_USE );
826     rSet.Put( aBool );
827 
828     aBool.SetValue(rViewOptions.GetOption( VOPT_HELPLINES ));
829     aBool.SetWhich( SID_HELPLINES_MOVE );
830     rSet.Put( aBool );
831 }
832 
833 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
834