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