xref: /core/sc/source/ui/docshell/docsh4.cxx (revision de8ea47e)
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 <config_features.h>
21 
22 #include <boost/property_tree/json_parser.hpp>
23 
24 #include <com/sun/star/frame/Desktop.hpp>
25 
26 using namespace ::com::sun::star;
27 
28 #include <scitems.hxx>
29 #include <editeng/flstitem.hxx>
30 #include <sfx2/fcontnr.hxx>
31 #include <sfx2/infobar.hxx>
32 #include <sfx2/objface.hxx>
33 #include <sfx2/docfile.hxx>
34 #include <sfx2/docfilt.hxx>
35 #include <svtools/ehdl.hxx>
36 #include <svtools/langtab.hxx>
37 #include <basic/sbxcore.hxx>
38 #include <basic/sberrors.hxx>
39 #include <svtools/sfxecode.hxx>
40 #include <svx/ofaitem.hxx>
41 #include <svl/whiter.hxx>
42 #include <vcl/svapp.hxx>
43 #include <vcl/weld.hxx>
44 #include <vcl/waitobj.hxx>
45 #include <svx/dataaccessdescriptor.hxx>
46 #include <svx/drawitem.hxx>
47 #include <svx/fmshell.hxx>
48 #include <sfx2/passwd.hxx>
49 #include <sfx2/filedlghelper.hxx>
50 #include <sfx2/dispatch.hxx>
51 #include <sfx2/sfxdlg.hxx>
52 #include <svl/PasswordHelper.hxx>
53 #include <svl/documentlockfile.hxx>
54 #include <svl/sharecontrolfile.hxx>
55 #include <unotools/securityoptions.hxx>
56 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
57 #include <sal/log.hxx>
58 #include <unotools/charclass.hxx>
59 
60 #include <comphelper/lok.hxx>
61 #include <comphelper/processfactory.hxx>
62 #include <docuno.hxx>
63 
64 #include <docsh.hxx>
65 #include "docshimp.hxx"
66 #include <docfunc.hxx>
67 #include <scres.hrc>
68 #include <strings.hrc>
69 #include <stlsheet.hxx>
70 #include <stlpool.hxx>
71 #include <appoptio.hxx>
72 #include <globstr.hrc>
73 #include <global.hxx>
74 #include <dbdocfun.hxx>
75 #include <printfun.hxx>
76 #include <viewdata.hxx>
77 #include <tabvwsh.hxx>
78 #include <impex.hxx>
79 #include <undodat.hxx>
80 #include <undocell.hxx>
81 #include <inputhdl.hxx>
82 #include <dbdata.hxx>
83 #include <servobj.hxx>
84 #include <rangenam.hxx>
85 #include <scmod.hxx>
86 #include <chgviset.hxx>
87 #include <reffact.hxx>
88 #include <chartlis.hxx>
89 #include <chartpos.hxx>
90 #include <waitoff.hxx>
91 #include <tablink.hxx>
92 #include <drwlayer.hxx>
93 #include <docoptio.hxx>
94 #include <undostyl.hxx>
95 #include <rangeseq.hxx>
96 #include <chgtrack.hxx>
97 #include <com/sun/star/document/UpdateDocMode.hpp>
98 #include <scresid.hxx>
99 #include <scabstdlg.hxx>
100 #include <sharedocdlg.hxx>
101 #include <conditio.hxx>
102 #include <sheetevents.hxx>
103 #include <formulacell.hxx>
104 #include <documentlinkmgr.hxx>
105 #include <memory>
106 #include <sfx2/notebookbar/SfxNotebookBar.hxx>
107 #include <helpids.h>
108 
109 #include <svx/xdef.hxx>
110 
111 void ScDocShell::ReloadAllLinks()
112 {
113     m_aDocument.SetLinkFormulaNeedingCheck(false);
114     getEmbeddedObjectContainer().setUserAllowsLinkUpdate(true);
115 
116     ReloadTabLinks();
117     vcl::Window *pDialogParent = GetActiveDialogParent();
118     m_aDocument.UpdateExternalRefLinks(pDialogParent);
119 
120     bool bAnyDde = m_aDocument.GetDocLinkManager().updateDdeOrOleOrWebServiceLinks(pDialogParent ? pDialogParent->GetFrameWeld() : nullptr);
121 
122     if (bAnyDde)
123     {
124         //  calculate formulas and paint like in the TrackTimeHdl
125         m_aDocument.TrackFormulas();
126         Broadcast(SfxHint(SfxHintId::ScDataChanged));
127 
128         //  Should FID_DATACHANGED become asynchronous some time
129         //  (e.g., with Invalidate at Window), an update needs to be forced here.
130     }
131 
132     m_aDocument.UpdateAreaLinks();
133 }
134 
135 IMPL_LINK_NOARG( ScDocShell, ReloadAllLinksHdl, Button*, void )
136 {
137     ReloadAllLinks();
138 
139     ScTabViewShell* pViewSh = GetBestViewShell();
140     SfxViewFrame* pViewFrame = pViewSh ? pViewSh->GetFrame() : nullptr;
141     if (pViewFrame)
142         pViewFrame->RemoveInfoBar("enablecontent");
143     SAL_WARN_IF(!pViewFrame, "sc", "expected there to be a ViewFrame");
144 }
145 
146 void ScDocShell::Execute( SfxRequest& rReq )
147 {
148     const SfxItemSet* pReqArgs = rReq.GetArgs();
149     SfxBindings* pBindings = GetViewBindings();
150     bool bUndo (m_aDocument.IsUndoEnabled());
151 
152     sal_uInt16 nSlot = rReq.GetSlot();
153     switch ( nSlot )
154     {
155         case SID_SC_SETTEXT:
156         {
157             const SfxPoolItem* pColItem;
158             const SfxPoolItem* pRowItem;
159             const SfxPoolItem* pTabItem;
160             const SfxPoolItem* pTextItem;
161             if( pReqArgs && pReqArgs->HasItem( FN_PARAM_1, &pColItem ) &&
162                             pReqArgs->HasItem( FN_PARAM_2, &pRowItem ) &&
163                             pReqArgs->HasItem( FN_PARAM_3, &pTabItem ) &&
164                             pReqArgs->HasItem( SID_SC_SETTEXT, &pTextItem ) )
165             {
166                 //  parameters are  1-based !!!
167                 SCCOL nCol = static_cast<const SfxInt16Item*>(pColItem)->GetValue() - 1;
168                 SCROW nRow = static_cast<const SfxInt32Item*>(pRowItem)->GetValue() - 1;
169                 SCTAB nTab = static_cast<const SfxInt16Item*>(pTabItem)->GetValue() - 1;
170 
171                 SCTAB nTabCount = m_aDocument.GetTableCount();
172                 if ( ValidCol(nCol) && ValidRow(nRow) && ValidTab(nTab,nTabCount) )
173                 {
174                     if ( m_aDocument.IsBlockEditable( nTab, nCol,nRow, nCol, nRow ) )
175                     {
176                         OUString aVal = static_cast<const SfxStringItem*>(pTextItem)->GetValue();
177                         m_aDocument.SetString( nCol, nRow, nTab, aVal );
178 
179                         PostPaintCell( nCol, nRow, nTab );
180                         SetDocumentModified();
181 
182                         rReq.Done();
183                         break;
184                     }
185                     else                // protected cell
186                     {
187 #if HAVE_FEATURE_SCRIPTING
188                         SbxBase::SetError( ERRCODE_BASIC_BAD_PARAMETER );      //! which error ?
189 #endif
190                         break;
191                     }
192                 }
193             }
194 #if HAVE_FEATURE_SCRIPTING
195             SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT );
196 #endif
197         }
198         break;
199 
200         case SID_SBA_IMPORT:
201         {
202             if (pReqArgs)
203             {
204                 const SfxPoolItem* pItem;
205                 svx::ODataAccessDescriptor aDesc;
206                 if ( pReqArgs->GetItemState( nSlot, true, &pItem ) == SfxItemState::SET )
207                 {
208                     uno::Any aAny = static_cast<const SfxUnoAnyItem*>(pItem)->GetValue();
209                     uno::Sequence<beans::PropertyValue> aProperties;
210                     if ( aAny >>= aProperties )
211                         aDesc.initializeFrom( aProperties );
212                 }
213 
214                 OUString sTarget;
215                 if ( pReqArgs->GetItemState( FN_PARAM_1, true, &pItem ) == SfxItemState::SET )
216                     sTarget = static_cast<const SfxStringItem*>(pItem)->GetValue();
217 
218                 bool bIsNewArea = true;         // Default sal_True (no inquiry)
219                 if ( pReqArgs->GetItemState( FN_PARAM_2, true, &pItem ) == SfxItemState::SET )
220                     bIsNewArea = static_cast<const SfxBoolItem*>(pItem)->GetValue();
221 
222                 // if necessary, create new database area
223                 bool bMakeArea = false;
224                 if (bIsNewArea)
225                 {
226                     ScDBCollection* pDBColl = m_aDocument.GetDBCollection();
227                     if ( !pDBColl || !pDBColl->getNamedDBs().findByUpperName(ScGlobal::pCharClass->uppercase(sTarget)) )
228                     {
229                         ScAddress aPos;
230                         if ( aPos.Parse( sTarget, &m_aDocument, m_aDocument.GetAddressConvention() ) & ScRefFlags::VALID )
231                         {
232                             bMakeArea = true;
233                             if (bUndo)
234                             {
235                                 OUString aStrImport = ScResId( STR_UNDO_IMPORTDATA );
236                                 ViewShellId nViewShellId(-1);
237                                 if (ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell())
238                                     nViewShellId = pViewSh->GetViewShellId();
239                                 GetUndoManager()->EnterListAction( aStrImport, aStrImport, 0, nViewShellId );
240                             }
241 
242                             ScDBData* pDBData = GetDBData( ScRange(aPos), SC_DB_IMPORT, ScGetDBSelection::Keep );
243                             OSL_ENSURE(pDBData, "Cannot create DB data");
244                             sTarget = pDBData->GetName();
245                         }
246                     }
247                 }
248 
249                 // inquire, before old DB range gets overwritten
250                 bool bDo = true;
251                 if (!bIsNewArea)
252                 {
253                     OUString aTemplate = ScResId( STR_IMPORT_REPLACE );
254                     OUString aMessage = aTemplate.getToken( 0, '#' )
255                         + sTarget
256                         + aTemplate.getToken( 1, '#' );
257 
258                     std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(nullptr,
259                                                                    VclMessageType::Question, VclButtonsType::YesNo,
260                                                                    aMessage));
261                     xQueryBox->set_default_response(RET_YES);
262                     bDo = xQueryBox->run() == RET_YES;
263                 }
264 
265                 if (bDo)
266                 {
267                     ScDBDocFunc(*this).UpdateImport( sTarget, aDesc );
268                     rReq.Done();
269 
270                     //  UpdateImport also updates the internal operations
271                 }
272                 else
273                     rReq.Ignore();
274 
275                 if ( bMakeArea && bUndo)
276                     GetUndoManager()->LeaveListAction();
277             }
278             else
279             {
280                 OSL_FAIL( "arguments expected" );
281             }
282         }
283         break;
284 
285         case SID_CHART_SOURCE:
286         case SID_CHART_ADDSOURCE:
287             if (pReqArgs)
288             {
289                 ScDocument& rDoc = GetDocument();
290                 const   SfxPoolItem* pItem;
291                 OUString  aChartName, aRangeName;
292 
293                 ScRange         aSingleRange;
294                 ScRangeListRef  aRangeListRef;
295                 bool            bMultiRange = false;
296 
297                 bool bColHeaders = true;
298                 bool bRowHeaders = true;
299                 bool bColInit = false;
300                 bool bRowInit = false;
301                 bool bAddRange = (nSlot == SID_CHART_ADDSOURCE);
302 
303                 if( pReqArgs->HasItem( SID_CHART_NAME, &pItem ) )
304                     aChartName = static_cast<const SfxStringItem*>(pItem)->GetValue();
305 
306                 if( pReqArgs->HasItem( SID_CHART_SOURCE, &pItem ) )
307                     aRangeName = static_cast<const SfxStringItem*>(pItem)->GetValue();
308 
309                 if( pReqArgs->HasItem( FN_PARAM_1, &pItem ) )
310                 {
311                     bColHeaders = static_cast<const SfxBoolItem*>(pItem)->GetValue();
312                     bColInit = true;
313                 }
314                 if( pReqArgs->HasItem( FN_PARAM_2, &pItem ) )
315                 {
316                     bRowHeaders = static_cast<const SfxBoolItem*>(pItem)->GetValue();
317                     bRowInit = true;
318                 }
319 
320                 ScAddress::Details aDetails(rDoc.GetAddressConvention(), 0, 0);
321                 bool bValid = (aSingleRange.ParseAny(aRangeName, &rDoc, aDetails) & ScRefFlags::VALID) == ScRefFlags::ZERO;
322                 if (!bValid)
323                 {
324                     aRangeListRef = new ScRangeList;
325                     aRangeListRef->Parse( aRangeName, &rDoc );
326                     if ( !aRangeListRef->empty() )
327                     {
328                         bMultiRange = true;
329                         aSingleRange = aRangeListRef->front(); // for header
330                         bValid = true;
331                     }
332                     else
333                         aRangeListRef.clear();
334                 }
335 
336                 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
337                 if (pViewSh && bValid && !aChartName.isEmpty() )
338                 {
339                     weld::Window* pParent = pViewSh->GetFrameWeld();
340 
341                     SCCOL nCol1 = aSingleRange.aStart.Col();
342                     SCROW nRow1 = aSingleRange.aStart.Row();
343                     SCCOL nCol2 = aSingleRange.aEnd.Col();
344                     SCROW nRow2 = aSingleRange.aEnd.Row();
345                     SCTAB nTab = aSingleRange.aStart.Tab();
346 
347                     //! limit always or not at all ???
348                     if (!bMultiRange)
349                         m_aDocument.LimitChartArea( nTab, nCol1,nRow1, nCol2,nRow2 );
350 
351                                         // Dialog for column/row headers
352                     bool bOk = true;
353                     if ( !bAddRange && ( !bColInit || !bRowInit ) )
354                     {
355                         ScChartPositioner aChartPositioner( &m_aDocument, nTab, nCol1,nRow1, nCol2,nRow2 );
356                         if (!bColInit)
357                             bColHeaders = aChartPositioner.HasColHeaders();
358                         if (!bRowInit)
359                             bRowHeaders = aChartPositioner.HasRowHeaders();
360 
361                         ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
362 
363                         ScopedVclPtr<AbstractScColRowLabelDlg> pDlg(pFact->CreateScColRowLabelDlg(pParent, bRowHeaders, bColHeaders));
364                         if ( pDlg->Execute() == RET_OK )
365                         {
366                             bColHeaders = pDlg->IsRow();
367                             bRowHeaders = pDlg->IsCol();
368 
369                             rReq.AppendItem(SfxBoolItem(FN_PARAM_1, bColHeaders));
370                             rReq.AppendItem(SfxBoolItem(FN_PARAM_2, bRowHeaders));
371                         }
372                         else
373                             bOk = false;
374                     }
375 
376                     if (bOk)            // execute
377                     {
378                         if (bMultiRange)
379                         {
380                             if (bUndo)
381                             {
382                                 GetUndoManager()->AddUndoAction(
383                                     std::make_unique<ScUndoChartData>( this, aChartName, aRangeListRef,
384                                                             bColHeaders, bRowHeaders, bAddRange ) );
385                             }
386                             m_aDocument.UpdateChartArea( aChartName, aRangeListRef,
387                                                         bColHeaders, bRowHeaders, bAddRange );
388                         }
389                         else
390                         {
391                             ScRange aNewRange( nCol1,nRow1,nTab, nCol2,nRow2,nTab );
392                             if (bUndo)
393                             {
394                                 GetUndoManager()->AddUndoAction(
395                                     std::make_unique<ScUndoChartData>( this, aChartName, aNewRange,
396                                                             bColHeaders, bRowHeaders, bAddRange ) );
397                             }
398                             m_aDocument.UpdateChartArea( aChartName, aNewRange,
399                                                         bColHeaders, bRowHeaders, bAddRange );
400                         }
401                     }
402                 }
403                 else
404                 {
405                     OSL_FAIL("UpdateChartArea: no ViewShell or wrong data");
406                 }
407                 rReq.Done();
408             }
409             else
410             {
411                 OSL_FAIL("SID_CHART_SOURCE without arguments");
412             }
413             break;
414 
415         case FID_AUTO_CALC:
416             {
417                 bool bNewVal;
418                 const SfxPoolItem* pItem;
419                 if ( pReqArgs && SfxItemState::SET == pReqArgs->GetItemState( nSlot, true, &pItem ) )
420                     bNewVal = static_cast<const SfxBoolItem*>(pItem)->GetValue();
421                 else
422                     bNewVal = !m_aDocument.GetAutoCalc();     // Toggle for menu
423                 m_aDocument.SetAutoCalc( bNewVal );
424                 SetDocumentModified();
425                 if (pBindings)
426                 {
427                     pBindings->Invalidate( FID_AUTO_CALC );
428                 }
429                 rReq.AppendItem( SfxBoolItem( FID_AUTO_CALC, bNewVal ) );
430                 rReq.Done();
431             }
432             break;
433         case FID_RECALC:
434             DoRecalc( rReq.IsAPI() );
435             rReq.Done();
436             break;
437         case FID_HARD_RECALC:
438             DoHardRecalc();
439             rReq.Done();
440             break;
441         case SID_UPDATETABLINKS:
442             {
443                 ScDocument& rDoc = GetDocument();
444 
445                 ScLkUpdMode nSet = rDoc.GetLinkMode();
446 
447                 if(nSet==LM_UNKNOWN)
448                 {
449                     ScAppOptions aAppOptions=SC_MOD()->GetAppOptions();
450                     nSet=aAppOptions.GetLinkMode();
451                 }
452 
453                 if (m_nCanUpdate == css::document::UpdateDocMode::NO_UPDATE)
454                     nSet = LM_NEVER;
455                 else if (m_nCanUpdate == css::document::UpdateDocMode::FULL_UPDATE)
456                     nSet = LM_ALWAYS;
457 
458                 if (nSet == LM_ALWAYS
459                     && !(SvtSecurityOptions()
460                          .isTrustedLocationUriForUpdatingLinks(
461                              GetMedium() == nullptr
462                              ? OUString() : GetMedium()->GetName())
463                          || (IsDocShared()
464                              && SvtSecurityOptions().isTrustedLocationUriForUpdatingLinks(
465                                  GetSharedFileURL()))))
466                 {
467                     nSet = LM_ON_DEMAND;
468                 }
469                 if (m_nCanUpdate == css::document::UpdateDocMode::QUIET_UPDATE
470                     && nSet == LM_ON_DEMAND)
471                 {
472                     nSet = LM_NEVER;
473                 }
474 
475                 if (nSet == LM_ALWAYS)
476                 {
477                     ReloadAllLinks();
478                     rReq.Done();
479                 }
480                 else if (nSet == LM_NEVER)
481                 {
482                     getEmbeddedObjectContainer().setUserAllowsLinkUpdate(false);
483                     rReq.Ignore();
484                 }
485                 else if (nSet == LM_ON_DEMAND)
486                 {
487                     ScTabViewShell* pViewSh = GetBestViewShell();
488                     SfxViewFrame* pViewFrame = pViewSh ? pViewSh->GetFrame() : nullptr;
489                     if (pViewFrame)
490                     {
491                         pViewFrame->RemoveInfoBar("enablecontent");
492                         auto pInfoBar = pViewFrame->AppendInfoBar("enablecontent", ScResId(STR_RELOAD_TABLES), InfoBarType::Warning);
493                         if (pInfoBar)
494                         {
495                             VclPtrInstance<PushButton> xBtn(&pViewFrame->GetWindow());
496                             xBtn->SetText(ScResId(STR_ENABLE_CONTENT));
497                             xBtn->SetSizePixel(xBtn->GetOptimalSize());
498                             xBtn->SetClickHdl(LINK(this, ScDocShell, ReloadAllLinksHdl));
499                             pInfoBar->addButton(xBtn);
500                         }
501                     }
502                     rReq.Done();
503                 }
504             }
505             break;
506 
507         case SID_REIMPORT_AFTER_LOAD:
508             {
509                 //  Is called after loading if there are DB areas with omitted data
510 
511                 bool bDone = false;
512                 ScDBCollection* pDBColl = m_aDocument.GetDBCollection();
513 
514                 if ((m_nCanUpdate != css::document::UpdateDocMode::NO_UPDATE) &&
515                    (m_nCanUpdate != css::document::UpdateDocMode::QUIET_UPDATE))
516                 {
517                     ScRange aRange;
518                     ScTabViewShell* pViewSh = GetBestViewShell();
519                     OSL_ENSURE(pViewSh,"SID_REIMPORT_AFTER_LOAD: no View");
520                     if (pViewSh && pDBColl)
521                     {
522                         vcl::Window* pWin = GetActiveDialogParent();
523                         std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
524                                                                        VclMessageType::Question, VclButtonsType::YesNo,
525                                                                        ScResId(STR_REIMPORT_AFTER_LOAD)));
526                         xQueryBox->set_default_response(RET_YES);
527                         if (xQueryBox->run() == RET_YES)
528                         {
529                             ScDBCollection::NamedDBs& rDBs = pDBColl->getNamedDBs();
530                             for (const auto& rxDB : rDBs)
531                             {
532                                 ScDBData& rDBData = *rxDB;
533                                 if ( rDBData.IsStripData() &&
534                                      rDBData.HasImportParam() && !rDBData.HasImportSelection() )
535                                 {
536                                     rDBData.GetArea(aRange);
537                                     pViewSh->MarkRange(aRange);
538 
539                                     //  Import and internal operations like SID_REFRESH_DBAREA
540                                     //  (inquiry for import not needed here)
541 
542                                     ScImportParam aImportParam;
543                                     rDBData.GetImportParam( aImportParam );
544                                     bool bContinue = pViewSh->ImportData( aImportParam );
545                                     rDBData.SetImportParam( aImportParam );
546 
547                                     //  mark (size may have changed)
548                                     rDBData.GetArea(aRange);
549                                     pViewSh->MarkRange(aRange);
550 
551                                     if ( bContinue )    // error at import -> abort
552                                     {
553                                         //  internal operations, if some where saved
554 
555                                         if ( rDBData.HasQueryParam() || rDBData.HasSortParam() ||
556                                              rDBData.HasSubTotalParam() )
557                                             pViewSh->RepeatDB();
558 
559                                         //  pivot tables, which have the range as source data
560 
561                                         RefreshPivotTables(aRange);
562                                     }
563                                 }
564                             }
565                             bDone = true;
566                         }
567                     }
568                 }
569 
570                 if ( !bDone && pDBColl )
571                 {
572                     //  if not, but then update the dependent formulas
573                     //! also for individual ranges, which cannot be updated
574 
575                     m_aDocument.CalcAll();        //! only for the dependent
576                     PostDataChanged();
577                 }
578 
579                 if (bDone)
580                     rReq.Done();
581                 else
582                     rReq.Ignore();
583             }
584             break;
585 
586         case SID_AUTO_STYLE:
587             OSL_FAIL("use ScAutoStyleHint instead of SID_AUTO_STYLE");
588             break;
589 
590         case SID_GET_COLORLIST:
591             {
592                 const SvxColorListItem* pColItem = GetItem(SID_COLOR_TABLE);
593                 const XColorListRef& pList = pColItem->GetColorList();
594                 rReq.SetReturnValue(OfaRefItem<XColorList>(SID_GET_COLORLIST, pList));
595             }
596             break;
597 
598         case FID_CHG_RECORD:
599             {
600                 ScDocument& rDoc = GetDocument();
601                 // get argument (recorded macro)
602                 const SfxBoolItem* pItem = rReq.GetArg<SfxBoolItem>(FID_CHG_RECORD);
603                 bool bDo = true;
604 
605                 // desired state
606                 ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
607                 bool bActivateTracking = (pChangeTrack == nullptr);   // toggle
608                 if ( pItem )
609                     bActivateTracking = pItem->GetValue();      // from argument
610 
611                 if ( !bActivateTracking )
612                 {
613                     if ( !pItem )
614                     {
615                         // no dialog on playing the macro
616                         vcl::Window* pWin = GetActiveDialogParent();
617                         std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
618                                                                    VclMessageType::Warning, VclButtonsType::YesNo,
619                                                                    ScResId(STR_END_REDLINING)));
620                         xWarn->set_default_response(RET_NO);
621                         bDo = (xWarn->run() == RET_YES );
622                     }
623 
624                     if ( bDo )
625                     {
626                         if (pChangeTrack)
627                         {
628                             if ( pChangeTrack->IsProtected() )
629                                 bDo = ExecuteChangeProtectionDialog();
630                         }
631                         if ( bDo )
632                         {
633                             rDoc.EndChangeTracking();
634                             PostPaintGridAll();
635                         }
636                     }
637                 }
638                 else
639                 {
640                     rDoc.StartChangeTracking();
641                     ScChangeViewSettings aChangeViewSet;
642                     aChangeViewSet.SetShowChanges(true);
643                     rDoc.SetChangeViewSettings(aChangeViewSet);
644                 }
645 
646                 if ( bDo )
647                 {
648                     UpdateAcceptChangesDialog();
649 
650                     // invalidate slots
651                     if (pBindings)
652                         pBindings->InvalidateAll(false);
653                     if ( !pItem )
654                         rReq.AppendItem( SfxBoolItem( FID_CHG_RECORD, bActivateTracking ) );
655                     rReq.Done();
656                 }
657                 else
658                     rReq.Ignore();
659             }
660             break;
661 
662         case SID_CHG_PROTECT :
663             {
664                 if ( ExecuteChangeProtectionDialog() )
665                 {
666                     rReq.Done();
667                     SetDocumentModified();
668                 }
669                 else
670                     rReq.Ignore();
671             }
672             break;
673 
674         case SID_DOCUMENT_MERGE:
675         case SID_DOCUMENT_COMPARE:
676             {
677                 bool bDo = true;
678                 ScChangeTrack* pChangeTrack = m_aDocument.GetChangeTrack();
679                 if ( pChangeTrack && !m_pImpl->bIgnoreLostRedliningWarning )
680                 {
681                     if ( nSlot == SID_DOCUMENT_COMPARE )
682                     {   //! old changes trace will be lost
683                         vcl::Window* pWin = GetActiveDialogParent();
684                         std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
685                                                                    VclMessageType::Warning, VclButtonsType::YesNo,
686                                                                    ScResId(STR_END_REDLINING)));
687                         xWarn->set_default_response(RET_NO);
688                         if (xWarn->run() == RET_YES)
689                             bDo = ExecuteChangeProtectionDialog( true );
690                         else
691                             bDo = false;
692                     }
693                     else    // merge might reject some actions
694                         bDo = ExecuteChangeProtectionDialog( true );
695                 }
696                 if ( !bDo )
697                 {
698                     rReq.Ignore();
699                     break;
700                 }
701                 SfxApplication* pApp = SfxGetpApp();
702                 const SfxPoolItem* pItem;
703                 const SfxStringItem* pStringItem(nullptr);
704                 SfxMedium* pMed = nullptr;
705                 if (pReqArgs && pReqArgs->GetItemState(SID_FILE_NAME, true, &pItem) == SfxItemState::SET)
706                 {
707                     pStringItem = dynamic_cast<const SfxStringItem*>(pItem);
708                 }
709                 if (pStringItem)
710                 {
711                     OUString aFileName = pStringItem->GetValue();
712 
713                     OUString aFilterName;
714                     pStringItem = nullptr;
715                     if (pReqArgs->GetItemState(SID_FILTER_NAME, true, &pItem) == SfxItemState::SET)
716                         pStringItem = dynamic_cast<const SfxStringItem*>(pItem);
717                     if (pStringItem)
718                     {
719                         aFilterName = pStringItem->GetValue();
720                     }
721                     OUString aOptions;
722                     pStringItem = nullptr;
723                     if (pReqArgs->GetItemState(SID_FILE_FILTEROPTIONS, true, &pItem) == SfxItemState::SET)
724                         pStringItem = dynamic_cast<const SfxStringItem*>(pItem);
725                     if (pStringItem)
726                     {
727                         aOptions = pStringItem->GetValue();
728                     }
729                     short nVersion = 0;
730                     const SfxInt16Item* pInt16Item(nullptr);
731                     if (pReqArgs->GetItemState(SID_VERSION, true, &pItem) == SfxItemState::SET)
732                         pInt16Item = dynamic_cast<const SfxInt16Item*>(pItem);
733                     if (pInt16Item)
734                     {
735                         nVersion = pInt16Item->GetValue();
736                     }
737 
738                     //  no filter specified -> detection
739                     if (aFilterName.isEmpty())
740                         ScDocumentLoader::GetFilterName( aFileName, aFilterName, aOptions, true, false );
741 
742                     //  filter name from dialog contains application prefix,
743                     //  GetFilter needs name without the prefix.
744                     ScDocumentLoader::RemoveAppPrefix( aFilterName );
745 
746                     std::shared_ptr<const SfxFilter> pFilter = ScDocShell::Factory().GetFilterContainer()->GetFilter4FilterName( aFilterName );
747                     std::unique_ptr<SfxItemSet> pSet(new SfxAllItemSet( pApp->GetPool() ));
748                     if (!aOptions.isEmpty())
749                         pSet->Put( SfxStringItem( SID_FILE_FILTEROPTIONS, aOptions ) );
750                     if ( nVersion != 0 )
751                         pSet->Put( SfxInt16Item( SID_VERSION, nVersion ) );
752                     pMed = new SfxMedium( aFileName, StreamMode::STD_READ, pFilter, std::move(pSet) );
753                 }
754                 else
755                 {
756                     const sfx2::DocumentInserter::Mode mode { nSlot==SID_DOCUMENT_COMPARE
757                         ? sfx2::DocumentInserter::Mode::Compare
758                         : sfx2::DocumentInserter::Mode::Merge};
759                     // start file dialog asynchronous
760                     m_pImpl->bIgnoreLostRedliningWarning = true;
761                     m_pImpl->pRequest.reset(new SfxRequest( rReq ));
762                     m_pImpl->pDocInserter.reset();
763 
764                     ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
765                     vcl::Window* pParent = pViewSh ? pViewSh->GetDialogParent() : nullptr;
766 
767                     m_pImpl->pDocInserter.reset( new ::sfx2::DocumentInserter(pParent ? pParent->GetFrameWeld() : nullptr,
768                         ScDocShell::Factory().GetFactoryName(), mode ) );
769                     m_pImpl->pDocInserter->StartExecuteModal( LINK( this, ScDocShell, DialogClosedHdl ) );
770                     return ;
771                 }
772 
773                 // now execute in earnest...
774                 SfxErrorContext aEc( ERRCTX_SFX_OPENDOC, pMed->GetName() );
775 
776                 // pOtherDocSh->DoClose() will be called explicitly later, but it is still more safe to use SfxObjectShellLock here
777                 ScDocShell* pOtherDocSh = new ScDocShell;
778                 SfxObjectShellLock aDocShTablesRef = pOtherDocSh;
779                 pOtherDocSh->DoLoad( pMed );
780                 ErrCode nErr = pOtherDocSh->GetErrorCode();
781                 if (nErr)
782                     ErrorHandler::HandleError( nErr );          // also warnings
783 
784                 if ( !pOtherDocSh->GetError() )                 // only errors
785                 {
786                     bool bHadTrack = ( m_aDocument.GetChangeTrack() != nullptr );
787 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
788                     sal_uLong nStart = 0;
789                     if ( nSlot == SID_DOCUMENT_MERGE && pChangeTrack )
790                     {
791                         nStart = pChangeTrack->GetActionMax() + 1;
792                     }
793 #endif
794                     if ( nSlot == SID_DOCUMENT_COMPARE )
795                         CompareDocument( pOtherDocSh->GetDocument() );
796                     else
797                         MergeDocument( pOtherDocSh->GetDocument() );
798 
799                     //  show "accept changes" dialog
800                     //! get view for this document!
801                     if ( !IsDocShared() )
802                     {
803                         SfxViewFrame* pViewFrm = SfxViewFrame::Current();
804                         if ( pViewFrm )
805                         {
806                             pViewFrm->ShowChildWindow( ScAcceptChgDlgWrapper::GetChildWindowId() ); //@51669
807                         }
808                         if ( pBindings )
809                         {
810                             pBindings->Invalidate( FID_CHG_ACCEPT );
811                         }
812                     }
813 
814                     rReq.SetReturnValue( SfxInt32Item( nSlot, 0 ) );        //! ???????
815                     rReq.Done();
816 
817                     if (!bHadTrack)         //  newly turned on -> show as well
818                     {
819                         ScChangeViewSettings* pOldSet = m_aDocument.GetChangeViewSettings();
820                         if ( !pOldSet || !pOldSet->ShowChanges() )
821                         {
822                             ScChangeViewSettings aChangeViewSet;
823                             aChangeViewSet.SetShowChanges(true);
824                             m_aDocument.SetChangeViewSettings(aChangeViewSet);
825                         }
826                     }
827 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
828                     else if ( nSlot == SID_DOCUMENT_MERGE && IsDocShared() && pChangeTrack )
829                     {
830                         sal_uLong nEnd = pChangeTrack->GetActionMax();
831                         if ( nEnd >= nStart )
832                         {
833                             // only show changes from merged document
834                             ScChangeViewSettings aChangeViewSet;
835                             aChangeViewSet.SetShowChanges( true );
836                             aChangeViewSet.SetShowAccepted( true );
837                             aChangeViewSet.SetHasActionRange();
838                             aChangeViewSet.SetTheActionRange( nStart, nEnd );
839                             m_aDocument.SetChangeViewSettings( aChangeViewSet );
840 
841                             // update view
842                             PostPaintExtras();
843                             PostPaintGridAll();
844                         }
845                     }
846 #endif
847                 }
848                 pOtherDocSh->DoClose();     // delete happens with the Ref
849             }
850             break;
851 
852         case SID_DELETE_SCENARIO:
853             if (pReqArgs)
854             {
855                 const SfxPoolItem* pItem;
856                 if ( pReqArgs->GetItemState( nSlot, true, &pItem ) == SfxItemState::SET )
857                 {
858                     if (const SfxStringItem* pStringItem = dynamic_cast<const SfxStringItem*>(pItem))
859                     {
860                         const OUString& aName = pStringItem->GetValue();
861                         SCTAB nTab;
862                         if (m_aDocument.GetTable( aName, nTab ))
863                         {
864                             //  move DeleteTable from viewfunc to docfunc!
865 
866                             ScTabViewShell* pSh = GetBestViewShell();
867                             if ( pSh )
868                             {
869                                 //! omit SetTabNo in DeleteTable?
870                                 SCTAB nDispTab = pSh->GetViewData().GetTabNo();
871                                 pSh->DeleteTable( nTab );
872                                 pSh->SetTabNo(nDispTab);
873                                 rReq.Done();
874                             }
875                         }
876                     }
877                 }
878             }
879             break;
880 
881         case SID_EDIT_SCENARIO:
882             {
883                 const SfxPoolItem* pItem;
884                 if ( pReqArgs->GetItemState( nSlot, true, &pItem ) == SfxItemState::SET )
885                 {
886                     if (const SfxStringItem* pStringItem = dynamic_cast<const SfxStringItem*>(pItem))
887                     {
888                         OUString aName = pStringItem->GetValue();
889                         SCTAB nTab;
890                         if (m_aDocument.GetTable( aName, nTab ))
891                         {
892                             if (m_aDocument.IsScenario(nTab))
893                             {
894                                 OUString aComment;
895                                 Color aColor;
896                                 ScScenarioFlags nFlags;
897                                 m_aDocument.GetScenarioData( nTab, aComment, aColor, nFlags );
898 
899                                 // Determine if the Sheet that the Scenario was created on
900                                 // is protected. But first we need to find that Sheet.
901                                 // Rewind back to the actual sheet.
902                                 SCTAB nActualTab = nTab;
903                                 do
904                                 {
905                                     nActualTab--;
906                                 }
907                                 while(m_aDocument.IsScenario(nActualTab));
908                                 bool bSheetProtected = m_aDocument.IsTabProtected(nActualTab);
909 
910                                 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
911 
912                                 vcl::Window* pWin = GetActiveDialogParent();
913                                 ScopedVclPtr<AbstractScNewScenarioDlg> pNewDlg(pFact->CreateScNewScenarioDlg(pWin ? pWin->GetFrameWeld() : nullptr, aName, true, bSheetProtected));
914                                 pNewDlg->SetScenarioData( aName, aComment, aColor, nFlags );
915                                 if ( pNewDlg->Execute() == RET_OK )
916                                 {
917                                     pNewDlg->GetScenarioData( aName, aComment, aColor, nFlags );
918                                     ModifyScenario( nTab, aName, aComment, aColor, nFlags );
919                                     rReq.Done();
920                                 }
921                             }
922                         }
923                     }
924                 }
925             }
926             break;
927 
928         case SID_ATTR_YEAR2000 :
929         {
930             const SfxPoolItem* pItem;
931             if ( pReqArgs->GetItemState( nSlot, true, &pItem ) == SfxItemState::SET )
932             {
933                 if (const SfxUInt16Item* pInt16Item = dynamic_cast<const SfxUInt16Item*>(pItem))
934                 {
935                     sal_uInt16 nY2k = pInt16Item->GetValue();
936                     // set always to DocOptions, so that it is also saved for S050
937                     // (and all inquiries run up until now on it as well).
938                     // SetDocOptions propagates that to the NumberFormatter
939                     ScDocOptions aDocOpt( m_aDocument.GetDocOptions() );
940                     aDocOpt.SetYear2000( nY2k );
941                     m_aDocument.SetDocOptions( aDocOpt );
942                     // the FormShell shall notice it as well
943                     ScTabViewShell* pSh = GetBestViewShell();
944                     if ( pSh )
945                     {
946                         FmFormShell* pFSh = pSh->GetFormShell();
947                         if ( pFSh )
948                             pFSh->SetY2KState( nY2k );
949                     }
950                 }
951             }
952         }
953         break;
954 
955 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
956         case SID_SHARE_DOC:
957             {
958                 ScViewData* pViewData = GetViewData();
959                 if ( !pViewData )
960                 {
961                     rReq.Ignore();
962                     break;
963                 }
964 
965                 vcl::Window* pWin = GetActiveDialogParent();
966                 ScShareDocumentDlg aDlg(pWin ? pWin->GetFrameWeld() : nullptr, pViewData);
967                 if (aDlg.run() == RET_OK)
968                 {
969                     bool bSetShared = aDlg.IsShareDocumentChecked();
970                     if ( bSetShared != IsDocShared() )
971                     {
972                         if ( bSetShared )
973                         {
974                             bool bContinue = true;
975                             if ( HasName() )
976                             {
977                                 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
978                                                                                VclMessageType::Question, VclButtonsType::YesNo,
979                                                                                ScResId(STR_DOC_WILLBESAVED)));
980                                 xQueryBox->set_default_response(RET_YES);
981                                 if (xQueryBox->run() == RET_NO)
982                                 {
983                                     bContinue = false;
984                                 }
985                             }
986                             if ( bContinue )
987                             {
988                                 EnableSharedSettings( true );
989 
990                                 SC_MOD()->SetInSharedDocSaving( true );
991                                 if ( !SwitchToShared( true, true ) )
992                                 {
993                                     // TODO/LATER: what should be done in case the switch has failed?
994                                     // for example in case the user has cancelled the saveAs operation
995                                 }
996 
997                                 SC_MOD()->SetInSharedDocSaving( false );
998 
999                                 InvalidateName();
1000                                 GetUndoManager()->Clear();
1001 
1002                                 ScTabView* pTabView = dynamic_cast< ScTabView* >( pViewData->GetView() );
1003                                 if ( pTabView )
1004                                 {
1005                                     pTabView->UpdateLayerLocks();
1006                                 }
1007                             }
1008                         }
1009                         else
1010                         {
1011                             uno::Reference< frame::XModel > xModel;
1012                             try
1013                             {
1014                                 // load shared file
1015                                 xModel.set( LoadSharedDocument(), uno::UNO_QUERY_THROW );
1016                                 uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY_THROW );
1017 
1018                                 // check if shared flag is set in shared file
1019                                 bool bShared = false;
1020                                 ScModelObj* pDocObj = ScModelObj::getImplementation( xModel );
1021                                 if ( pDocObj )
1022                                 {
1023                                     ScDocShell* pDocShell = dynamic_cast< ScDocShell* >( pDocObj->GetEmbeddedObject() );
1024                                     if ( pDocShell )
1025                                     {
1026                                         bShared = pDocShell->HasSharedXMLFlagSet();
1027                                     }
1028                                 }
1029 
1030                                 // #i87870# check if shared status was disabled and enabled again
1031                                 bool bOwnEntry = false;
1032                                 try
1033                                 {
1034                                     ::svt::ShareControlFile aControlFile( GetSharedFileURL() );
1035                                     bOwnEntry = aControlFile.HasOwnEntry();
1036                                 }
1037                                 catch ( uno::Exception& )
1038                                 {
1039                                 }
1040 
1041                                 if ( bShared && bOwnEntry )
1042                                 {
1043                                     uno::Reference< frame::XStorable > xStorable( xModel, uno::UNO_QUERY_THROW );
1044                                     if ( xStorable->isReadonly() )
1045                                     {
1046                                         xCloseable->close( true );
1047 
1048                                         OUString aUserName( ScResId( STR_UNKNOWN_USER ) );
1049                                         try
1050                                         {
1051                                             ::svt::DocumentLockFile aLockFile( GetSharedFileURL() );
1052                                             LockFileEntry aData = aLockFile.GetLockData();
1053                                             if ( !aData[LockFileComponent::OOOUSERNAME].isEmpty() )
1054                                             {
1055                                                 aUserName = aData[LockFileComponent::OOOUSERNAME];
1056                                             }
1057                                             else if ( !aData[LockFileComponent::SYSUSERNAME].isEmpty() )
1058                                             {
1059                                                 aUserName = aData[LockFileComponent::SYSUSERNAME];
1060                                             }
1061                                         }
1062                                         catch ( uno::Exception& )
1063                                         {
1064                                         }
1065                                         OUString aMessage( ScResId( STR_FILE_LOCKED_TRY_LATER ) );
1066                                         aMessage = aMessage.replaceFirst( "%1", aUserName );
1067 
1068                                         std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
1069                                                                                    VclMessageType::Warning, VclButtonsType::Ok,
1070                                                                                    aMessage));
1071                                         xWarn->run();
1072                                     }
1073                                     else
1074                                     {
1075                                         std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
1076                                                                                    VclMessageType::Warning, VclButtonsType::YesNo,
1077                                                                                    ScResId(STR_DOC_DISABLESHARED)));
1078                                         xWarn->set_default_response(RET_YES);
1079 
1080                                         if (xWarn->run() == RET_YES)
1081                                         {
1082                                             xCloseable->close( true );
1083 
1084                                             if ( !SwitchToShared( false, true ) )
1085                                             {
1086                                                 // TODO/LATER: what should be done in case the switch has failed?
1087                                                 // for example in case the user has cancelled the saveAs operation
1088                                             }
1089 
1090                                             EnableSharedSettings( false );
1091 
1092                                             if ( pBindings )
1093                                             {
1094                                                 pBindings->ExecuteSynchron( SID_SAVEDOC );
1095                                             }
1096 
1097                                             ScTabView* pTabView = dynamic_cast< ScTabView* >( pViewData->GetView() );
1098                                             if ( pTabView )
1099                                             {
1100                                                 pTabView->UpdateLayerLocks();
1101                                             }
1102                                         }
1103                                         else
1104                                         {
1105                                             xCloseable->close( true );
1106                                         }
1107                                     }
1108                                 }
1109                                 else
1110                                 {
1111                                     xCloseable->close( true );
1112                                     std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
1113                                                                                VclMessageType::Warning, VclButtonsType::Ok,
1114                                                                                ScResId(STR_DOC_NOLONGERSHARED)));
1115                                     xWarn->run();
1116                                 }
1117                             }
1118                             catch ( uno::Exception& )
1119                             {
1120                                 OSL_FAIL( "SID_SHARE_DOC: caught exception" );
1121                                 SC_MOD()->SetInSharedDocSaving( false );
1122 
1123                                 try
1124                                 {
1125                                     uno::Reference< util::XCloseable > xClose( xModel, uno::UNO_QUERY_THROW );
1126                                     xClose->close( true );
1127                                 }
1128                                 catch ( uno::Exception& )
1129                                 {
1130                                 }
1131                             }
1132                         }
1133                     }
1134                 }
1135                 rReq.Done();
1136             }
1137             break;
1138 #endif
1139         case SID_OPEN_CALC:
1140         {
1141             SfxStringItem aApp(SID_DOC_SERVICE, OUString("com.sun.star.sheet.SpreadsheetDocument"));
1142             SfxStringItem aTarget(SID_TARGETNAME, OUString("_blank"));
1143             GetViewData()->GetDispatcher().ExecuteList(
1144                 SID_OPENDOC, SfxCallMode::API|SfxCallMode::SYNCHRON,
1145                 { &aApp, &aTarget });
1146         }
1147         break;
1148         case SID_NOTEBOOKBAR:
1149         {
1150             const SfxStringItem* pFile = rReq.GetArg<SfxStringItem>( SID_NOTEBOOKBAR );
1151 
1152             if ( pBindings && sfx2::SfxNotebookBar::IsActive() )
1153                 sfx2::SfxNotebookBar::ExecMethod(*pBindings, pFile ? pFile->GetValue() : "");
1154             else if ( pBindings )
1155                 sfx2::SfxNotebookBar::CloseMethod(*pBindings);
1156         }
1157         break;
1158         case SID_LANGUAGE_STATUS:
1159         {
1160             sal_Int32 nPos = 0;
1161             OUString aLangText;
1162             const SfxStringItem* pItem = rReq.GetArg<SfxStringItem>(nSlot);
1163             if ( pItem )
1164                 aLangText = pItem->GetValue();
1165 
1166             if ( !aLangText.isEmpty() )
1167             {
1168                 LanguageType eLang, eLatin, eCjk, eCtl;
1169                 const OUString aDocLangPrefix("Default_");
1170                 const OUString aNoLang("LANGUAGE_NONE");
1171                 const OUString aResetLang("RESET_LANGUAGES");
1172 
1173                 ScDocument& rDoc = GetDocument();
1174                 rDoc.GetLanguage( eLatin, eCjk, eCtl );
1175 
1176                 if ( aLangText == "*" )
1177                 {
1178                     SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create();
1179                     ScopedVclPtr<VclAbstractDialog> pDlg(pFact->CreateVclDialog(GetActiveDialogParent(), SID_LANGUAGE_OPTIONS));
1180                     pDlg->Execute();
1181 
1182                     rDoc.GetLanguage( eLang, eCjk, eCtl );
1183                 }
1184                 else if ( (nPos = aLangText.indexOf(aDocLangPrefix)) != -1 )
1185                 {
1186                     aLangText = aLangText.replaceAt(nPos, aDocLangPrefix.getLength(), "");
1187 
1188                     if ( aLangText == aNoLang )
1189                     {
1190                         eLang = LANGUAGE_NONE;
1191                         rDoc.SetLanguage( eLang, eCjk, eCtl );
1192                     }
1193                     else if ( aLangText == aResetLang )
1194                     {
1195                         bool bAutoSpell;
1196 
1197                         ScModule::GetSpellSettings(eLang, eCjk, eCtl, bAutoSpell);
1198                         rDoc.SetLanguage(eLang, eCjk, eCtl);
1199                     }
1200                     else
1201                     {
1202                         eLang = SvtLanguageTable::GetLanguageType( aLangText );
1203                         if ( eLang != LANGUAGE_DONTKNOW  && SvtLanguageOptions::GetScriptTypeOfLanguage(eLang) == SvtScriptType::LATIN )
1204                         {
1205                             rDoc.SetLanguage( eLang, eCjk, eCtl );
1206                         }
1207                         else
1208                         {
1209                             eLang = eLatin;
1210                         }
1211                     }
1212                 }
1213 
1214                 if ( eLang != eLatin )
1215                 {
1216                     if ( ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell() )
1217                     {
1218                         ScInputHandler* pInputHandler = SC_MOD()->GetInputHdl(pViewSh);
1219                         if ( pInputHandler )
1220                             pInputHandler->UpdateSpellSettings();
1221 
1222                         pViewSh->UpdateDrawTextOutliner();
1223                     }
1224 
1225                     SetDocumentModified();
1226                     Broadcast(SfxHint(SfxHintId::LanguageChanged));
1227                     PostPaintGridAll();
1228                 }
1229             }
1230         }
1231         break;
1232         default:
1233         {
1234             // small (?) hack -> forwarding of the slots to TabViewShell
1235             ScTabViewShell* pSh = GetBestViewShell();
1236             if ( pSh )
1237                 pSh->Execute( rReq );
1238 #if HAVE_FEATURE_SCRIPTING
1239             else
1240                 SbxBase::SetError( ERRCODE_BASIC_NO_ACTIVE_OBJECT );
1241 #endif
1242         }
1243     }
1244 }
1245 
1246 void UpdateAcceptChangesDialog()
1247 {
1248     //  update "accept changes" dialog
1249     //! notify all views
1250     SfxViewFrame* pViewFrm = SfxViewFrame::Current();
1251     if ( pViewFrm && pViewFrm->HasChildWindow( FID_CHG_ACCEPT ) )
1252     {
1253         SfxChildWindow* pChild = pViewFrm->GetChildWindow( FID_CHG_ACCEPT );
1254         if ( pChild )
1255             static_cast<ScAcceptChgDlgWrapper*>(pChild)->ReInitDlg();
1256     }
1257 }
1258 
1259 bool ScDocShell::ExecuteChangeProtectionDialog( bool bJustQueryIfProtected )
1260 {
1261     bool bDone = false;
1262     ScChangeTrack* pChangeTrack = m_aDocument.GetChangeTrack();
1263     if ( pChangeTrack )
1264     {
1265         bool bProtected = pChangeTrack->IsProtected();
1266         if ( bJustQueryIfProtected && !bProtected )
1267             return true;
1268 
1269         OUString aTitle( ScResId( bProtected ? SCSTR_CHG_UNPROTECT : SCSTR_CHG_PROTECT ) );
1270         OUString aText( ScResId( SCSTR_PASSWORD ) );
1271         OUString aPassword;
1272 
1273         vcl::Window* pWin = ScDocShell::GetActiveDialogParent();
1274         SfxPasswordDialog aDlg(pWin ? pWin->GetFrameWeld() : nullptr, &aText);
1275         aDlg.set_title(aTitle);
1276         aDlg.SetMinLen(1);
1277         aDlg.set_help_id(GetStaticInterface()->GetSlot(SID_CHG_PROTECT)->GetCommand());
1278         aDlg.SetEditHelpId( HID_CHG_PROTECT );
1279         if ( !bProtected )
1280             aDlg.ShowExtras(SfxShowExtras::CONFIRM);
1281         if (aDlg.run() == RET_OK)
1282             aPassword = aDlg.GetPassword();
1283 
1284         if (!aPassword.isEmpty())
1285         {
1286             if ( bProtected )
1287             {
1288                 if ( SvPasswordHelper::CompareHashPassword(pChangeTrack->GetProtection(), aPassword) )
1289                 {
1290                     if ( bJustQueryIfProtected )
1291                         bDone = true;
1292                     else
1293                         pChangeTrack->SetProtection(
1294                             css::uno::Sequence< sal_Int8 > (0) );
1295                 }
1296                 else
1297                 {
1298                     std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
1299                                                                   VclMessageType::Info, VclButtonsType::Ok,
1300                                                                   ScResId(SCSTR_WRONGPASSWORD)));
1301                     xInfoBox->run();
1302                 }
1303             }
1304             else
1305             {
1306                 css::uno::Sequence< sal_Int8 > aPass;
1307                 SvPasswordHelper::GetHashPassword( aPass, aPassword );
1308                 pChangeTrack->SetProtection( aPass );
1309             }
1310             if ( bProtected != pChangeTrack->IsProtected() )
1311             {
1312                 UpdateAcceptChangesDialog();
1313                 bDone = true;
1314             }
1315         }
1316     }
1317     else if ( bJustQueryIfProtected )
1318         bDone = true;
1319     return bDone;
1320 }
1321 
1322 void ScDocShell::DoRecalc( bool bApi )
1323 {
1324     ScDocShellRecalcGuard aGuard(m_aDocument);
1325     bool bDone = false;
1326     ScTabViewShell* pSh = GetBestViewShell();
1327     ScInputHandler* pHdl = ( pSh ? SC_MOD()->GetInputHdl( pSh ) : nullptr );
1328     if ( pSh )
1329     {
1330         if ( pHdl && pHdl->IsInputMode() && pHdl->IsFormulaMode() && !bApi )
1331         {
1332             pHdl->FormulaPreview();     // partial result as QuickHelp
1333             bDone = true;
1334         }
1335         else
1336         {
1337             ScTabView::UpdateInputLine();     // InputEnterHandler
1338             pSh->UpdateInputHandler();
1339         }
1340     }
1341     if (!bDone)                         // otherwise re-calculate document
1342     {
1343         WaitObject aWaitObj( GetActiveDialogParent() );
1344         if ( pHdl )
1345         {
1346             // tdf97897 set current cell to Dirty to force recalculation of cell
1347             ScFormulaCell* pFC = m_aDocument.GetFormulaCell( pHdl->GetCursorPos());
1348             if (pFC)
1349                 pFC->SetDirty();
1350         }
1351         m_aDocument.CalcFormulaTree();
1352         if ( pSh )
1353             pSh->UpdateCharts(true);
1354 
1355         m_aDocument.BroadcastUno( SfxHint( SfxHintId::DataChanged ) );
1356 
1357         //  If there are charts, then paint everything, so that PostDataChanged
1358         //  and the charts do not come one after the other and parts are painted twice.
1359 
1360         ScChartListenerCollection* pCharts = m_aDocument.GetChartListenerCollection();
1361         if ( pCharts && pCharts->hasListeners() )
1362             PostPaintGridAll();
1363         else
1364             PostDataChanged();
1365     }
1366 }
1367 
1368 void ScDocShell::DoHardRecalc()
1369 {
1370     auto start = std::chrono::steady_clock::now();
1371     ScDocShellRecalcGuard aGuard(m_aDocument);
1372     WaitObject aWaitObj( GetActiveDialogParent() );
1373     ScTabViewShell* pSh = GetBestViewShell();
1374     if ( pSh )
1375     {
1376         ScTabView::UpdateInputLine();     // InputEnterHandler
1377         pSh->UpdateInputHandler();
1378     }
1379     m_aDocument.CalcAll();
1380     GetDocFunc().DetectiveRefresh();    // creates own Undo
1381     if ( pSh )
1382         pSh->UpdateCharts(true);
1383 
1384     // set notification flags for "calculate" event (used in SfxHintId::DataChanged broadcast)
1385     // (might check for the presence of any formulas on each sheet)
1386     SCTAB nTabCount = m_aDocument.GetTableCount();
1387     if (m_aDocument.HasAnySheetEventScript( ScSheetEventId::CALCULATE, true )) // search also for VBA handler
1388         for (SCTAB nTab=0; nTab<nTabCount; nTab++)
1389             m_aDocument.SetCalcNotification(nTab);
1390 
1391     // CalcAll doesn't broadcast value changes, so SfxHintId::ScCalcAll is broadcasted globally
1392     // in addition to SfxHintId::DataChanged.
1393     m_aDocument.BroadcastUno( SfxHint( SfxHintId::ScCalcAll ) );
1394     m_aDocument.BroadcastUno( SfxHint( SfxHintId::DataChanged ) );
1395 
1396     // use hard recalc also to disable stream-copying of all sheets
1397     // (somewhat consistent with charts)
1398     for (SCTAB nTab=0; nTab<nTabCount; nTab++)
1399         m_aDocument.SetStreamValid(nTab, false);
1400 
1401     PostPaintGridAll();
1402     auto end = std::chrono::steady_clock::now();
1403     SAL_INFO("sc.timing", "ScDocShell::DoHardRecalc(): took " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms");
1404 }
1405 
1406 void ScDocShell::DoAutoStyle( const ScRange& rRange, const OUString& rStyle )
1407 {
1408     ScStyleSheetPool* pStylePool = m_aDocument.GetStyleSheetPool();
1409     ScStyleSheet* pStyleSheet =
1410         pStylePool->FindCaseIns( rStyle, SfxStyleFamily::Para );
1411     if (!pStyleSheet)
1412         pStyleSheet = static_cast<ScStyleSheet*>(
1413             pStylePool->Find( ScResId(STR_STYLENAME_STANDARD), SfxStyleFamily::Para ));
1414     if (pStyleSheet)
1415     {
1416         OSL_ENSURE(rRange.aStart.Tab() == rRange.aEnd.Tab(),
1417                         "DoAutoStyle with several tables");
1418         SCTAB nTab = rRange.aStart.Tab();
1419         SCCOL nStartCol = rRange.aStart.Col();
1420         SCROW nStartRow = rRange.aStart.Row();
1421         SCCOL nEndCol = rRange.aEnd.Col();
1422         SCROW nEndRow = rRange.aEnd.Row();
1423         m_aDocument.ApplyStyleAreaTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, *pStyleSheet );
1424         m_aDocument.ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, nTab );
1425         PostPaint( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, PaintPartFlags::Grid );
1426     }
1427 }
1428 
1429 void ScDocShell::NotifyStyle( const SfxStyleSheetHint& rHint )
1430 {
1431     SfxHintId nId = rHint.GetId();
1432     const SfxStyleSheetBase* pStyle = rHint.GetStyleSheet();
1433     if (!pStyle)
1434         return;
1435 
1436     if ( pStyle->GetFamily() == SfxStyleFamily::Page )
1437     {
1438         if ( nId == SfxHintId::StyleSheetModified )
1439         {
1440             ScDocShellModificator aModificator( *this );
1441 
1442             const OUString& aNewName = pStyle->GetName();
1443             OUString aOldName = aNewName;
1444             const SfxStyleSheetModifiedHint* pExtendedHint = dynamic_cast<const SfxStyleSheetModifiedHint*>(&rHint); // name changed?
1445             if (pExtendedHint)
1446                 aOldName = pExtendedHint->GetOldName();
1447 
1448             if ( aNewName != aOldName )
1449                 m_aDocument.RenamePageStyleInUse( aOldName, aNewName );
1450 
1451             SCTAB nTabCount = m_aDocument.GetTableCount();
1452             for (SCTAB nTab=0; nTab<nTabCount; nTab++)
1453                 if (m_aDocument.GetPageStyle(nTab) == aNewName)   // already adjusted to new
1454                 {
1455                     m_aDocument.PageStyleModified( nTab, aNewName );
1456                     ScPrintFunc aPrintFunc( this, GetPrinter(), nTab );
1457                     aPrintFunc.UpdatePages();
1458                 }
1459 
1460             aModificator.SetDocumentModified();
1461 
1462             if (pExtendedHint)
1463             {
1464                 SfxBindings* pBindings = GetViewBindings();
1465                 if (pBindings)
1466                 {
1467                     pBindings->Invalidate( SID_STATUS_PAGESTYLE );
1468                     pBindings->Invalidate( SID_STYLE_FAMILY4 );
1469                     pBindings->Invalidate( FID_RESET_PRINTZOOM );
1470                     pBindings->Invalidate( SID_ATTR_PARA_LEFT_TO_RIGHT );
1471                     pBindings->Invalidate( SID_ATTR_PARA_RIGHT_TO_LEFT );
1472                 }
1473             }
1474         }
1475     }
1476     else if ( pStyle->GetFamily() == SfxStyleFamily::Para )
1477     {
1478         if ( nId == SfxHintId::StyleSheetModified)
1479         {
1480             const OUString& aNewName = pStyle->GetName();
1481             OUString aOldName = aNewName;
1482             const SfxStyleSheetModifiedHint* pExtendedHint = dynamic_cast<const SfxStyleSheetModifiedHint*>(&rHint);
1483             if (pExtendedHint)
1484                 aOldName = pExtendedHint->GetOldName();
1485             if ( aNewName != aOldName )
1486             {
1487                 for(SCTAB i = 0; i < m_aDocument.GetTableCount(); ++i)
1488                 {
1489                     ScConditionalFormatList* pList = m_aDocument.GetCondFormList(i);
1490                     if (pList)
1491                         pList->RenameCellStyle( aOldName,aNewName );
1492                 }
1493             }
1494         }
1495     }
1496 
1497     //  everything else goes via slots...
1498 }
1499 
1500 //  like in printfun.cxx
1501 #define ZOOM_MIN    10
1502 
1503 void ScDocShell::SetPrintZoom( SCTAB nTab, sal_uInt16 nScale, sal_uInt16 nPages )
1504 {
1505     OUString aStyleName = m_aDocument.GetPageStyle( nTab );
1506     ScStyleSheetPool* pStylePool = m_aDocument.GetStyleSheetPool();
1507     SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SfxStyleFamily::Page );
1508     OSL_ENSURE( pStyleSheet, "PageStyle not found" );
1509     if ( pStyleSheet )
1510     {
1511         ScDocShellModificator aModificator( *this );
1512 
1513         SfxItemSet& rSet = pStyleSheet->GetItemSet();
1514         const bool bUndo(m_aDocument.IsUndoEnabled());
1515         if (bUndo)
1516         {
1517             sal_uInt16 nOldScale = rSet.Get(ATTR_PAGE_SCALE).GetValue();
1518             sal_uInt16 nOldPages = rSet.Get(ATTR_PAGE_SCALETOPAGES).GetValue();
1519             GetUndoManager()->AddUndoAction( std::make_unique<ScUndoPrintZoom>(
1520                             this, nTab, nOldScale, nOldPages, nScale, nPages ) );
1521         }
1522 
1523         rSet.Put( SfxUInt16Item( ATTR_PAGE_SCALE, nScale ) );
1524         rSet.Put( SfxUInt16Item( ATTR_PAGE_SCALETOPAGES, nPages ) );
1525 
1526         ScPrintFunc aPrintFunc( this, GetPrinter(), nTab );
1527         aPrintFunc.UpdatePages();
1528         aModificator.SetDocumentModified();
1529 
1530         SfxBindings* pBindings = GetViewBindings();
1531         if (pBindings)
1532             pBindings->Invalidate( FID_RESET_PRINTZOOM );
1533     }
1534 }
1535 
1536 bool ScDocShell::AdjustPrintZoom( const ScRange& rRange )
1537 {
1538     bool bChange = false;
1539     SCTAB nTab = rRange.aStart.Tab();
1540 
1541     OUString aStyleName = m_aDocument.GetPageStyle( nTab );
1542     ScStyleSheetPool* pStylePool = m_aDocument.GetStyleSheetPool();
1543     SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SfxStyleFamily::Page );
1544     OSL_ENSURE( pStyleSheet, "PageStyle not found" );
1545     if ( pStyleSheet )
1546     {
1547         SfxItemSet& rSet = pStyleSheet->GetItemSet();
1548         bool bHeaders = rSet.Get(ATTR_PAGE_HEADERS).GetValue();
1549         sal_uInt16 nOldScale = rSet.Get(ATTR_PAGE_SCALE).GetValue();
1550         sal_uInt16 nOldPages = rSet.Get(ATTR_PAGE_SCALETOPAGES).GetValue();
1551         const ScRange* pRepeatCol = m_aDocument.GetRepeatColRange( nTab );
1552         const ScRange* pRepeatRow = m_aDocument.GetRepeatRowRange( nTab );
1553 
1554         //  calculate needed scaling for selection
1555 
1556         sal_uInt16 nNewScale = nOldScale;
1557 
1558         long nBlkTwipsX = 0;
1559         if (bHeaders)
1560             nBlkTwipsX += long(PRINT_HEADER_WIDTH);
1561         SCCOL nStartCol = rRange.aStart.Col();
1562         SCCOL nEndCol = rRange.aEnd.Col();
1563         if ( pRepeatCol && nStartCol >= pRepeatCol->aStart.Col() )
1564         {
1565             for (SCCOL i=pRepeatCol->aStart.Col(); i<=pRepeatCol->aEnd.Col(); i++ )
1566                 nBlkTwipsX += m_aDocument.GetColWidth( i, nTab );
1567             if ( nStartCol <= pRepeatCol->aEnd.Col() )
1568                 nStartCol = pRepeatCol->aEnd.Col() + 1;
1569         }
1570         // legacy compilers' own scope for i
1571         {
1572             for ( SCCOL i=nStartCol; i<=nEndCol; i++ )
1573                 nBlkTwipsX += m_aDocument.GetColWidth( i, nTab );
1574         }
1575 
1576         long nBlkTwipsY = 0;
1577         if (bHeaders)
1578             nBlkTwipsY += long(PRINT_HEADER_HEIGHT);
1579         SCROW nStartRow = rRange.aStart.Row();
1580         SCROW nEndRow = rRange.aEnd.Row();
1581         if ( pRepeatRow && nStartRow >= pRepeatRow->aStart.Row() )
1582         {
1583             nBlkTwipsY += m_aDocument.GetRowHeight( pRepeatRow->aStart.Row(),
1584                     pRepeatRow->aEnd.Row(), nTab );
1585             if ( nStartRow <= pRepeatRow->aEnd.Row() )
1586                 nStartRow = pRepeatRow->aEnd.Row() + 1;
1587         }
1588         nBlkTwipsY += m_aDocument.GetRowHeight( nStartRow, nEndRow, nTab );
1589 
1590         Size aPhysPage;
1591         long nHdr, nFtr;
1592         ScPrintFunc aOldPrFunc( this, GetPrinter(), nTab );
1593         aOldPrFunc.GetScaleData( aPhysPage, nHdr, nFtr );
1594         nBlkTwipsY += nHdr + nFtr;
1595 
1596         if ( nBlkTwipsX == 0 )      // hidden columns/rows may lead to 0
1597             nBlkTwipsX = 1;
1598         if ( nBlkTwipsY == 0 )
1599             nBlkTwipsY = 1;
1600 
1601         long nNeeded = std::min( aPhysPage.Width()  * 100 / nBlkTwipsX,
1602                             aPhysPage.Height() * 100 / nBlkTwipsY );
1603         if ( nNeeded < ZOOM_MIN )
1604             nNeeded = ZOOM_MIN;         // boundary
1605         if ( nNeeded < static_cast<long>(nNewScale) )
1606             nNewScale = static_cast<sal_uInt16>(nNeeded);
1607 
1608         bChange = ( nNewScale != nOldScale || nOldPages != 0 );
1609         if ( bChange )
1610             SetPrintZoom( nTab, nNewScale, 0 );
1611     }
1612     return bChange;
1613 }
1614 
1615 void ScDocShell::PageStyleModified( const OUString& rStyleName, bool bApi )
1616 {
1617     ScDocShellModificator aModificator( *this );
1618 
1619     SCTAB nTabCount = m_aDocument.GetTableCount();
1620     SCTAB nUseTab = MAXTAB+1;
1621     for (SCTAB nTab=0; nTab<nTabCount && nUseTab>MAXTAB; nTab++)
1622         if ( m_aDocument.GetPageStyle(nTab) == rStyleName &&
1623                 ( !bApi || m_aDocument.GetPageSize(nTab).Width() ) )
1624             nUseTab = nTab;
1625                                 // at bApi only if breaks already shown
1626 
1627     if (ValidTab(nUseTab))      // not used -> nothing to do
1628     {
1629         bool bWarn = false;
1630 
1631         ScPrintFunc aPrintFunc( this, GetPrinter(), nUseTab );  //! cope without CountPages
1632         if (!aPrintFunc.UpdatePages())                          //  sets breaks on all tabs
1633             bWarn = true;
1634 
1635         if (bWarn && !bApi)
1636         {
1637             vcl::Window* pWin = GetActiveDialogParent();
1638             ScWaitCursorOff aWaitOff(pWin);
1639             std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pWin ? pWin->GetFrameWeld() : nullptr,
1640                                                           VclMessageType::Info, VclButtonsType::Ok,
1641                                                           ScResId(STR_PRINT_INVALID_AREA)));
1642             xInfoBox->run();
1643         }
1644     }
1645 
1646     aModificator.SetDocumentModified();
1647 
1648     SfxBindings* pBindings = GetViewBindings();
1649     if (pBindings)
1650     {
1651         pBindings->Invalidate( FID_RESET_PRINTZOOM );
1652         pBindings->Invalidate( SID_ATTR_PARA_LEFT_TO_RIGHT );
1653         pBindings->Invalidate( SID_ATTR_PARA_RIGHT_TO_LEFT );
1654     }
1655 }
1656 
1657 void ScDocShell::ExecutePageStyle( const SfxViewShell& rCaller,
1658                                    SfxRequest&   rReq,
1659                                    SCTAB         nCurTab )
1660 {
1661     const SfxItemSet* pReqArgs = rReq.GetArgs();
1662 
1663     switch ( rReq.GetSlot() )
1664     {
1665         case SID_STATUS_PAGESTYLE:  // click on StatusBar control
1666         case SID_FORMATPAGE:
1667             {
1668                 if ( pReqArgs == nullptr )
1669                 {
1670                     OUString aOldName = m_aDocument.GetPageStyle( nCurTab );
1671                     ScStyleSheetPool* pStylePool = m_aDocument.GetStyleSheetPool();
1672                     SfxStyleSheetBase* pStyleSheet
1673                         = pStylePool->Find( aOldName, SfxStyleFamily::Page );
1674 
1675                     OSL_ENSURE( pStyleSheet, "PageStyle not found! :-/" );
1676 
1677                     if ( pStyleSheet )
1678                     {
1679                         ScStyleSaveData aOldData;
1680                         const bool bUndo(m_aDocument.IsUndoEnabled());
1681                         if (bUndo)
1682                             aOldData.InitFromStyle( pStyleSheet );
1683 
1684                         SfxItemSet&     rStyleSet = pStyleSheet->GetItemSet();
1685                         rStyleSet.MergeRange( XATTR_FILL_FIRST, XATTR_FILL_LAST );
1686 
1687                         ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
1688 
1689                         vcl::Window* pParent = GetActiveDialogParent();
1690                         VclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateScStyleDlg(pParent ? pParent->GetFrameWeld() : nullptr, *pStyleSheet, true));
1691 
1692                         std::shared_ptr<SfxRequest> pRequest(new SfxRequest(rReq));
1693                         rReq.Ignore(); // the 'old' request is not relevant any more
1694                         pDlg->StartExecuteAsync([this, pDlg, pRequest, pStyleSheet, aOldData, aOldName, &rStyleSet, nCurTab, &rCaller, bUndo](sal_Int32 nResult){
1695                             if ( nResult == RET_OK )
1696                             {
1697                                 const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
1698 
1699                                 WaitObject aWait( GetActiveDialogParent() );
1700 
1701                                 OUString aNewName = pStyleSheet->GetName();
1702                                 if ( aNewName != aOldName &&
1703                                     m_aDocument.RenamePageStyleInUse( aOldName, aNewName ) )
1704                                 {
1705                                     SfxBindings* pBindings = GetViewBindings();
1706                                     if (pBindings)
1707                                     {
1708                                         pBindings->Invalidate( SID_STATUS_PAGESTYLE );
1709                                         pBindings->Invalidate( FID_RESET_PRINTZOOM );
1710                                     }
1711                                 }
1712 
1713                                 if ( pOutSet )
1714                                     m_aDocument.ModifyStyleSheet( *pStyleSheet, *pOutSet );
1715 
1716                                 // memorizing for GetState():
1717                                 GetPageOnFromPageStyleSet( &rStyleSet, nCurTab, m_bHeaderOn, m_bFooterOn );
1718                                 rCaller.GetViewFrame()->GetBindings().Invalidate( SID_HFEDIT );
1719 
1720                                 ScStyleSaveData aNewData;
1721                                 aNewData.InitFromStyle( pStyleSheet );
1722                                 if (bUndo)
1723                                 {
1724                                     GetUndoManager()->AddUndoAction(
1725                                             std::make_unique<ScUndoModifyStyle>( this, SfxStyleFamily::Page,
1726                                                         aOldData, aNewData ) );
1727                                 }
1728 
1729                                 PageStyleModified( aNewName, false );
1730                                 pRequest->Done();
1731                             }
1732                             pDlg->disposeOnce();
1733                         });
1734                     }
1735                 }
1736             }
1737             break;
1738 
1739         case SID_HFEDIT:
1740             {
1741                 if ( pReqArgs == nullptr )
1742                 {
1743                     OUString aStr( m_aDocument.GetPageStyle( nCurTab ) );
1744 
1745                     ScStyleSheetPool* pStylePool
1746                         = m_aDocument.GetStyleSheetPool();
1747 
1748                     SfxStyleSheetBase* pStyleSheet
1749                         = pStylePool->Find( aStr, SfxStyleFamily::Page );
1750 
1751                     OSL_ENSURE( pStyleSheet, "PageStyle not found! :-/" );
1752 
1753                     if ( pStyleSheet )
1754                     {
1755                         SfxItemSet&  rStyleSet = pStyleSheet->GetItemSet();
1756 
1757                         SvxPageUsage eUsage = rStyleSet.Get( ATTR_PAGE ).GetPageUsage();
1758                         bool bShareHeader = rStyleSet
1759                                                     .Get(ATTR_PAGE_HEADERSET)
1760                                                     .GetItemSet()
1761                                                     .Get(ATTR_PAGE_SHARED)
1762                                                     .GetValue();
1763                         bool bShareFooter = rStyleSet
1764                                                     .Get(ATTR_PAGE_FOOTERSET)
1765                                                     .GetItemSet()
1766                                                     .Get(ATTR_PAGE_SHARED)
1767                                                     .GetValue();
1768                         sal_uInt16 nResId = 0;
1769 
1770                         switch ( eUsage )
1771                         {
1772                             case SvxPageUsage::Left:
1773                             case SvxPageUsage::Right:
1774                             {
1775                                 if ( m_bHeaderOn && m_bFooterOn )
1776                                     nResId = RID_SCDLG_HFEDIT;
1777                                 else if ( SvxPageUsage::Right == eUsage )
1778                                 {
1779                                     if ( !m_bHeaderOn && m_bFooterOn )
1780                                         nResId = RID_SCDLG_HFEDIT_RIGHTFOOTER;
1781                                     else if ( m_bHeaderOn && !m_bFooterOn )
1782                                         nResId = RID_SCDLG_HFEDIT_RIGHTHEADER;
1783                                 }
1784                                 else
1785                                 {
1786                                     //  #69193a# respect "shared" setting
1787                                     if ( !m_bHeaderOn && m_bFooterOn )
1788                                         nResId = bShareFooter ?
1789                                                     RID_SCDLG_HFEDIT_RIGHTFOOTER :
1790                                                     RID_SCDLG_HFEDIT_LEFTFOOTER;
1791                                     else if ( m_bHeaderOn && !m_bFooterOn )
1792                                         nResId = bShareHeader ?
1793                                                     RID_SCDLG_HFEDIT_RIGHTHEADER :
1794                                                     RID_SCDLG_HFEDIT_LEFTHEADER;
1795                                 }
1796                             }
1797                             break;
1798 
1799                             case SvxPageUsage::Mirror:
1800                             case SvxPageUsage::All:
1801                             default:
1802                             {
1803                                 if ( !bShareHeader && !bShareFooter )
1804                                 {
1805                                     if ( m_bHeaderOn && m_bFooterOn )
1806                                         nResId = RID_SCDLG_HFEDIT_ALL;
1807                                     else if ( !m_bHeaderOn && m_bFooterOn )
1808                                         nResId = RID_SCDLG_HFEDIT_FOOTER;
1809                                     else if ( m_bHeaderOn && !m_bFooterOn )
1810                                         nResId = RID_SCDLG_HFEDIT_HEADER;
1811                                 }
1812                                 else if ( bShareHeader && bShareFooter )
1813                                 {
1814                                     if ( m_bHeaderOn && m_bFooterOn )
1815                                         nResId = RID_SCDLG_HFEDIT;
1816                                     else
1817                                     {
1818                                         if ( !m_bHeaderOn && m_bFooterOn )
1819                                             nResId = RID_SCDLG_HFEDIT_RIGHTFOOTER;
1820                                         else if ( m_bHeaderOn && !m_bFooterOn )
1821                                             nResId = RID_SCDLG_HFEDIT_RIGHTHEADER;
1822                                     }
1823                                 }
1824                                 else if ( !bShareHeader &&  bShareFooter )
1825                                 {
1826                                     if ( m_bHeaderOn && m_bFooterOn )
1827                                         nResId = RID_SCDLG_HFEDIT_SFTR;
1828                                     else if ( !m_bHeaderOn && m_bFooterOn )
1829                                         nResId = RID_SCDLG_HFEDIT_RIGHTFOOTER;
1830                                     else if ( m_bHeaderOn && !m_bFooterOn )
1831                                         nResId = RID_SCDLG_HFEDIT_HEADER;
1832                                 }
1833                                 else if (  bShareHeader && !bShareFooter )
1834                                 {
1835                                     if ( m_bHeaderOn && m_bFooterOn )
1836                                         nResId = RID_SCDLG_HFEDIT_SHDR;
1837                                     else if ( !m_bHeaderOn && m_bFooterOn )
1838                                         nResId = RID_SCDLG_HFEDIT_FOOTER;
1839                                     else if ( m_bHeaderOn && !m_bFooterOn )
1840                                         nResId = RID_SCDLG_HFEDIT_RIGHTHEADER;
1841                                 }
1842                             }
1843                         }
1844 
1845                         ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
1846 
1847                         vcl::Window *pDialogParent = GetActiveDialogParent();
1848                         VclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateScHFEditDlg(
1849                                                                                 pDialogParent ? pDialogParent->GetFrameWeld() : nullptr,
1850                                                                                 rStyleSet,
1851                                                                                 aStr,
1852                                                                                 nResId));
1853                         std::shared_ptr<SfxRequest> xRequest(new SfxRequest(rReq));
1854                         rReq.Ignore(); // the 'old' request is not relevant any more
1855                         pDlg->StartExecuteAsync([this, pDlg, pStyleSheet, xRequest](sal_Int32 nResult){
1856                             if ( nResult == RET_OK )
1857                             {
1858                                 const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
1859 
1860                                 if ( pOutSet )
1861                                     m_aDocument.ModifyStyleSheet( *pStyleSheet, *pOutSet );
1862 
1863                                 SetDocumentModified();
1864                                 xRequest->Done();
1865                                 pDlg->disposeOnce();
1866                             }
1867                         });
1868                     }
1869                 }
1870             }
1871             break;
1872 
1873         default:
1874         break;
1875     }
1876 }
1877 
1878 void ScDocShell::GetStatePageStyle( SfxItemSet&     rSet,
1879                                     SCTAB           nCurTab )
1880 {
1881     SfxWhichIter aIter(rSet);
1882     sal_uInt16 nWhich = aIter.FirstWhich();
1883     while ( nWhich )
1884     {
1885         switch (nWhich)
1886         {
1887             case SID_STATUS_PAGESTYLE:
1888                 rSet.Put( SfxStringItem( nWhich, m_aDocument.GetPageStyle( nCurTab ) ) );
1889                 break;
1890 
1891             case SID_HFEDIT:
1892                 {
1893                     OUString            aStr        = m_aDocument.GetPageStyle( nCurTab );
1894                     ScStyleSheetPool*   pStylePool  = m_aDocument.GetStyleSheetPool();
1895                     SfxStyleSheetBase*  pStyleSheet = pStylePool->Find( aStr, SfxStyleFamily::Page );
1896 
1897                     OSL_ENSURE( pStyleSheet, "PageStyle not found! :-/" );
1898 
1899                     if ( pStyleSheet )
1900                     {
1901                         SfxItemSet& rStyleSet = pStyleSheet->GetItemSet();
1902                         GetPageOnFromPageStyleSet( &rStyleSet, nCurTab, m_bHeaderOn, m_bFooterOn );
1903 
1904                         if ( !m_bHeaderOn && !m_bFooterOn )
1905                             rSet.DisableItem( nWhich );
1906                     }
1907                 }
1908                 break;
1909         }
1910 
1911         nWhich = aIter.NextWhich();
1912     }
1913 }
1914 
1915 void ScDocShell::GetState( SfxItemSet &rSet )
1916 {
1917     bool bTabView = GetBestViewShell() != nullptr;
1918 
1919     SfxWhichIter aIter(rSet);
1920     for (sal_uInt16 nWhich = aIter.FirstWhich(); nWhich; nWhich = aIter.NextWhich())
1921     {
1922         if (!bTabView)
1923         {
1924             rSet.DisableItem(nWhich);
1925             continue;
1926         }
1927 
1928         switch (nWhich)
1929         {
1930             case FID_AUTO_CALC:
1931                 if ( m_aDocument.GetHardRecalcState() != ScDocument::HardRecalcState::OFF )
1932                     rSet.DisableItem( nWhich );
1933                 else
1934                     rSet.Put( SfxBoolItem( nWhich, m_aDocument.GetAutoCalc() ) );
1935                 break;
1936 
1937             case FID_CHG_RECORD:
1938                 if ( IsDocShared() )
1939                     rSet.DisableItem( nWhich );
1940                 else
1941                     rSet.Put( SfxBoolItem( nWhich,
1942                         m_aDocument.GetChangeTrack() != nullptr ) );
1943                 break;
1944 
1945             case SID_CHG_PROTECT:
1946                 {
1947                     ScChangeTrack* pChangeTrack = m_aDocument.GetChangeTrack();
1948                     if ( pChangeTrack && !IsDocShared() )
1949                         rSet.Put( SfxBoolItem( nWhich,
1950                             pChangeTrack->IsProtected() ) );
1951                     else
1952                         rSet.DisableItem( nWhich );
1953                 }
1954                 break;
1955 
1956             case SID_DOCUMENT_COMPARE:
1957                 {
1958                     if ( IsDocShared() )
1959                     {
1960                         rSet.DisableItem( nWhich );
1961                     }
1962                 }
1963                 break;
1964 
1965             //  When a formula is edited, FID_RECALC must be enabled in any case. Recalc for
1966             //  the doc was disabled once because of a bug if AutoCalc was on, but is now
1967             //  always enabled because of another bug.
1968 
1969             case SID_TABLES_COUNT:
1970                 rSet.Put( SfxInt16Item( nWhich, m_aDocument.GetTableCount() ) );
1971                 break;
1972 
1973             case SID_ATTR_YEAR2000 :
1974                 rSet.Put( SfxUInt16Item( nWhich,
1975                     m_aDocument.GetDocOptions().GetYear2000() ) );
1976             break;
1977 
1978             case SID_SHARE_DOC:
1979                 {
1980                     if ( IsReadOnly() )
1981                     {
1982                         rSet.DisableItem( nWhich );
1983                     }
1984                 }
1985                 break;
1986 
1987             case SID_ATTR_CHAR_FONTLIST:
1988                 rSet.Put( SvxFontListItem( m_pImpl->pFontList.get(), nWhich ) );
1989                 break;
1990 
1991             case SID_NOTEBOOKBAR:
1992                 {
1993                     if (GetViewBindings())
1994                     {
1995                         bool bVisible = sfx2::SfxNotebookBar::StateMethod(*GetViewBindings(),
1996                                                                           "modules/scalc/ui/");
1997                         rSet.Put( SfxBoolItem( SID_NOTEBOOKBAR, bVisible ) );
1998                     }
1999                 }
2000                 break;
2001 
2002             case SID_LANGUAGE_STATUS:
2003                 {
2004                     LanguageType eLatin, eCjk, eCtl;
2005 
2006                     GetDocument().GetLanguage( eLatin, eCjk, eCtl );
2007                     rSet.Put(SfxStringItem(nWhich, SvtLanguageTable::GetLanguageString(eLatin)));
2008                 }
2009                 break;
2010 
2011             default:
2012                 {
2013                 }
2014                 break;
2015         }
2016     }
2017 }
2018 
2019 void ScDocShell::Draw( OutputDevice* pDev, const JobSetup & /* rSetup */, sal_uInt16 nAspect )
2020 {
2021 
2022     SCTAB nVisTab = m_aDocument.GetVisibleTab();
2023     if (!m_aDocument.HasTable(nVisTab))
2024         return;
2025 
2026     ComplexTextLayoutFlags nOldLayoutMode = pDev->GetLayoutMode();
2027     pDev->SetLayoutMode( ComplexTextLayoutFlags::Default );     // even if it's the same, to get the metafile action
2028 
2029     if ( nAspect == ASPECT_THUMBNAIL )
2030     {
2031         tools::Rectangle aBoundRect = GetVisArea( ASPECT_THUMBNAIL );
2032         ScViewData aTmpData( this, nullptr );
2033         aTmpData.SetTabNo(nVisTab);
2034         SnapVisArea( aBoundRect );
2035         aTmpData.SetScreen( aBoundRect );
2036         ScPrintFunc::DrawToDev( &m_aDocument, pDev, 1.0, aBoundRect, &aTmpData, true );
2037     }
2038     else
2039     {
2040         tools::Rectangle aOldArea = SfxObjectShell::GetVisArea();
2041         tools::Rectangle aNewArea = aOldArea;
2042         ScViewData aTmpData( this, nullptr );
2043         aTmpData.SetTabNo(nVisTab);
2044         SnapVisArea( aNewArea );
2045         if ( aNewArea != aOldArea && (m_aDocument.GetPosLeft() > 0 || m_aDocument.GetPosTop() > 0) )
2046             SfxObjectShell::SetVisArea( aNewArea );
2047         aTmpData.SetScreen( aNewArea );
2048         ScPrintFunc::DrawToDev( &m_aDocument, pDev, 1.0, aNewArea, &aTmpData, true );
2049     }
2050 
2051     pDev->SetLayoutMode( nOldLayoutMode );
2052 }
2053 
2054 tools::Rectangle ScDocShell::GetVisArea( sal_uInt16 nAspect ) const
2055 {
2056     SfxObjectCreateMode eShellMode = GetCreateMode();
2057     if ( eShellMode == SfxObjectCreateMode::ORGANIZER )
2058     {
2059         //  without contents we also don't know how large are the contents;
2060         //  return empty rectangle, it will then be calculated after the loading
2061         return tools::Rectangle();
2062     }
2063 
2064     if( nAspect == ASPECT_THUMBNAIL )
2065     {
2066         SCTAB nVisTab = m_aDocument.GetVisibleTab();
2067         if (!m_aDocument.HasTable(nVisTab))
2068         {
2069             nVisTab = 0;
2070             const_cast<ScDocShell*>(this)->m_aDocument.SetVisibleTab(nVisTab);
2071         }
2072         Size aSize = m_aDocument.GetPageSize(nVisTab);
2073         const long SC_PREVIEW_SIZE_X = 10000;
2074         const long SC_PREVIEW_SIZE_Y = 12400;
2075         tools::Rectangle aArea( 0,0, SC_PREVIEW_SIZE_X, SC_PREVIEW_SIZE_Y);
2076         if (aSize.Width() > aSize.Height())
2077         {
2078             aArea.SetRight( SC_PREVIEW_SIZE_Y );
2079             aArea.SetBottom( SC_PREVIEW_SIZE_X );
2080         }
2081 
2082         bool bNegativePage = m_aDocument.IsNegativePage( m_aDocument.GetVisibleTab() );
2083         if ( bNegativePage )
2084             ScDrawLayer::MirrorRectRTL( aArea );
2085         SnapVisArea( aArea );
2086         return aArea;
2087     }
2088     else if( nAspect == ASPECT_CONTENT && eShellMode != SfxObjectCreateMode::EMBEDDED )
2089     {
2090         //  fetch visarea like after loading
2091 
2092         SCTAB nVisTab = m_aDocument.GetVisibleTab();
2093         if (!m_aDocument.HasTable(nVisTab))
2094         {
2095             nVisTab = 0;
2096             const_cast<ScDocShell*>(this)->m_aDocument.SetVisibleTab(nVisTab);
2097         }
2098         SCCOL nStartCol;
2099         SCROW nStartRow;
2100         m_aDocument.GetDataStart( nVisTab, nStartCol, nStartRow );
2101         SCCOL nEndCol;
2102         SCROW nEndRow;
2103         m_aDocument.GetPrintArea( nVisTab, nEndCol, nEndRow );
2104         if (nStartCol>nEndCol)
2105             nStartCol = nEndCol;
2106         if (nStartRow>nEndRow)
2107             nStartRow = nEndRow;
2108         tools::Rectangle aNewArea = m_aDocument
2109                                 .GetMMRect( nStartCol,nStartRow, nEndCol,nEndRow, nVisTab );
2110         //TODO/LATER: different methods for setting VisArea?!
2111         const_cast<ScDocShell*>(this)->SfxObjectShell::SetVisArea( aNewArea );
2112         return aNewArea;
2113     }
2114     else
2115         return SfxObjectShell::GetVisArea( nAspect );
2116 }
2117 
2118 namespace {
2119 
2120 [[nodiscard]]
2121 long SnapHorizontal( const ScDocument& rDoc, SCTAB nTab, long nVal, SCCOL& rStartCol )
2122 {
2123     SCCOL nCol = 0;
2124     long nTwips = static_cast<long>(nVal / HMM_PER_TWIPS);
2125     long nSnap = 0;
2126     while ( nCol<MAXCOL )
2127     {
2128         long nAdd = rDoc.GetColWidth(nCol, nTab);
2129         if ( nSnap + nAdd/2 < nTwips || nCol < rStartCol )
2130         {
2131             nSnap += nAdd;
2132             ++nCol;
2133         }
2134         else
2135             break;
2136     }
2137     nVal = static_cast<long>( nSnap * HMM_PER_TWIPS );
2138     rStartCol = nCol;
2139     return nVal;
2140 }
2141 
2142 [[nodiscard]]
2143 long SnapVertical( const ScDocument& rDoc, SCTAB nTab, long nVal, SCROW& rStartRow )
2144 {
2145     SCROW nRow = 0;
2146     long nTwips = static_cast<long>(nVal / HMM_PER_TWIPS);
2147     long nSnap = 0;
2148 
2149     bool bFound = false;
2150     for (SCROW i = nRow; i <= MAXROW; ++i)
2151     {
2152         SCROW nLastRow;
2153         if (rDoc.RowHidden(i, nTab, nullptr, &nLastRow))
2154         {
2155             i = nLastRow;
2156             continue;
2157         }
2158 
2159         nRow = i;
2160         long nAdd = rDoc.GetRowHeight(i, nTab);
2161         if ( nSnap + nAdd/2 < nTwips || nRow < rStartRow )
2162         {
2163             nSnap += nAdd;
2164             ++nRow;
2165         }
2166         else
2167         {
2168             bFound = true;
2169             break;
2170         }
2171     }
2172     if (!bFound)
2173         nRow = MAXROW;  // all hidden down to the bottom
2174 
2175     nVal = static_cast<long>( nSnap * HMM_PER_TWIPS );
2176     rStartRow = nRow;
2177     return nVal;
2178 }
2179 
2180 }
2181 
2182 void ScDocShell::SnapVisArea( tools::Rectangle& rRect ) const
2183 {
2184     SCTAB nTab = m_aDocument.GetVisibleTab();
2185     long nOrigTop = rRect.Top();
2186     long nOrigLeft = rRect.Left();
2187     bool bNegativePage = m_aDocument.IsNegativePage( nTab );
2188     if ( bNegativePage )
2189         ScDrawLayer::MirrorRectRTL( rRect );        // calculate with positive (LTR) values
2190 
2191     SCCOL nCol = m_aDocument.GetPosLeft();
2192     long nSetLeft = SnapHorizontal( m_aDocument, nTab, rRect.Left(), nCol );
2193     rRect.SetLeft( nSetLeft );
2194     ++nCol;                                         // at least one column
2195     long nCorrectionLeft = (nOrigLeft == 0 && nCol > 0) ? nSetLeft : 0; // initial correction
2196     rRect.SetRight( SnapHorizontal( m_aDocument, nTab, rRect.Right() + nCorrectionLeft, nCol ));
2197 
2198     SCROW nRow = m_aDocument.GetPosTop();
2199     long nSetTop = SnapVertical( m_aDocument, nTab, rRect.Top(), nRow );
2200     rRect.SetTop( nSetTop );
2201     ++nRow;                                         // at least one row
2202     long nCorrectionTop = (nOrigTop == 0 && nRow > 0) ? nSetTop : 0; // initial correction
2203     rRect.SetBottom( SnapVertical( m_aDocument, nTab, rRect.Bottom() + nCorrectionTop, nRow ));
2204 
2205     if ( bNegativePage )
2206         ScDrawLayer::MirrorRectRTL( rRect );        // back to real rectangle
2207 }
2208 
2209 void ScDocShell::GetPageOnFromPageStyleSet( const SfxItemSet* pStyleSet,
2210                                             SCTAB             nCurTab,
2211                                             bool&             rbHeader,
2212                                             bool&             rbFooter )
2213 {
2214     if ( !pStyleSet )
2215     {
2216         ScStyleSheetPool*  pStylePool  = m_aDocument.GetStyleSheetPool();
2217         SfxStyleSheetBase* pStyleSheet = pStylePool->
2218                                             Find( m_aDocument.GetPageStyle( nCurTab ),
2219                                                   SfxStyleFamily::Page );
2220 
2221         OSL_ENSURE( pStyleSheet, "PageStyle not found! :-/" );
2222 
2223         if ( pStyleSheet )
2224             pStyleSet = &pStyleSheet->GetItemSet();
2225         else
2226             rbHeader = rbFooter = false;
2227     }
2228 
2229     OSL_ENSURE( pStyleSet, "PageStyle-Set not found! :-(" );
2230     if (!pStyleSet)
2231         return;
2232 
2233     const SvxSetItem*   pSetItem = nullptr;
2234     const SfxItemSet*   pSet     = nullptr;
2235 
2236     pSetItem = &pStyleSet->Get( ATTR_PAGE_HEADERSET );
2237     pSet     = &pSetItem->GetItemSet();
2238     rbHeader = pSet->Get(ATTR_PAGE_ON).GetValue();
2239 
2240     pSetItem = &pStyleSet->Get( ATTR_PAGE_FOOTERSET );
2241     pSet     = &pSetItem->GetItemSet();
2242     rbFooter = pSet->Get(ATTR_PAGE_ON).GetValue();
2243 }
2244 
2245 #if defined(_WIN32)
2246 bool ScDocShell::DdeGetData( const OUString& rItem,
2247                              const OUString& rMimeType,
2248                              css::uno::Any & rValue )
2249 {
2250     SotClipboardFormatId eFormatId = SotExchange::GetFormatIdFromMimeType( rMimeType );
2251     if (SotClipboardFormatId::STRING == eFormatId || SotClipboardFormatId::STRING_TSVC == eFormatId)
2252     {
2253         if( rItem.equalsIgnoreAsciiCase( "Format" ) )
2254         {
2255             OString aFmtByte(OUStringToOString(m_aDdeTextFmt,
2256                 osl_getThreadTextEncoding()));
2257             rValue <<= css::uno::Sequence< sal_Int8 >(
2258                                         reinterpret_cast<const sal_Int8*>(aFmtByte.getStr()),
2259                                         aFmtByte.getLength() + 1 );
2260             return true;
2261         }
2262         ScImportExport aObj( &m_aDocument, rItem );
2263         if ( !aObj.IsRef() )
2264             return false;                           // invalid range
2265 
2266         if( m_aDdeTextFmt[0] == 'F' )
2267             aObj.SetFormulas( true );
2268         if( m_aDdeTextFmt == "SYLK" ||
2269             m_aDdeTextFmt == "FSYLK" )
2270         {
2271             OString aData;
2272             if( aObj.ExportByteString( aData, osl_getThreadTextEncoding(),
2273                                         SotClipboardFormatId::SYLK ) )
2274             {
2275                 rValue <<= css::uno::Sequence< sal_Int8 >(
2276                                             reinterpret_cast<const sal_Int8*>(aData.getStr()),
2277                                             aData.getLength() + 1 );
2278                 return true;
2279             }
2280             else
2281                 return false;
2282         }
2283         if( m_aDdeTextFmt == "CSV" ||
2284             m_aDdeTextFmt == "FCSV" )
2285             aObj.SetSeparator( ',' );
2286         aObj.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::ToSpace, 0, false ) );
2287         return aObj.ExportData( rMimeType, rValue );
2288     }
2289 
2290     ScImportExport aObj( &m_aDocument, rItem );
2291     aObj.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::ToSpace, 0, false ) );
2292     return aObj.IsRef() && aObj.ExportData( rMimeType, rValue );
2293 }
2294 
2295 bool ScDocShell::DdeSetData( const OUString& rItem,
2296                              const OUString& rMimeType,
2297                              const css::uno::Any & rValue )
2298 {
2299     SotClipboardFormatId eFormatId = SotExchange::GetFormatIdFromMimeType( rMimeType );
2300     if (SotClipboardFormatId::STRING == eFormatId || SotClipboardFormatId::STRING_TSVC == eFormatId)
2301     {
2302         if( rItem.equalsIgnoreAsciiCase( "Format" ) )
2303         {
2304             if ( ScByteSequenceToString::GetString( m_aDdeTextFmt, rValue, osl_getThreadTextEncoding() ) )
2305             {
2306                 m_aDdeTextFmt = m_aDdeTextFmt.toAsciiUpperCase();
2307                 return true;
2308             }
2309             return false;
2310         }
2311         ScImportExport aObj( &m_aDocument, rItem );
2312         if( m_aDdeTextFmt[0] == 'F' )
2313             aObj.SetFormulas( true );
2314         if( m_aDdeTextFmt == "SYLK" ||
2315             m_aDdeTextFmt == "FSYLK" )
2316         {
2317             OUString aData;
2318             if ( ScByteSequenceToString::GetString( aData, rValue, osl_getThreadTextEncoding() ) )
2319             {
2320                 return aObj.ImportString( aData, SotClipboardFormatId::SYLK );
2321             }
2322             return false;
2323         }
2324         if( m_aDdeTextFmt == "CSV" ||
2325             m_aDdeTextFmt == "FCSV" )
2326             aObj.SetSeparator( ',' );
2327         OSL_ENSURE( false, "Implementation is missing" );
2328         return false;
2329     }
2330     /*ScImportExport aObj( &aDocument, rItem );
2331     return aObj.IsRef() && ScImportExport::ImportData( rMimeType, rValue );*/
2332     OSL_ENSURE( false, "Implementation is missing" );
2333     return false;
2334 }
2335 #endif
2336 
2337 ::sfx2::SvLinkSource* ScDocShell::DdeCreateLinkSource( const OUString& rItem )
2338 {
2339     //  only check for valid item string - range is parsed again in ScServerObject ctor
2340 
2341     //  named range?
2342     OUString aPos = rItem;
2343     ScRangeName* pRange = m_aDocument.GetRangeName();
2344     if( pRange )
2345     {
2346         const ScRangeData* pData = pRange->findByUpperName(ScGlobal::pCharClass->uppercase(aPos));
2347         if (pData)
2348         {
2349             if( pData->HasType( ScRangeData::Type::RefArea    )
2350                 || pData->HasType( ScRangeData::Type::AbsArea )
2351                 || pData->HasType( ScRangeData::Type::AbsPos  ) )
2352                 pData->GetSymbol( aPos );           // continue with the name's contents
2353         }
2354     }
2355 
2356     // Address in DDE function must be always parsed as CONV_OOO so that it
2357     // would always work regardless of current address conversion.  We do this
2358     // because the address item in a DDE entry is *not* normalized when saved
2359     // into ODF.
2360     ScRange aRange;
2361     bool bValid = ( (aRange.Parse(aPos, &m_aDocument, formula::FormulaGrammar::CONV_OOO ) & ScRefFlags::VALID) ||
2362                     (aRange.aStart.Parse(aPos, &m_aDocument, formula::FormulaGrammar::CONV_OOO) & ScRefFlags::VALID) );
2363 
2364     ScServerObject* pObj = nullptr;            // NULL = error
2365     if ( bValid )
2366         pObj = new ScServerObject( this, rItem );
2367 
2368     //  GetLinkManager()->InsertServer() is in the ScServerObject ctor
2369 
2370     return pObj;
2371 }
2372 
2373 void ScDocShell::LOKCommentNotify(LOKCommentNotificationType nType, const ScDocument* pDocument, const ScAddress& rPos, const ScPostIt* pNote)
2374 {
2375     if ( !pDocument->IsDocVisible() || // don't want callbacks until document load
2376          !comphelper::LibreOfficeKit::isActive() ||
2377          comphelper::LibreOfficeKit::isTiledAnnotations() )
2378         return;
2379 
2380     boost::property_tree::ptree aAnnotation;
2381     aAnnotation.put("action", (nType == LOKCommentNotificationType::Add ? "Add" :
2382                                (nType == LOKCommentNotificationType::Remove ? "Remove" :
2383                                 (nType == LOKCommentNotificationType::Modify ? "Modify" : "???"))));
2384 
2385     assert(pNote);
2386     aAnnotation.put("id", pNote->GetId());
2387     aAnnotation.put("tab", rPos.Tab());
2388 
2389     if (nType != LOKCommentNotificationType::Remove)
2390     {
2391         aAnnotation.put("author", pNote->GetAuthor());
2392         aAnnotation.put("dateTime", pNote->GetDate());
2393         aAnnotation.put("text", pNote->GetText());
2394 
2395         // Calculating the cell cursor position
2396         ScViewData* pViewData = GetViewData();
2397         if (pViewData && pViewData->GetActiveWin())
2398         {
2399             Point aScrPos = pViewData->GetScrPos(rPos.Col(), rPos.Row(), pViewData->GetActivePart(), true);
2400             long nSizeXPix;
2401             long nSizeYPix;
2402             pViewData->GetMergeSizePixel(rPos.Col(), rPos.Row(), nSizeXPix, nSizeYPix);
2403 
2404             const double fPPTX = pViewData->GetPPTX();
2405             const double fPPTY = pViewData->GetPPTY();
2406             tools::Rectangle aRect(Point(aScrPos.getX() / fPPTX, aScrPos.getY() / fPPTY),
2407                             Size(nSizeXPix / fPPTX, nSizeYPix / fPPTY));
2408 
2409             aAnnotation.put("cellPos", aRect.toString());
2410         }
2411     }
2412 
2413     boost::property_tree::ptree aTree;
2414     aTree.add_child("comment", aAnnotation);
2415     std::stringstream aStream;
2416     boost::property_tree::write_json(aStream, aTree);
2417     std::string aPayload = aStream.str();
2418 
2419     SfxViewShell* pViewShell = SfxViewShell::GetFirst();
2420     while (pViewShell)
2421     {
2422         pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_COMMENT, aPayload.c_str());
2423         pViewShell = SfxViewShell::GetNext(*pViewShell);
2424     }
2425 }
2426 
2427 ScViewData* ScDocShell::GetViewData()
2428 {
2429     SfxViewShell* pCur = SfxViewShell::Current();
2430     ScTabViewShell* pViewSh = dynamic_cast< ScTabViewShell *>( pCur );
2431     return pViewSh ? &pViewSh->GetViewData() : nullptr;
2432 }
2433 
2434 SCTAB ScDocShell::GetCurTab()
2435 {
2436     //! this must be made non-static and use a ViewShell from this document!
2437 
2438     ScViewData* pViewData = GetViewData();
2439 
2440     return pViewData ? pViewData->GetTabNo() : static_cast<SCTAB>(0);
2441 }
2442 
2443 ScTabViewShell* ScDocShell::GetBestViewShell( bool bOnlyVisible )
2444 {
2445     ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
2446     // wrong Doc?
2447     if( pViewSh && pViewSh->GetViewData().GetDocShell() != this )
2448         pViewSh = nullptr;
2449     if( !pViewSh )
2450     {
2451         // 1. find ViewShell
2452         SfxViewFrame* pFrame = SfxViewFrame::GetFirst( this, bOnlyVisible );
2453         if( pFrame )
2454         {
2455             SfxViewShell* p = pFrame->GetViewShell();
2456             pViewSh = dynamic_cast< ScTabViewShell *>( p );
2457         }
2458     }
2459     return pViewSh;
2460 }
2461 
2462 SfxBindings* ScDocShell::GetViewBindings()
2463 {
2464     //  used to invalidate slots after changes to this document
2465 
2466     SfxViewShell* pViewSh = GetBestViewShell();
2467     if (pViewSh)
2468         return &pViewSh->GetViewFrame()->GetBindings();
2469     else
2470         return nullptr;
2471 }
2472 
2473 ScDocShell* ScDocShell::GetShellByNum( sal_uInt16 nDocNo )      // static
2474 {
2475     ScDocShell* pFound = nullptr;
2476     SfxObjectShell* pShell = SfxObjectShell::GetFirst();
2477     sal_uInt16 nShellCnt = 0;
2478 
2479     while ( pShell && !pFound )
2480     {
2481         if ( dynamic_cast<const ScDocShell*>(pShell) != nullptr )
2482         {
2483             if ( nShellCnt == nDocNo )
2484                 pFound = static_cast<ScDocShell*>(pShell);
2485             else
2486                 ++nShellCnt;
2487         }
2488         pShell = SfxObjectShell::GetNext( *pShell );
2489     }
2490 
2491     return pFound;
2492 }
2493 
2494 IMPL_LINK( ScDocShell, DialogClosedHdl, sfx2::FileDialogHelper*, _pFileDlg, void )
2495 {
2496     OSL_ENSURE( _pFileDlg, "ScDocShell::DialogClosedHdl(): no file dialog" );
2497     OSL_ENSURE( m_pImpl->pDocInserter, "ScDocShell::DialogClosedHdl(): no document inserter" );
2498 
2499     if ( ERRCODE_NONE == _pFileDlg->GetError() )
2500     {
2501         sal_uInt16 nSlot = m_pImpl->pRequest->GetSlot();
2502         std::unique_ptr<SfxMedium> pMed = m_pImpl->pDocInserter->CreateMedium();
2503         // #i87094# If a .odt was selected pMed is NULL.
2504         if (pMed)
2505         {
2506             m_pImpl->pRequest->AppendItem( SfxStringItem( SID_FILE_NAME, pMed->GetName() ) );
2507             if ( SID_DOCUMENT_COMPARE == nSlot )
2508             {
2509                 if ( pMed->GetFilter() )
2510                     m_pImpl->pRequest->AppendItem(
2511                             SfxStringItem( SID_FILTER_NAME, pMed->GetFilter()->GetFilterName() ) );
2512                 OUString sOptions = ScDocumentLoader::GetOptions( *pMed );
2513                 if ( !sOptions.isEmpty() )
2514                     m_pImpl->pRequest->AppendItem( SfxStringItem( SID_FILE_FILTEROPTIONS, sOptions ) );
2515             }
2516             const SfxPoolItem* pItem = nullptr;
2517             const SfxInt16Item* pInt16Item(nullptr);
2518             SfxItemSet* pSet = pMed->GetItemSet();
2519             if (pSet && pSet->GetItemState(SID_VERSION, true, &pItem) == SfxItemState::SET)
2520             {
2521                 pInt16Item = dynamic_cast<const SfxInt16Item*>(pItem);
2522             }
2523             if (pInt16Item)
2524             {
2525                 m_pImpl->pRequest->AppendItem( *pItem );
2526             }
2527 
2528             Execute( *(m_pImpl->pRequest) );
2529         }
2530     }
2531 
2532     m_pImpl->bIgnoreLostRedliningWarning = false;
2533 }
2534 
2535 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
2536 
2537 void ScDocShell::EnableSharedSettings( bool bEnable )
2538 {
2539     SetDocumentModified();
2540 
2541     if ( bEnable )
2542     {
2543         m_aDocument.EndChangeTracking();
2544         m_aDocument.StartChangeTracking();
2545 
2546         // hide accept or reject changes dialog
2547         sal_uInt16 nId = ScAcceptChgDlgWrapper::GetChildWindowId();
2548         SfxViewFrame* pViewFrame = SfxViewFrame::Current();
2549         if ( pViewFrame && pViewFrame->HasChildWindow( nId ) )
2550         {
2551             pViewFrame->ToggleChildWindow( nId );
2552             SfxBindings* pBindings = GetViewBindings();
2553             if ( pBindings )
2554             {
2555                 pBindings->Invalidate( FID_CHG_ACCEPT );
2556             }
2557         }
2558     }
2559     else
2560     {
2561         m_aDocument.EndChangeTracking();
2562     }
2563 
2564     ScChangeViewSettings aChangeViewSet;
2565     aChangeViewSet.SetShowChanges( false );
2566     m_aDocument.SetChangeViewSettings( aChangeViewSet );
2567 }
2568 
2569 uno::Reference< frame::XModel > ScDocShell::LoadSharedDocument()
2570 {
2571     uno::Reference< frame::XModel > xModel;
2572     try
2573     {
2574         SC_MOD()->SetInSharedDocLoading( true );
2575         uno::Reference< frame::XDesktop2 > xLoader = frame::Desktop::create( ::comphelper::getProcessComponentContext() );
2576         uno::Sequence < beans::PropertyValue > aArgs( 1 );
2577         aArgs[0].Name = "Hidden";
2578         aArgs[0].Value <<= true;
2579 
2580         if ( GetMedium() )
2581         {
2582             const SfxStringItem* pPasswordItem = SfxItemSet::GetItem<SfxStringItem>(GetMedium()->GetItemSet(), SID_PASSWORD, false);
2583             if ( pPasswordItem && !pPasswordItem->GetValue().isEmpty() )
2584             {
2585                 aArgs.realloc( 2 );
2586                 aArgs[1].Name = "Password";
2587                 aArgs[1].Value <<= pPasswordItem->GetValue();
2588             }
2589             const SfxUnoAnyItem* pEncryptionItem = SfxItemSet::GetItem<SfxUnoAnyItem>(GetMedium()->GetItemSet(), SID_ENCRYPTIONDATA, false);
2590             if (pEncryptionItem)
2591             {
2592                 aArgs.realloc(aArgs.getLength() + 1);
2593                 aArgs[aArgs.getLength() - 1].Name = "EncryptionData";
2594                 aArgs[aArgs.getLength() - 1].Value = pEncryptionItem->GetValue();
2595             }
2596         }
2597 
2598         xModel.set(
2599             xLoader->loadComponentFromURL( GetSharedFileURL(), "_blank", 0, aArgs ),
2600             uno::UNO_QUERY_THROW );
2601         SC_MOD()->SetInSharedDocLoading( false );
2602     }
2603     catch ( uno::Exception& )
2604     {
2605         OSL_FAIL( "ScDocShell::LoadSharedDocument(): caught exception" );
2606         SC_MOD()->SetInSharedDocLoading( false );
2607         try
2608         {
2609             uno::Reference< util::XCloseable > xClose( xModel, uno::UNO_QUERY_THROW );
2610             xClose->close( true );
2611             return uno::Reference< frame::XModel >();
2612         }
2613         catch ( uno::Exception& )
2614         {
2615             return uno::Reference< frame::XModel >();
2616         }
2617     }
2618     return xModel;
2619 }
2620 
2621 #endif
2622 
2623 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
2624