xref: /core/sc/source/ui/view/tabvwsha.cxx (revision 20b8c7f3)
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 <o3tl/temporary.hxx>
25 #include <sfx2/bindings.hxx>
26 #include <sfx2/request.hxx>
27 #include <sfx2/sfxdlg.hxx>
28 #include <sfx2/sidebar/Sidebar.hxx>
29 #include <sfx2/viewfrm.hxx>
30 #include <svl/ilstitem.hxx>
31 #include <svl/numformat.hxx>
32 #include <svl/zformat.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 
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 & (1U << 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         TranslateId pGlobStrId;
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& rDoc        = 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 ( rDoc.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 = rDoc.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                         nNumFmt = rDoc.GetNumberFormat( nPosX, nPosY, nTab );
131                         // If the number format is time (without date) and the
132                         // result is not within 24 hours, use a duration
133                         // format. Summing date+time doesn't make much sense
134                         // otherwise but we also don't want to display duration
135                         // for a single date+time value.
136                         if (nVal < 0.0 || nVal >= 1.0)
137                         {
138                             const SvNumberformat* pFormat = pFormatter->GetEntry(nNumFmt);
139                             if (pFormat && (pFormat->GetType() == SvNumFormatType::TIME))
140                                 nNumFmt = pFormatter->GetTimeFormat( nVal, pFormat->GetLanguage(), true);
141                         }
142                     }
143 
144                     OUString aValStr;
145                     const Color* pDummy;
146                     pFormatter->GetOutputString( nVal, nNumFmt, aValStr, &pDummy );
147                     aStr += aValStr;
148                 }
149             }
150             if ( bFirst )
151             {
152                 rFuncStr += aStr;
153                 bFirst = false;
154             }
155             else
156                 rFuncStr += "; " + aStr;
157         }
158     }
159 
160     return !rFuncStr.isEmpty();
161 }
162 
163 //  Functions that are disabled, depending on the selection
164 //  Default:
165 //      SID_DELETE,
166 //      SID_DELETE_CONTENTS,
167 //      FID_DELETE_CELL
168 //      FID_VALIDATION
169 
170 void ScTabViewShell::GetState( SfxItemSet& rSet )
171 {
172     ScViewData& rViewData   = GetViewData();
173     ScDocument& rDoc        = rViewData.GetDocument();
174     ScDocShell* pDocShell   = rViewData.GetDocShell();
175     ScMarkData& rMark       = rViewData.GetMarkData();
176     SCCOL       nPosX       = rViewData.GetCurX();
177     SCROW       nPosY       = rViewData.GetCurY();
178     SCTAB       nTab        = rViewData.GetTabNo();
179 
180     SfxViewFrame* pThisFrame = GetViewFrame();
181     bool bOle = GetViewFrame()->GetFrame().IsInPlace();
182 
183     SCTAB nTabSelCount = rMark.GetSelectCount();
184 
185     SfxWhichIter    aIter(rSet);
186     sal_uInt16          nWhich = aIter.FirstWhich();
187 
188     while ( nWhich )
189     {
190         switch ( nWhich )
191         {
192             case FID_CHG_COMMENT:
193                 {
194                     ScDocShell* pDocSh = GetViewData().GetDocShell();
195                     ScAddress aPos( nPosX, nPosY, nTab );
196                     if ( pDocSh->IsReadOnly() || !pDocSh->GetChangeAction(aPos) || pDocSh->IsDocShared() )
197                         rSet.DisableItem( nWhich );
198                 }
199                 break;
200 
201             case SID_OPENDLG_EDIT_PRINTAREA:
202             case SID_ADD_PRINTAREA:
203             case SID_DEFINE_PRINTAREA:
204                 {
205                     if ( pDocShell && pDocShell->IsDocShared() )
206                     {
207                         rSet.DisableItem( nWhich );
208                     }
209                 }
210                 break;
211 
212             case SID_DELETE_PRINTAREA:
213                 if ( pDocShell && pDocShell->IsDocShared() )
214                 {
215                     rSet.DisableItem( nWhich );
216                 }
217                 else if (rDoc.IsPrintEntireSheet(nTab))
218                     rSet.DisableItem(nWhich);
219                 break;
220 
221             case SID_STATUS_PAGESTYLE:
222             case SID_HFEDIT:
223                 GetViewData().GetDocShell()->GetStatePageStyle( rSet, nTab );
224                 break;
225 
226             case SID_SEARCH_ITEM:
227             {
228                 SvxSearchItem aItem(ScGlobal::GetSearchItem()); // make a copy.
229                 // Search on current selection if a range is marked.
230                 aItem.SetSelection(rMark.IsMarked());
231                 rSet.Put(aItem);
232                 break;
233             }
234 
235             case SID_SEARCH_OPTIONS:
236                 {
237                     // Anything goes
238                     SearchOptionFlags nOptions = SearchOptionFlags::ALL;
239 
240                     // No replacement if ReadOnly
241                     if (GetViewData().GetDocShell()->IsReadOnly())
242                         nOptions &= ~SearchOptionFlags( SearchOptionFlags::REPLACE | SearchOptionFlags::REPLACE_ALL );
243                     rSet.Put( SfxUInt16Item( nWhich, static_cast<sal_uInt16>(nOptions) ) );
244                 }
245                 break;
246 
247             case SID_CURRENTCELL:
248                 {
249                     ScAddress aScAddress( GetViewData().GetCurX(), GetViewData().GetCurY(), 0 );
250                     OUString  aAddr(aScAddress.Format(ScRefFlags::ADDR_ABS, nullptr, rDoc.GetAddressConvention()));
251                     SfxStringItem   aPosItem( SID_CURRENTCELL, aAddr );
252 
253                     rSet.Put( aPosItem );
254                 }
255                 break;
256 
257             case SID_CURRENTTAB:
258                 // Table for Basic is 1-based
259                 rSet.Put( SfxUInt16Item( nWhich, static_cast<sal_uInt16>(GetViewData().GetTabNo()) + 1 ) );
260                 break;
261 
262             case SID_CURRENTDOC:
263                 rSet.Put( SfxStringItem( nWhich, GetViewData().GetDocShell()->GetTitle() ) );
264                 break;
265 
266             case FID_TOGGLEINPUTLINE:
267                 {
268                     sal_uInt16 nId = ScInputWindowWrapper::GetChildWindowId();
269 
270                     if ( pThisFrame->KnowsChildWindow( nId ) )
271                     {
272                         SfxChildWindow* pWnd = pThisFrame->GetChildWindow( nId );
273                         rSet.Put( SfxBoolItem( nWhich, pWnd != nullptr ) );
274                     }
275                     else
276                         rSet.DisableItem( nWhich );
277                 }
278                 break;
279 
280             case FID_DEL_MANUALBREAKS:
281                 if (!rDoc.HasManualBreaks(nTab))
282                     rSet.DisableItem( nWhich );
283                 break;
284 
285             case FID_RESET_PRINTZOOM:
286                 {
287                     // disable if already set to default
288 
289                     OUString aStyleName = rDoc.GetPageStyle( nTab );
290                     ScStyleSheetPool* pStylePool = rDoc.GetStyleSheetPool();
291                     SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName,
292                                                     SfxStyleFamily::Page );
293                     OSL_ENSURE( pStyleSheet, "PageStyle not found" );
294                     if ( pStyleSheet )
295                     {
296                         SfxItemSet& rStyleSet = pStyleSheet->GetItemSet();
297                         sal_uInt16 nScale = rStyleSet.Get(ATTR_PAGE_SCALE).GetValue();
298                         sal_uInt16 nPages = rStyleSet.Get(ATTR_PAGE_SCALETOPAGES).GetValue();
299                         if ( nScale == 100 && nPages == 0 )
300                             rSet.DisableItem( nWhich );
301                     }
302                 }
303                 break;
304 
305             case SID_ZOOM_IN:
306                 {
307                     const Fraction& rZoomY = GetViewData().GetZoomY();
308                     tools::Long nZoom = tools::Long(rZoomY * 100);
309                     if (nZoom >= tools::Long(MAXZOOM))
310                         rSet.DisableItem(nWhich);
311                 }
312                 break;
313             case SID_ZOOM_OUT:
314                 {
315                     const Fraction& rZoomY = GetViewData().GetZoomY();
316                     tools::Long nZoom = tools::Long(rZoomY * 100);
317                     if (nZoom <= tools::Long(MINZOOM))
318                         rSet.DisableItem(nWhich);
319                 }
320                 break;
321 
322             case FID_SCALE:
323             case SID_ATTR_ZOOM:
324                 if ( bOle )
325                     rSet.DisableItem( nWhich );
326                 else
327                 {
328                     const Fraction& rOldY = GetViewData().GetZoomY();
329                     sal_uInt16 nZoom = static_cast<sal_uInt16>(tools::Long( rOldY * 100 ));
330                     rSet.Put( SvxZoomItem( SvxZoomType::PERCENT, nZoom, nWhich ) );
331                 }
332                 break;
333 
334             case SID_ATTR_ZOOMSLIDER:
335                 {
336                     if ( bOle )
337                         rSet.DisableItem( nWhich );
338                     else
339                     {
340                         const Fraction& rOldY = GetViewData().GetZoomY();
341                         sal_uInt16 nCurrentZoom = static_cast<sal_uInt16>(tools::Long( rOldY * 100 ));
342 
343                         if( nCurrentZoom )
344                         {
345                             SvxZoomSliderItem aZoomSliderItem( nCurrentZoom, MINZOOM, MAXZOOM, SID_ATTR_ZOOMSLIDER );
346                             aZoomSliderItem.AddSnappingPoint( 100 );
347                             rSet.Put( aZoomSliderItem );
348                         }
349                     }
350                 }
351                 break;
352 
353             case FID_FUNCTION_BOX:
354             {
355                 const bool bBoxOpen = ::sfx2::sidebar::Sidebar::IsPanelVisible(u"ScFunctionsPanel",
356                                                     pThisFrame->GetFrame().GetFrameInterface());
357                 rSet.Put(SfxBoolItem(nWhich, bBoxOpen));
358                 break;
359             }
360 
361             case FID_TOGGLESYNTAX:
362                 rSet.Put(SfxBoolItem(nWhich, GetViewData().IsSyntaxMode()));
363                 break;
364 
365             case FID_TOGGLEHEADERS:
366                 rSet.Put(SfxBoolItem(nWhich, GetViewData().IsHeaderMode()));
367                 break;
368 
369             case FID_TOGGLEFORMULA:
370                 {
371                     const ScViewOptions& rOpts = rViewData.GetOptions();
372                     bool bFormulaMode = rOpts.GetOption( VOPT_FORMULAS );
373                     rSet.Put(SfxBoolItem(nWhich, bFormulaMode ));
374                 }
375                 break;
376 
377             case FID_NORMALVIEWMODE:
378             case FID_PAGEBREAKMODE:
379                 // always handle both slots - they exclude each other
380                 if ( bOle )
381                 {
382                     rSet.DisableItem( FID_NORMALVIEWMODE );
383                     rSet.DisableItem( FID_PAGEBREAKMODE );
384                 }
385                 else
386                 {
387                     rSet.Put(SfxBoolItem(FID_NORMALVIEWMODE, !GetViewData().IsPagebreakMode()));
388                     rSet.Put(SfxBoolItem(FID_PAGEBREAKMODE, GetViewData().IsPagebreakMode()));
389                 }
390                 break;
391 
392             case FID_PROTECT_DOC:
393                 {
394                     if ( pDocShell && pDocShell->IsDocShared() )
395                     {
396                         rSet.DisableItem( nWhich );
397                     }
398                     else
399                     {
400                         rSet.Put( SfxBoolItem( nWhich, rDoc.IsDocProtected() ) );
401                     }
402                 }
403                 break;
404 
405             case FID_PROTECT_TABLE:
406                 {
407                     if ( pDocShell && pDocShell->IsDocShared() )
408                     {
409                         rSet.DisableItem( nWhich );
410                     }
411                     else
412                     {
413                         rSet.Put( SfxBoolItem( nWhich, rDoc.IsTabProtected( nTab ) ) );
414                     }
415                 }
416                 break;
417 
418             case SID_AUTO_OUTLINE:
419                 {
420                     if (rDoc.GetChangeTrack()!=nullptr || GetViewData().IsMultiMarked())
421                     {
422                         rSet.DisableItem( nWhich );
423                     }
424                 }
425                 break;
426 
427             case SID_OUTLINE_DELETEALL:
428                 {
429                     SCTAB nOlTab = GetViewData().GetTabNo();
430                     ScOutlineTable* pOlTable = rDoc.GetOutlineTable( nOlTab );
431                     if (pOlTable == nullptr)
432                         rSet.DisableItem( nWhich );
433                 }
434                 break;
435 
436             case SID_WINDOW_SPLIT:
437                 rSet.Put(SfxBoolItem(nWhich,
438                             rViewData.GetHSplitMode() == SC_SPLIT_NORMAL ||
439                             rViewData.GetVSplitMode() == SC_SPLIT_NORMAL ));
440                 break;
441 
442             case SID_WINDOW_FIX:
443                 if(!comphelper::LibreOfficeKit::isActive())
444                 {
445                     rSet.Put(SfxBoolItem(nWhich,
446                                 rViewData.GetHSplitMode() == SC_SPLIT_FIX ||
447                                 rViewData.GetVSplitMode() == SC_SPLIT_FIX ));
448                 }
449                 else
450                 {
451                     rSet.Put(SfxBoolItem(nWhich,
452                             rViewData.GetLOKSheetFreezeIndex(true) > 0 ||
453                             rViewData.GetLOKSheetFreezeIndex(false) > 0 ));
454                 }
455                 break;
456 
457             case SID_WINDOW_FIX_COL:
458             case SID_WINDOW_FIX_ROW:
459                 {
460                     bool bIsCol = (nWhich == SID_WINDOW_FIX_COL);
461                     sal_Int32 nFreezeIndex = rViewData.GetLOKSheetFreezeIndex(bIsCol);
462                     rSet.Put(SfxInt32Item(nWhich, nFreezeIndex));
463                 }
464                 break;
465 
466             case FID_CHG_SHOW:
467                 {
468                     if ( rDoc.GetChangeTrack() == nullptr || ( pDocShell && pDocShell->IsDocShared() ) )
469                         rSet.DisableItem( nWhich );
470                 }
471                 break;
472             case FID_CHG_ACCEPT:
473                 {
474                     if(
475                        ( !rDoc.GetChangeTrack() &&  !pThisFrame->HasChildWindow(FID_CHG_ACCEPT) )
476                        ||
477                        ( pDocShell && pDocShell->IsDocShared() )
478                       )
479                     {
480                         rSet.DisableItem( nWhich);
481                     }
482                     else
483                     {
484                         rSet.Put(SfxBoolItem(FID_CHG_ACCEPT,
485                             pThisFrame->HasChildWindow(FID_CHG_ACCEPT)));
486                     }
487                 }
488                 break;
489 
490             case SID_FORMATPAGE:
491                 // in protected tables
492                 if ( pDocShell && ( pDocShell->IsReadOnly() || pDocShell->IsDocShared() ) )
493                     rSet.DisableItem( nWhich );
494                 break;
495 
496             case SID_PRINTPREVIEW:
497                 // Toggle slot needs a State
498                 rSet.Put( SfxBoolItem( nWhich, false ) );
499                 break;
500 
501             case SID_READONLY_MODE:
502                 rSet.Put( SfxBoolItem( nWhich, GetViewData().GetDocShell()->IsReadOnly() ) );
503                 break;
504 
505             case FID_TAB_DESELECTALL:
506                 if ( nTabSelCount == 1 )
507                     rSet.DisableItem( nWhich );     // enabled only if several sheets are selected
508                 break;
509 
510             case FID_TOGGLEHIDDENCOLROW:
511                 const svtools::ColorConfig& rColorCfg = SC_MOD()->GetColorConfig();
512                 rSet.Put( SfxBoolItem( nWhich, rColorCfg.GetColorValue(svtools::CALCHIDDENROWCOL).bIsVisible) );
513                 break;
514 
515         } // switch ( nWitch )
516         nWhich = aIter.NextWhich();
517     } // while ( nWitch )
518 }
519 
520 void ScTabViewShell::ExecuteCellFormatDlg(SfxRequest& rReq, const OString &rName)
521 {
522     ScDocument& rDoc = GetViewData().GetDocument();
523 
524     std::shared_ptr<SvxBoxItem> aLineOuter(std::make_shared<SvxBoxItem>(ATTR_BORDER));
525     std::shared_ptr<SvxBoxInfoItem> aLineInner(std::make_shared<SvxBoxInfoItem>(ATTR_BORDER_INNER));
526 
527     const ScPatternAttr*    pOldAttrs       = GetSelectionPattern();
528 
529     auto pOldSet = std::make_shared<SfxItemSet>(pOldAttrs->GetItemSet());
530 
531     pOldSet->MergeRange(XATTR_FILLSTYLE, XATTR_FILLCOLOR);
532 
533     pOldSet->MergeRange(SID_ATTR_BORDER_STYLES, SID_ATTR_BORDER_DEFAULT_WIDTH);
534 
535     // We only allow these border line types.
536     std::vector<sal_Int32> aBorderStyles{
537         table::BorderLineStyle::SOLID,
538         table::BorderLineStyle::DOTTED,
539         table::BorderLineStyle::DASHED,
540         table::BorderLineStyle::FINE_DASHED,
541         table::BorderLineStyle::DASH_DOT,
542         table::BorderLineStyle::DASH_DOT_DOT,
543         table::BorderLineStyle::DOUBLE_THIN };
544 
545     pOldSet->Put(SfxIntegerListItem(SID_ATTR_BORDER_STYLES, std::move(aBorderStyles)));
546 
547     // Set the default border width to 0.75 points.
548     SfxInt64Item aBorderWidthItem(SID_ATTR_BORDER_DEFAULT_WIDTH, 75);
549     pOldSet->Put(aBorderWidthItem);
550 
551     // Get border items and put them in the set:
552     GetSelectionFrame( aLineOuter, aLineInner );
553 
554     //Fix border incorrect for RTL fdo#62399
555     if( rDoc.IsLayoutRTL( GetViewData().GetTabNo() ) )
556     {
557         std::unique_ptr<SvxBoxItem> aNewFrame(aLineOuter->Clone());
558         std::unique_ptr<SvxBoxInfoItem> aTempInfo(aLineInner->Clone());
559 
560         if ( aLineInner->IsValid(SvxBoxInfoItemValidFlags::LEFT) )
561             aNewFrame->SetLine( aLineOuter->GetLeft(), SvxBoxItemLine::RIGHT );
562         if ( aLineInner->IsValid(SvxBoxInfoItemValidFlags::RIGHT) )
563             aNewFrame->SetLine( aLineOuter->GetRight(), SvxBoxItemLine::LEFT );
564 
565         aLineInner->SetValid( SvxBoxInfoItemValidFlags::LEFT, aTempInfo->IsValid(SvxBoxInfoItemValidFlags::RIGHT));
566         aLineInner->SetValid( SvxBoxInfoItemValidFlags::RIGHT, aTempInfo->IsValid(SvxBoxInfoItemValidFlags::LEFT));
567 
568         pOldSet->Put( std::move(aNewFrame) );
569     }
570     else
571     {
572         pOldSet->Put( *aLineOuter );
573     }
574 
575     pOldSet->Put( *aLineInner );
576 
577     // Generate NumberFormat Value from Value and Language and box it.
578     pOldSet->Put( SfxUInt32Item( ATTR_VALUE_FORMAT,
579         pOldAttrs->GetNumberFormat( rDoc.GetFormatTable() ) ) );
580 
581     std::unique_ptr<SvxNumberInfoItem> pNumberInfoItem = MakeNumberInfoItem(rDoc, GetViewData());
582     pOldSet->MergeRange( SID_ATTR_NUMBERFORMAT_INFO, SID_ATTR_NUMBERFORMAT_INFO );
583     pOldSet->Put( std::move(pNumberInfoItem) );
584 
585     bInFormatDialog = true;
586     ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
587 
588     VclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateScAttrDlg(GetFrameWeld(), pOldSet.get()));
589 
590     if (!rName.isEmpty())
591         pDlg->SetCurPageId(rName);
592 
593     auto pRequest = std::make_shared<SfxRequest>(rReq);
594     rReq.Ignore(); // the 'old' request is not relevant any more
595 
596     pDlg->StartExecuteAsync([pDlg, pOldSet, pRequest, this](sal_Int32 nResult){
597         bInFormatDialog = false;
598 
599         if ( nResult == RET_OK )
600         {
601             const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
602             if(const SvxNumberInfoItem* pItem = pOutSet->GetItemIfSet(SID_ATTR_NUMBERFORMAT_INFO))
603             {
604                 UpdateNumberFormatter(*pItem);
605             }
606 
607             ApplyAttributes(pOutSet, pOldSet.get());
608 
609             pRequest->Done(*pOutSet);
610         }
611 
612         pDlg->disposeOnce();
613     });
614 }
615 
616 bool ScTabViewShell::IsRefInputMode() const
617 {
618     ScModule* pScMod = SC_MOD();
619     if ( pScMod )
620     {
621         if( pScMod->IsRefDialogOpen() )
622             return pScMod->IsFormulaMode();
623         if( pScMod->IsFormulaMode() )
624         {
625             ScInputHandler* pHdl = pScMod->GetInputHdl();
626             if ( pHdl )
627             {
628                 OUString aString = pHdl->GetEditString();
629                 if ( !pHdl->GetSelIsRef() && aString.getLength() > 1 &&
630                      ( aString[0] == '+' || aString[0] == '-' ) )
631                 {
632                     const ScViewData& rViewData = GetViewData();
633                     ScDocument& rDoc = rViewData.GetDocument();
634                     const ScAddress aPos( rViewData.GetCurPos() );
635                     ScCompiler aComp( rDoc, aPos, rDoc.GetGrammar() );
636                     aComp.SetCloseBrackets( false );
637                     std::unique_ptr<ScTokenArray> pArr(aComp.CompileString(aString));
638                     if ( pArr && pArr->MayReferenceFollow() )
639                     {
640                         return true;
641                     }
642                 }
643                 else
644                 {
645                     return true;
646                 }
647             }
648         }
649     }
650 
651     return false;
652 }
653 
654 void ScTabViewShell::ExecuteInputDirect()
655 {
656     if ( !IsRefInputMode() )
657     {
658         ScModule* pScMod = SC_MOD();
659         if ( pScMod )
660         {
661             pScMod->InputEnterHandler();
662         }
663     }
664 }
665 
666 void ScTabViewShell::UpdateInputHandler( bool bForce /* = sal_False */, bool bStopEditing /* = sal_True */ )
667 {
668     ScInputHandler* pHdl = mpInputHandler ? mpInputHandler.get() : SC_MOD()->GetInputHdl();
669 
670     if ( pHdl )
671     {
672         OUString                aString;
673         const EditTextObject*   pObject     = nullptr;
674         ScViewData&             rViewData   = GetViewData();
675         ScDocument&             rDoc        = rViewData.GetDocument();
676         SCCOL                   nPosX       = rViewData.GetCurX();
677         SCROW                   nPosY       = rViewData.GetCurY();
678         SCTAB                   nTab        = rViewData.GetTabNo();
679         SCTAB                   nStartTab   = 0;
680         SCTAB                   nEndTab     = 0;
681         SCCOL                   nStartCol   = 0;
682         SCROW                   nStartRow   = 0;
683         SCCOL                   nEndCol     = 0;
684         SCROW                   nEndRow     = 0;
685         ScAddress aPos = rViewData.GetCurPos();
686 
687         rViewData.GetSimpleArea( nStartCol, nStartRow, nStartTab,
688                                   nEndCol,   nEndRow,   nEndTab );
689 
690         PutInOrder( nStartCol, nEndCol );
691         PutInOrder( nStartRow, nEndRow );
692         PutInOrder( nStartTab, nEndTab );
693 
694         bool bHideFormula = false;
695         bool bHideAll     = false;
696 
697         if (rDoc.IsTabProtected(nTab))
698         {
699             const ScProtectionAttr* pProt = rDoc.GetAttr( nPosX,nPosY,nTab,
700                                                            ATTR_PROTECTION);
701             bHideFormula = pProt->GetHideFormula();
702             bHideAll     = pProt->GetHideCell();
703         }
704 
705         if (!bHideAll)
706         {
707             ScRefCellValue rCell(rDoc, aPos);
708             if (rCell.getType() == CELLTYPE_FORMULA)
709             {
710                 if (!bHideFormula)
711                     aString = rCell.getFormula()->GetFormula();
712             }
713             else if (rCell.getType() == CELLTYPE_EDIT)
714             {
715                 pObject = rCell.getEditText();
716             }
717             else
718             {
719                 SvNumberFormatter* pFormatter = rDoc.GetFormatTable();
720                 sal_uInt32 nNumFmt = rDoc.GetNumberFormat( aPos );
721 
722                 aString = ScCellFormat::GetInputString( rCell, nNumFmt, *pFormatter, rDoc );
723                 if (rCell.getType() == CELLTYPE_STRING)
724                 {
725                     // Put a ' in front if necessary, so that the string is not
726                     // unintentionally interpreted as a number, and to show the
727                     // user that it is a string (#35060#).
728                     //! also for numberformat "Text"? -> then remove when editing
729                     if ( pFormatter->IsNumberFormat(aString, nNumFmt, o3tl::temporary(double())) )
730                         aString = "'" + aString;
731                 }
732             }
733         }
734 
735         ScInputHdlState aState( ScAddress( nPosX,     nPosY,     nTab ),
736                                 ScAddress( nStartCol, nStartRow, nTab ),
737                                 ScAddress( nEndCol,   nEndRow,   nTab ),
738                                 aString,
739                                 pObject );
740 
741         //  if using the view's local input handler, this view can always be set
742         //  as current view inside NotifyChange.
743         ScTabViewShell* pSourceSh = mpInputHandler ? this : nullptr;
744 
745         pHdl->NotifyChange( &aState, bForce, pSourceSh, bStopEditing );
746     }
747 
748     SfxBindings& rBindings = GetViewFrame()->GetBindings();
749     rBindings.Invalidate( SID_STATUS_SUM );         // always together with the input row
750     rBindings.Invalidate( SID_ATTR_SIZE );
751     rBindings.Invalidate( SID_TABLE_CELL );
752 }
753 
754 void ScTabViewShell::UpdateInputHandlerCellAdjust( SvxCellHorJustify eJust )
755 {
756     if( ScInputHandler* pHdl = mpInputHandler ? mpInputHandler.get() : SC_MOD()->GetInputHdl() )
757         pHdl->UpdateCellAdjust( eJust );
758 }
759 
760 void ScTabViewShell::ExecuteSave( SfxRequest& rReq )
761 {
762     // only SID_SAVEDOC / SID_SAVEASDOC
763     bool bCommitChanges = true;
764     const SfxItemSet* pReqArgs = rReq.GetArgs();
765     const SfxPoolItem* pItem;
766 
767     if (pReqArgs && pReqArgs->HasItem(FN_PARAM_1, &pItem))
768         bCommitChanges = !static_cast<const SfxBoolItem*>(pItem)->GetValue();
769 
770     // Finish entering unless 'DontTerminateEdit' is specified, even if a formula is being processed
771     if (bCommitChanges)
772     {
773         bool bLOKActive = comphelper::LibreOfficeKit::isActive();
774 
775         // Disable error dialog box when about to save in lok mode as
776         // this ultimately invokes SvpSalInstance::DoYield() when we want
777         // to save immediately without committing any erroneous input in possibly
778         // a cell with validation rules. After save is complete the user
779         // can continue editing.
780         SC_MOD()->InputEnterHandler(ScEnterMode::NORMAL, bLOKActive /* bBeforeSavingInLOK */);
781 
782         if (bLOKActive)
783         {
784             // Normally this isn't needed, but in Calc when editing a cell formula
785             // and manually saving (without changing cells or hitting enter), while
786             // InputEnterHandler will mark the doc as modified (when it is), because
787             // we will save the doc immediately afterwards, the modified state event
788             // is clobbered. To avoid that, we need to update SID_DOC_MODIFIED so that
789             // a possible state of "true" after "InputEnterHandler" will be sent
790             // as a notification. It is important that the notification goes through
791             // normal process (cache) rather than directly notifying the views.
792             // Otherwise, because there is a previous state of "false" in cache, the
793             // "false" state after saving will be ignored.
794             // This will work only if .uno:ModifiedStatus message will be removed from
795             // the mechanism that keeps in the message queue only last message of
796             // a particular status even if the values are different.
797             GetViewData().GetDocShell()->GetViewBindings()->Update(SID_DOC_MODIFIED);
798         }
799     }
800 
801     if ( GetViewData().GetDocShell()->IsDocShared() )
802     {
803         GetViewData().GetDocShell()->SetDocumentModified();
804     }
805 
806     // otherwise as normal
807     GetViewData().GetDocShell()->ExecuteSlot( rReq );
808 }
809 
810 void ScTabViewShell::GetSaveState( SfxItemSet& rSet )
811 {
812     SfxShell* pDocSh = GetViewData().GetDocShell();
813 
814     SfxWhichIter aIter(rSet);
815     sal_uInt16 nWhich = aIter.FirstWhich();
816     while( nWhich )
817     {
818         if ( nWhich != SID_SAVEDOC || !GetViewData().GetDocShell()->IsDocShared() )
819         {
820             // get state from DocShell
821             pDocSh->GetSlotState( nWhich, nullptr, &rSet );
822         }
823         nWhich = aIter.NextWhich();
824     }
825 }
826 
827 void ScTabViewShell::ExecDrawOpt( const SfxRequest& rReq )
828 {
829     ScViewOptions aViewOptions = GetViewData().GetOptions();
830     ScGridOptions aGridOptions = aViewOptions.GetGridOptions();
831 
832     SfxBindings& rBindings = GetViewFrame()->GetBindings();
833     const SfxItemSet* pArgs = rReq.GetArgs();
834     const SfxPoolItem* pItem;
835     sal_uInt16 nSlotId = rReq.GetSlot();
836     switch (nSlotId)
837     {
838         case SID_GRID_VISIBLE:
839             if ( pArgs && pArgs->GetItemState(nSlotId,true,&pItem) == SfxItemState::SET )
840             {
841                 aGridOptions.SetGridVisible( static_cast<const SfxBoolItem*>(pItem)->GetValue() );
842                 aViewOptions.SetGridOptions(aGridOptions);
843                 rBindings.Invalidate(SID_GRID_VISIBLE);
844             }
845             break;
846 
847         case SID_GRID_USE:
848             if ( pArgs && pArgs->GetItemState(nSlotId,true,&pItem) == SfxItemState::SET )
849             {
850                 aGridOptions.SetUseGridSnap( static_cast<const SfxBoolItem*>(pItem)->GetValue() );
851                 aViewOptions.SetGridOptions(aGridOptions);
852                 rBindings.Invalidate(SID_GRID_USE);
853             }
854             break;
855 
856         case SID_HELPLINES_MOVE:
857             if ( pArgs && pArgs->GetItemState(nSlotId,true,&pItem) == SfxItemState::SET )
858             {
859                 aViewOptions.SetOption( VOPT_HELPLINES, static_cast<const SfxBoolItem*>(pItem)->GetValue() );
860                 rBindings.Invalidate(SID_HELPLINES_MOVE);
861             }
862             break;
863     }
864 
865     GetViewData().SetOptions(aViewOptions);
866 }
867 
868 void ScTabViewShell::GetDrawOptState( SfxItemSet& rSet )
869 {
870     SfxBoolItem aBool;
871 
872     const ScViewOptions& rViewOptions = GetViewData().GetOptions();
873     const ScGridOptions& rGridOptions = rViewOptions.GetGridOptions();
874 
875     aBool.SetValue(rGridOptions.GetGridVisible());
876     aBool.SetWhich( SID_GRID_VISIBLE );
877     rSet.Put( aBool );
878 
879     aBool.SetValue(rGridOptions.GetUseGridSnap());
880     aBool.SetWhich( SID_GRID_USE );
881     rSet.Put( aBool );
882 
883     aBool.SetValue(rViewOptions.GetOption( VOPT_HELPLINES ));
884     aBool.SetWhich( SID_HELPLINES_MOVE );
885     rSet.Put( aBool );
886 }
887 
888 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
889