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