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