xref: /core/sc/source/ui/view/cellsh3.cxx (revision ad07f4df8cc992df4f523e6b60540688d44431a9)
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 <scitems.hxx>
21 #include <editeng/editview.hxx>
22 #include <editeng/editeng.hxx>
23 #include <formula/formulahelper.hxx>
24 #include <sfx2/viewfrm.hxx>
25 #include <sfx2/bindings.hxx>
26 #include <sfx2/dispatch.hxx>
27 #include <sfx2/request.hxx>
28 #include <svl/stritem.hxx>
29 #include <vcl/svapp.hxx>
30 #include <vcl/weld.hxx>
31 #include <globstr.hrc>
32 #include <scresid.hxx>
33 #include <scmod.hxx>
34 #include <appoptio.hxx>
35 #include <tabvwsh.hxx>
36 #include <document.hxx>
37 #include <sc.hrc>
38 #include <reffact.hxx>
39 #include <uiitems.hxx>
40 #include <autoform.hxx>
41 #include <cellsh.hxx>
42 #include <inputhdl.hxx>
43 #include <inputopt.hxx>
44 #include <editable.hxx>
45 #include <funcdesc.hxx>
46 #include <markdata.hxx>
47 #include <scabstdlg.hxx>
48 #include <columnspanset.hxx>
49 #include <comphelper/lok.hxx>
50 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
51 #include <inputwin.hxx>
52 #include <officecfg/Office/Calc.hxx>
53 
54 #include <memory>
55 
56 using sc::TwipsToEvenHMM;
57 
58 namespace
59 {
60 /// Rid ourselves of unwanted " quoted json characters.
escapeJSON(const OUString & aStr)61 OString escapeJSON(const OUString &aStr)
62 {
63     OUString aEscaped = aStr;
64     aEscaped = aEscaped.replaceAll("\n", " ");
65     aEscaped = aEscaped.replaceAll("\"", "'");
66     return OUStringToOString(aEscaped, RTL_TEXTENCODING_UTF8);
67 }
68 
lcl_lokGetWholeFunctionList()69 void lcl_lokGetWholeFunctionList()
70 {
71     const SfxViewShell* pViewShell = SfxViewShell::Current();
72     if (!(comphelper::LibreOfficeKit::isActive()
73         && pViewShell && pViewShell->isLOKMobilePhone()))
74         return;
75 
76     const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList();
77     sal_uInt32 nListCount = pFuncList->GetCount();
78     std::set<OUString> aFuncNameOrderedSet;
79     for(sal_uInt32 i = 0; i < nListCount; ++i)
80     {
81         const ScFuncDesc* pDesc = pFuncList->GetFunction( i );
82         if ( pDesc->mxFuncName )
83         {
84             aFuncNameOrderedSet.insert(*pDesc->mxFuncName);
85         }
86     }
87     ScFunctionMgr* pFuncManager = ScGlobal::GetStarCalcFunctionMgr();
88     if (!(pFuncManager && aFuncNameOrderedSet.size()))
89         return;
90 
91     OStringBuffer aPayload(
92         "{ \"wholeList\": true, "
93         "\"categories\": [ ");
94 
95     formula::FormulaHelper aHelper(pFuncManager);
96     sal_uInt32 nCategoryCount = pFuncManager->getCount();
97     for (sal_uInt32 i = 0; i < nCategoryCount; ++i)
98     {
99         OUString sCategoryName = ScFunctionMgr::GetCategoryName(i);
100         aPayload.append("{"
101             "\"name\": \""
102             + escapeJSON(sCategoryName)
103             + "\"}, ");
104     }
105     sal_Int32 nLen = aPayload.getLength();
106     aPayload[nLen - 2] = ' ';
107     aPayload[nLen - 1] = ']';
108     aPayload.append(", ");
109 
110     OUString aDescFuncNameStr;
111     aPayload.append("\"functions\": [ ");
112     sal_uInt32 nCurIndex = 0;
113     for (const OUString& aFuncNameStr : aFuncNameOrderedSet)
114     {
115         aDescFuncNameStr = aFuncNameStr + "()";
116         sal_Int32 nNextFStart = 0;
117         const formula::IFunctionDescription* ppFDesc;
118         ::std::vector< OUString > aArgs;
119         OUString eqPlusFuncName = "=" + aDescFuncNameStr;
120         if ( aHelper.GetNextFunc( eqPlusFuncName, false, nNextFStart, nullptr, &ppFDesc, &aArgs ) )
121         {
122             if ( ppFDesc && !ppFDesc->getFunctionName().isEmpty() )
123             {
124                 if (ppFDesc->getCategory())
125                 {
126                     aPayload.append("{"
127                         "\"index\": "
128                         + OString::number(static_cast<sal_Int64>(nCurIndex))
129                         + ", "
130                         "\"category\": "
131                         + OString::number(static_cast<sal_Int64>(ppFDesc->getCategory()->getNumber()))
132                         + ", "
133                         "\"signature\": \""
134                         + escapeJSON(ppFDesc->getSignature())
135                         + "\", "
136                         "\"description\": \""
137                         + escapeJSON(ppFDesc->getDescription())
138                         + "\"}, ");
139                 }
140             }
141         }
142         ++nCurIndex;
143     }
144     nLen = aPayload.getLength();
145     aPayload[nLen - 2] = ' ';
146     aPayload[nLen - 1] = ']';
147     aPayload.append(" }");
148 
149     OString s = aPayload.makeStringAndClear();
150     pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CALC_FUNCTION_LIST, s);
151 }
152 
153 } // end namespace
154 
Execute(SfxRequest & rReq)155 void ScCellShell::Execute( SfxRequest& rReq )
156 {
157     ScTabViewShell* pTabViewShell   = GetViewData().GetViewShell();
158     SfxBindings&        rBindings   = pTabViewShell->GetViewFrame().GetBindings();
159     ScModule* pScMod = ScModule::get();
160     const SfxItemSet*   pReqArgs    = rReq.GetArgs();
161     sal_uInt16              nSlot       = rReq.GetSlot();
162 
163     if (nSlot != SID_CURRENTCELL)       // this comes with MouseButtonUp
164         pTabViewShell->HideListBox();   // Autofilter-DropDown-Listbox
165 
166     if ( GetViewData().HasEditView( GetViewData().GetActivePart() ) )
167     {
168         switch ( nSlot )
169         {
170             //  when opening a reference-dialog the subshell may not be switched
171             //  (on closing the dialog StopEditShell is called)
172             case SID_OPENDLG_FUNCTION:
173                     //  inplace leads to trouble with EditShell ...
174                     //! cannot always be switched ????
175                     if (!pTabViewShell->GetViewFrame().GetFrame().IsInPlace())
176                         pTabViewShell->SetDontSwitch(true);         // do not switch off EditShell
177                     [[fallthrough]];
178 
179             case FID_CELL_FORMAT:
180             case SID_ENABLE_HYPHENATION:
181             case SID_DATA_SELECT:
182             case SID_OPENDLG_CONSOLIDATE:
183             case SID_OPENDLG_SOLVE:
184             case SID_OPENDLG_OPTSOLVER:
185 
186                     pScMod->InputEnterHandler();
187                     pTabViewShell->UpdateInputHandler();
188 
189                     pTabViewShell->SetDontSwitch(false);
190 
191                     break;
192 
193             default:
194                     break;
195         }
196     }
197 
198     switch ( nSlot )
199     {
200         case SID_STATUS_SELMODE:
201             if ( pReqArgs )
202             {
203                 /* 0: STD   Click cancels selection
204                  * 1: ER    Click extends selection
205                  * 2: ERG   Click defines further selection
206                  */
207                 sal_uInt16 nMode = static_cast<const SfxUInt16Item&>(pReqArgs->Get( nSlot )).GetValue();
208 
209                 switch ( nMode )
210                 {
211                     case 1: nMode = KEY_SHIFT;  break;
212                     case 2: nMode = KEY_MOD1;   break; // control-key
213                     case 0:
214                     default:
215                         nMode = 0;
216                 }
217 
218                 pTabViewShell->LockModifiers( nMode );
219             }
220             else
221             {
222                 //  no arguments (also executed by double click on the status bar controller):
223                 //  advance to next selection mode
224 
225                 sal_uInt16 nModifiers = pTabViewShell->GetLockedModifiers();
226                 switch ( nModifiers )
227                 {
228                     case KEY_SHIFT: nModifiers = KEY_MOD1;  break;      // EXT -> ADD
229                     case KEY_MOD1:  nModifiers = 0;         break;      // ADD -> STD
230                     default:        nModifiers = KEY_SHIFT; break;      // STD -> EXT
231                 }
232                 pTabViewShell->LockModifiers( nModifiers );
233             }
234 
235             rBindings.Invalidate( SID_STATUS_SELMODE );
236             rReq.Done();
237             break;
238 
239         //  SID_STATUS_SELMODE_NORM is not used ???
240 
241         case SID_STATUS_SELMODE_NORM:
242             pTabViewShell->LockModifiers( 0 );
243             rBindings.Invalidate( SID_STATUS_SELMODE );
244             break;
245 
246         //  SID_STATUS_SELMODE_ERG / SID_STATUS_SELMODE_ERW as toggles:
247 
248         case SID_STATUS_SELMODE_ERG:
249             if ( pTabViewShell->GetLockedModifiers() & KEY_MOD1 )
250                 pTabViewShell->LockModifiers( 0 );
251             else
252                 pTabViewShell->LockModifiers( KEY_MOD1 );
253             rBindings.Invalidate( SID_STATUS_SELMODE );
254             break;
255 
256         case SID_STATUS_SELMODE_ERW:
257             if ( pTabViewShell->GetLockedModifiers() & KEY_SHIFT )
258                 pTabViewShell->LockModifiers( 0 );
259             else
260                 pTabViewShell->LockModifiers( KEY_SHIFT );
261             rBindings.Invalidate( SID_STATUS_SELMODE );
262             break;
263 
264         case SID_ENTER_STRING:
265             {
266                 if ( pReqArgs )
267                 {
268                     // In the LOK case, we want to set the document modified state
269                     // right away at the start of the edit, so that the content is
270                     // saved even when the user leaves the document before hitting
271                     // Enter
272                     // NOTE: This also means we want to set the modified state
273                     // regardless of the DontCommit parameter's value.
274                     if (comphelper::LibreOfficeKit::isActive() && !GetViewData().GetDocShell().IsModified())
275                     {
276                         GetViewData().GetDocShell().SetModified();
277                         rBindings.Invalidate(SID_SAVEDOC);
278                         rBindings.Invalidate(SID_DOC_MODIFIED);
279                     }
280 
281                     OUString aInputString = pReqArgs->Get(SID_ENTER_STRING).GetValue();
282                     const SfxPoolItem* pDontCommitItem;
283                     bool bCommit = true;
284                     if (pReqArgs->HasItem(FN_PARAM_1, &pDontCommitItem))
285                         bCommit = !(static_cast<const SfxBoolItem*>(pDontCommitItem)->GetValue());
286 
287                     ScInputHandler* pInputHandler = pScMod->GetInputHdl(pTabViewShell);
288                     if (bCommit)
289                     {
290                         pTabViewShell->EnterDataToCurrentCell(aInputString, nullptr, true /*bMatrixExpand*/);
291                     }
292                     else if (pInputHandler)
293                     {
294                         pScMod->SetInputMode(SC_INPUT_TABLE);
295 
296                         EditView* pTableView = pInputHandler->GetActiveView();
297                         pInputHandler->DataChanging();
298                         if (pTableView)
299                             pTableView->getEditEngine().SetText(aInputString);
300                         pInputHandler->DataChanged();
301 
302                         pScMod->SetInputMode(SC_INPUT_NONE);
303                     }
304 
305                     if (!pInputHandler || !pInputHandler->IsInEnterHandler())
306                     {
307                         //  UpdateInputHandler is needed after the cell content
308                         //  has changed, but if called from EnterHandler, UpdateInputHandler
309                         //  will be called later when moving the cursor.
310                         pTabViewShell->UpdateInputHandler();
311                     }
312 
313                     rReq.Done();
314 
315                     //  no GrabFocus here, as otherwise on a Mac the tab jumps before the
316                     //  sideview, when the input was not finished
317                     //  (GrabFocus is called in KillEditView)
318                 }
319             }
320             break;
321 
322         case SID_INSERT_MATRIX:
323             {
324                 if ( pReqArgs )
325                 {
326                     OUString aStr = static_cast<const SfxStringItem&>(pReqArgs->
327                                     Get( SID_INSERT_MATRIX )).GetValue();
328                     ScDocument& rDoc = GetViewData().GetDocument();
329                     pTabViewShell->EnterMatrix( aStr, rDoc.GetGrammar() );
330                     rReq.Done();
331                 }
332             }
333             break;
334 
335         case FID_INPUTLINE_ENTER:
336         case FID_INPUTLINE_BLOCK:
337         case FID_INPUTLINE_MATRIX:
338             {
339                 if( pReqArgs == nullptr ) //XXX temporary HACK to avoid GPF
340                     break;
341 
342                 const ScInputStatusItem* pStatusItem
343                     = static_cast<const ScInputStatusItem*>(&pReqArgs->
344                             Get( FID_INPUTLINE_STATUS ));
345 
346                 const ScAddress& aCursorPos = pStatusItem->GetPos();
347                 const OUString& aString = pStatusItem->GetString();
348                 const EditTextObject* pData = pStatusItem->GetEditData();
349 
350                 if (pData)
351                 {
352                     if (nSlot == FID_INPUTLINE_BLOCK)
353                     {
354                         pTabViewShell->EnterBlock( aString, pData );
355                     }
356                     else if ( !aString.isEmpty() && ( aString[0] == '=' || aString[0] == '+' || aString[0] == '-' ) )
357                     {
358                         pTabViewShell->EnterData( aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab(),
359                                 aString, pData, true /*bMatrixExpand*/);
360                     }
361                     else
362                     {
363                         pTabViewShell->EnterData(aCursorPos.Col(), aCursorPos.Row(), aCursorPos.Tab(), *pData);
364                     }
365                 }
366                 else
367                 {
368                     if (nSlot == FID_INPUTLINE_ENTER)
369                     {
370                         if (
371                             aCursorPos.Col() == GetViewData().GetCurX() &&
372                             aCursorPos.Row() == GetViewData().GetCurY() &&
373                             aCursorPos.Tab() == GetViewData().GetTabNo()
374                             )
375                         {
376                             SfxStringItem   aItem( SID_ENTER_STRING, aString );
377 
378                             const SfxPoolItem* aArgs[2];
379                             aArgs[0] = &aItem;
380                             aArgs[1] = nullptr;
381                             rBindings.Execute( SID_ENTER_STRING, aArgs );
382                         }
383                         else
384                         {
385                             pTabViewShell->EnterData( aCursorPos.Col(),
386                                                     aCursorPos.Row(),
387                                                     aCursorPos.Tab(),
388                                                     aString, nullptr,
389                                                     true /*bMatrixExpand*/);
390                             rReq.Done();
391                         }
392                     }
393                     else if (nSlot == FID_INPUTLINE_BLOCK)
394                     {
395                         pTabViewShell->EnterBlock( aString, nullptr );
396                         rReq.Done();
397                     }
398                     else
399                     {
400                         ScDocument& rDoc = GetViewData().GetDocument();
401                         pTabViewShell->EnterMatrix( aString, rDoc.GetGrammar() );
402                         rReq.Done();
403                     }
404                 }
405 
406                 pTabViewShell->SetAutoSpellData(
407                     aCursorPos.Col(), aCursorPos.Row(), pStatusItem->GetMisspellRanges());
408 
409                 //  no GrabFocus here, as otherwise on a Mac the tab jumps before the
410                 //  sideview, when the input was not finished
411                 //  (GrabFocus is called in KillEditView)
412             }
413             break;
414 
415         case SID_OPENDLG_FUNCTION:
416             {
417                 const SfxViewShell* pViewShell = SfxViewShell::Current();
418                 if (comphelper::LibreOfficeKit::isActive()
419                     && pViewShell && pViewShell->isLOKMobilePhone())
420                 {
421                     // not set the dialog id in the mobile case or we would
422                     // not be able to get cell address pasted in the edit view
423                     // by just tapping on them
424                     lcl_lokGetWholeFunctionList();
425                 }
426                 else
427                 {
428                     sal_uInt16 nId = SID_OPENDLG_FUNCTION;
429                     SfxViewFrame& rViewFrm = pTabViewShell->GetViewFrame();
430                     SfxChildWindow* pWnd = rViewFrm.GetChildWindow( nId );
431                     bool bVis = comphelper::LibreOfficeKit::isActive() || pWnd == nullptr;
432                     pScMod->SetRefDialog( nId, bVis );
433                 }
434                 rReq.Ignore();
435             }
436             break;
437 
438         case SID_OPENDLG_CONSOLIDATE:
439             {
440                 sal_uInt16          nId  = ScConsolidateDlgWrapper::GetChildWindowId();
441                 SfxViewFrame& rViewFrm = pTabViewShell->GetViewFrame();
442                 SfxChildWindow* pWnd = rViewFrm.GetChildWindow( nId );
443 
444                 pScMod->SetRefDialog( nId, pWnd == nullptr );
445             }
446             break;
447 
448         case SID_EASY_CONDITIONAL_FORMAT_DIALOG:
449             {
450                 if (pReqArgs != nullptr)
451                 {
452                     const SfxPoolItem* pFormat;
453                     if (pReqArgs->HasItem( FN_PARAM_1, &pFormat))
454                     {
455                         sal_Int16 nFormat = static_cast<const SfxInt16Item*>(pFormat)->GetValue();
456                         sal_uInt16 nId = sc::ConditionalFormatEasyDialogWrapper::GetChildWindowId();
457                         SfxViewFrame& rViewFrame = pTabViewShell->GetViewFrame();
458                         SfxChildWindow* pWindow = rViewFrame.GetChildWindow(nId);
459                         GetViewData().GetDocument().SetEasyConditionalFormatDialogData(
460                             std::make_unique<ScConditionMode>(
461                                 static_cast<ScConditionMode>(nFormat)));
462 
463                         pScMod->SetRefDialog( nId, pWindow == nullptr );
464                     }
465                 }
466             }
467             break;
468 
469         case FID_CELL_FORMAT:
470             {
471                 if ( pReqArgs != nullptr )
472                 {
473                     // set cell attribute without dialog:
474                     SfxItemSet aEmptySet(SfxItemSet::makeFixedSfxItemSet<ATTR_PATTERN_START, ATTR_PATTERN_END>(*pReqArgs->GetPool()));
475 
476                     SfxItemSet aNewSet(SfxItemSet::makeFixedSfxItemSet<ATTR_PATTERN_START, ATTR_PATTERN_END>(*pReqArgs->GetPool()));
477 
478                     const SfxPoolItem*  pAttr = nullptr;
479                     sal_uInt16              nWhich = 0;
480 
481                     for ( nWhich=ATTR_PATTERN_START; nWhich<=ATTR_PATTERN_END; nWhich++ )
482                         if ( pReqArgs->GetItemState( nWhich, true, &pAttr ) == SfxItemState::SET )
483                             aNewSet.Put( *pAttr );
484 
485                     pTabViewShell->ApplyAttributes( aNewSet, aEmptySet );
486 
487                     rReq.Done();
488                 }
489                 else
490                 {
491                     pTabViewShell->ExecuteCellFormatDlg( rReq, u""_ustr );
492                 }
493             }
494             break;
495 
496         case SID_ENABLE_HYPHENATION:
497             pTabViewShell->ExecuteCellFormatDlg(rReq, u"alignment"_ustr);
498             break;
499 
500         case SID_PROPERTY_PANEL_CELLTEXT_DLG:
501             pTabViewShell->ExecuteCellFormatDlg( rReq, u"font"_ustr );
502             break;
503 
504         case SID_CELL_FORMAT_BORDER:
505             pTabViewShell->ExecuteCellFormatDlg( rReq, u"borders"_ustr );
506             break;
507 
508         case SID_CHAR_DLG_EFFECT:
509             pTabViewShell->ExecuteCellFormatDlg( rReq, u"fonteffects"_ustr );
510             break;
511 
512         case SID_OPENDLG_SOLVE:
513             {
514                 sal_uInt16          nId  = ScSolverDlgWrapper::GetChildWindowId();
515                 SfxViewFrame& rViewFrm = pTabViewShell->GetViewFrame();
516                 SfxChildWindow* pWnd = rViewFrm.GetChildWindow( nId );
517 
518                 pScMod->SetRefDialog( nId, pWnd == nullptr );
519             }
520             break;
521 
522         case SID_OPENDLG_OPTSOLVER:
523             {
524                 sal_uInt16 nId = ScOptSolverDlgWrapper::GetChildWindowId();
525                 SfxViewFrame& rViewFrm = pTabViewShell->GetViewFrame();
526                 SfxChildWindow* pWnd = rViewFrm.GetChildWindow( nId );
527 
528                 pScMod->SetRefDialog( nId, pWnd == nullptr );
529             }
530             break;
531 
532         case SID_OPENDLG_TABOP:
533             {
534                 sal_uInt16          nId  = ScTabOpDlgWrapper::GetChildWindowId();
535                 SfxViewFrame& rViewFrm = pTabViewShell->GetViewFrame();
536                 SfxChildWindow* pWnd = rViewFrm.GetChildWindow( nId );
537 
538                 pScMod->SetRefDialog( nId, pWnd == nullptr );
539             }
540             break;
541 
542         case SID_SCENARIOS:
543             {
544                 ScDocument& rDoc = GetViewData().GetDocument();
545                 ScMarkData& rMark = GetViewData().GetMarkData();
546                 SCTAB nTab = GetViewData().GetTabNo();
547 
548                 if ( rDoc.IsScenario(nTab) )
549                 {
550                     rMark.MarkToMulti();
551                     if ( rMark.IsMultiMarked() )
552                     {
553 
554                         bool bExtend = rReq.IsAPI();
555                         if (!bExtend)
556                         {
557                             std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(pTabViewShell->GetFrameWeld(),
558                                                                            VclMessageType::Question, VclButtonsType::YesNo,
559                                                                            ScResId(STR_UPDATE_SCENARIO)));
560                             xQueryBox->set_default_response(RET_YES);
561                             bExtend = xQueryBox->run() == RET_YES;
562                         }
563 
564                         if (bExtend)
565                         {
566                             pTabViewShell->ExtendScenario();
567                             rReq.Done();
568                         }
569                     }
570                     else if( ! rReq.IsAPI() )
571                     {
572                         std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(pTabViewShell->GetFrameWeld(),
573                                                                        VclMessageType::Warning, VclButtonsType::Ok,
574                                                                        ScResId(STR_NOAREASELECTED)));
575                         xErrorBox->run();
576                     }
577                 }
578                 else
579                 {
580                     rMark.MarkToMulti();
581                     if ( rMark.IsMultiMarked() )
582                     {
583                         SCTAB i=1;
584                         OUString aBaseName;
585                         OUString aName;
586                         Color  aColor;
587                         ScScenarioFlags nFlags;
588 
589                         OUString aTmp;
590                         rDoc.GetName(nTab, aTmp);
591                         aBaseName = aTmp + "_" + ScResId(STR_SCENARIO) + "_";
592 
593                         //  first test, if the prefix is recognised as valid,
594                         //  else avoid only doubles
595                         bool bPrefix = ScDocument::ValidTabName( aBaseName );
596                         OSL_ENSURE(bPrefix, "invalid sheet name");
597 
598                         while ( rDoc.IsScenario(nTab+i) )
599                             i++;
600 
601                         bool bValid;
602                         SCTAB nDummy;
603                         do
604                         {
605                             aName = aBaseName + OUString::number( i );
606                             if (bPrefix)
607                                 bValid = rDoc.ValidNewTabName( aName );
608                             else
609                                 bValid = !rDoc.GetTable( aName, nDummy );
610                             ++i;
611                         }
612                         while ( !bValid && i <= MAXTAB + 2 );
613 
614                         if ( pReqArgs != nullptr )
615                         {
616                             OUString aArgName;
617                             OUString aArgComment;
618                             if ( const SfxStringItem* pItem = pReqArgs->GetItemIfSet( SID_SCENARIOS ) )
619                                 aArgName = pItem->GetValue();
620                             if ( const SfxStringItem* pItem = pReqArgs->GetItemIfSet( SID_NEW_TABLENAME ) )
621                                 aArgComment = pItem->GetValue();
622 
623                             aColor = COL_LIGHTGRAY;        // Default
624                             nFlags = ScScenarioFlags::NONE;         // not TwoWay
625 
626                             pTabViewShell->MakeScenario( aArgName, aArgComment, aColor, nFlags );
627                             if( ! rReq.IsAPI() )
628                                 rReq.Done();
629                         }
630                         else
631                         {
632                             bool bSheetProtected = rDoc.IsTabProtected(nTab);
633                             ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
634 
635                             ScopedVclPtr<AbstractScNewScenarioDlg> pNewDlg(pFact->CreateScNewScenarioDlg(pTabViewShell->GetFrameWeld(), aName, false, bSheetProtected));
636                             if ( pNewDlg->Execute() == RET_OK )
637                             {
638                                 OUString aComment;
639                                 pNewDlg->GetScenarioData( aName, aComment, aColor, nFlags );
640                                 pTabViewShell->MakeScenario( aName, aComment, aColor, nFlags );
641 
642                                 rReq.AppendItem( SfxStringItem( SID_SCENARIOS, aName ) );
643                                 rReq.AppendItem( SfxStringItem( SID_NEW_TABLENAME, aComment ) );
644                                 rReq.Done();
645                             }
646                         }
647                     }
648                     else if( ! rReq.IsAPI() )
649                     {
650                         pTabViewShell->ErrorMessage(STR_ERR_NEWSCENARIO);
651                     }
652                 }
653             }
654             break;
655 
656         case SID_SELECTALL:
657             {
658                 SCTAB nTab = GetViewData().GetTabNo();
659                 SCCOL nStartCol = GetViewData().GetCurX();
660                 SCROW nStartRow = GetViewData().GetCurY();
661                 SCCOL nEndCol = nStartCol;
662                 SCROW nEndRow = nStartRow;
663                 bool bCanMark = false;
664 
665                 ScMarkData& rMarkdata = GetViewData().GetMarkData();
666                 const bool bSelectFirst(officecfg::Office::Calc::Input::SelectRangeBeforeAll::get());
667 
668                 if (bSelectFirst && !rMarkdata.IsMarked())
669                 {
670                     const ScDocument& rDoc = GetViewData().GetDocument();
671                     rDoc.GetDataArea( nTab, nStartCol, nStartRow, nEndCol, nEndRow, true, false );
672                     bCanMark = nStartCol != nEndCol || nStartRow != nEndRow;
673                 }
674 
675                 if (bCanMark)
676                 {
677                     const ScRange aRange(nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab);
678                     pTabViewShell->MarkRange(aRange, false);
679                 }
680                 else
681                     pTabViewShell->SelectAll();
682 
683                 rReq.Done();
684             }
685             break;
686 
687         case FID_ROW_HEIGHT:
688             {
689                 const SfxPoolItem* pRow;
690                 const SfxUInt16Item* pHeight;
691                 sal_uInt16 nHeight;
692 
693                 if ( pReqArgs && (pHeight = pReqArgs->GetItemIfSet( FID_ROW_HEIGHT )) &&
694                                  pReqArgs->HasItem( FN_PARAM_1, &pRow ) )
695                 {
696                     std::vector<sc::ColRowSpan> aRanges;
697                     SCCOLROW nRow = static_cast<const SfxInt32Item*>(pRow)->GetValue() - 1;
698                     nHeight = pHeight->GetValue();
699                     ScMarkData& rMark = GetViewData().GetMarkData();
700 
701                     if ( rMark.IsRowMarked( static_cast<SCROW>(nRow) ) )
702                     {
703                         aRanges = rMark.GetMarkedRowSpans();
704                     }
705                     else
706                     {
707                         aRanges.emplace_back(nRow, nRow);
708                     }
709 
710                     pTabViewShell->SetWidthOrHeight(false, aRanges, SC_SIZE_DIRECT, o3tl::toTwips(nHeight, o3tl::Length::mm100));
711                 }
712                 else if ( pReqArgs && (pHeight = pReqArgs->GetItemIfSet( FID_ROW_HEIGHT )) )
713                 {
714                     nHeight = pHeight->GetValue();
715 
716                     // #101390#; the value of the macro is in HMM so use convertMm100ToTwip to convert
717                     pTabViewShell->SetMarkedWidthOrHeight( false, SC_SIZE_DIRECT,
718                         o3tl::toTwips(nHeight, o3tl::Length::mm100));
719                     if( ! rReq.IsAPI() )
720                         rReq.Done();
721                 }
722                 else
723                 {
724                     ScViewData& rData      = GetViewData();
725                     FieldUnit eMetric = pScMod->GetMetric();
726                     sal_uInt16      nCurHeight = rData.GetDocument().
727                                                 GetRowHeight( rData.GetCurY(),
728                                                               rData.GetTabNo() );
729                     ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
730                     VclPtr<AbstractScMetricInputDlg> pDlg(pFact->CreateScMetricInputDlg(
731                         pTabViewShell->GetFrameWeld(), u"RowHeightDialog"_ustr, nCurHeight,
732                         rData.GetDocument().GetSheetOptimalMinRowHeight(rData.GetTabNo()),
733                         eMetric, 2, MAX_ROW_HEIGHT));
734 
735                     pDlg->StartExecuteAsync([pDlg, pTabViewShell](sal_Int32 nResult){
736                         if (nResult == RET_OK)
737                         {
738                             SfxRequest pRequest(pTabViewShell->GetViewFrame(), FID_ROW_HEIGHT);
739                             tools::Long nVal = pDlg->GetInputValue();
740                             pTabViewShell->SetMarkedWidthOrHeight( false, SC_SIZE_DIRECT, static_cast<sal_uInt16>(nVal) );
741 
742                             // #101390#; the value of the macro should be in HMM so use TwipsToEvenHMM to convert
743                             pRequest.AppendItem( SfxUInt16Item( FID_ROW_HEIGHT, static_cast<sal_uInt16>(TwipsToEvenHMM(nVal)) ) );
744                             pRequest.Done();
745                         }
746                         pDlg->disposeOnce();
747                     });
748                 }
749             }
750             break;
751 
752         case FID_ROW_OPT_HEIGHT:
753             {
754                 if ( pReqArgs )
755                 {
756                     const SfxUInt16Item&  rUInt16Item = pReqArgs->Get( FID_ROW_OPT_HEIGHT );
757 
758                     // #101390#; the value of the macro is in HMM so use convertMm100ToTwip to convert
759                     pTabViewShell->SetMarkedWidthOrHeight( false, SC_SIZE_OPTIMAL,
760                                     o3tl::toTwips(rUInt16Item.GetValue(), o3tl::Length::mm100) );
761                     ScGlobal::nLastRowHeightExtra = rUInt16Item.GetValue();
762 
763                     if( ! rReq.IsAPI() )
764                         rReq.Done();
765                 }
766                 else
767                 {
768                     FieldUnit eMetric = pScMod->GetMetric();
769 
770                     ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
771                     VclPtr<AbstractScMetricInputDlg> pDlg(pFact->CreateScMetricInputDlg(
772                         pTabViewShell->GetFrameWeld(), u"OptimalRowHeightDialog"_ustr,
773                         ScGlobal::nLastRowHeightExtra, 0, eMetric, 2, MAX_EXTRA_HEIGHT));
774 
775                     pDlg->StartExecuteAsync([pDlg, pTabViewShell](sal_Int32 nResult){
776                         if ( nResult == RET_OK )
777                         {
778                             SfxRequest pRequest(pTabViewShell->GetViewFrame(), FID_ROW_OPT_HEIGHT);
779                             tools::Long nVal = pDlg->GetInputValue();
780                             pTabViewShell->SetMarkedWidthOrHeight( false, SC_SIZE_OPTIMAL, static_cast<sal_uInt16>(nVal) );
781                             ScGlobal::nLastRowHeightExtra = nVal;
782 
783                             // #101390#; the value of the macro should be in HMM so use TwipsToEvenHMM to convert
784                             pRequest.AppendItem( SfxUInt16Item( FID_ROW_OPT_HEIGHT, static_cast<sal_uInt16>(TwipsToEvenHMM(nVal)) ) );
785                             pRequest.Done();
786                         }
787                         pDlg->disposeOnce();
788                     });
789                 }
790             }
791             break;
792 
793         case FID_COL_WIDTH:
794             {
795                 const SfxPoolItem* pColumn;
796                 const SfxUInt16Item* pWidth;
797                 sal_uInt16 nWidth;
798 
799                 if ( pReqArgs && (pWidth = pReqArgs->GetItemIfSet( FID_COL_WIDTH )) &&
800                                  pReqArgs->HasItem( FN_PARAM_1, &pColumn ) )
801                 {
802                     std::vector<sc::ColRowSpan> aRanges;
803                     SCCOLROW nColumn = static_cast<const SfxUInt16Item*>(pColumn)->GetValue() - 1;
804                     nWidth = pWidth->GetValue();
805                     ScMarkData& rMark = GetViewData().GetMarkData();
806 
807                     if ( rMark.IsColumnMarked( static_cast<SCCOL>(nColumn) ) )
808                     {
809                         aRanges = rMark.GetMarkedColSpans();
810                     }
811                     else
812                     {
813                         aRanges.emplace_back(nColumn, nColumn);
814                     }
815 
816                     pTabViewShell->SetWidthOrHeight(true, aRanges, SC_SIZE_DIRECT, o3tl::toTwips(nWidth, o3tl::Length::mm100));
817                 }
818                 else if ( pReqArgs && (pWidth = pReqArgs->GetItemIfSet( FID_COL_WIDTH )) )
819                 {
820                     nWidth = pWidth->GetValue();
821 
822                     // #101390#; the value of the macro is in HMM so use convertMm100ToTwip to convert
823                     pTabViewShell->SetMarkedWidthOrHeight( true, SC_SIZE_DIRECT,
824                         o3tl::toTwips(nWidth, o3tl::Length::mm100));
825                     if( ! rReq.IsAPI() )
826                         rReq.Done();
827                 }
828                 else
829                 {
830                     FieldUnit eMetric = pScMod->GetMetric();
831                     ScViewData& rData      = GetViewData();
832                     sal_uInt16      nCurHeight = rData.GetDocument().
833                                                 GetColWidth( rData.GetCurX(),
834                                                              rData.GetTabNo() );
835                     ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
836                     VclPtr<AbstractScMetricInputDlg> pDlg(pFact->CreateScMetricInputDlg(
837                         pTabViewShell->GetFrameWeld(), u"ColWidthDialog"_ustr, nCurHeight,
838                         STD_COL_WIDTH, eMetric, 2, MAX_COL_WIDTH));
839 
840                     pDlg->StartExecuteAsync([pDlg, pTabViewShell](sal_Int32 nResult){
841                         if ( nResult == RET_OK )
842                         {
843                             SfxRequest pRequest(pTabViewShell->GetViewFrame(), FID_COL_WIDTH);
844                             tools::Long nVal = pDlg->GetInputValue();
845                             pTabViewShell->SetMarkedWidthOrHeight( true, SC_SIZE_DIRECT, static_cast<sal_uInt16>(nVal) );
846 
847                             // #101390#; the value of the macro should be in HMM so use TwipsToEvenHMM to convert
848                             pRequest.AppendItem( SfxUInt16Item( FID_COL_WIDTH, static_cast<sal_uInt16>(TwipsToEvenHMM(nVal))) );
849                             pRequest.Done();
850                         }
851                         pDlg->disposeOnce();
852                     });
853                 }
854             }
855             break;
856 
857         case FID_COL_OPT_WIDTH:
858             {
859                 if ( pReqArgs )
860                 {
861                     const SfxUInt16Item&  rUInt16Item = pReqArgs->Get( FID_COL_OPT_WIDTH );
862 
863                     // #101390#; the value of the macro is in HMM so use convertMm100ToTwip to convert
864                     pTabViewShell->SetMarkedWidthOrHeight( true, SC_SIZE_OPTIMAL,
865                                     o3tl::toTwips(rUInt16Item.GetValue(), o3tl::Length::mm100) );
866                     ScGlobal::nLastColWidthExtra = rUInt16Item.GetValue();
867 
868                     if( ! rReq.IsAPI() )
869                         rReq.Done();
870                 }
871                 else
872                 {
873                     FieldUnit eMetric = pScMod->GetMetric();
874 
875                     ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
876                     VclPtr<AbstractScMetricInputDlg> pDlg(pFact->CreateScMetricInputDlg(
877                         pTabViewShell->GetFrameWeld(), u"OptimalColWidthDialog"_ustr,
878                         ScGlobal::nLastColWidthExtra, STD_EXTRA_WIDTH, eMetric, 2, MAX_EXTRA_WIDTH));
879 
880                     pDlg->StartExecuteAsync([pDlg, pTabViewShell](sal_Int32 nResult){
881                         SfxRequest pRequest(pTabViewShell->GetViewFrame(), FID_COL_OPT_WIDTH);
882                         if ( nResult == RET_OK )
883                         {
884                             tools::Long nVal = pDlg->GetInputValue();
885                             pTabViewShell->SetMarkedWidthOrHeight( true, SC_SIZE_OPTIMAL, static_cast<sal_uInt16>(nVal) );
886                             ScGlobal::nLastColWidthExtra = nVal;
887 
888                             // #101390#; the value of the macro should be in HMM so use TwipsToEvenHMM to convert
889                             pRequest.AppendItem( SfxUInt16Item( FID_COL_OPT_WIDTH, static_cast<sal_uInt16>(TwipsToEvenHMM(nVal)) ) );
890                             pRequest.Done();
891                         }
892                         pDlg->disposeOnce();
893                     });
894                 }
895             }
896             break;
897 
898         case FID_COL_OPT_DIRECT:
899             pTabViewShell->SetMarkedWidthOrHeight( true, SC_SIZE_OPTIMAL, STD_EXTRA_WIDTH );
900             rReq.Done();
901             break;
902 
903         case FID_ROW_HIDE:
904             pTabViewShell->SetMarkedWidthOrHeight( false, SC_SIZE_DIRECT, 0 );
905             rReq.Done();
906             break;
907         case FID_ROW_SHOW:
908             pTabViewShell->SetMarkedWidthOrHeight( false, SC_SIZE_SHOW, 0 );
909             rReq.Done();
910             break;
911         case FID_COL_HIDE:
912             pTabViewShell->SetMarkedWidthOrHeight( true, SC_SIZE_DIRECT, 0 );
913             rReq.Done();
914             break;
915         case FID_COL_SHOW:
916             pTabViewShell->SetMarkedWidthOrHeight( true, SC_SIZE_SHOW, 0 );
917             rReq.Done();
918             break;
919 
920         case SID_CELL_FORMAT_RESET:
921             {
922                 pTabViewShell->DeleteContents( InsertDeleteFlags::HARDATTR | InsertDeleteFlags::EDITATTR );
923                 rReq.Done();
924             }
925             break;
926 
927         case FID_MERGE_ON:
928         case FID_MERGE_OFF:
929         case FID_MERGE_TOGGLE:
930         {
931             if ( !GetViewData().GetDocument().GetChangeTrack() )
932             {
933                 // test whether to merge or to split
934                 bool bMerge = false;
935                 bool bCenter = false;
936                 switch( nSlot )
937                 {
938                     case FID_MERGE_ON:
939                         bMerge = true;
940                     break;
941                     case FID_MERGE_OFF:
942                         bMerge = false;
943                     break;
944                     case FID_MERGE_TOGGLE:
945                     {
946                         bCenter = true;
947                         std::unique_ptr<SfxPoolItem> pItem;
948                         if( rBindings.QueryState( nSlot, pItem ) >= SfxItemState::DEFAULT )
949                             bMerge = !static_cast< SfxBoolItem* >( pItem.get() )->GetValue();
950                     }
951                     break;
952                 }
953 
954                 if( bMerge )
955                 {
956                     // merge - check if to move contents of covered cells
957                     bool bMoveContents = false;
958                     bool bApi = rReq.IsAPI();
959                     const SfxPoolItem* pItem;
960                     if ( pReqArgs &&
961                         pReqArgs->GetItemState(nSlot, true, &pItem) == SfxItemState::SET )
962                     {
963                         assert(dynamic_cast<const SfxBoolItem*>( pItem) && "wrong item");
964                         bMoveContents = static_cast<const SfxBoolItem*>(pItem)->GetValue();
965                     }
966 
967                     pTabViewShell->MergeCells( bApi, bMoveContents, bCenter, nSlot );
968                 }
969                 else
970                 {
971                     // split cells
972                     if (pTabViewShell->RemoveMerge())
973                     {
974                         rBindings.Invalidate( nSlot );
975                         rReq.Done();
976                     }
977                 }
978                 break;
979             }
980         }
981         break;
982 
983         case SID_AUTOFORMAT:
984             {
985                 weld::Window* pDlgParent = pTabViewShell->GetFrameWeld();
986                 SCCOL nStartCol;
987                 SCROW nStartRow;
988                 SCTAB nStartTab;
989                 SCCOL nEndCol;
990                 SCROW nEndRow;
991                 SCTAB nEndTab;
992 
993                 const ScMarkData& rMark = GetViewData().GetMarkData();
994                 if ( !rMark.IsMarked() && !rMark.IsMultiMarked() )
995                     pTabViewShell->MarkDataArea();
996 
997                 GetViewData().GetSimpleArea( nStartCol,nStartRow,nStartTab,
998                                               nEndCol,nEndRow,nEndTab );
999 
1000                 if (   ( std::abs(nEndCol-nStartCol) > 1 )
1001                     && ( std::abs(nEndRow-nStartRow) > 1 ) )
1002                 {
1003                     if ( pReqArgs )
1004                     {
1005                         const SfxStringItem& rNameItem = pReqArgs->Get( SID_AUTOFORMAT );
1006                         ScAutoFormat* pFormat = ScGlobal::GetOrCreateAutoFormat();
1007                         ScAutoFormat::const_iterator it = pFormat->find(rNameItem.GetValue());
1008                         ScAutoFormat::const_iterator itBeg = pFormat->begin();
1009                         size_t nIndex = std::distance(itBeg, it);
1010 
1011                         pTabViewShell->AutoFormat( nIndex );
1012 
1013                         if( ! rReq.IsAPI() )
1014                             rReq.Done();
1015                     }
1016                     else
1017                     {
1018                         ScGlobal::ClearAutoFormat();
1019                         std::unique_ptr<ScAutoFormatData> pNewEntry(pTabViewShell->CreateAutoFormatData());
1020                         ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
1021 
1022                         ScopedVclPtr<AbstractScAutoFormatDlg> pDlg(pFact->CreateScAutoFormatDlg(pDlgParent, ScGlobal::GetOrCreateAutoFormat(), pNewEntry.get(), GetViewData()));
1023 
1024                         if ( pDlg->Execute() == RET_OK )
1025                         {
1026                             ScEditableTester aTester( pTabViewShell );
1027                             if ( !aTester.IsEditable() )
1028                             {
1029                                 pTabViewShell->ErrorMessage(aTester.GetMessageId());
1030                             }
1031                             else
1032                             {
1033                                 pTabViewShell->AutoFormat( pDlg->GetIndex() );
1034 
1035                                 rReq.AppendItem( SfxStringItem( SID_AUTOFORMAT, pDlg->GetCurrFormatName() ) );
1036                                 rReq.Done();
1037                             }
1038                         }
1039                     }
1040                 }
1041                 else
1042                 {
1043                     std::unique_ptr<weld::MessageDialog> xErrorBox(Application::CreateMessageDialog(pDlgParent,
1044                                                                    VclMessageType::Warning, VclButtonsType::Ok,
1045                                                                    ScResId(STR_INVALID_AFAREA)));
1046                     xErrorBox->run();
1047                 }
1048             }
1049             break;
1050 
1051         case SID_CANCEL:
1052             {
1053                 if (GetViewData().HasEditView(GetViewData().GetActivePart()))
1054                     pScMod->InputCancelHandler();
1055                 else if (pTabViewShell->HasPaintBrush())
1056                     pTabViewShell->ResetBrushDocument();            // abort format paint brush
1057                 else if (pTabViewShell->HasHintWindow())
1058                     pTabViewShell->RemoveHintWindow();
1059                 else if( ScViewUtil::IsFullScreen( *pTabViewShell ) )
1060                     ScViewUtil::SetFullScreen( *pTabViewShell, false );
1061                 else
1062                 {
1063                     // TODO/LATER: when is this code executed?
1064                     pTabViewShell->Escape();
1065                 }
1066             }
1067             break;
1068 
1069         case SID_ACCEPT_FORMULA:
1070             {
1071                 if (GetViewData().HasEditView(GetViewData().GetActivePart()))
1072                     pScMod->InputEnterHandler();
1073             }
1074             break;
1075 
1076         case SID_START_FORMULA:
1077             {
1078                 ScInputHandler* pInputHandler = pScMod->GetInputHdl();
1079                 if (pInputHandler && pInputHandler->GetInputWindow())
1080                     pInputHandler->GetInputWindow()->StartFormula();
1081             }
1082             break;
1083 
1084         case SID_DATA_SELECT:
1085             pTabViewShell->StartDataSelect();
1086             break;
1087 
1088         case SID_DETECTIVE_FILLMODE:
1089             {
1090                 bool bOldMode = pTabViewShell->IsAuditShell();
1091                 pTabViewShell->SetAuditShell( !bOldMode );
1092                 pTabViewShell->Invalidate( nSlot );
1093             }
1094             break;
1095 
1096         case FID_INPUTLINE_STATUS:
1097             OSL_FAIL("Execute from InputLine status");
1098             break;
1099 
1100         case SID_STATUS_DOCPOS:
1101             // Launch navigator.
1102             GetViewData().GetDispatcher().Execute(
1103                 SID_NAVIGATOR, SfxCallMode::SYNCHRON|SfxCallMode::RECORD );
1104             break;
1105 
1106         case SID_MARKAREA:
1107             // called from Basic at the hidden view to select a range in the visible view
1108             OSL_FAIL("old slot SID_MARKAREA");
1109             break;
1110 
1111         case FID_MOVE_KEEP_INSERT_MODE:
1112         {
1113             const SfxBoolItem* pEnabledArg = rReq.GetArg<SfxBoolItem>(FID_MOVE_KEEP_INSERT_MODE);
1114             if (!pEnabledArg) {
1115                 SAL_WARN("sfx.appl", "FID_MOVE_KEEP_INSERT_MODE: must specify if you would like this to be enabled");
1116                 break;
1117             }
1118 
1119             ScInputOptions aInputOptions = pScMod->GetInputOptions();
1120 
1121             aInputOptions.SetMoveKeepEdit(pEnabledArg->GetValue());
1122             pScMod->SetInputOptions(aInputOptions);
1123 
1124             if (comphelper::LibreOfficeKit::isActive())
1125                 pTabViewShell->SetMoveKeepEdit(pEnabledArg->GetValue());
1126 
1127             break;
1128         }
1129 
1130         default:
1131             OSL_FAIL("ScCellShell::Execute: unknown slot");
1132             break;
1133     }
1134 }
1135 
1136 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
1137