tdf#130857 qt weld: Implement QtInstanceWidget::strip_mnemonic
[LibreOffice.git] / sc / source / ui / docshell / docsh4.cxx
blob8020cb8c7471d01da0364795c491785f1b73be06
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <config_features.h>
22 #include <com/sun/star/frame/Desktop.hpp>
24 #include <scitems.hxx>
25 #include <editeng/flstitem.hxx>
26 #include <sfx2/fcontnr.hxx>
27 #include <sfx2/infobar.hxx>
28 #include <sfx2/objface.hxx>
29 #include <sfx2/docfile.hxx>
30 #include <sfx2/docfilt.hxx>
31 #include <sfx2/sfxresid.hxx>
32 #include <sfx2/strings.hrc>
33 #include <svtools/ehdl.hxx>
34 #include <svtools/langtab.hxx>
35 #include <basic/sbxcore.hxx>
36 #include <basic/sberrors.hxx>
37 #include <svtools/sfxecode.hxx>
38 #include <svx/ofaitem.hxx>
39 #include <svl/stritem.hxx>
40 #include <svl/whiter.hxx>
41 #include <vcl/stdtext.hxx>
42 #include <vcl/svapp.hxx>
43 #include <vcl/weld.hxx>
44 #include <svx/dataaccessdescriptor.hxx>
45 #include <svx/drawitem.hxx>
46 #include <svx/fmshell.hxx>
47 #include <sfx2/passwd.hxx>
48 #include <sfx2/filedlghelper.hxx>
49 #include <sfx2/dispatch.hxx>
50 #include <sfx2/sfxdlg.hxx>
51 #include <svl/PasswordHelper.hxx>
52 #include <svl/documentlockfile.hxx>
53 #include <svl/sharecontrolfile.hxx>
54 #include <tools/json_writer.hxx>
55 #include <unotools/securityoptions.hxx>
56 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
57 #include <sal/log.hxx>
58 #include <unotools/charclass.hxx>
59 #include <comphelper/diagnose_ex.hxx>
60 #include <o3tl/string_view.hxx>
62 #include <comphelper/lok.hxx>
63 #include <comphelper/processfactory.hxx>
64 #include <comphelper/propertyvalue.hxx>
65 #include <docuno.hxx>
67 #include <docsh.hxx>
68 #include "docshimp.hxx"
69 #include <docfunc.hxx>
70 #include <scres.hrc>
71 #include <strings.hrc>
72 #include <stlsheet.hxx>
73 #include <stlpool.hxx>
74 #include <appoptio.hxx>
75 #include <globstr.hrc>
76 #include <global.hxx>
77 #include <dbdocfun.hxx>
78 #include <printfun.hxx>
79 #include <viewdata.hxx>
80 #include <tabvwsh.hxx>
81 #include <impex.hxx>
82 #include <undodat.hxx>
83 #include <undocell.hxx>
84 #include <inputhdl.hxx>
85 #include <dbdata.hxx>
86 #include <servobj.hxx>
87 #include <rangenam.hxx>
88 #include <scmod.hxx>
89 #include <chgviset.hxx>
90 #include <reffact.hxx>
91 #include <chartlis.hxx>
92 #include <chartpos.hxx>
93 #include <tablink.hxx>
94 #include <drwlayer.hxx>
95 #include <docoptio.hxx>
96 #include <undostyl.hxx>
97 #include <rangeseq.hxx>
98 #include <chgtrack.hxx>
99 #include <com/sun/star/document/UpdateDocMode.hpp>
100 #include <scresid.hxx>
101 #include <scabstdlg.hxx>
102 #include <sharedocdlg.hxx>
103 #include <conditio.hxx>
104 #include <sheetevents.hxx>
105 #include <formulacell.hxx>
106 #include <documentlinkmgr.hxx>
107 #include <memory>
108 #include <sfx2/notebookbar/SfxNotebookBar.hxx>
109 #include <helpids.h>
110 #include <editeng/eeitem.hxx>
111 #include <editeng/langitem.hxx>
112 #include <officecfg/Office/Common.hxx>
114 #include <svx/xdef.hxx>
116 using namespace ::com::sun::star;
118 void ScDocShell::SetInitialLinkUpdate( const SfxMedium* pMed )
120 if (pMed)
122 const SfxUInt16Item* pUpdateDocItem = pMed->GetItemSet().GetItem(SID_UPDATEDOCMODE, false);
123 m_nCanUpdate = pUpdateDocItem ? pUpdateDocItem->GetValue() : css::document::UpdateDocMode::NO_UPDATE;
126 // GetLinkUpdateModeState() evaluates m_nCanUpdate so that must have
127 // been set first. Do not override an already forbidden LinkUpdate (the
128 // default is allow).
129 comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = getEmbeddedObjectContainer();
130 if (rEmbeddedObjectContainer.getUserAllowsLinkUpdate())
132 // For anything else than LM_ALWAYS we need user confirmation.
133 rEmbeddedObjectContainer.setUserAllowsLinkUpdate( GetLinkUpdateModeState() == LM_ALWAYS);
137 ScLkUpdMode ScDocShell::GetLinkUpdateModeState() const
139 ScLkUpdMode nSet;
140 if (m_nCanUpdate == css::document::UpdateDocMode::NO_UPDATE)
141 nSet = LM_NEVER;
142 else if (m_nCanUpdate == css::document::UpdateDocMode::FULL_UPDATE)
143 nSet = LM_ALWAYS;
144 else
146 nSet = GetDocument().GetLinkMode();
147 if (nSet == LM_UNKNOWN)
149 ScAppOptions aAppOptions = ScModule::get()->GetAppOptions();
150 nSet = aAppOptions.GetLinkMode();
154 if (nSet != LM_NEVER
155 && (SvtSecurityOptions::isUntrustedReferer(
156 GetMedium() == nullptr ? OUString() : GetMedium()->GetName())
157 || (IsDocShared() && SvtSecurityOptions::isUntrustedReferer(GetSharedFileURL()))))
159 nSet = LM_NEVER;
161 else if (nSet == LM_ALWAYS
162 && !(SvtSecurityOptions::isTrustedLocationUriForUpdatingLinks(
163 GetMedium() == nullptr ? OUString() : GetMedium()->GetName())
164 || (IsDocShared()
165 && SvtSecurityOptions::isTrustedLocationUriForUpdatingLinks(
166 GetSharedFileURL()))))
168 nSet = LM_ON_DEMAND;
170 if (m_nCanUpdate == css::document::UpdateDocMode::QUIET_UPDATE
171 && nSet == LM_ON_DEMAND)
173 nSet = LM_NEVER;
176 return nSet;
179 void ScDocShell::AllowLinkUpdate()
181 m_pDocument->SetLinkFormulaNeedingCheck(false);
182 getEmbeddedObjectContainer().setUserAllowsLinkUpdate(true);
185 void ScDocShell::ReloadAllLinks()
187 AllowLinkUpdate();
189 ReloadTabLinks();
190 weld::Window *pDialogParent = GetActiveDialogParent();
191 m_pDocument->UpdateExternalRefLinks(pDialogParent);
193 bool bAnyDde = m_pDocument->GetDocLinkManager().updateDdeOrOleOrWebServiceLinks(pDialogParent);
195 if (bAnyDde)
197 // calculate formulas and paint like in the TrackTimeHdl
198 m_pDocument->TrackFormulas();
199 Broadcast(SfxHint(SfxHintId::ScDataChanged));
201 // Should FID_DATACHANGED become asynchronous some time
202 // (e.g., with Invalidate at Window), an update needs to be forced here.
205 m_pDocument->UpdateAreaLinks();
208 IMPL_LINK( ScDocShell, ReloadAllLinksHdl, weld::Button&, rButton, void )
210 ScDocument& rDoc = GetDocument();
211 if (rDoc.HasLinkFormulaNeedingCheck() && rDoc.GetDocLinkManager().hasExternalRefLinks())
213 // If we have WEBSERVICE/Dde link and other external links in the document, it might indicate some
214 // exfiltration attempt, add *another* warning about this on top of the "Security Warning"
215 // shown in the infobar before they got here.
216 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(&rButton,
217 VclMessageType::Warning, VclButtonsType::YesNo,
218 ScResId(STR_TRUST_DOCUMENT_WARNING)));
219 xQueryBox->set_secondary_text(ScResId(STR_WEBSERVICE_WITH_LINKS_WARNING));
220 xQueryBox->set_default_response(RET_NO);
221 if (xQueryBox->run() != RET_YES)
222 return;
225 ReloadAllLinks();
227 ScTabViewShell* pViewSh = GetBestViewShell();
228 SfxViewFrame* pViewFrame = pViewSh ? pViewSh->GetFrame() : nullptr;
229 if (pViewFrame)
230 pViewFrame->RemoveInfoBar(u"enablecontent");
231 SAL_WARN_IF(!pViewFrame, "sc", "expected there to be a ViewFrame");
234 namespace
236 class LinkHelp
238 public:
239 DECL_STATIC_LINK(LinkHelp, DispatchHelpLinksHdl, weld::Button&, void);
243 IMPL_STATIC_LINK(LinkHelp, DispatchHelpLinksHdl, weld::Button&, rBtn, void)
245 if (Help* pHelp = Application::GetHelp())
246 pHelp->Start(HID_UPDATE_LINK_WARNING, &rBtn);
249 void ScDocShell::Execute( SfxRequest& rReq )
251 const SfxItemSet* pReqArgs = rReq.GetArgs();
252 SfxBindings* pBindings = GetViewBindings();
253 bool bUndo (m_pDocument->IsUndoEnabled());
255 sal_uInt16 nSlot = rReq.GetSlot();
256 switch ( nSlot )
258 case SID_SC_SETTEXT:
260 const SfxPoolItem* pColItem;
261 const SfxPoolItem* pRowItem;
262 const SfxPoolItem* pTabItem;
263 const SfxPoolItem* pTextItem;
264 if( pReqArgs && pReqArgs->HasItem( FN_PARAM_1, &pColItem ) &&
265 pReqArgs->HasItem( FN_PARAM_2, &pRowItem ) &&
266 pReqArgs->HasItem( FN_PARAM_3, &pTabItem ) &&
267 pReqArgs->HasItem( SID_SC_SETTEXT, &pTextItem ) )
269 // parameters are 1-based !!!
270 SCCOL nCol = static_cast<const SfxInt16Item*>(pColItem)->GetValue() - 1;
271 SCROW nRow = static_cast<const SfxInt32Item*>(pRowItem)->GetValue() - 1;
272 SCTAB nTab = static_cast<const SfxInt16Item*>(pTabItem)->GetValue() - 1;
274 SCTAB nTabCount = m_pDocument->GetTableCount();
275 if ( m_pDocument->ValidCol(nCol) && m_pDocument->ValidRow(nRow) && ValidTab(nTab,nTabCount) )
277 if ( m_pDocument->IsBlockEditable( nTab, nCol,nRow, nCol, nRow ) )
279 OUString aVal = static_cast<const SfxStringItem*>(pTextItem)->GetValue();
280 m_pDocument->SetString( nCol, nRow, nTab, aVal );
282 PostPaintCell( nCol, nRow, nTab );
283 SetDocumentModified();
285 rReq.Done();
286 break;
288 else // protected cell
290 #if HAVE_FEATURE_SCRIPTING
291 SbxBase::SetError( ERRCODE_BASIC_BAD_PARAMETER ); //! which error ?
292 #endif
293 break;
297 #if HAVE_FEATURE_SCRIPTING
298 SbxBase::SetError( ERRCODE_BASIC_NO_OBJECT );
299 #endif
301 break;
303 case SID_SBA_IMPORT:
305 if (pReqArgs)
307 const SfxPoolItem* pItem;
308 svx::ODataAccessDescriptor aDesc;
309 if ( pReqArgs->GetItemState( nSlot, true, &pItem ) == SfxItemState::SET )
311 uno::Any aAny = static_cast<const SfxUnoAnyItem*>(pItem)->GetValue();
312 uno::Sequence<beans::PropertyValue> aProperties;
313 if ( aAny >>= aProperties )
314 aDesc.initializeFrom( aProperties );
317 OUString sTarget;
318 if ( pReqArgs->GetItemState( FN_PARAM_1, true, &pItem ) == SfxItemState::SET )
319 sTarget = static_cast<const SfxStringItem*>(pItem)->GetValue();
321 bool bIsNewArea = true; // Default sal_True (no inquiry)
322 if ( pReqArgs->GetItemState( FN_PARAM_2, true, &pItem ) == SfxItemState::SET )
323 bIsNewArea = static_cast<const SfxBoolItem*>(pItem)->GetValue();
325 // if necessary, create new database area
326 bool bMakeArea = false;
327 if (bIsNewArea)
329 ScDBCollection* pDBColl = m_pDocument->GetDBCollection();
330 if ( !pDBColl || !pDBColl->getNamedDBs().findByUpperName(ScGlobal::getCharClass().uppercase(sTarget)) )
332 ScAddress aPos;
333 if ( aPos.Parse( sTarget, *m_pDocument, m_pDocument->GetAddressConvention() ) & ScRefFlags::VALID )
335 bMakeArea = true;
336 if (bUndo)
338 OUString aStrImport = ScResId( STR_UNDO_IMPORTDATA );
339 ViewShellId nViewShellId(-1);
340 if (ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell())
341 nViewShellId = pViewSh->GetViewShellId();
342 GetUndoManager()->EnterListAction( aStrImport, aStrImport, 0, nViewShellId );
345 ScDBData* pDBData = GetDBData( ScRange(aPos), SC_DB_IMPORT, ScGetDBSelection::Keep );
346 assert(pDBData && "Cannot create DB data");
347 sTarget = pDBData->GetName();
352 // inquire, before old DB range gets overwritten
353 bool bDo = true;
354 if (!bIsNewArea)
356 OUString aTemplate = ScResId( STR_IMPORT_REPLACE );
357 OUString aMessage = o3tl::getToken(aTemplate, 0, '#' )
358 + sTarget
359 + o3tl::getToken(aTemplate, 1, '#' );
361 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(nullptr,
362 VclMessageType::Question, VclButtonsType::YesNo,
363 aMessage));
364 xQueryBox->set_default_response(RET_YES);
365 bDo = xQueryBox->run() == RET_YES;
368 if (bDo)
370 ScDBDocFunc(*this).UpdateImport( sTarget, aDesc );
371 rReq.Done();
373 // UpdateImport also updates the internal operations
375 else
376 rReq.Ignore();
378 if ( bMakeArea && bUndo)
379 GetUndoManager()->LeaveListAction();
381 else
383 OSL_FAIL( "arguments expected" );
386 break;
388 case SID_CHART_SOURCE:
389 case SID_CHART_ADDSOURCE:
390 ExecuteChartSource(rReq);
391 break;
393 case FID_AUTO_CALC:
395 bool bNewVal;
396 const SfxPoolItem* pItem;
397 if ( pReqArgs && SfxItemState::SET == pReqArgs->GetItemState( nSlot, true, &pItem ) )
398 bNewVal = static_cast<const SfxBoolItem*>(pItem)->GetValue();
399 else
400 bNewVal = !m_pDocument->GetAutoCalc(); // Toggle for menu
401 m_pDocument->SetAutoCalc( bNewVal );
402 SetDocumentModified();
403 if (pBindings)
405 pBindings->Invalidate( FID_AUTO_CALC );
407 rReq.AppendItem( SfxBoolItem( FID_AUTO_CALC, bNewVal ) );
408 rReq.Done();
410 break;
411 case SID_OPEN_HYPERLINK:
413 ScViewData* pViewData = GetViewData();
414 if ( !pViewData )
416 rReq.Ignore();
417 break;
420 if (ScModule::get()->IsEditMode())
422 if (EditView* pEditView = pViewData->GetEditView(pViewData->GetActivePart()))
424 const SvxFieldItem* pFieldItem = pEditView->GetFieldAtSelection(/*bAlsoCheckBeforeCursor=*/true);
425 const SvxFieldData* pField = pFieldItem ? pFieldItem->GetField() : nullptr;
426 if (const SvxURLField* pURLField = dynamic_cast<const SvxURLField*>(pField))
428 ScGlobal::OpenURL(pURLField->GetURL(), pURLField->GetTargetFrame(), true);
429 rReq.Done();
430 break;
433 rReq.Ignore();
434 break;
437 ScGridWindow* pWin = pViewData->GetActiveWin();
438 if ( !pWin )
440 rReq.Ignore();
441 break;
444 ScAddress aCell {pViewData->GetCurPos()};
445 std::vector<UrlData> vUrls = pWin->GetEditUrls(aCell);
446 if (vUrls.empty())
448 rReq.Ignore();
449 break;
452 for (UrlData& data : vUrls)
454 ScGlobal::OpenURL(data.aUrl, data.aTarget, true);
456 rReq.Done();
458 break;
459 case FID_RECALC:
460 DoRecalc( rReq.IsAPI() );
461 rReq.Done();
462 break;
463 case FID_HARD_RECALC:
464 DoHardRecalc();
465 rReq.Done();
466 break;
467 case SID_UPDATETABLINKS:
469 ScLkUpdMode nSet = GetLinkUpdateModeState();
471 if (nSet == LM_ALWAYS)
473 ReloadAllLinks();
474 rReq.Done();
476 else if (nSet == LM_NEVER)
478 getEmbeddedObjectContainer().setUserAllowsLinkUpdate(false);
479 rReq.Ignore();
481 else if (nSet == LM_ON_DEMAND)
483 ScTabViewShell* pViewSh = GetBestViewShell();
484 SfxViewFrame* pViewFrame = pViewSh ? pViewSh->GetFrame() : nullptr;
485 if (pViewFrame)
487 pViewFrame->RemoveInfoBar(u"enablecontent");
488 auto pInfoBar = pViewFrame->AppendInfoBar(u"enablecontent"_ustr, SfxResId(RID_SECURITY_WARNING_TITLE),
489 ScResId(STR_RELOAD_TABLES), InfobarType::WARNING);
490 if (pInfoBar)
492 weld::Button& rHelpBtn = pInfoBar->addButton();
493 rHelpBtn.set_label(GetStandardText(StandardButtonType::Help).replaceFirst("~", ""));
494 rHelpBtn.connect_clicked(LINK(nullptr, LinkHelp, DispatchHelpLinksHdl));
495 weld::Button& rBtn = pInfoBar->addButton();
496 rBtn.set_label(ScResId(STR_ENABLE_CONTENT));
497 rBtn.set_tooltip_text(ScResId(STR_ENABLE_CONTENT_TOOLTIP));
498 rBtn.connect_clicked(LINK(this, ScDocShell, ReloadAllLinksHdl));
500 // when active content is disabled the "Allow updating" button has no functionality.
501 if (officecfg::Office::Common::Security::Scripting::DisableActiveContent::get())
503 rBtn.set_tooltip_text(ScResId(STR_ENABLE_CONTENT_TOOLTIP_DISABLED));
504 rBtn.set_sensitive(false);
508 rReq.Done();
511 break;
513 case SID_REIMPORT_AFTER_LOAD:
515 // Is called after loading if there are DB areas with omitted data
517 bool bDone = false;
518 ScDBCollection* pDBColl = m_pDocument->GetDBCollection();
520 if ((m_nCanUpdate != css::document::UpdateDocMode::NO_UPDATE) &&
521 (m_nCanUpdate != css::document::UpdateDocMode::QUIET_UPDATE))
523 ScRange aRange;
524 ScTabViewShell* pViewSh = GetBestViewShell();
525 OSL_ENSURE(pViewSh,"SID_REIMPORT_AFTER_LOAD: no View");
526 if (pViewSh && pDBColl)
528 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(GetActiveDialogParent(),
529 VclMessageType::Question, VclButtonsType::YesNo,
530 ScResId(STR_REIMPORT_AFTER_LOAD)));
531 xQueryBox->set_default_response(RET_YES);
532 if (xQueryBox->run() == RET_YES)
534 ScDBCollection::NamedDBs& rDBs = pDBColl->getNamedDBs();
535 for (const auto& rxDB : rDBs)
537 ScDBData& rDBData = *rxDB;
538 if ( rDBData.IsStripData() &&
539 rDBData.HasImportParam() && !rDBData.HasImportSelection() )
541 rDBData.GetArea(aRange);
542 pViewSh->MarkRange(aRange);
544 // Import and internal operations like SID_REFRESH_DBAREA
545 // (inquiry for import not needed here)
547 ScImportParam aImportParam;
548 rDBData.GetImportParam( aImportParam );
549 bool bContinue = pViewSh->ImportData( aImportParam );
550 rDBData.SetImportParam( aImportParam );
552 // mark (size may have changed)
553 rDBData.GetArea(aRange);
554 pViewSh->MarkRange(aRange);
556 if ( bContinue ) // error at import -> abort
558 // internal operations, if some where saved
560 if ( rDBData.HasQueryParam() || rDBData.HasSortParam() ||
561 rDBData.HasSubTotalParam() )
562 pViewSh->RepeatDB();
564 // pivot tables, which have the range as source data
566 RefreshPivotTables(aRange);
570 bDone = true;
575 if ( !bDone && pDBColl )
577 // if not, but then update the dependent formulas
578 //! also for individual ranges, which cannot be updated
580 m_pDocument->CalcAll(); //! only for the dependent
581 PostDataChanged();
584 if (bDone)
585 rReq.Done();
586 else
587 rReq.Ignore();
589 break;
591 case SID_AUTO_STYLE:
592 OSL_FAIL("use ScAutoStyleHint instead of SID_AUTO_STYLE");
593 break;
595 case SID_GET_COLORLIST:
597 const SvxColorListItem* pColItem = GetItem(SID_COLOR_TABLE);
598 const XColorListRef& pList = pColItem->GetColorList();
599 rReq.SetReturnValue(OfaXColorListItem(SID_GET_COLORLIST, pList));
601 break;
603 case FID_CHG_RECORD:
605 ScDocument& rDoc = GetDocument();
606 // get argument (recorded macro)
607 const SfxBoolItem* pItem = rReq.GetArg<SfxBoolItem>(FID_CHG_RECORD);
608 bool bDo = true;
610 // desired state
611 ScChangeTrack* pChangeTrack = rDoc.GetChangeTrack();
612 bool bActivateTracking = (pChangeTrack == nullptr); // toggle
613 if ( pItem )
614 bActivateTracking = pItem->GetValue(); // from argument
616 if ( !bActivateTracking )
618 if ( !pItem )
620 // no dialog on playing the macro
621 std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(GetActiveDialogParent(),
622 VclMessageType::Warning, VclButtonsType::YesNo,
623 ScResId(STR_END_REDLINING)));
624 xWarn->set_default_response(RET_NO);
625 bDo = (xWarn->run() == RET_YES );
628 if ( bDo )
630 if (pChangeTrack)
632 if ( pChangeTrack->IsProtected() )
633 bDo = ExecuteChangeProtectionDialog();
635 if ( bDo )
637 rDoc.EndChangeTracking();
638 PostPaintGridAll();
642 else
644 rDoc.StartChangeTracking();
645 ScChangeViewSettings aChangeViewSet;
646 aChangeViewSet.SetShowChanges(true);
647 rDoc.SetChangeViewSettings(aChangeViewSet);
650 if ( bDo )
652 UpdateAcceptChangesDialog();
654 // invalidate slots
655 if (pBindings)
656 pBindings->InvalidateAll(false);
657 if ( !pItem )
658 rReq.AppendItem( SfxBoolItem( FID_CHG_RECORD, bActivateTracking ) );
659 rReq.Done();
661 else
662 rReq.Ignore();
664 break;
666 case SID_CHG_PROTECT :
668 if ( ExecuteChangeProtectionDialog() )
670 rReq.Done();
671 SetDocumentModified();
673 else
674 rReq.Ignore();
676 break;
678 case SID_DOCUMENT_MERGE:
679 case SID_DOCUMENT_COMPARE:
681 bool bDo = true;
682 ScChangeTrack* pChangeTrack = m_pDocument->GetChangeTrack();
683 if ( pChangeTrack && !m_pImpl->bIgnoreLostRedliningWarning )
685 if ( nSlot == SID_DOCUMENT_COMPARE )
686 { //! old changes trace will be lost
687 std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(GetActiveDialogParent(),
688 VclMessageType::Warning, VclButtonsType::YesNo,
689 ScResId(STR_END_REDLINING)));
690 xWarn->set_default_response(RET_NO);
691 if (xWarn->run() == RET_YES)
692 bDo = ExecuteChangeProtectionDialog( true );
693 else
694 bDo = false;
696 else // merge might reject some actions
697 bDo = ExecuteChangeProtectionDialog( true );
699 if ( !bDo )
701 rReq.Ignore();
702 break;
704 SfxApplication* pApp = SfxGetpApp();
705 const SfxPoolItem* pItem;
706 const SfxStringItem* pFileNameItem(nullptr);
707 SfxMedium* pMed = nullptr;
708 if (pReqArgs)
709 pFileNameItem = pReqArgs->GetItemIfSet(SID_FILE_NAME);
710 if (pFileNameItem)
712 OUString aFileName = pFileNameItem->GetValue();
714 OUString aFilterName;
715 if (const SfxStringItem* pFilterItem = pReqArgs->GetItemIfSet(SID_FILTER_NAME))
717 aFilterName = pFilterItem->GetValue();
719 OUString aOptions;
720 if (const SfxStringItem* pOptionsItem = pReqArgs->GetItemIfSet(SID_FILE_FILTEROPTIONS))
722 aOptions = pOptionsItem->GetValue();
724 short nVersion = 0;
725 const SfxInt16Item* pInt16Item(nullptr);
726 if (pReqArgs->GetItemState(SID_VERSION, true, &pItem) == SfxItemState::SET)
727 pInt16Item = dynamic_cast<const SfxInt16Item*>(pItem);
728 if (pInt16Item)
730 nVersion = pInt16Item->GetValue();
733 // no filter specified -> detection
734 if (aFilterName.isEmpty())
735 ScDocumentLoader::GetFilterName( aFileName, aFilterName, aOptions, true, false );
737 // filter name from dialog contains application prefix,
738 // GetFilter needs name without the prefix.
739 ScDocumentLoader::RemoveAppPrefix( aFilterName );
741 std::shared_ptr<const SfxFilter> pFilter = ScDocShell::Factory().GetFilterContainer()->GetFilter4FilterName( aFilterName );
742 auto pSet = std::make_shared<SfxAllItemSet>( pApp->GetPool() );
743 if (!aOptions.isEmpty())
744 pSet->Put( SfxStringItem( SID_FILE_FILTEROPTIONS, aOptions ) );
745 if ( nVersion != 0 )
746 pSet->Put( SfxInt16Item( SID_VERSION, nVersion ) );
747 pMed = new SfxMedium( aFileName, StreamMode::STD_READ, std::move(pFilter), std::move(pSet) );
749 else
751 const sfx2::DocumentInserter::Mode mode { nSlot==SID_DOCUMENT_COMPARE
752 ? sfx2::DocumentInserter::Mode::Compare
753 : sfx2::DocumentInserter::Mode::Merge};
754 // start file dialog asynchronous
755 m_pImpl->bIgnoreLostRedliningWarning = true;
756 m_pImpl->pRequest.reset(new SfxRequest( rReq ));
757 m_pImpl->pDocInserter.reset();
759 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
760 weld::Window* pParent = pViewSh ? pViewSh->GetFrameWeld() : nullptr;
761 m_pImpl->pDocInserter.reset( new ::sfx2::DocumentInserter(pParent,
762 ScDocShell::Factory().GetFactoryName(), mode ) );
763 m_pImpl->pDocInserter->StartExecuteModal( LINK( this, ScDocShell, DialogClosedHdl ) );
764 return ;
767 // now execute in earnest...
768 SfxErrorContext aEc( ERRCTX_SFX_OPENDOC, pMed->GetName() );
770 // pOtherDocSh->DoClose() will be called explicitly later, but it is still more safe to use SfxObjectShellLock here
771 rtl::Reference<ScDocShell> pOtherDocSh = new ScDocShell;
772 pOtherDocSh->DoLoad( pMed );
773 ErrCodeMsg nErr = pOtherDocSh->GetErrorCode();
774 if (nErr)
775 ErrorHandler::HandleError( nErr ); // also warnings
777 if ( !pOtherDocSh->GetErrorIgnoreWarning() ) // only errors
779 bool bHadTrack = ( m_pDocument->GetChangeTrack() != nullptr );
780 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
781 sal_uLong nStart = 0;
782 if ( nSlot == SID_DOCUMENT_MERGE && pChangeTrack )
784 nStart = pChangeTrack->GetActionMax() + 1;
786 #endif
787 if ( nSlot == SID_DOCUMENT_COMPARE )
788 CompareDocument( pOtherDocSh->GetDocument() );
789 else
790 MergeDocument( pOtherDocSh->GetDocument() );
792 // show "accept changes" dialog
793 //! get view for this document!
794 if ( !IsDocShared() )
796 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
797 if ( pViewFrm )
799 pViewFrm->ShowChildWindow( ScAcceptChgDlgWrapper::GetChildWindowId() ); //@51669
801 if ( pBindings )
803 pBindings->Invalidate( FID_CHG_ACCEPT );
807 rReq.SetReturnValue( SfxInt32Item( TypedWhichId<SfxInt32Item>(nSlot), 0 ) ); //! ???????
808 rReq.Done();
810 if (!bHadTrack) // newly turned on -> show as well
812 ScChangeViewSettings* pOldSet = m_pDocument->GetChangeViewSettings();
813 if ( !pOldSet || !pOldSet->ShowChanges() )
815 ScChangeViewSettings aChangeViewSet;
816 aChangeViewSet.SetShowChanges(true);
817 m_pDocument->SetChangeViewSettings(aChangeViewSet);
820 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
821 else if ( nSlot == SID_DOCUMENT_MERGE && IsDocShared() && pChangeTrack )
823 sal_uLong nEnd = pChangeTrack->GetActionMax();
824 if ( nEnd >= nStart )
826 // only show changes from merged document
827 ScChangeViewSettings aChangeViewSet;
828 aChangeViewSet.SetShowChanges( true );
829 aChangeViewSet.SetShowAccepted( true );
830 aChangeViewSet.SetHasActionRange();
831 aChangeViewSet.SetTheActionRange( nStart, nEnd );
832 m_pDocument->SetChangeViewSettings( aChangeViewSet );
834 // update view
835 PostPaintExtras();
836 PostPaintGridAll();
839 #endif
841 pOtherDocSh->DoClose(); // delete happens with the Ref
843 break;
845 case SID_DELETE_SCENARIO:
846 if (pReqArgs)
848 const SfxPoolItem* pItem;
849 if ( pReqArgs->GetItemState( nSlot, true, &pItem ) == SfxItemState::SET )
851 if (const SfxStringItem* pStringItem = dynamic_cast<const SfxStringItem*>(pItem))
853 const OUString& aName = pStringItem->GetValue();
854 SCTAB nTab;
855 if (m_pDocument->GetTable( aName, nTab ))
857 // move DeleteTable from viewfunc to docfunc!
859 ScTabViewShell* pSh = GetBestViewShell();
860 if ( pSh )
862 //! omit SetTabNo in DeleteTable?
863 SCTAB nDispTab = pSh->GetViewData().GetTabNo();
864 pSh->DeleteTable( nTab );
865 pSh->SetTabNo(nDispTab);
866 rReq.Done();
872 break;
874 case SID_EDIT_SCENARIO:
876 const SfxPoolItem* pItem;
877 if ( pReqArgs->GetItemState( nSlot, true, &pItem ) == SfxItemState::SET )
879 if (const SfxStringItem* pStringItem = dynamic_cast<const SfxStringItem*>(pItem))
881 OUString aName = pStringItem->GetValue();
882 SCTAB nTab;
883 if (m_pDocument->GetTable( aName, nTab ))
885 if (m_pDocument->IsScenario(nTab))
887 OUString aComment;
888 Color aColor;
889 ScScenarioFlags nFlags;
890 m_pDocument->GetScenarioData( nTab, aComment, aColor, nFlags );
892 // Determine if the Sheet that the Scenario was created on
893 // is protected. But first we need to find that Sheet.
894 // Rewind back to the actual sheet.
895 SCTAB nActualTab = nTab;
898 nActualTab--;
900 while(m_pDocument->IsScenario(nActualTab));
901 bool bSheetProtected = m_pDocument->IsTabProtected(nActualTab);
903 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
905 ScopedVclPtr<AbstractScNewScenarioDlg> pNewDlg(pFact->CreateScNewScenarioDlg(GetActiveDialogParent(), aName, true, bSheetProtected));
906 pNewDlg->SetScenarioData( aName, aComment, aColor, nFlags );
907 if ( pNewDlg->Execute() == RET_OK )
909 pNewDlg->GetScenarioData( aName, aComment, aColor, nFlags );
910 ModifyScenario( nTab, aName, aComment, aColor, nFlags );
911 rReq.Done();
918 break;
920 case SID_ATTR_YEAR2000 :
922 const SfxPoolItem* pItem;
923 if ( pReqArgs->GetItemState( nSlot, true, &pItem ) == SfxItemState::SET )
925 if (const SfxUInt16Item* pInt16Item = dynamic_cast<const SfxUInt16Item*>(pItem))
927 sal_uInt16 nY2k = pInt16Item->GetValue();
928 // set always to DocOptions, so that it is also saved for S050
929 // (and all inquiries run up until now on it as well).
930 // SetDocOptions propagates that to the NumberFormatter
931 ScDocOptions aDocOpt( m_pDocument->GetDocOptions() );
932 aDocOpt.SetYear2000( nY2k );
933 m_pDocument->SetDocOptions( aDocOpt );
934 // the FormShell shall notice it as well
935 ScTabViewShell* pSh = GetBestViewShell();
936 if ( pSh )
938 FmFormShell* pFSh = pSh->GetFormShell();
939 if ( pFSh )
940 pFSh->SetY2KState( nY2k );
945 break;
947 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
948 case SID_SHARE_DOC:
950 ScViewData* pViewData = GetViewData();
951 if ( !pViewData )
953 rReq.Ignore();
954 break;
957 weld::Window* pWin = GetActiveDialogParent();
958 ScShareDocumentDlg aDlg(pWin, pViewData);
959 if (aDlg.run() == RET_OK)
961 bool bSetShared = aDlg.IsShareDocumentChecked();
962 if ( bSetShared != IsDocShared() )
964 if ( bSetShared )
966 bool bContinue = true;
967 if ( HasName() )
969 std::unique_ptr<weld::MessageDialog> xQueryBox(Application::CreateMessageDialog(pWin,
970 VclMessageType::Question, VclButtonsType::YesNo,
971 ScResId(STR_DOC_WILLBESAVED)));
972 xQueryBox->set_default_response(RET_YES);
973 if (xQueryBox->run() == RET_NO)
975 bContinue = false;
978 if ( bContinue )
980 EnableSharedSettings( true );
982 ScModule* mod = ScModule::get();
983 mod->SetInSharedDocSaving(true);
984 if ( !SwitchToShared( true, true ) )
986 // TODO/LATER: what should be done in case the switch has failed?
987 // for example in case the user has cancelled the saveAs operation
990 mod->SetInSharedDocSaving(false);
992 InvalidateName();
993 GetUndoManager()->Clear();
995 ScTabView* pTabView = pViewData->GetView();
996 if ( pTabView )
998 pTabView->UpdateLayerLocks();
1002 else
1004 uno::Reference< frame::XModel > xModel;
1007 // load shared file
1008 xModel.set( LoadSharedDocument(), uno::UNO_SET_THROW );
1009 uno::Reference< util::XCloseable > xCloseable( xModel, uno::UNO_QUERY_THROW );
1011 // check if shared flag is set in shared file
1012 bool bShared = false;
1013 ScModelObj* pDocObj = comphelper::getFromUnoTunnel<ScModelObj>( xModel );
1014 if ( pDocObj )
1016 ScDocShell* pDocShell = dynamic_cast< ScDocShell* >( pDocObj->GetEmbeddedObject() );
1017 if ( pDocShell )
1019 bShared = pDocShell->HasSharedXMLFlagSet();
1023 // #i87870# check if shared status was disabled and enabled again
1024 bool bOwnEntry = false;
1027 ::svt::ShareControlFile aControlFile( GetSharedFileURL() );
1028 bOwnEntry = aControlFile.HasOwnEntry();
1030 catch ( uno::Exception& )
1034 if ( bShared && bOwnEntry )
1036 uno::Reference< frame::XStorable > xStorable( xModel, uno::UNO_QUERY_THROW );
1037 if ( xStorable->isReadonly() )
1039 xCloseable->close( true );
1041 OUString aUserName( ScResId( STR_UNKNOWN_USER ) );
1044 ::svt::DocumentLockFile aLockFile( GetSharedFileURL() );
1045 LockFileEntry aData = aLockFile.GetLockData();
1046 if ( !aData[LockFileComponent::OOOUSERNAME].isEmpty() )
1048 aUserName = aData[LockFileComponent::OOOUSERNAME];
1050 else if ( !aData[LockFileComponent::SYSUSERNAME].isEmpty() )
1052 aUserName = aData[LockFileComponent::SYSUSERNAME];
1055 catch ( uno::Exception& )
1058 OUString aMessage( ScResId( STR_FILE_LOCKED_TRY_LATER ) );
1059 aMessage = aMessage.replaceFirst( "%1", aUserName );
1061 std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(pWin,
1062 VclMessageType::Warning, VclButtonsType::Ok,
1063 aMessage));
1064 xWarn->run();
1066 else
1068 std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(pWin,
1069 VclMessageType::Warning, VclButtonsType::YesNo,
1070 ScResId(STR_DOC_DISABLESHARED)));
1071 xWarn->set_default_response(RET_YES);
1073 if (xWarn->run() == RET_YES)
1075 xCloseable->close( true );
1077 if ( !SwitchToShared( false, true ) )
1079 // TODO/LATER: what should be done in case the switch has failed?
1080 // for example in case the user has cancelled the saveAs operation
1083 EnableSharedSettings( false );
1085 // Do *not* use dispatch mechanism in this place - we don't want others (extensions etc.) to intercept this.
1086 GetModel()->store();
1088 ScTabView* pTabView = pViewData->GetView();
1089 if ( pTabView )
1091 pTabView->UpdateLayerLocks();
1094 else
1096 xCloseable->close( true );
1100 else
1102 xCloseable->close( true );
1103 std::unique_ptr<weld::MessageDialog> xWarn(Application::CreateMessageDialog(pWin,
1104 VclMessageType::Warning, VclButtonsType::Ok,
1105 ScResId(STR_DOC_NOLONGERSHARED)));
1106 xWarn->run();
1109 catch ( uno::Exception& )
1111 TOOLS_WARN_EXCEPTION( "sc", "SID_SHARE_DOC" );
1112 ScModule::get()->SetInSharedDocSaving(false);
1116 uno::Reference< util::XCloseable > xClose( xModel, uno::UNO_QUERY_THROW );
1117 xClose->close( true );
1119 catch ( uno::Exception& )
1126 rReq.Done();
1128 break;
1129 #endif
1130 case SID_OPEN_CALC:
1132 ScViewData* pViewData = GetViewData();
1133 if (pViewData)
1135 SfxStringItem aApp(SID_DOC_SERVICE, u"com.sun.star.sheet.SpreadsheetDocument"_ustr);
1136 SfxStringItem aTarget(SID_TARGETNAME, u"_blank"_ustr);
1137 pViewData->GetDispatcher().ExecuteList(
1138 SID_OPENDOC, SfxCallMode::API|SfxCallMode::SYNCHRON,
1139 { &aApp, &aTarget });
1142 break;
1143 case SID_NOTEBOOKBAR:
1145 const SfxStringItem* pFile = rReq.GetArg<SfxStringItem>( SID_NOTEBOOKBAR );
1147 if ( pBindings && sfx2::SfxNotebookBar::IsActive() )
1148 sfx2::SfxNotebookBar::ExecMethod(*pBindings, pFile ? pFile->GetValue() : u""_ustr);
1149 else if ( pBindings )
1150 sfx2::SfxNotebookBar::CloseMethod(*pBindings);
1152 break;
1153 case SID_LANGUAGE_STATUS:
1155 OUString aLangText;
1156 const SfxStringItem* pItem = rReq.GetArg<SfxStringItem>(nSlot);
1157 if ( pItem )
1158 aLangText = pItem->GetValue();
1160 if ( !aLangText.isEmpty() )
1162 LanguageType eLang, eLatin, eCjk, eCtl;
1163 static constexpr OUString aSelectionLangPrefix(u"Current_"_ustr);
1164 static constexpr OUString aParagraphLangPrefix(u"Paragraph_"_ustr);
1165 static constexpr OUString aDocLangPrefix(u"Default_"_ustr);
1167 bool bSelection = false;
1168 bool bParagraph = false;
1170 ScDocument& rDoc = GetDocument();
1171 rDoc.GetLanguage( eLatin, eCjk, eCtl );
1173 sal_Int32 nPos = 0;
1174 if ( aLangText == "*" )
1176 if (ScTabViewShell* pSh = GetBestViewShell())
1178 pSh->ExecuteCellFormatDlg(rReq, u"font"_ustr);
1179 pBindings->Invalidate(SID_LANGUAGE_STATUS);
1182 else if ( (nPos = aLangText.indexOf(aDocLangPrefix)) != -1 )
1184 aLangText = aLangText.replaceAt(nPos, aDocLangPrefix.getLength(), u"");
1186 if ( aLangText == "LANGUAGE_NONE" )
1188 eLang = LANGUAGE_NONE;
1189 rDoc.SetLanguage( eLang, eCjk, eCtl );
1191 else if ( aLangText == "RESET_LANGUAGES" )
1193 ScModule::GetSpellSettings(eLang, eCjk, eCtl);
1194 rDoc.SetLanguage(eLang, eCjk, eCtl);
1196 else
1198 eLang = SvtLanguageTable::GetLanguageType( aLangText );
1199 if ( eLang != LANGUAGE_DONTKNOW && SvtLanguageOptions::GetScriptTypeOfLanguage(eLang) == SvtScriptType::LATIN )
1201 rDoc.SetLanguage( eLang, eCjk, eCtl );
1203 else
1205 eLang = eLatin;
1209 else if (-1 != (nPos = aLangText.indexOf( aSelectionLangPrefix )))
1211 bSelection = true;
1212 aLangText = aLangText.replaceAt( nPos, aSelectionLangPrefix.getLength(), u"" );
1214 else if (-1 != (nPos = aLangText.indexOf( aParagraphLangPrefix )))
1216 bParagraph = true;
1217 aLangText = aLangText.replaceAt( nPos, aParagraphLangPrefix.getLength(), u"" );
1220 if (bSelection)
1222 ScTabViewShell* pViewShell = GetBestViewShell();
1223 if (pViewShell)
1225 const ScPatternAttr* pSelAttrs = pViewShell->GetSelectionPattern();
1226 if (pSelAttrs)
1228 const SfxItemSet& rOldSet = pSelAttrs->GetItemSet();
1229 SfxItemPool* pItemPool = rOldSet.GetPool();
1230 auto pNewSet = std::make_shared<SfxItemSet>(rOldSet);
1232 if (aLangText == "LANGUAGE_NONE")
1234 pNewSet->Put(SvxLanguageItem(LANGUAGE_NONE,
1235 pItemPool->GetWhichIDFromSlotID(SID_ATTR_CHAR_LANGUAGE)));
1236 pNewSet->Put(SvxLanguageItem(LANGUAGE_NONE,
1237 pItemPool->GetWhichIDFromSlotID(SID_ATTR_CHAR_CJK_LANGUAGE)));
1238 pNewSet->Put(SvxLanguageItem(LANGUAGE_NONE,
1239 pItemPool->GetWhichIDFromSlotID(SID_ATTR_CHAR_CTL_LANGUAGE)));
1241 else
1243 const LanguageType nLangType = SvtLanguageTable::GetLanguageType(aLangText);
1244 const SvtScriptType nScriptType =
1245 SvtLanguageOptions::GetScriptTypeOfLanguage(nLangType);
1246 if (nScriptType == SvtScriptType::LATIN)
1247 pNewSet->Put(SvxLanguageItem(nLangType,
1248 pItemPool->GetWhichIDFromSlotID(SID_ATTR_CHAR_LANGUAGE)));
1249 if (nScriptType == SvtScriptType::COMPLEX)
1250 pNewSet->Put(SvxLanguageItem(nLangType,
1251 pItemPool->GetWhichIDFromSlotID(SID_ATTR_CHAR_CTL_LANGUAGE)));
1252 if (nScriptType == SvtScriptType::ASIAN)
1253 pNewSet->Put(SvxLanguageItem(nLangType,
1254 pItemPool->GetWhichIDFromSlotID(SID_ATTR_CHAR_CJK_LANGUAGE)));
1256 pViewShell->ApplyAttributes(*pNewSet, rOldSet);
1257 pBindings->Invalidate(SID_LANGUAGE_STATUS);
1261 else if (bParagraph)
1263 ScViewData* pViewData = GetViewData();
1264 if (!pViewData)
1265 return;
1267 EditView* pEditView = pViewData->GetEditView(pViewData->GetActivePart());
1268 if (!pEditView)
1269 return;
1271 const LanguageType nLangToUse = SvtLanguageTable::GetLanguageType( aLangText );
1272 SvtScriptType nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( nLangToUse );
1274 SfxItemSet aAttrs = pEditView->getEditEngine().GetEmptyItemSet();
1275 if (nScriptType == SvtScriptType::LATIN)
1276 aAttrs.Put( SvxLanguageItem( nLangToUse, EE_CHAR_LANGUAGE ) );
1277 if (nScriptType == SvtScriptType::COMPLEX)
1278 aAttrs.Put( SvxLanguageItem( nLangToUse, EE_CHAR_LANGUAGE_CTL ) );
1279 if (nScriptType == SvtScriptType::ASIAN)
1280 aAttrs.Put( SvxLanguageItem( nLangToUse, EE_CHAR_LANGUAGE_CJK ) );
1281 ESelection aOldSel;
1282 if (bParagraph)
1284 ESelection aSel = pEditView->GetSelection();
1285 aOldSel = aSel;
1286 aSel.start.nIndex = 0;
1287 aSel.end.nIndex = EE_TEXTPOS_MAX;
1288 pEditView->SetSelection( aSel );
1291 pEditView->SetAttribs( aAttrs );
1292 if (bParagraph)
1293 pEditView->SetSelection( aOldSel );
1295 else if ( eLang != eLatin )
1297 if ( ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell() )
1299 ScInputHandler* pInputHandler = ScModule::get()->GetInputHdl(pViewSh);
1300 if ( pInputHandler )
1301 pInputHandler->UpdateSpellSettings();
1303 pViewSh->UpdateDrawTextOutliner();
1306 SetDocumentModified();
1307 Broadcast(SfxHint(SfxHintId::LanguageChanged));
1308 PostPaintGridAll();
1312 break;
1313 case SID_SPELLCHECK_IGNORE_ALL:
1315 ScViewData* pViewData = GetViewData();
1316 if (!pViewData)
1317 return;
1319 EditView* pEditView = pViewData->GetEditView(pViewData->GetActivePart());
1320 if (!pEditView)
1321 return;
1323 OUString sIgnoreText;
1324 const SfxStringItem* pItem2 = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
1325 if (pItem2)
1326 sIgnoreText = pItem2->GetValue();
1328 if(sIgnoreText == "Spelling")
1330 ESelection aOldSel = pEditView->GetSelection();
1331 pEditView->SpellIgnoreWord();
1332 pEditView->SetSelection( aOldSel );
1335 break;
1336 case SID_SPELLCHECK_APPLY_SUGGESTION:
1338 ScViewData* pViewData = GetViewData();
1339 if (!pViewData)
1340 return;
1342 EditView* pEditView = pViewData->GetEditView(pViewData->GetActivePart());
1343 if (!pEditView)
1344 return;
1346 OUString sApplyText;
1347 const SfxStringItem* pItem2 = rReq.GetArg<SfxStringItem>(FN_PARAM_1);
1348 if (pItem2)
1349 sApplyText = pItem2->GetValue();
1351 static constexpr OUString sSpellingRule(u"Spelling_"_ustr);
1352 sal_Int32 nPos = 0;
1353 if(-1 != (nPos = sApplyText.indexOf( sSpellingRule )))
1355 sApplyText = sApplyText.replaceAt(nPos, sSpellingRule.getLength(), u"");
1356 pEditView->InsertText( sApplyText );
1359 break;
1360 case SID_REFRESH_VIEW:
1362 PostPaintGridAll();
1364 break;
1365 default:
1367 // small (?) hack -> forwarding of the slots to TabViewShell
1368 ScTabViewShell* pSh = GetBestViewShell();
1369 if ( pSh )
1370 pSh->Execute( rReq );
1371 #if HAVE_FEATURE_SCRIPTING
1372 else
1373 SbxBase::SetError( ERRCODE_BASIC_NO_ACTIVE_OBJECT );
1374 #endif
1379 void UpdateAcceptChangesDialog()
1381 // update "accept changes" dialog
1382 //! notify all views
1383 SfxViewFrame* pViewFrm = SfxViewFrame::Current();
1384 if ( pViewFrm && pViewFrm->HasChildWindow( FID_CHG_ACCEPT ) )
1386 SfxChildWindow* pChild = pViewFrm->GetChildWindow( FID_CHG_ACCEPT );
1387 if ( pChild )
1388 static_cast<ScAcceptChgDlgWrapper*>(pChild)->ReInitDlg();
1392 void ScDocShell::ExecuteChartSource(SfxRequest& rReq)
1394 const SfxItemSet* pReqArgs = rReq.GetArgs();
1395 sal_uInt16 nSlot = rReq.GetSlot();
1396 bool bUndo (m_pDocument->IsUndoEnabled());
1397 if (!pReqArgs)
1399 OSL_FAIL("SID_CHART_SOURCE without arguments");
1400 return;
1403 ScDocument& rDoc = GetDocument();
1404 const SfxPoolItem* pItem;
1405 OUString aChartName, aRangeName;
1407 ScRange aSingleRange;
1408 ScRangeListRef aRangeListRef;
1409 bool bMultiRange = false;
1411 bool bColHeaders = true;
1412 bool bRowHeaders = true;
1413 bool bColInit = false;
1414 bool bRowInit = false;
1415 bool bAddRange = (nSlot == SID_CHART_ADDSOURCE);
1417 if( const SfxStringItem* pChartItem = pReqArgs->GetItemIfSet( SID_CHART_NAME ) )
1418 aChartName = pChartItem->GetValue();
1420 if( const SfxStringItem* pChartItem = pReqArgs->GetItemIfSet( SID_CHART_SOURCE ) )
1421 aRangeName = pChartItem->GetValue();
1423 if( pReqArgs->HasItem( FN_PARAM_1, &pItem ) )
1425 bColHeaders = static_cast<const SfxBoolItem*>(pItem)->GetValue();
1426 bColInit = true;
1428 if( pReqArgs->HasItem( FN_PARAM_2, &pItem ) )
1430 bRowHeaders = static_cast<const SfxBoolItem*>(pItem)->GetValue();
1431 bRowInit = true;
1434 ScAddress::Details aDetails(rDoc.GetAddressConvention(), 0, 0);
1435 bool bValid = (aSingleRange.ParseAny(aRangeName, rDoc, aDetails) & ScRefFlags::VALID) != ScRefFlags::ZERO;
1436 if (!bValid)
1438 aRangeListRef = new ScRangeList;
1439 aRangeListRef->Parse( aRangeName, rDoc, rDoc.GetAddressConvention());
1440 if ( !aRangeListRef->empty() )
1442 bMultiRange = true;
1443 aSingleRange = aRangeListRef->front(); // for header
1444 bValid = true;
1446 else
1447 aRangeListRef.clear();
1450 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
1451 if (!pViewSh || !bValid || aChartName.isEmpty() )
1453 OSL_FAIL("UpdateChartArea: no ViewShell or wrong data");
1454 rReq.Done();
1455 return;
1458 weld::Window* pParent = pViewSh->GetFrameWeld();
1460 SCCOL nCol1 = aSingleRange.aStart.Col();
1461 SCROW nRow1 = aSingleRange.aStart.Row();
1462 SCCOL nCol2 = aSingleRange.aEnd.Col();
1463 SCROW nRow2 = aSingleRange.aEnd.Row();
1464 SCTAB nTab = aSingleRange.aStart.Tab();
1466 //! limit always or not at all ???
1467 if (!bMultiRange)
1468 m_pDocument->LimitChartArea( nTab, nCol1,nRow1, nCol2,nRow2 );
1470 // Dialog for column/row headers
1471 if ( !bAddRange && ( !bColInit || !bRowInit ) )
1473 ScChartPositioner aChartPositioner( *m_pDocument, nTab, nCol1,nRow1, nCol2,nRow2 );
1474 if (!bColInit)
1475 bColHeaders = aChartPositioner.HasColHeaders();
1476 if (!bRowInit)
1477 bRowHeaders = aChartPositioner.HasRowHeaders();
1479 auto xRequest = std::make_shared<SfxRequest>(rReq);
1480 rReq.Ignore(); // the 'old' request is not relevant any more
1481 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
1482 VclPtr<AbstractScColRowLabelDlg> pDlg(pFact->CreateScColRowLabelDlg(pParent, bRowHeaders, bColHeaders));
1483 pDlg->StartExecuteAsync(
1484 [this, pDlg, xRequest=std::move(xRequest), bUndo, bMultiRange,
1485 aChartName, aRangeListRef=std::move(aRangeListRef), bAddRange,
1486 nCol1, nRow1, nCol2, nRow2, nTab] (sal_Int32 nResult)->void
1488 if (nResult == RET_OK)
1490 bool bColHeaders2 = pDlg->IsRow();
1491 bool bRowHeaders2 = pDlg->IsCol();
1493 xRequest->AppendItem(SfxBoolItem(FN_PARAM_1, bColHeaders2));
1494 xRequest->AppendItem(SfxBoolItem(FN_PARAM_2, bRowHeaders2));
1495 ExecuteChartSourcePost(bUndo, bMultiRange,
1496 aChartName, aRangeListRef, bColHeaders2, bRowHeaders2, bAddRange,
1497 nCol1, nRow1, nCol2, nRow2, nTab);
1499 pDlg->disposeOnce();
1500 xRequest->Done();
1504 else
1506 ExecuteChartSourcePost(bUndo, bMultiRange,
1507 aChartName, aRangeListRef, bColHeaders, bRowHeaders, bAddRange,
1508 nCol1, nRow1,nCol2, nRow2, nTab);
1509 rReq.Done();
1513 void ScDocShell::ExecuteChartSourcePost(bool bUndo, bool bMultiRange,
1514 const OUString& rChartName, const ScRangeListRef& rRangeListRef,
1515 bool bColHeaders, bool bRowHeaders, bool bAddRange,
1516 SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, SCTAB nTab )
1518 if (bMultiRange)
1520 if (bUndo)
1522 GetUndoManager()->AddUndoAction(
1523 std::make_unique<ScUndoChartData>( this, rChartName, rRangeListRef,
1524 bColHeaders, bRowHeaders, bAddRange ) );
1526 m_pDocument->UpdateChartArea( rChartName, rRangeListRef,
1527 bColHeaders, bRowHeaders, bAddRange );
1529 else
1531 ScRange aNewRange( nCol1,nRow1,nTab, nCol2,nRow2,nTab );
1532 if (bUndo)
1534 GetUndoManager()->AddUndoAction(
1535 std::make_unique<ScUndoChartData>( this, rChartName, aNewRange,
1536 bColHeaders, bRowHeaders, bAddRange ) );
1538 m_pDocument->UpdateChartArea( rChartName, aNewRange,
1539 bColHeaders, bRowHeaders, bAddRange );
1543 bool ScDocShell::ExecuteChangeProtectionDialog( bool bJustQueryIfProtected )
1545 bool bDone = false;
1546 ScChangeTrack* pChangeTrack = m_pDocument->GetChangeTrack();
1547 if ( pChangeTrack )
1549 bool bProtected = pChangeTrack->IsProtected();
1550 if ( bJustQueryIfProtected && !bProtected )
1551 return true;
1553 OUString aTitle( ScResId( bProtected ? SCSTR_CHG_UNPROTECT : SCSTR_CHG_PROTECT ) );
1554 OUString aText( ScResId( SCSTR_PASSWORD ) );
1555 OUString aPassword;
1557 weld::Window* pWin = ScDocShell::GetActiveDialogParent();
1558 SfxPasswordDialog aDlg(pWin, &aText);
1559 aDlg.set_title(aTitle);
1560 aDlg.SetMinLen(1);
1561 aDlg.set_help_id(GetStaticInterface()->GetSlot(SID_CHG_PROTECT)->GetCommand());
1562 aDlg.SetEditHelpId( HID_CHG_PROTECT );
1563 if ( !bProtected )
1564 aDlg.ShowExtras(SfxShowExtras::CONFIRM);
1565 if (aDlg.run() == RET_OK)
1566 aPassword = aDlg.GetPassword();
1568 if (!aPassword.isEmpty())
1570 if ( bProtected )
1572 if ( SvPasswordHelper::CompareHashPassword(pChangeTrack->GetProtection(), aPassword) )
1574 if ( bJustQueryIfProtected )
1575 bDone = true;
1576 else
1577 pChangeTrack->SetProtection( {} );
1579 else
1581 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pWin,
1582 VclMessageType::Info, VclButtonsType::Ok,
1583 ScResId(SCSTR_WRONGPASSWORD)));
1584 xInfoBox->run();
1587 else
1589 css::uno::Sequence< sal_Int8 > aPass;
1590 SvPasswordHelper::GetHashPassword( aPass, aPassword );
1591 pChangeTrack->SetProtection( aPass );
1593 if ( bProtected != pChangeTrack->IsProtected() )
1595 UpdateAcceptChangesDialog();
1596 bDone = true;
1600 else if ( bJustQueryIfProtected )
1601 bDone = true;
1602 return bDone;
1605 void ScDocShell::DoRecalc( bool bApi )
1607 if (m_pDocument->IsInDocShellRecalc())
1609 SAL_WARN("sc","ScDocShell::DoRecalc tries re-entering while in Recalc; probably Forms->BASIC->Dispatcher.");
1610 return;
1612 ScDocShellRecalcGuard aGuard(*m_pDocument);
1613 bool bDone = false;
1614 ScTabViewShell* pSh = GetBestViewShell();
1615 ScInputHandler* pHdl = (pSh ? ScModule::get()->GetInputHdl(pSh) : nullptr);
1616 if ( pSh )
1618 if ( pHdl && pHdl->IsInputMode() && pHdl->IsFormulaMode() && !bApi )
1620 pHdl->FormulaPreview(); // partial result as QuickHelp
1621 bDone = true;
1623 else
1625 ScTabView::UpdateInputLine(); // InputEnterHandler
1626 pSh->UpdateInputHandler();
1629 if (bDone) // otherwise re-calculate document
1630 return;
1632 weld::WaitObject aWaitObj( GetActiveDialogParent() );
1633 if ( pHdl )
1635 // tdf97897 set current cell to Dirty to force recalculation of cell
1636 ScFormulaCell* pFC = m_pDocument->GetFormulaCell( pHdl->GetCursorPos());
1637 if (pFC)
1638 pFC->SetDirty();
1640 m_pDocument->CalcFormulaTree();
1641 if ( pSh )
1642 pSh->UpdateCharts(true);
1644 m_pDocument->BroadcastUno( SfxHint( SfxHintId::DataChanged ) );
1646 // If there are charts, then paint everything, so that PostDataChanged
1647 // and the charts do not come one after the other and parts are painted twice.
1649 ScChartListenerCollection* pCharts = m_pDocument->GetChartListenerCollection();
1650 if ( pCharts && pCharts->hasListeners() )
1651 PostPaintGridAll();
1652 else
1653 PostDataChanged();
1656 void ScDocShell::DoHardRecalc()
1658 if (m_pDocument->IsInDocShellRecalc())
1660 SAL_WARN("sc","ScDocShell::DoHardRecalc tries re-entering while in Recalc; probably Forms->BASIC->Dispatcher.");
1661 return;
1663 auto start = std::chrono::steady_clock::now();
1664 ScDocShellRecalcGuard aGuard(*m_pDocument);
1665 weld::WaitObject aWaitObj( GetActiveDialogParent() );
1666 ScTabViewShell* pSh = GetBestViewShell();
1667 if ( pSh )
1669 ScTabView::UpdateInputLine(); // InputEnterHandler
1670 pSh->UpdateInputHandler();
1672 m_pDocument->CalcAll();
1673 GetDocFunc().DetectiveRefresh(); // creates own Undo
1674 if ( pSh )
1675 pSh->UpdateCharts(true);
1677 // set notification flags for "calculate" event (used in SfxHintId::DataChanged broadcast)
1678 // (might check for the presence of any formulas on each sheet)
1679 SCTAB nTabCount = m_pDocument->GetTableCount();
1680 if (m_pDocument->HasAnySheetEventScript( ScSheetEventId::CALCULATE, true )) // search also for VBA handler
1681 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
1682 m_pDocument->SetCalcNotification(nTab);
1684 // CalcAll doesn't broadcast value changes, so SfxHintId::ScCalcAll is broadcasted globally
1685 // in addition to SfxHintId::DataChanged.
1686 m_pDocument->BroadcastUno( SfxHint( SfxHintId::ScCalcAll ) );
1687 m_pDocument->BroadcastUno( SfxHint( SfxHintId::DataChanged ) );
1689 // use hard recalc also to disable stream-copying of all sheets
1690 // (somewhat consistent with charts)
1691 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
1692 m_pDocument->SetStreamValid(nTab, false);
1694 PostPaintGridAll();
1695 auto end = std::chrono::steady_clock::now();
1696 SAL_INFO("sc.timing", "ScDocShell::DoHardRecalc(): took " << std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count() << "ms");
1699 void ScDocShell::DoAutoStyle( const ScRange& rRange, const OUString& rStyle )
1701 ScStyleSheetPool* pStylePool = m_pDocument->GetStyleSheetPool();
1702 ScStyleSheet* pStyleSheet = pStylePool->FindAutoStyle(rStyle);
1703 if (!pStyleSheet)
1704 return;
1706 OSL_ENSURE(rRange.aStart.Tab() == rRange.aEnd.Tab(),
1707 "DoAutoStyle with several tables");
1708 SCTAB nTab = rRange.aStart.Tab();
1709 SCCOL nStartCol = rRange.aStart.Col();
1710 SCROW nStartRow = rRange.aStart.Row();
1711 SCCOL nEndCol = rRange.aEnd.Col();
1712 SCROW nEndRow = rRange.aEnd.Row();
1713 m_pDocument->ApplyStyleAreaTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, *pStyleSheet );
1714 m_pDocument->ExtendMerge( nStartCol, nStartRow, nEndCol, nEndRow, nTab );
1715 PostPaint( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, PaintPartFlags::Grid );
1718 void ScDocShell::NotifyStyle( const SfxStyleSheetHint& rHint )
1720 SfxHintId nId = rHint.GetId();
1721 const SfxStyleSheetBase* pStyle = rHint.GetStyleSheet();
1722 if (!pStyle)
1723 return;
1725 if ( pStyle->GetFamily() == SfxStyleFamily::Page )
1727 if ( nId == SfxHintId::StyleSheetModified || nId == SfxHintId::StyleSheetModifiedExtended )
1729 ScDocShellModificator aModificator( *this );
1731 const OUString& aNewName = pStyle->GetName();
1732 OUString aOldName = aNewName;
1733 if ( nId == SfxHintId::StyleSheetModifiedExtended )
1735 const SfxStyleSheetModifiedHint& rExtendedHint = static_cast<const SfxStyleSheetModifiedHint&>(rHint); // name changed?
1736 aOldName = rExtendedHint.GetOldName();
1738 if ( aNewName != aOldName )
1739 m_pDocument->RenamePageStyleInUse( aOldName, aNewName );
1741 SCTAB nTabCount = m_pDocument->GetTableCount();
1742 for (SCTAB nTab=0; nTab<nTabCount; nTab++)
1743 if (m_pDocument->GetPageStyle(nTab) == aNewName) // already adjusted to new
1745 m_pDocument->PageStyleModified( nTab, aNewName );
1746 ScPrintFunc aPrintFunc( this, GetPrinter(), nTab );
1747 aPrintFunc.UpdatePages();
1750 aModificator.SetDocumentModified();
1752 if (nId == SfxHintId::StyleSheetModifiedExtended)
1754 SfxBindings* pBindings = GetViewBindings();
1755 if (pBindings)
1757 pBindings->Invalidate( SID_STATUS_PAGESTYLE );
1758 pBindings->Invalidate( SID_STYLE_FAMILY4 );
1759 pBindings->Invalidate( FID_RESET_PRINTZOOM );
1760 pBindings->Invalidate( SID_ATTR_PARA_LEFT_TO_RIGHT );
1761 pBindings->Invalidate( SID_ATTR_PARA_RIGHT_TO_LEFT );
1766 else if ( pStyle->GetFamily() == SfxStyleFamily::Para )
1768 if (nId == SfxHintId::StyleSheetModifiedExtended)
1770 const SfxStyleSheetModifiedHint& rExtendedHint = static_cast<const SfxStyleSheetModifiedHint&>(rHint);
1771 const OUString& aNewName = pStyle->GetName();
1772 const OUString& aOldName = rExtendedHint.GetOldName();
1773 if ( aNewName != aOldName )
1775 for(SCTAB i = 0; i < m_pDocument->GetTableCount(); ++i)
1777 ScConditionalFormatList* pList = m_pDocument->GetCondFormList(i);
1778 if (pList)
1779 pList->RenameCellStyle( aOldName,aNewName );
1785 // everything else goes via slots...
1788 // like in printfun.cxx
1789 #define ZOOM_MIN 10
1791 void ScDocShell::SetPrintZoom( SCTAB nTab, sal_uInt16 nScale, sal_uInt16 nPages )
1793 OUString aStyleName = m_pDocument->GetPageStyle( nTab );
1794 ScStyleSheetPool* pStylePool = m_pDocument->GetStyleSheetPool();
1795 SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SfxStyleFamily::Page );
1796 OSL_ENSURE( pStyleSheet, "PageStyle not found" );
1797 if ( !pStyleSheet )
1798 return;
1800 ScDocShellModificator aModificator( *this );
1802 SfxItemSet& rSet = pStyleSheet->GetItemSet();
1803 const bool bUndo(m_pDocument->IsUndoEnabled());
1804 if (bUndo)
1806 sal_uInt16 nOldScale = rSet.Get(ATTR_PAGE_SCALE).GetValue();
1807 sal_uInt16 nOldPages = rSet.Get(ATTR_PAGE_SCALETOPAGES).GetValue();
1808 GetUndoManager()->AddUndoAction( std::make_unique<ScUndoPrintZoom>(
1809 this, nTab, nOldScale, nOldPages, nScale, nPages ) );
1812 rSet.Put( SfxUInt16Item( ATTR_PAGE_SCALE, nScale ) );
1813 rSet.Put( SfxUInt16Item( ATTR_PAGE_SCALETOPAGES, nPages ) );
1815 ScPrintFunc aPrintFunc( this, GetPrinter(), nTab );
1816 aPrintFunc.UpdatePages();
1817 aModificator.SetDocumentModified();
1819 SfxBindings* pBindings = GetViewBindings();
1820 if (pBindings)
1821 pBindings->Invalidate( FID_RESET_PRINTZOOM );
1824 bool ScDocShell::AdjustPrintZoom( const ScRange& rRange )
1826 bool bChange = false;
1827 SCTAB nTab = rRange.aStart.Tab();
1829 OUString aStyleName = m_pDocument->GetPageStyle( nTab );
1830 ScStyleSheetPool* pStylePool = m_pDocument->GetStyleSheetPool();
1831 SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SfxStyleFamily::Page );
1832 OSL_ENSURE( pStyleSheet, "PageStyle not found" );
1833 if ( pStyleSheet )
1835 SfxItemSet& rSet = pStyleSheet->GetItemSet();
1836 bool bHeaders = rSet.Get(ATTR_PAGE_HEADERS).GetValue();
1837 sal_uInt16 nOldScale = rSet.Get(ATTR_PAGE_SCALE).GetValue();
1838 sal_uInt16 nOldPages = rSet.Get(ATTR_PAGE_SCALETOPAGES).GetValue();
1839 std::optional<ScRange> oRepeatCol = m_pDocument->GetRepeatColRange( nTab );
1840 std::optional<ScRange> oRepeatRow = m_pDocument->GetRepeatRowRange( nTab );
1842 // calculate needed scaling for selection
1844 sal_uInt16 nNewScale = nOldScale;
1846 tools::Long nBlkTwipsX = 0;
1847 if (bHeaders)
1848 nBlkTwipsX += PRINT_HEADER_WIDTH;
1849 SCCOL nStartCol = rRange.aStart.Col();
1850 SCCOL nEndCol = rRange.aEnd.Col();
1851 if ( oRepeatCol && nStartCol >= oRepeatCol->aStart.Col() )
1853 for (SCCOL i=oRepeatCol->aStart.Col(); i<=oRepeatCol->aEnd.Col(); i++ )
1854 nBlkTwipsX += m_pDocument->GetColWidth( i, nTab );
1855 if ( nStartCol <= oRepeatCol->aEnd.Col() )
1856 nStartCol = oRepeatCol->aEnd.Col() + 1;
1858 // legacy compilers' own scope for i
1860 for ( SCCOL i=nStartCol; i<=nEndCol; i++ )
1861 nBlkTwipsX += m_pDocument->GetColWidth( i, nTab );
1864 tools::Long nBlkTwipsY = 0;
1865 if (bHeaders)
1866 nBlkTwipsY += PRINT_HEADER_HEIGHT;
1867 SCROW nStartRow = rRange.aStart.Row();
1868 SCROW nEndRow = rRange.aEnd.Row();
1869 if ( oRepeatRow && nStartRow >= oRepeatRow->aStart.Row() )
1871 nBlkTwipsY += m_pDocument->GetRowHeight( oRepeatRow->aStart.Row(),
1872 oRepeatRow->aEnd.Row(), nTab );
1873 if ( nStartRow <= oRepeatRow->aEnd.Row() )
1874 nStartRow = oRepeatRow->aEnd.Row() + 1;
1876 nBlkTwipsY += m_pDocument->GetRowHeight( nStartRow, nEndRow, nTab );
1878 Size aPhysPage;
1879 tools::Long nHdr, nFtr;
1880 ScPrintFunc aOldPrFunc( this, GetPrinter(), nTab );
1881 aOldPrFunc.GetScaleData( aPhysPage, nHdr, nFtr );
1882 nBlkTwipsY += nHdr + nFtr;
1884 if ( nBlkTwipsX == 0 ) // hidden columns/rows may lead to 0
1885 nBlkTwipsX = 1;
1886 if ( nBlkTwipsY == 0 )
1887 nBlkTwipsY = 1;
1889 tools::Long nNeeded = std::min( aPhysPage.Width() * 100 / nBlkTwipsX,
1890 aPhysPage.Height() * 100 / nBlkTwipsY );
1891 if ( nNeeded < ZOOM_MIN )
1892 nNeeded = ZOOM_MIN; // boundary
1893 if ( nNeeded < static_cast<tools::Long>(nNewScale) )
1894 nNewScale = static_cast<sal_uInt16>(nNeeded);
1896 bChange = ( nNewScale != nOldScale || nOldPages != 0 );
1897 if ( bChange )
1898 SetPrintZoom( nTab, nNewScale, 0 );
1900 return bChange;
1903 void ScDocShell::PageStyleModified( std::u16string_view rStyleName, bool bApi )
1905 ScDocShellModificator aModificator( *this );
1907 SCTAB nTabCount = m_pDocument->GetTableCount();
1908 SCTAB nUseTab = MAXTAB+1;
1909 for (SCTAB nTab=0; nTab<nTabCount && nUseTab>MAXTAB; nTab++)
1910 if ( m_pDocument->GetPageStyle(nTab) == rStyleName &&
1911 ( !bApi || m_pDocument->GetPageSize(nTab).Width() ) )
1912 nUseTab = nTab;
1913 // at bApi only if breaks already shown
1915 if (ValidTab(nUseTab)) // not used -> nothing to do
1917 bool bWarn = false;
1919 ScPrintFunc aPrintFunc( this, GetPrinter(), nUseTab ); //! cope without CountPages
1920 if (!aPrintFunc.UpdatePages()) // sets breaks on all tabs
1921 bWarn = true;
1923 if (bWarn && !bApi)
1925 weld::Window* pWin = GetActiveDialogParent();
1926 weld::WaitObject aWaitOff(pWin);
1927 std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pWin,
1928 VclMessageType::Info, VclButtonsType::Ok,
1929 ScResId(STR_PRINT_INVALID_AREA)));
1930 xInfoBox->run();
1934 aModificator.SetDocumentModified();
1936 SfxBindings* pBindings = GetViewBindings();
1937 if (pBindings)
1939 pBindings->Invalidate( FID_RESET_PRINTZOOM );
1940 pBindings->Invalidate( SID_ATTR_PARA_LEFT_TO_RIGHT );
1941 pBindings->Invalidate( SID_ATTR_PARA_RIGHT_TO_LEFT );
1945 void ScDocShell::ExecutePageStyle( const SfxViewShell& rCaller,
1946 SfxRequest& rReq,
1947 SCTAB nCurTab )
1949 const SfxItemSet* pReqArgs = rReq.GetArgs();
1951 switch ( rReq.GetSlot() )
1953 case SID_STATUS_PAGESTYLE: // click on StatusBar control
1954 case SID_FORMATPAGE:
1956 if ( pReqArgs == nullptr )
1958 OUString aOldName = m_pDocument->GetPageStyle( nCurTab );
1959 ScStyleSheetPool* pStylePool = m_pDocument->GetStyleSheetPool();
1960 SfxStyleSheetBase* pStyleSheet
1961 = pStylePool->Find( aOldName, SfxStyleFamily::Page );
1963 OSL_ENSURE( pStyleSheet, "PageStyle not found! :-/" );
1965 if ( pStyleSheet )
1967 auto xOldData = std::make_shared<ScStyleSaveData>();
1968 const bool bUndo(m_pDocument->IsUndoEnabled());
1969 if (bUndo)
1970 xOldData->InitFromStyle(pStyleSheet);
1972 SfxItemSet& rStyleSet = pStyleSheet->GetItemSet();
1973 rStyleSet.MergeRange( XATTR_FILL_FIRST, XATTR_FILL_LAST );
1975 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
1977 VclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateScStyleDlg(GetActiveDialogParent(), *pStyleSheet, true));
1979 auto xRequest = std::make_shared<SfxRequest>(rReq);
1980 rReq.Ignore(); // the 'old' request is not relevant any more
1981 pDlg->StartExecuteAsync([this, pDlg, xRequest=std::move(xRequest), pStyleSheet,
1982 xOldData=std::move(xOldData), aOldName, &rStyleSet,
1983 nCurTab, &rCaller, bUndo](sal_Int32 nResult) {
1984 if ( nResult == RET_OK )
1986 const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
1988 weld::WaitObject aWait( GetActiveDialogParent() );
1990 OUString aNewName = pStyleSheet->GetName();
1991 if ( aNewName != aOldName &&
1992 m_pDocument->RenamePageStyleInUse( aOldName, aNewName ) )
1994 SfxBindings* pBindings = GetViewBindings();
1995 if (pBindings)
1997 pBindings->Invalidate( SID_STATUS_PAGESTYLE );
1998 pBindings->Invalidate( FID_RESET_PRINTZOOM );
2002 if ( pOutSet )
2003 m_pDocument->ModifyStyleSheet( *pStyleSheet, *pOutSet );
2005 // memorizing for GetState():
2006 GetPageOnFromPageStyleSet( &rStyleSet, nCurTab, m_bHeaderOn, m_bFooterOn );
2007 rCaller.GetViewFrame().GetBindings().Invalidate( SID_HFEDIT );
2009 ScStyleSaveData aNewData;
2010 aNewData.InitFromStyle( pStyleSheet );
2011 if (bUndo)
2013 GetUndoManager()->AddUndoAction(
2014 std::make_unique<ScUndoModifyStyle>( this, SfxStyleFamily::Page,
2015 *xOldData, aNewData ) );
2018 PageStyleModified( aNewName, false );
2019 xRequest->Done();
2021 pDlg->disposeOnce();
2026 break;
2028 case SID_HFEDIT:
2030 if ( pReqArgs == nullptr )
2032 OUString aStr( m_pDocument->GetPageStyle( nCurTab ) );
2034 ScStyleSheetPool* pStylePool
2035 = m_pDocument->GetStyleSheetPool();
2037 SfxStyleSheetBase* pStyleSheet
2038 = pStylePool->Find( aStr, SfxStyleFamily::Page );
2040 OSL_ENSURE( pStyleSheet, "PageStyle not found! :-/" );
2042 if ( pStyleSheet )
2044 SfxItemSet& rStyleSet = pStyleSheet->GetItemSet();
2046 SvxPageUsage eUsage = rStyleSet.Get( ATTR_PAGE ).GetPageUsage();
2047 bool bShareHeader = rStyleSet
2048 .Get(ATTR_PAGE_HEADERSET)
2049 .GetItemSet()
2050 .Get(ATTR_PAGE_SHARED)
2051 .GetValue();
2052 bool bShareFooter = rStyleSet
2053 .Get(ATTR_PAGE_FOOTERSET)
2054 .GetItemSet()
2055 .Get(ATTR_PAGE_SHARED)
2056 .GetValue();
2057 sal_uInt16 nResId = 0;
2059 switch ( eUsage )
2061 case SvxPageUsage::Left:
2062 case SvxPageUsage::Right:
2064 if ( m_bHeaderOn && m_bFooterOn )
2065 nResId = RID_SCDLG_HFEDIT;
2066 else if ( SvxPageUsage::Right == eUsage )
2068 if ( !m_bHeaderOn && m_bFooterOn )
2069 nResId = RID_SCDLG_HFEDIT_RIGHTFOOTER;
2070 else if ( m_bHeaderOn && !m_bFooterOn )
2071 nResId = RID_SCDLG_HFEDIT_RIGHTHEADER;
2073 else
2075 // #69193a# respect "shared" setting
2076 if ( !m_bHeaderOn && m_bFooterOn )
2077 nResId = bShareFooter ?
2078 RID_SCDLG_HFEDIT_RIGHTFOOTER :
2079 RID_SCDLG_HFEDIT_LEFTFOOTER;
2080 else if ( m_bHeaderOn && !m_bFooterOn )
2081 nResId = bShareHeader ?
2082 RID_SCDLG_HFEDIT_RIGHTHEADER :
2083 RID_SCDLG_HFEDIT_LEFTHEADER;
2086 break;
2088 case SvxPageUsage::Mirror:
2089 case SvxPageUsage::All:
2090 default:
2092 if ( !bShareHeader && !bShareFooter )
2094 if ( m_bHeaderOn && m_bFooterOn )
2095 nResId = RID_SCDLG_HFEDIT_ALL;
2096 else if ( !m_bHeaderOn && m_bFooterOn )
2097 nResId = RID_SCDLG_HFEDIT_FOOTER;
2098 else if ( m_bHeaderOn && !m_bFooterOn )
2099 nResId = RID_SCDLG_HFEDIT_HEADER;
2101 else if ( bShareHeader && bShareFooter )
2103 if ( m_bHeaderOn && m_bFooterOn )
2104 nResId = RID_SCDLG_HFEDIT;
2105 else
2107 if ( !m_bHeaderOn && m_bFooterOn )
2108 nResId = RID_SCDLG_HFEDIT_RIGHTFOOTER;
2109 else if ( m_bHeaderOn && !m_bFooterOn )
2110 nResId = RID_SCDLG_HFEDIT_RIGHTHEADER;
2113 else if ( !bShareHeader && bShareFooter )
2115 if ( m_bHeaderOn && m_bFooterOn )
2116 nResId = RID_SCDLG_HFEDIT_SFTR;
2117 else if ( !m_bHeaderOn && m_bFooterOn )
2118 nResId = RID_SCDLG_HFEDIT_RIGHTFOOTER;
2119 else if ( m_bHeaderOn && !m_bFooterOn )
2120 nResId = RID_SCDLG_HFEDIT_HEADER;
2122 else if ( bShareHeader && !bShareFooter )
2124 if ( m_bHeaderOn && m_bFooterOn )
2125 nResId = RID_SCDLG_HFEDIT_SHDR;
2126 else if ( !m_bHeaderOn && m_bFooterOn )
2127 nResId = RID_SCDLG_HFEDIT_FOOTER;
2128 else if ( m_bHeaderOn && !m_bFooterOn )
2129 nResId = RID_SCDLG_HFEDIT_RIGHTHEADER;
2134 ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create();
2136 VclPtr<SfxAbstractTabDialog> pDlg(pFact->CreateScHFEditDlg(
2137 GetActiveDialogParent(),
2138 rStyleSet,
2139 aStr,
2140 nResId));
2141 auto xRequest = std::make_shared<SfxRequest>(rReq);
2142 rReq.Ignore(); // the 'old' request is not relevant any more
2143 pDlg->StartExecuteAsync([this, pDlg, pStyleSheet, xRequest=std::move(xRequest)](sal_Int32 nResult){
2144 if ( nResult == RET_OK )
2146 const SfxItemSet* pOutSet = pDlg->GetOutputItemSet();
2148 if ( pOutSet )
2149 m_pDocument->ModifyStyleSheet( *pStyleSheet, *pOutSet );
2151 SetDocumentModified();
2152 xRequest->Done();
2154 pDlg->disposeOnce();
2159 break;
2161 default:
2162 break;
2166 void ScDocShell::GetStatePageStyle( SfxItemSet& rSet,
2167 SCTAB nCurTab )
2169 SfxWhichIter aIter(rSet);
2170 sal_uInt16 nWhich = aIter.FirstWhich();
2171 while ( nWhich )
2173 switch (nWhich)
2175 case SID_STATUS_PAGESTYLE:
2176 rSet.Put( SfxStringItem( nWhich, m_pDocument->GetPageStyle( nCurTab ) ) );
2177 break;
2179 case SID_HFEDIT:
2181 OUString aStr = m_pDocument->GetPageStyle( nCurTab );
2182 ScStyleSheetPool* pStylePool = m_pDocument->GetStyleSheetPool();
2183 SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStr, SfxStyleFamily::Page );
2185 OSL_ENSURE( pStyleSheet, "PageStyle not found! :-/" );
2187 if ( pStyleSheet )
2189 SfxItemSet& rStyleSet = pStyleSheet->GetItemSet();
2190 GetPageOnFromPageStyleSet( &rStyleSet, nCurTab, m_bHeaderOn, m_bFooterOn );
2192 if ( !m_bHeaderOn && !m_bFooterOn )
2193 rSet.DisableItem( nWhich );
2196 break;
2199 nWhich = aIter.NextWhich();
2203 void ScDocShell::GetState( SfxItemSet &rSet )
2205 bool bTabView = GetBestViewShell() != nullptr;
2207 SfxWhichIter aIter(rSet);
2208 for (sal_uInt16 nWhich = aIter.FirstWhich(); nWhich; nWhich = aIter.NextWhich())
2210 if (!bTabView)
2212 rSet.DisableItem(nWhich);
2213 continue;
2216 switch (nWhich)
2218 case FID_AUTO_CALC:
2219 if ( m_pDocument->GetHardRecalcState() != ScDocument::HardRecalcState::OFF )
2220 rSet.DisableItem( nWhich );
2221 else
2222 rSet.Put( SfxBoolItem( nWhich, m_pDocument->GetAutoCalc() ) );
2223 break;
2225 case FID_CHG_RECORD:
2226 if ( IsDocShared() )
2227 rSet.DisableItem( nWhich );
2228 else
2229 rSet.Put( SfxBoolItem( nWhich,
2230 m_pDocument->GetChangeTrack() != nullptr ) );
2231 break;
2233 case SID_CHG_PROTECT:
2235 ScChangeTrack* pChangeTrack = m_pDocument->GetChangeTrack();
2236 if ( pChangeTrack && !IsDocShared() )
2237 rSet.Put( SfxBoolItem( nWhich,
2238 pChangeTrack->IsProtected() ) );
2239 else
2240 rSet.DisableItem( nWhich );
2242 break;
2244 case SID_DOCUMENT_COMPARE:
2246 if ( IsDocShared() )
2248 rSet.DisableItem( nWhich );
2251 break;
2253 // When a formula is edited, FID_RECALC must be enabled in any case. Recalc for
2254 // the doc was disabled once because of a bug if AutoCalc was on, but is now
2255 // always enabled because of another bug.
2257 case SID_TABLES_COUNT:
2258 rSet.Put( SfxInt16Item( nWhich, m_pDocument->GetTableCount() ) );
2259 break;
2261 case SID_ATTR_YEAR2000 :
2262 rSet.Put( SfxUInt16Item( nWhich,
2263 m_pDocument->GetDocOptions().GetYear2000() ) );
2264 break;
2266 case SID_SHARE_DOC:
2268 if ( IsReadOnly() || GetObjectShell()->isExportLocked() )
2270 rSet.DisableItem( nWhich );
2273 break;
2275 case SID_ATTR_CHAR_FONTLIST:
2276 rSet.Put( SvxFontListItem( m_pImpl->pFontList.get(), nWhich ) );
2277 break;
2279 case SID_NOTEBOOKBAR:
2281 if (SfxBindings* pBindings = GetViewBindings())
2283 bool bVisible = sfx2::SfxNotebookBar::StateMethod(*pBindings,
2284 u"modules/scalc/ui/");
2285 rSet.Put( SfxBoolItem( SID_NOTEBOOKBAR, bVisible ) );
2288 break;
2290 case SID_LANGUAGE_STATUS:
2292 OUString sLanguage;
2293 sal_uInt16 nLangWhich = 0;
2294 LanguageType eLatin = LANGUAGE_DONTKNOW, eCjk = LANGUAGE_DONTKNOW,
2295 eCtl = LANGUAGE_DONTKNOW;
2297 if (comphelper::LibreOfficeKit::isActive())
2299 GetDocument().GetLanguage( eLatin, eCjk, eCtl );
2300 sLanguage = SvtLanguageTable::GetLanguageString(eLatin);
2302 if (eLatin == LANGUAGE_NONE)
2303 sLanguage += ";-";
2304 else
2305 sLanguage += ";" + LanguageTag(eLatin).getBcp47(false);
2307 else if (ScTabViewShell* pViewShell = GetBestViewShell())
2309 ScMarkData aMark = pViewShell->GetViewData().GetMarkData();
2310 SCCOL nCol = pViewShell->GetViewData().GetCurX();
2311 SCROW nRow = pViewShell->GetViewData().GetCurY();
2312 SCTAB nTab = pViewShell->GetViewData().GetTabNo();
2314 aMark.SetMarkArea(ScRange(nCol, nRow, nTab));
2315 const ScPatternAttr* pSelAttrs = GetDocument().GetSelectionPattern(aMark);
2316 if (pSelAttrs)
2318 const SfxItemSet& rItemSet = pSelAttrs->GetItemSet();
2319 nLangWhich = rItemSet.GetPool()->GetWhichIDFromSlotID(SID_ATTR_CHAR_LANGUAGE);
2320 if (SfxItemState::SET == rItemSet.GetItemState(nLangWhich))
2321 eLatin = static_cast<const SvxLanguageItem&>(rItemSet.Get(nLangWhich)).GetLanguage();
2323 nLangWhich = rItemSet.GetPool()->GetWhichIDFromSlotID(SID_ATTR_CHAR_CJK_LANGUAGE);
2324 if (SfxItemState::SET == rItemSet.GetItemState(nLangWhich))
2325 eCjk = static_cast<const SvxLanguageItem&>(rItemSet.Get(nLangWhich)).GetLanguage();
2327 nLangWhich = rItemSet.GetPool()->GetWhichIDFromSlotID(SID_ATTR_CHAR_CTL_LANGUAGE);
2328 if (SfxItemState::SET == rItemSet.GetItemState(nLangWhich))
2329 eCtl = static_cast<const SvxLanguageItem&>(rItemSet.Get(nLangWhich)).GetLanguage();
2331 if (eLatin != LANGUAGE_DONTKNOW)
2332 sLanguage = SvtLanguageTable::GetLanguageString(eLatin);
2333 else if (eCjk != LANGUAGE_DONTKNOW)
2334 sLanguage = SvtLanguageTable::GetLanguageString(eCjk);
2335 else if (eCtl != LANGUAGE_DONTKNOW)
2336 sLanguage = SvtLanguageTable::GetLanguageString(eCtl);
2338 if (sLanguage.isEmpty())
2340 GetDocument().GetLanguage(eLatin, eCjk, eCtl);
2341 sLanguage = SvtLanguageTable::GetLanguageString(eLatin);
2345 rSet.Put(SfxStringItem(nWhich, sLanguage));
2347 break;
2349 default:
2352 break;
2357 void ScDocShell::Draw( OutputDevice* pDev, const JobSetup & /* rSetup */, sal_uInt16 nAspect, bool /*bOutputToWindow*/ )
2360 SCTAB nVisTab = m_pDocument->GetVisibleTab();
2361 if (!m_pDocument->HasTable(nVisTab))
2362 return;
2364 vcl::text::ComplexTextLayoutFlags nOldLayoutMode = pDev->GetLayoutMode();
2365 pDev->SetLayoutMode( vcl::text::ComplexTextLayoutFlags::Default ); // even if it's the same, to get the metafile action
2367 if ( nAspect == ASPECT_THUMBNAIL )
2369 tools::Rectangle aBoundRect = GetVisArea( ASPECT_THUMBNAIL );
2370 ScViewData aTmpData( *this, nullptr );
2371 aTmpData.SetTabNo(nVisTab);
2372 SnapVisArea( aBoundRect );
2373 aTmpData.SetScreen( aBoundRect );
2374 ScPrintFunc::DrawToDev( *m_pDocument, pDev, 1.0, aBoundRect, &aTmpData, true );
2376 else
2378 tools::Rectangle aOldArea = SfxObjectShell::GetVisArea();
2379 tools::Rectangle aNewArea = aOldArea;
2380 ScViewData aTmpData( *this, nullptr );
2381 aTmpData.SetTabNo(nVisTab);
2382 SnapVisArea( aNewArea );
2383 if ( aNewArea != aOldArea && (m_pDocument->GetPosLeft() > 0 || m_pDocument->GetPosTop() > 0) )
2384 SfxObjectShell::SetVisArea( aNewArea );
2385 aTmpData.SetScreen( aNewArea );
2386 ScPrintFunc::DrawToDev( *m_pDocument, pDev, 1.0, aNewArea, &aTmpData, true );
2389 pDev->SetLayoutMode( nOldLayoutMode );
2392 tools::Rectangle ScDocShell::GetVisArea( sal_uInt16 nAspect ) const
2394 SfxObjectCreateMode eShellMode = GetCreateMode();
2395 if ( eShellMode == SfxObjectCreateMode::ORGANIZER )
2397 // without contents we also don't know how large are the contents;
2398 // return empty rectangle, it will then be calculated after the loading
2399 return tools::Rectangle();
2402 if( nAspect == ASPECT_THUMBNAIL )
2404 SCTAB nVisTab = m_pDocument->GetVisibleTab();
2405 if (!m_pDocument->HasTable(nVisTab))
2407 nVisTab = 0;
2408 const_cast<ScDocShell*>(this)->m_pDocument->SetVisibleTab(nVisTab);
2410 Size aSize = m_pDocument->GetPageSize(nVisTab);
2411 const tools::Long SC_PREVIEW_SIZE_X = 10000;
2412 const tools::Long SC_PREVIEW_SIZE_Y = 12400;
2413 tools::Rectangle aArea( 0,0, SC_PREVIEW_SIZE_X, SC_PREVIEW_SIZE_Y);
2414 if (aSize.Width() > aSize.Height())
2416 aArea.SetRight( SC_PREVIEW_SIZE_Y );
2417 aArea.SetBottom( SC_PREVIEW_SIZE_X );
2420 bool bNegativePage = m_pDocument->IsNegativePage( m_pDocument->GetVisibleTab() );
2421 if ( bNegativePage )
2422 ScDrawLayer::MirrorRectRTL( aArea );
2423 SnapVisArea( aArea );
2424 return aArea;
2426 else if( nAspect == ASPECT_CONTENT && eShellMode != SfxObjectCreateMode::EMBEDDED )
2428 // fetch visarea like after loading
2430 SCTAB nVisTab = m_pDocument->GetVisibleTab();
2431 if (!m_pDocument->HasTable(nVisTab))
2433 nVisTab = 0;
2434 const_cast<ScDocShell*>(this)->m_pDocument->SetVisibleTab(nVisTab);
2436 SCCOL nStartCol;
2437 SCROW nStartRow;
2438 m_pDocument->GetDataStart( nVisTab, nStartCol, nStartRow );
2439 SCCOL nEndCol;
2440 SCROW nEndRow;
2441 m_pDocument->GetPrintArea( nVisTab, nEndCol, nEndRow );
2442 if (nStartCol>nEndCol)
2443 nStartCol = nEndCol;
2444 if (nStartRow>nEndRow)
2445 nStartRow = nEndRow;
2446 tools::Rectangle aNewArea = m_pDocument
2447 ->GetMMRect( nStartCol,nStartRow, nEndCol,nEndRow, nVisTab );
2448 return aNewArea;
2450 else
2451 return SfxObjectShell::GetVisArea( nAspect );
2454 namespace {
2456 [[nodiscard]]
2457 tools::Long SnapHorizontal( const ScDocument& rDoc, SCTAB nTab, tools::Long nVal, SCCOL& rStartCol )
2459 SCCOL nCol = 0;
2460 tools::Long nTwips = o3tl::convert(nVal, o3tl::Length::mm100, o3tl::Length::twip);
2461 tools::Long nSnap = 0;
2462 while ( nCol<rDoc.MaxCol() )
2464 tools::Long nAdd = rDoc.GetColWidth(nCol, nTab);
2465 if ( nSnap + nAdd/2 < nTwips || nCol < rStartCol )
2467 nSnap += nAdd;
2468 ++nCol;
2470 else
2471 break;
2473 nVal = o3tl::convert(nSnap, o3tl::Length::twip, o3tl::Length::mm100);
2474 rStartCol = nCol;
2475 return nVal;
2478 [[nodiscard]]
2479 tools::Long SnapVertical( const ScDocument& rDoc, SCTAB nTab, tools::Long nVal, SCROW& rStartRow )
2481 SCROW nRow = 0;
2482 tools::Long nTwips = o3tl::convert(nVal, o3tl::Length::mm100, o3tl::Length::twip);
2483 tools::Long nSnap = 0;
2485 bool bFound = false;
2486 for (SCROW i = nRow; i <= rDoc.MaxRow(); ++i)
2488 SCROW nLastRow;
2489 if (rDoc.RowHidden(i, nTab, nullptr, &nLastRow))
2491 i = nLastRow;
2492 continue;
2495 nRow = i;
2496 tools::Long nAdd = rDoc.GetRowHeight(i, nTab);
2497 if ( nSnap + nAdd/2 < nTwips || nRow < rStartRow )
2499 nSnap += nAdd;
2500 ++nRow;
2502 else
2504 bFound = true;
2505 break;
2508 if (!bFound)
2509 nRow = rDoc.MaxRow(); // all hidden down to the bottom
2511 nVal = o3tl::convert(nSnap, o3tl::Length::twip, o3tl::Length::mm100);
2512 rStartRow = nRow;
2513 return nVal;
2518 void ScDocShell::SnapVisArea( tools::Rectangle& rRect ) const
2520 SCTAB nTab = m_pDocument->GetVisibleTab();
2521 tools::Long nOrigTop = rRect.Top();
2522 tools::Long nOrigLeft = rRect.Left();
2523 bool bNegativePage = m_pDocument->IsNegativePage( nTab );
2524 if ( bNegativePage )
2525 ScDrawLayer::MirrorRectRTL( rRect ); // calculate with positive (LTR) values
2527 SCCOL nCol = m_pDocument->GetPosLeft();
2528 tools::Long nSetLeft = SnapHorizontal( *m_pDocument, nTab, rRect.Left(), nCol );
2529 rRect.SetLeft( nSetLeft );
2530 ++nCol; // at least one column
2531 tools::Long nCorrectionLeft = (nOrigLeft == 0 && nCol > 0) ? nSetLeft : 0; // initial correction
2532 rRect.SetRight( SnapHorizontal( *m_pDocument, nTab, rRect.Right() + nCorrectionLeft, nCol ));
2534 SCROW nRow = m_pDocument->GetPosTop();
2535 tools::Long nSetTop = SnapVertical( *m_pDocument, nTab, rRect.Top(), nRow );
2536 rRect.SetTop( nSetTop );
2537 ++nRow; // at least one row
2538 tools::Long nCorrectionTop = (nOrigTop == 0 && nRow > 0) ? nSetTop : 0; // initial correction
2539 rRect.SetBottom( SnapVertical( *m_pDocument, nTab, rRect.Bottom() + nCorrectionTop, nRow ));
2541 if ( bNegativePage )
2542 ScDrawLayer::MirrorRectRTL( rRect ); // back to real rectangle
2545 void ScDocShell::GetPageOnFromPageStyleSet( const SfxItemSet* pStyleSet,
2546 SCTAB nCurTab,
2547 bool& rbHeader,
2548 bool& rbFooter )
2550 if ( !pStyleSet )
2552 ScStyleSheetPool* pStylePool = m_pDocument->GetStyleSheetPool();
2553 SfxStyleSheetBase* pStyleSheet = pStylePool->
2554 Find( m_pDocument->GetPageStyle( nCurTab ),
2555 SfxStyleFamily::Page );
2557 OSL_ENSURE( pStyleSheet, "PageStyle not found! :-/" );
2559 if ( pStyleSheet )
2560 pStyleSet = &pStyleSheet->GetItemSet();
2561 else
2562 rbHeader = rbFooter = false;
2565 OSL_ENSURE( pStyleSet, "PageStyle-Set not found! :-(" );
2566 if (!pStyleSet)
2567 return;
2569 const SvxSetItem* pSetItem = nullptr;
2570 const SfxItemSet* pSet = nullptr;
2572 pSetItem = &pStyleSet->Get( ATTR_PAGE_HEADERSET );
2573 pSet = &pSetItem->GetItemSet();
2574 rbHeader = pSet->Get(ATTR_PAGE_ON).GetValue();
2576 pSetItem = &pStyleSet->Get( ATTR_PAGE_FOOTERSET );
2577 pSet = &pSetItem->GetItemSet();
2578 rbFooter = pSet->Get(ATTR_PAGE_ON).GetValue();
2581 #if defined(_WIN32)
2582 bool ScDocShell::DdeGetData( const OUString& rItem,
2583 const OUString& rMimeType,
2584 css::uno::Any & rValue )
2586 SotClipboardFormatId eFormatId = SotExchange::GetFormatIdFromMimeType( rMimeType );
2587 if (SotClipboardFormatId::STRING == eFormatId || SotClipboardFormatId::STRING_TSVC == eFormatId)
2589 if( rItem.equalsIgnoreAsciiCase( "Format" ) )
2591 OString aFmtByte(OUStringToOString(m_aDdeTextFmt,
2592 osl_getThreadTextEncoding()));
2593 rValue <<= css::uno::Sequence< sal_Int8 >(
2594 reinterpret_cast<const sal_Int8*>(aFmtByte.getStr()),
2595 aFmtByte.getLength() + 1 );
2596 return true;
2598 ScImportExport aObj( *m_pDocument, rItem );
2599 if ( !aObj.IsRef() )
2600 return false; // invalid range
2602 if( m_aDdeTextFmt[0] == 'F' )
2603 aObj.SetFormulas( true );
2604 if( m_aDdeTextFmt == "SYLK" ||
2605 m_aDdeTextFmt == "FSYLK" )
2607 OString aData;
2608 if( aObj.ExportByteString( aData, osl_getThreadTextEncoding(),
2609 SotClipboardFormatId::SYLK ) )
2611 rValue <<= css::uno::Sequence< sal_Int8 >(
2612 reinterpret_cast<const sal_Int8*>(aData.getStr()),
2613 aData.getLength() + 1 );
2614 return true;
2616 else
2617 return false;
2619 if( m_aDdeTextFmt == "CSV" ||
2620 m_aDdeTextFmt == "FCSV" )
2621 aObj.SetSeparator( ',' );
2622 aObj.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::ToSpace, 0, false ) );
2623 return aObj.ExportData( rMimeType, rValue );
2626 ScImportExport aObj( *m_pDocument, rItem );
2627 aObj.SetExportTextOptions( ScExportTextOptions( ScExportTextOptions::ToSpace, 0, false ) );
2628 return aObj.IsRef() && aObj.ExportData( rMimeType, rValue );
2631 bool ScDocShell::DdeSetData( const OUString& rItem,
2632 const OUString& rMimeType,
2633 const css::uno::Any & rValue )
2635 SotClipboardFormatId eFormatId = SotExchange::GetFormatIdFromMimeType( rMimeType );
2636 if (SotClipboardFormatId::STRING == eFormatId || SotClipboardFormatId::STRING_TSVC == eFormatId)
2638 if( rItem.equalsIgnoreAsciiCase( "Format" ) )
2640 if ( ScByteSequenceToString::GetString( m_aDdeTextFmt, rValue ) )
2642 m_aDdeTextFmt = m_aDdeTextFmt.toAsciiUpperCase();
2643 return true;
2645 return false;
2647 ScImportExport aObj( *m_pDocument, rItem );
2648 if( m_aDdeTextFmt[0] == 'F' )
2649 aObj.SetFormulas( true );
2650 if( m_aDdeTextFmt == "SYLK" ||
2651 m_aDdeTextFmt == "FSYLK" )
2653 OUString aData;
2654 if ( ScByteSequenceToString::GetString( aData, rValue ) )
2656 return aObj.ImportString( aData, SotClipboardFormatId::SYLK );
2658 return false;
2660 if( m_aDdeTextFmt == "CSV" ||
2661 m_aDdeTextFmt == "FCSV" )
2662 aObj.SetSeparator( ',' );
2663 OSL_ENSURE( false, "Implementation is missing" );
2664 return false;
2666 /*ScImportExport aObj( aDocument, rItem );
2667 return aObj.IsRef() && ScImportExport::ImportData( rMimeType, rValue );*/
2668 OSL_ENSURE( false, "Implementation is missing" );
2669 return false;
2671 #endif
2673 ::sfx2::SvLinkSource* ScDocShell::DdeCreateLinkSource( const OUString& rItem )
2675 if (officecfg::Office::Common::Security::Scripting::DisableActiveContent::get())
2676 return nullptr;
2678 // only check for valid item string - range is parsed again in ScServerObject ctor
2680 // named range?
2681 OUString aPos = rItem;
2682 ScRangeName* pRange = m_pDocument->GetRangeName();
2683 if( pRange )
2685 const ScRangeData* pData = pRange->findByUpperName(ScGlobal::getCharClass().uppercase(aPos));
2686 if (pData)
2688 if( pData->HasType( ScRangeData::Type::RefArea )
2689 || pData->HasType( ScRangeData::Type::AbsArea )
2690 || pData->HasType( ScRangeData::Type::AbsPos ) )
2691 aPos = pData->GetSymbol(); // continue with the name's contents
2695 // Address in DDE function must be always parsed as CONV_OOO so that it
2696 // would always work regardless of current address conversion. We do this
2697 // because the address item in a DDE entry is *not* normalized when saved
2698 // into ODF.
2699 ScRange aRange;
2700 bool bValid = ( (aRange.Parse(aPos, *m_pDocument, formula::FormulaGrammar::CONV_OOO ) & ScRefFlags::VALID) ||
2701 (aRange.aStart.Parse(aPos, *m_pDocument, formula::FormulaGrammar::CONV_OOO) & ScRefFlags::VALID) );
2703 ScServerObject* pObj = nullptr; // NULL = error
2704 if ( bValid )
2705 pObj = new ScServerObject( this, rItem );
2707 // GetLinkManager()->InsertServer() is in the ScServerObject ctor
2709 return pObj;
2712 void ScDocShell::LOKCommentNotify(LOKCommentNotificationType nType, const ScDocument& rDocument, const ScAddress& rPos, const ScPostIt* pNote)
2714 if ( !rDocument.IsDocVisible() || // don't want callbacks until document load
2715 !comphelper::LibreOfficeKit::isActive() ||
2716 comphelper::LibreOfficeKit::isTiledAnnotations() )
2717 return;
2719 tools::JsonWriter aAnnotation;
2721 auto commentNode = aAnnotation.startNode("comment");
2722 aAnnotation.put("action", (nType == LOKCommentNotificationType::Add ? "Add" :
2723 (nType == LOKCommentNotificationType::Remove ? "Remove" :
2724 (nType == LOKCommentNotificationType::Modify ? "Modify" : "???"))));
2726 assert(pNote);
2727 aAnnotation.put("id", pNote->GetId());
2728 aAnnotation.put("tab", rPos.Tab());
2730 if (nType != LOKCommentNotificationType::Remove)
2732 aAnnotation.put("author", pNote->GetAuthor());
2733 aAnnotation.put("dateTime", pNote->GetDate());
2734 aAnnotation.put("text", pNote->GetText());
2736 // Calculating the cell cursor position
2737 ScViewData* pViewData = GetViewData();
2738 if (pViewData && pViewData->GetActiveWin())
2739 aAnnotation.put("cellRange", ScPostIt::NoteRangeToJsonString(rDocument, rPos));
2743 OString aPayload = aAnnotation.finishAndGetAsOString();
2745 ScViewData* pViewData = GetViewData();
2746 SfxViewShell* pThisViewShell = ( pViewData ? pViewData->GetViewShell() : nullptr );
2747 SfxViewShell* pViewShell = SfxViewShell::GetFirst();
2748 while (pViewShell)
2750 if (pThisViewShell == nullptr || pViewShell->GetDocId() == pThisViewShell->GetDocId())
2751 pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_COMMENT, aPayload);
2752 pViewShell = SfxViewShell::GetNext(*pViewShell);
2756 ScViewData* ScDocShell::GetViewData()
2758 SfxViewShell* pCur = SfxViewShell::Current();
2759 ScTabViewShell* pViewSh = dynamic_cast< ScTabViewShell *>( pCur );
2760 return pViewSh ? &pViewSh->GetViewData() : nullptr;
2763 SCTAB ScDocShell::GetCurTab()
2765 //! this must be made non-static and use a ViewShell from this document!
2767 ScViewData* pViewData = GetViewData();
2769 return pViewData ? pViewData->GetTabNo() : static_cast<SCTAB>(0);
2772 ScTabViewShell* ScDocShell::GetBestViewShell( bool bOnlyVisible )
2774 ScTabViewShell* pViewSh = ScTabViewShell::GetActiveViewShell();
2775 // wrong Doc?
2776 if( pViewSh && pViewSh->GetViewData().GetDocShell() != this )
2777 pViewSh = nullptr;
2778 if( !pViewSh )
2780 // 1. find ViewShell
2781 SfxViewFrame* pFrame = SfxViewFrame::GetFirst( this, bOnlyVisible );
2782 if( pFrame )
2784 SfxViewShell* p = pFrame->GetViewShell();
2785 pViewSh = dynamic_cast< ScTabViewShell *>( p );
2788 return pViewSh;
2791 SfxBindings* ScDocShell::GetViewBindings()
2793 // used to invalidate slots after changes to this document
2795 SfxViewShell* pViewSh = GetBestViewShell();
2796 if (pViewSh)
2797 return &pViewSh->GetViewFrame().GetBindings();
2798 else
2799 return nullptr;
2802 ScDocShell* ScDocShell::GetShellByNum( sal_uInt16 nDocNo ) // static
2804 ScDocShell* pFound = nullptr;
2805 SfxObjectShell* pShell = SfxObjectShell::GetFirst();
2806 sal_uInt16 nShellCnt = 0;
2808 while ( pShell && !pFound )
2810 if ( auto pDocSh = dynamic_cast<ScDocShell*>(pShell) )
2812 if ( nShellCnt == nDocNo )
2813 pFound = pDocSh;
2814 else
2815 ++nShellCnt;
2817 pShell = SfxObjectShell::GetNext( *pShell );
2820 return pFound;
2823 IMPL_LINK( ScDocShell, DialogClosedHdl, sfx2::FileDialogHelper*, _pFileDlg, void )
2825 assert( _pFileDlg && "ScDocShell::DialogClosedHdl(): no file dialog");
2826 OSL_ENSURE( m_pImpl->pDocInserter, "ScDocShell::DialogClosedHdl(): no document inserter" );
2828 if ( ERRCODE_NONE == _pFileDlg->GetError() )
2830 sal_uInt16 nSlot = m_pImpl->pRequest->GetSlot();
2831 std::unique_ptr<SfxMedium> pMed = m_pImpl->pDocInserter->CreateMedium();
2832 // #i87094# If a .odt was selected pMed is NULL.
2833 if (pMed)
2835 m_pImpl->pRequest->AppendItem( SfxStringItem( SID_FILE_NAME, pMed->GetName() ) );
2836 if ( SID_DOCUMENT_COMPARE == nSlot )
2838 if ( pMed->GetFilter() )
2839 m_pImpl->pRequest->AppendItem(
2840 SfxStringItem( SID_FILTER_NAME, pMed->GetFilter()->GetFilterName() ) );
2841 OUString sOptions = ScDocumentLoader::GetOptions( *pMed );
2842 if ( !sOptions.isEmpty() )
2843 m_pImpl->pRequest->AppendItem( SfxStringItem( SID_FILE_FILTEROPTIONS, sOptions ) );
2845 const SfxPoolItem* pItem = nullptr;
2846 const SfxInt16Item* pInt16Item(nullptr);
2847 if (pMed->GetItemSet().GetItemState(SID_VERSION, true, &pItem) == SfxItemState::SET)
2849 pInt16Item = dynamic_cast<const SfxInt16Item*>(pItem);
2851 if (pInt16Item)
2853 m_pImpl->pRequest->AppendItem( *pItem );
2856 Execute( *(m_pImpl->pRequest) );
2860 m_pImpl->bIgnoreLostRedliningWarning = false;
2863 #if HAVE_FEATURE_MULTIUSER_ENVIRONMENT
2865 void ScDocShell::EnableSharedSettings( bool bEnable )
2867 SetDocumentModified();
2869 if ( bEnable )
2871 m_pDocument->EndChangeTracking();
2872 m_pDocument->StartChangeTracking();
2874 // hide accept or reject changes dialog
2875 sal_uInt16 nId = ScAcceptChgDlgWrapper::GetChildWindowId();
2876 SfxViewFrame* pViewFrame = SfxViewFrame::Current();
2877 if ( pViewFrame && pViewFrame->HasChildWindow( nId ) )
2879 pViewFrame->ToggleChildWindow( nId );
2880 SfxBindings* pBindings = GetViewBindings();
2881 if ( pBindings )
2883 pBindings->Invalidate( FID_CHG_ACCEPT );
2887 else
2889 m_pDocument->EndChangeTracking();
2892 ScChangeViewSettings aChangeViewSet;
2893 aChangeViewSet.SetShowChanges( false );
2894 m_pDocument->SetChangeViewSettings( aChangeViewSet );
2897 uno::Reference< frame::XModel > ScDocShell::LoadSharedDocument()
2899 uno::Reference< frame::XModel > xModel;
2900 ScModule* mod = ScModule::get();
2903 mod->SetInSharedDocLoading(true);
2904 uno::Reference< frame::XDesktop2 > xLoader = frame::Desktop::create( ::comphelper::getProcessComponentContext() );
2905 uno::Sequence aArgs{ comphelper::makePropertyValue(u"Hidden"_ustr, true) };
2907 if ( GetMedium() )
2909 const SfxStringItem* pPasswordItem = GetMedium()->GetItemSet().GetItem(SID_PASSWORD, false);
2910 if ( pPasswordItem && !pPasswordItem->GetValue().isEmpty() )
2912 aArgs.realloc( 2 );
2913 auto pArgs = aArgs.getArray();
2914 pArgs[1].Name = "Password";
2915 pArgs[1].Value <<= pPasswordItem->GetValue();
2917 const SfxUnoAnyItem* pEncryptionItem = GetMedium()->GetItemSet().GetItem(SID_ENCRYPTIONDATA, false);
2918 if (pEncryptionItem)
2920 aArgs.realloc(aArgs.getLength() + 1);
2921 auto pArgs = aArgs.getArray();
2922 pArgs[aArgs.getLength() - 1].Name = "EncryptionData";
2923 pArgs[aArgs.getLength() - 1].Value = pEncryptionItem->GetValue();
2927 xModel.set(
2928 xLoader->loadComponentFromURL( GetSharedFileURL(), u"_blank"_ustr, 0, aArgs ),
2929 uno::UNO_QUERY_THROW );
2930 mod->SetInSharedDocLoading(false);
2932 catch ( uno::Exception& )
2934 OSL_FAIL( "ScDocShell::LoadSharedDocument(): caught exception" );
2935 mod->SetInSharedDocLoading(false);
2938 uno::Reference< util::XCloseable > xClose( xModel, uno::UNO_QUERY_THROW );
2939 xClose->close( true );
2940 return uno::Reference< frame::XModel >();
2942 catch ( uno::Exception& )
2944 return uno::Reference< frame::XModel >();
2947 return xModel;
2950 #endif
2952 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */