diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 05:54:39 +0000 |
commit | 267c6f2ac71f92999e969232431ba04678e7437e (patch) | |
tree | 358c9467650e1d0a1d7227a21dac2e3d08b622b2 /sw/source/uibase/app | |
parent | Initial commit. (diff) | |
download | libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.tar.xz libreoffice-267c6f2ac71f92999e969232431ba04678e7437e.zip |
Adding upstream version 4:24.2.0.upstream/4%24.2.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sw/source/uibase/app')
-rw-r--r-- | sw/source/uibase/app/appenv.cxx | 497 | ||||
-rw-r--r-- | sw/source/uibase/app/appenv.hxx | 19 | ||||
-rw-r--r-- | sw/source/uibase/app/apphdl.cxx | 1128 | ||||
-rw-r--r-- | sw/source/uibase/app/applab.cxx | 397 | ||||
-rw-r--r-- | sw/source/uibase/app/appopt.cxx | 527 | ||||
-rw-r--r-- | sw/source/uibase/app/docsh.cxx | 1433 | ||||
-rw-r--r-- | sw/source/uibase/app/docsh2.cxx | 1805 | ||||
-rw-r--r-- | sw/source/uibase/app/docshdrw.cxx | 100 | ||||
-rw-r--r-- | sw/source/uibase/app/docshini.cxx | 711 | ||||
-rw-r--r-- | sw/source/uibase/app/docst.cxx | 1693 | ||||
-rw-r--r-- | sw/source/uibase/app/docstyle.cxx | 3380 | ||||
-rw-r--r-- | sw/source/uibase/app/mainwn.cxx | 133 | ||||
-rw-r--r-- | sw/source/uibase/app/swdll.cxx | 184 | ||||
-rw-r--r-- | sw/source/uibase/app/swdllimpl.hxx | 45 | ||||
-rw-r--r-- | sw/source/uibase/app/swmodul1.cxx | 693 | ||||
-rw-r--r-- | sw/source/uibase/app/swmodule.cxx | 401 | ||||
-rw-r--r-- | sw/source/uibase/app/swwait.cxx | 83 |
17 files changed, 13229 insertions, 0 deletions
diff --git a/sw/source/uibase/app/appenv.cxx b/sw/source/uibase/app/appenv.cxx new file mode 100644 index 0000000000..6c744867ad --- /dev/null +++ b/sw/source/uibase/app/appenv.cxx @@ -0,0 +1,497 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <hintids.hxx> + +#include <comphelper/string.hxx> +#include <sfx2/request.hxx> + +#include <sfx2/bindings.hxx> +#include <sfx2/printer.hxx> +#include <sfx2/viewfrm.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/lrspitem.hxx> +#include <editeng/ulspitem.hxx> +#include <editeng/pbinitem.hxx> +#include <editeng/paperinf.hxx> +#include <osl/diagnose.h> +#include <fmthdft.hxx> +#include <swwait.hxx> +#include <swmodule.hxx> +#include <wrtsh.hxx> +#include <view.hxx> +#include <docsh.hxx> +#include <frmatr.hxx> +#include <fldbas.hxx> +#include <swundo.hxx> +#include <IDocumentDeviceAccess.hxx> +#include <dialoghelp.hxx> +#include <fmtcol.hxx> +#include <frmmgr.hxx> +#include <fldmgr.hxx> +#include <pagedesc.hxx> +#include <poolfmt.hxx> +#include <expfld.hxx> +#include <SwStyleNameMapper.hxx> +#include <fmtpdsc.hxx> + +#include <cmdid.h> +#include <strings.hrc> +#include <swabstdlg.hxx> +#include <envimg.hxx> +#include "appenv.hxx" + +#define ENV_NEWDOC RET_OK +#define ENV_INSERT RET_USER + +// Function used for labels and envelopes in applab.cxx and appenv.cxx +OUString InsertLabEnvText( SwWrtShell& rSh, SwFieldMgr& rFieldMgr, const OUString& rText ) +{ + OUString sRet; + OUString aText = rText.replaceAll("\r", ""); + + sal_Int32 nTokenPos = 0; + while( -1 != nTokenPos ) + { + OUString aLine = aText.getToken( 0, '\n', nTokenPos ); + while ( !aLine.isEmpty() ) + { + OUString sTmpText; + bool bField = false; + + sal_Int32 nPos = aLine.indexOf( '<' ); + if (0 != nPos) + { + sal_Int32 const nCopy((nPos != -1) ? nPos : aLine.getLength()); + sTmpText = aLine.copy(0, nCopy); + aLine = aLine.copy(nCopy); + } + else + { + nPos = aLine.indexOf( '>' ); + if ( nPos == -1 ) + { + sTmpText = aLine; + aLine.clear(); + } + else + { + sTmpText = aLine.copy( 0, nPos + 1); + aLine = aLine.copy( nPos + 1); + + // Database fields must contain at least 3 points! + OUString sDBName( sTmpText.copy( 1, sTmpText.getLength() - 2)); + if (comphelper::string::getTokenCount(sDBName, '.') >= 3) + { + sDBName = ::ReplacePoint(sDBName, true); + SwInsertField_Data aData(SwFieldTypesEnum::Database, 0, sDBName, OUString(), 0, &rSh); + rFieldMgr.InsertField( aData ); + sRet = sDBName; + bField = true; + } + } + } + if ( !bField ) + rSh.Insert( sTmpText ); + } + rSh.SplitNode(); + } + rSh.DelLeft(); // Again remove last linebreak + + return sRet; +} + +static void lcl_CopyCollAttr(SwWrtShell const * pOldSh, SwWrtShell* pNewSh, sal_uInt16 nCollId) +{ + sal_uInt16 nCollCnt = pOldSh->GetTextFormatCollCount(); + for( sal_uInt16 nCnt = 0; nCnt < nCollCnt; ++nCnt ) + { + SwTextFormatColl* pColl = &pOldSh->GetTextFormatColl(nCnt); + if(nCollId == pColl->GetPoolFormatId()) + pNewSh->GetTextCollFromPool(nCollId)->SetFormatAttr(pColl->GetAttrSet()); + } +} + +void SwModule::InsertEnv( SfxRequest& rReq ) +{ + static sal_uInt16 nTitleNo = 0; + + SwDocShell *pMyDocSh; + SfxViewFrame *pFrame; + SwView *pNewView; + SwWrtShell *pOldSh, + *pSh; + + // Get current shell + pMyDocSh = static_cast<SwDocShell*>( SfxObjectShell::Current()); + pOldSh = pMyDocSh ? pMyDocSh->GetWrtShell() : nullptr; + + // Create new document (don't show!) + SfxObjectShellLock xDocSh( new SwDocShell( SfxObjectCreateMode::STANDARD ) ); + xDocSh->DoInitNew(); + pFrame = SfxViewFrame::LoadHiddenDocument( *xDocSh, SFX_INTERFACE_NONE ); + pNewView = static_cast<SwView*>( pFrame->GetViewShell()); + pNewView->AttrChangedNotify(nullptr); // so that SelectShell is being called + pSh = pNewView->GetWrtShellPtr(); + + if (!pSh) + return; + + OUString aTmp = SwResId(STR_ENV_TITLE) + OUString::number( ++nTitleNo ); + xDocSh->SetTitle( aTmp ); + + // if applicable, copy the old Collections "Sender" and "Receiver" to + // a new document + if ( pOldSh ) + { + ::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_ENVELOPE_ADDRESS); + ::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_SEND_ADDRESS); + } + + // Read SwEnvItem from config + SwEnvCfgItem aEnvCfg; + + // Check if there's already an envelope. + bool bEnvChange = false; + + SfxItemSetFixed<FN_ENVELOP, FN_ENVELOP> aSet(GetPool()); + aSet.Put(aEnvCfg.GetItem()); + + SfxPrinter* pTempPrinter = pSh->getIDocumentDeviceAccess().getPrinter( true ); + if(pOldSh ) + { + const SwPageDesc& rCurPageDesc = pOldSh->GetPageDesc(pOldSh->GetCurPageDesc()); + OUString sEnvelope; + SwStyleNameMapper::FillUIName( RES_POOLPAGE_ENVELOPE, sEnvelope ); + bEnvChange = rCurPageDesc.GetName() == sEnvelope; + + IDocumentDeviceAccess& rIDDA_old = pOldSh->getIDocumentDeviceAccess(); + if( rIDDA_old.getPrinter( false ) ) + { + IDocumentDeviceAccess& rIDDA = pSh->getIDocumentDeviceAccess(); + rIDDA.setJobsetup( *rIDDA_old.getJobsetup() ); + //#69563# if it isn't the same printer then the pointer has been invalidated! + pTempPrinter = rIDDA.getPrinter( true ); + } + pTempPrinter->SetPaperBin(rCurPageDesc.GetMaster().GetPaperBin().GetValue()); + + } + + ScopedVclPtr<SfxAbstractTabDialog> pDlg; + short nMode = ENV_INSERT; + + const SwEnvItem* pItem = rReq.GetArg<SwEnvItem>(FN_ENVELOP); + if ( !pItem ) + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + pDlg.disposeAndReset(pFact->CreateSwEnvDlg(GetFrameWeld(pMyDocSh), aSet, pOldSh, pTempPrinter, !bEnvChange)); + nMode = pDlg->Execute(); + } + else + { + const SfxBoolItem* pBoolItem = rReq.GetArg<SfxBoolItem>(FN_PARAM_1); + if ( pBoolItem && pBoolItem->GetValue() ) + nMode = ENV_NEWDOC; + } + + if (nMode == ENV_NEWDOC || nMode == ENV_INSERT) + { + SwWait aWait( static_cast<SwDocShell&>(*xDocSh), true ); + + // Read dialog and save item to config + const SwEnvItem& rItem = pItem ? *pItem : static_cast<const SwEnvItem&>( pDlg->GetOutputItemSet()->Get(FN_ENVELOP) ); + aEnvCfg.GetItem() = rItem; + aEnvCfg.Commit(); + + // When we print we take the Jobsetup that is set up in the dialog. + // Information has to be set here, before a possible destruction of + // the new shell because the shell's printer has been handed to the + // dialog. + if ( nMode != ENV_NEWDOC ) + { + OSL_ENSURE(pOldSh, "No document - wasn't 'Insert' disabled???"); + SvxPaperBinItem aItem( RES_PAPER_BIN ); + aItem.SetValue(static_cast<sal_uInt8>(pSh->getIDocumentDeviceAccess().getPrinter(true)->GetPaperBin())); + pOldSh->GetPageDescFromPool(RES_POOLPAGE_ENVELOPE)->GetMaster().SetFormatAttr(aItem); + } + + SwWrtShell *pTmp = nMode == ENV_INSERT ? pOldSh : pSh; + const SwPageDesc* pFollow = nullptr; + SwTextFormatColl *pSend = pTmp->GetTextCollFromPool(RES_POOLCOLL_SEND_ADDRESS), + *pAddr = pTmp->GetTextCollFromPool(RES_POOLCOLL_ENVELOPE_ADDRESS); + const OUString sSendMark = pSend->GetName(); + const OUString sAddrMark = pAddr->GetName(); + + if (nMode == ENV_INSERT) + { + + SetView(&pOldSh->GetView()); // Set pointer to top view + + // Delete new document + xDocSh->DoClose(); + pSh = pOldSh; + //#i4251# selected text or objects in the document should + //not be deleted on inserting envelopes + pSh->EnterStdMode(); + // Here it goes (insert) + pSh->StartUndo(SwUndoId::UI_INSERT_ENVELOPE); + pSh->StartAllAction(); + pSh->SttEndDoc(true); + + if (bEnvChange) + { + // followup template: page 2 + pFollow = pSh->GetPageDesc(pSh->GetCurPageDesc()).GetFollow(); + + // Delete text from the first page + if ( !pSh->SttNxtPg(true) ) + pSh->EndPg(true); + pSh->DelRight(); + // Delete frame of the first page + if ( pSh->GotoFly(sSendMark) ) + { + pSh->EnterSelFrameMode(); + pSh->DelRight(); + } + if ( pSh->GotoFly(sAddrMark) ) + { + pSh->EnterSelFrameMode(); + pSh->DelRight(); + } + pSh->SttEndDoc(true); + } + else + // Followup template: page 1 + pFollow = &pSh->GetPageDesc(pSh->GetCurPageDesc()); + + // Insert page break + if ( pSh->IsCursorInTable() ) + { + pSh->SplitNode(); + pSh->Right( SwCursorSkipMode::Chars, false, 1, false ); + SfxItemSetFixed<RES_PAGEDESC, RES_PAGEDESC> aBreakSet( pSh->GetAttrPool() ); + aBreakSet.Put( SwFormatPageDesc( pFollow ) ); + pSh->SetTableAttr( aBreakSet ); + } + else + { + OUString sFollowName(pFollow->GetName()); + pSh->InsertPageBreak(&sFollowName, std::nullopt); + } + pSh->SttEndDoc(true); + } + else + { + pFollow = &pSh->GetPageDesc(pSh->GetCurPageDesc()); + // Let's go (print) + pSh->StartAllAction(); + pSh->DoUndo(false); + + // Again, copy the new collections "Sender" and "Receiver" to + // a new document + if ( pOldSh ) + { + ::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_ENVELOPE_ADDRESS); + ::lcl_CopyCollAttr(pOldSh, pSh, RES_POOLCOLL_SEND_ADDRESS); + } + } + + CurrShell aCurr(pSh); + pSh->SetNewDoc(); // Avoid performance problems + + // Remember Flys of this site + std::vector<SwFrameFormat*> aFlyArr; + if( ENV_NEWDOC != nMode && !bEnvChange ) + pSh->GetPageObjs( aFlyArr ); + + // Get page description + SwPageDesc* pDesc = pSh->GetPageDescFromPool(RES_POOLPAGE_ENVELOPE); + SwFrameFormat& rFormat = pDesc->GetMaster(); + + Printer *pPrt = pSh->getIDocumentDeviceAccess().getPrinter( true ); + + // Borders (are put together by Shift-Offset and alignment) + Size aPaperSize = pPrt->PixelToLogic( pPrt->GetPaperSizePixel(), + MapMode(MapUnit::MapTwip)); + if ( !aPaperSize.Width() && !aPaperSize.Height() ) + aPaperSize = SvxPaperInfo::GetPaperSize(PAPER_A4); + if ( aPaperSize.Width() > aPaperSize.Height() ) + Swap( aPaperSize ); + + tools::Long lLeft = rItem.m_nShiftRight, + lUpper = rItem.m_nShiftDown; + + sal_uInt16 nPageW = o3tl::narrowing<sal_uInt16>(std::max(rItem.m_nWidth, rItem.m_nHeight)), + nPageH = o3tl::narrowing<sal_uInt16>(std::min(rItem.m_nWidth, rItem.m_nHeight)); + + switch (rItem.m_eAlign) + { + case ENV_HOR_LEFT: break; + case ENV_HOR_CNTR: lLeft += std::max(tools::Long(0), aPaperSize.Width() - nPageW) / 2; + break; + case ENV_HOR_RGHT: lLeft += std::max(tools::Long(0), aPaperSize.Width() - nPageW); + break; + case ENV_VER_LEFT: lUpper += std::max(tools::Long(0), aPaperSize.Width() - nPageH); + break; + case ENV_VER_CNTR: lUpper += std::max(tools::Long(0), aPaperSize.Width() - nPageH) / 2; + break; + case ENV_VER_RGHT: break; + } + SvxLRSpaceItem aLRMargin( RES_LR_SPACE ); + SvxULSpaceItem aULMargin( RES_UL_SPACE ); + aLRMargin.SetLeft (o3tl::narrowing<sal_uInt16>(lLeft) ); + aULMargin.SetUpper(o3tl::narrowing<sal_uInt16>(lUpper)); + aLRMargin.SetRight(0); + aULMargin.SetLower(0); + rFormat.SetFormatAttr(aLRMargin); + rFormat.SetFormatAttr(aULMargin); + + // Header and footer + rFormat.SetFormatAttr(SwFormatHeader(false)); + pDesc->ChgHeaderShare(false); + rFormat.SetFormatAttr(SwFormatFooter(false)); + pDesc->ChgFooterShare(false); + + // Page numbering + pDesc->SetUseOn(UseOnPage::All); + + // Page size + rFormat.SetFormatAttr(SwFormatFrameSize(SwFrameSize::Fixed, + nPageW + lLeft, nPageH + lUpper)); + + // Set type of page numbering + SvxNumberType aType; + aType.SetNumberingType(SVX_NUM_NUMBER_NONE); + pDesc->SetNumType(aType); + + // Followup template + if (pFollow) + pDesc->SetFollow(pFollow); + + // Landscape + pDesc->SetLandscape( rItem.m_eAlign >= ENV_VER_LEFT && + rItem.m_eAlign <= ENV_VER_RGHT); + + // Apply page description + + size_t nPos; + pSh->FindPageDescByName( pDesc->GetName(), + false, + &nPos ); + + pSh->ChgPageDesc( nPos, *pDesc); + pSh->ChgCurPageDesc(*pDesc); + + // Insert Frame + SwFlyFrameAttrMgr aMgr(false, pSh, Frmmgr_Type::ENVELP, nullptr); + SwFieldMgr aFieldMgr; + aMgr.SetHeightSizeType(SwFrameSize::Variable); + + // Overwrite defaults! + aMgr.GetAttrSet().Put( SvxBoxItem(RES_BOX) ); + aMgr.SetULSpace( 0, 0 ); + aMgr.SetLRSpace( 0, 0 ); + + // Sender + if (rItem.m_bSend) + { + pSh->SttEndDoc(true); + aMgr.InsertFlyFrame(RndStdIds::FLY_AT_PAGE, + Point(rItem.m_nSendFromLeft + lLeft, rItem.m_nSendFromTop + lUpper), + Size (rItem.m_nAddrFromLeft - rItem.m_nSendFromLeft, 0)); + + pSh->EnterSelFrameMode(); + pSh->SetFlyName(sSendMark); + pSh->UnSelectFrame(); + pSh->LeaveSelFrameMode(); + pSh->SetTextFormatColl( pSend ); + InsertLabEnvText( *pSh, aFieldMgr, rItem.m_aSendText ); + aMgr.UpdateAttrMgr(); + } + + // Addressee + pSh->SttEndDoc(true); + + aMgr.InsertFlyFrame(RndStdIds::FLY_AT_PAGE, + Point(rItem.m_nAddrFromLeft + lLeft, rItem.m_nAddrFromTop + lUpper), + Size (nPageW - rItem.m_nAddrFromLeft - 566, 0)); + pSh->EnterSelFrameMode(); + pSh->SetFlyName(sAddrMark); + pSh->UnSelectFrame(); + pSh->LeaveSelFrameMode(); + pSh->SetTextFormatColl( pAddr ); + InsertLabEnvText(*pSh, aFieldMgr, rItem.m_aAddrText); + + // Move Flys to the "old" pages + if (!aFlyArr.empty()) + pSh->SetPageObjsNewPage(aFlyArr); + + // Finished + pSh->SttEndDoc(true); + + pSh->EndAllAction(); + + if (nMode == ENV_NEWDOC) + pSh->DoUndo(); + else + pSh->EndUndo(SwUndoId::UI_INSERT_ENVELOPE); + + if (nMode == ENV_NEWDOC) + { + pFrame->GetFrame().Appear(); + + if ( rItem.m_aAddrText.indexOf('<') >= 0 ) + { + static sal_uInt16 const aInva[] = + { + SID_SBA_BRW_UPDATE, + SID_SBA_BRW_INSERT, + SID_SBA_BRW_MERGE, + 0 + }; + pFrame->GetBindings().Invalidate( aInva ); + + // Open database beamer + ShowDBObj(*pNewView, pSh->GetDBData()); + } + } + + if ( !pItem ) + { + rReq.AppendItem( rItem ); + if ( nMode == ENV_NEWDOC ) + rReq.AppendItem( SfxBoolItem( FN_PARAM_1, true ) ); + } + + rReq.Done(); + } + else // Abort + { + rReq.Ignore(); + + xDocSh->DoClose(); + --nTitleNo; + + // Set pointer to top view + if (pOldSh) + SetView(&pOldSh->GetView()); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/app/appenv.hxx b/sw/source/uibase/app/appenv.hxx new file mode 100644 index 0000000000..f077702bb9 --- /dev/null +++ b/sw/source/uibase/app/appenv.hxx @@ -0,0 +1,19 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <rtl/ustring.hxx> + +class SwWrtShell; +class SwFieldMgr; + +OUString InsertLabEnvText(SwWrtShell&, SwFieldMgr&, const OUString&); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/app/apphdl.cxx b/sw/source/uibase/app/apphdl.cxx new file mode 100644 index 0000000000..bca9d20dbd --- /dev/null +++ b/sw/source/uibase/app/apphdl.cxx @@ -0,0 +1,1128 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <config_features.h> +#include <config_fuzzers.h> +#include <config_wasm_strip.h> + +#include <comphelper/propertysequence.hxx> +#include <comphelper/servicehelper.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/event.hxx> +#include <sfx2/objitem.hxx> +#include <svx/dataaccessdescriptor.hxx> +#include <svtools/restartdialog.hxx> +#include <svl/eitem.hxx> +#include <svl/whiter.hxx> +#include <svl/stritem.hxx> +#include <svl/voiditem.hxx> +#include <sfx2/lokhelper.hxx> +#include <sfx2/request.hxx> +#include <sfx2/fcontnr.hxx> +#include <svl/ctloptions.hxx> +#include <svtools/colorcfg.hxx> +#include <svtools/accessibilityoptions.hxx> +#include <comphelper/diagnose_ex.hxx> +#include <unotools/useroptions.hxx> +#include <com/sun/star/document/UpdateDocMode.hpp> +#include <sfx2/docfile.hxx> +#include <sfx2/objface.hxx> +#include <vcl/settings.hxx> +#include <vcl/svapp.hxx> +#include <o3tl/string_view.hxx> + +#include <view.hxx> +#include <pview.hxx> +#include <srcview.hxx> +#include <wrtsh.hxx> +#include <docsh.hxx> +#include <cmdid.h> +#include <initui.hxx> +#include <uitool.hxx> +#include <swmodule.hxx> +#include <wview.hxx> +#include <usrpref.hxx> +#include <gloslst.hxx> +#include <glosdoc.hxx> +#include <doc.hxx> +#include <IDocumentLayoutAccess.hxx> +#include <IDocumentFieldsAccess.hxx> +#include <prtopt.hxx> +#include <modcfg.hxx> +#include <fontcfg.hxx> +#include <barcfg.hxx> +#include <navicfg.hxx> +#include <uinums.hxx> +#include <dbconfig.hxx> +#include <mmconfigitem.hxx> +#include <strings.hrc> +#include <unotxdoc.hxx> +#include <com/sun/star/container/XChild.hpp> +#include <com/sun/star/sdbc/XConnection.hpp> +#include <com/sun/star/sdb/TextConnectionSettings.hpp> +#include <com/sun/star/sdbc/XDataSource.hpp> +#include <com/sun/star/task/OfficeRestartManager.hpp> +#include <org/freedesktop/PackageKit/SyncDbusSessionHelper.hpp> +#include <swabstdlg.hxx> +#include <comphelper/dispatchcommand.hxx> +#include <comphelper/processfactory.hxx> +#include <comphelper/lok.hxx> +#include <LibreOfficeKit/LibreOfficeKitEnums.h> + +#include <salhelper/simplereferenceobject.hxx> +#include <rtl/ref.hxx> + +#include <officecfg/Office/Common.hxx> + +using namespace ::com::sun::star; + +// Slotmaps for the application's methods + +// here are the SlotID's being included +// see Idl-file +#define ShellClass_SwModule +#include <sfx2/msg.hxx> +#include <swslots.hxx> + +SFX_IMPL_INTERFACE(SwModule, SfxModule) + +void SwModule::InitInterface_Impl() +{ + GetStaticInterface()->RegisterStatusBar(StatusBarId::WriterStatusBar); + + GetStaticInterface()->RegisterObjectBar(SFX_OBJECTBAR_APPLICATION, + SfxVisibilityFlags::Standard | SfxVisibilityFlags::Client | SfxVisibilityFlags::Viewer, + ToolbarId::Module_Toolbox); +} + +// other states +void SwModule::StateOther(SfxItemSet &rSet) +{ + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + + SwView* pActView = ::GetActiveView(); + bool bWebView = dynamic_cast<SwWebView*>( pActView ) != nullptr; + + while(nWhich) + { + switch(nWhich) + { + case FN_BUSINESS_CARD: + case FN_LABEL: + case FN_ENVELOP: + { + bool bDisable = false; + SfxViewShell* pCurrView = SfxViewShell::Current(); + if( !pCurrView || dynamic_cast< const SwView *>( pCurrView ) == nullptr ) + bDisable = true; + SwDocShell *pDocSh = static_cast<SwDocShell*>( SfxObjectShell::Current()); + if ( bDisable || + (pDocSh && (pDocSh->IsReadOnly() || + pDocSh->GetCreateMode() == SfxObjectCreateMode::EMBEDDED)) ) + rSet.DisableItem( nWhich ); + + } + break; + case FN_XFORMS_INIT: + // slot is always active! + break; + case FN_EDIT_FORMULA: + { + SwWrtShell* pSh = nullptr; + SelectionType nSelection = SelectionType::NONE; + if( pActView ) + pSh = &pActView->GetWrtShell(); + if( pSh ) + nSelection = pSh->GetSelectionType(); + + if( (pSh && pSh->HasSelection()) || + !(nSelection & (SelectionType::Text | SelectionType::Table))) + rSet.DisableItem(nWhich); + } + break; + case SID_ATTR_METRIC: + rSet.Put( SfxUInt16Item( SID_ATTR_METRIC, static_cast< sal_uInt16 >(::GetDfltMetric(bWebView)))); + break; + case FN_SET_MODOPT_TBLNUMFMT: + rSet.Put( SfxBoolItem( nWhich, m_pModuleConfig-> + IsInsTableFormatNum( bWebView ))); + break; + case FN_MAILMERGE_WIZARD: + { + SfxObjectShell* pObjectShell = GetObjectShell(); + if (pObjectShell && pObjectShell->isExportLocked()) + rSet.DisableItem(nWhich); + break; + } + case FN_MAILMERGE_FIRST_ENTRY: + case FN_MAILMERGE_PREV_ENTRY: + case FN_MAILMERGE_NEXT_ENTRY: + case FN_MAILMERGE_LAST_ENTRY: + { + std::shared_ptr<SwMailMergeConfigItem> xConfigItem; + if (SwView* pView = GetActiveView()) + xConfigItem = pView->GetMailMergeConfigItem(); + if (!xConfigItem) + rSet.DisableItem(nWhich); + else if (xConfigItem->GetConnection().is() + && !xConfigItem->GetConnection()->isClosed()) + { + bool bFirst, bLast; + bool bValid = xConfigItem->IsResultSetFirstLast(bFirst, bLast); + + if (!bValid || + (bFirst && (nWhich == FN_MAILMERGE_FIRST_ENTRY || nWhich == FN_MAILMERGE_PREV_ENTRY)) || + (bLast && (nWhich == FN_MAILMERGE_LAST_ENTRY || nWhich == FN_MAILMERGE_NEXT_ENTRY))) + { + rSet.DisableItem(nWhich); + } + } + } + break; + case FN_MAILMERGE_CURRENT_ENTRY: + case FN_MAILMERGE_EXCLUDE_ENTRY: + { + // just trigger calling statusChanged() of MMExcludeEntryController + // resp. MMCurrentEntryController + rSet.InvalidateItem(nWhich); + } + break; + case FN_MAILMERGE_CREATE_DOCUMENTS: + case FN_MAILMERGE_SAVE_DOCUMENTS: + case FN_MAILMERGE_PRINT_DOCUMENTS: + case FN_MAILMERGE_EMAIL_DOCUMENTS: + { + std::shared_ptr<SwMailMergeConfigItem> xConfigItem; + if (SwView* pView = GetActiveView()) + xConfigItem = pView->EnsureMailMergeConfigItem(); + + // #i51949# hide e-Mail option if e-Mail is not supported + // #i63267# printing might be disabled + // Without attempting to open the database, (in case it is remote or passworded), + // hide everything after determining there are no valid results. tdf#121606 + if (!xConfigItem || + xConfigItem->GetCurrentDBData().sDataSource.isEmpty() || + xConfigItem->GetCurrentDBData().sCommand.isEmpty() || + (xConfigItem->GetConnection().is() && !xConfigItem->GetConnection()->isClosed() && !xConfigItem->GetResultSet().is()) || + (nWhich == FN_MAILMERGE_PRINT_DOCUMENTS && Application::GetSettings().GetMiscSettings().GetDisablePrinting()) || + (nWhich == FN_MAILMERGE_EMAIL_DOCUMENTS && !xConfigItem->IsMailAvailable())) + { + rSet.DisableItem(nWhich); + } + } + break; + default: + OSL_FAIL("::StateOther: default"); + } + nWhich = aIter.NextWhich(); + } +} + +// start field dialog +static void NewXForms( SfxRequest& rReq ); // implementation: below + +std::shared_ptr<SwMailMergeConfigItem> SwView::EnsureMailMergeConfigItem(const SfxItemSet* pArgs) +{ + // create if it does not exist yet + std::shared_ptr<SwMailMergeConfigItem> xMMConfig = GetMailMergeConfigItem(); + if (!xMMConfig) + { + xMMConfig = std::make_shared<SwMailMergeConfigItem>(); + xMMConfig->SetSourceView(this); + + //set the first used database as default source on the config item + const SfxUnoAnyItem* pItem = nullptr; + if (pArgs && (pItem = pArgs->GetItemIfSet( + FN_PARAM_DATABASE_PROPERTIES, false))) + { + //mailmerge has been called from the database beamer + uno::Sequence< beans::PropertyValue> aDBValues; + if (pItem->GetValue() >>= aDBValues) + { + SwDBData aDBData; + svx::ODataAccessDescriptor aDescriptor(aDBValues); + aDescriptor[svx::DataAccessDescriptorProperty::DataSource] >>= aDBData.sDataSource; + aDescriptor[svx::DataAccessDescriptorProperty::Command] >>= aDBData.sCommand; + aDescriptor[svx::DataAccessDescriptorProperty::CommandType] >>= aDBData.nCommandType; + + uno::Reference< sdbc::XConnection> xConnection; + uno::Reference< sdbc::XDataSource> xSource; + uno::Reference< sdbcx::XColumnsSupplier> xColumnsSupplier; + if (aDescriptor.has(svx::DataAccessDescriptorProperty::Connection)) + aDescriptor[svx::DataAccessDescriptorProperty::Connection] >>= xConnection; + uno::Reference<container::XChild> xChild(xConnection, uno::UNO_QUERY); + if (xChild.is()) + xSource.set(xChild->getParent(), uno::UNO_QUERY); + xMMConfig->SetCurrentConnection( + xSource, SharedConnection(xConnection, SharedConnection::NoTakeOwnership), + xColumnsSupplier, aDBData); + } + } + else + { + std::vector<OUString> aDBNameList; + std::vector<OUString> aAllDBNames; + GetWrtShell().GetAllUsedDB(aDBNameList, &aAllDBNames); + if (!aDBNameList.empty()) + { + OUString sDBName(aDBNameList[0]); + SwDBData aDBData; + sal_Int32 nIdx{ 0 }; + aDBData.sDataSource = sDBName.getToken(0, DB_DELIM, nIdx); + aDBData.sCommand = sDBName.getToken(0, DB_DELIM, nIdx); + aDBData.nCommandType = o3tl::toInt32(o3tl::getToken(sDBName, 0, DB_DELIM, nIdx)); + //set the currently used database for the wizard + xMMConfig->SetCurrentDBData(aDBData); + } + } + + SetMailMergeConfigItem(xMMConfig); + } + return xMMConfig; +} + +#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS + +namespace +{ + +SwView* lcl_LoadDoc(SwView* pView, const OUString& rURL) +{ + SwView* pNewView = nullptr; + if(!rURL.isEmpty()) + { + SfxStringItem aURL(SID_FILE_NAME, rURL); + SfxStringItem aTargetFrameName( SID_TARGETNAME, "_blank" ); + SfxBoolItem aHidden( SID_HIDDEN, true ); + SfxStringItem aReferer(SID_REFERER, pView->GetDocShell()->GetTitle()); + const SfxPoolItemHolder aResult( + pView->GetViewFrame().GetDispatcher()->ExecuteList(SID_OPENDOC, + SfxCallMode::SYNCHRON, + { &aURL, &aHidden, &aReferer, &aTargetFrameName })); + const SfxObjectItem* pItem(static_cast<const SfxObjectItem*>(aResult.getItem())); + SfxShell* pShell = pItem ? pItem->GetShell() : nullptr; + + if(pShell) + { + SfxViewShell* pViewShell = pShell->GetViewShell(); + if(pViewShell) + { + pNewView = dynamic_cast<SwView*>(pViewShell); + if (pNewView) + { + pNewView->GetViewFrame().GetFrame().Appear(); + } + else + { + pViewShell->GetViewFrame().DoClose(); + } + } + } + } + else + { + SfxStringItem aFactory(SID_NEWDOCDIRECT, SwDocShell::Factory().GetFilterContainer()->GetName()); + const SfxPoolItemHolder aResult(pView->GetViewFrame().GetDispatcher()->ExecuteList( + SID_NEWDOCDIRECT, + SfxCallMode::SYNCHRON, { &aFactory })); + const SfxFrameItem* pItem(static_cast<const SfxFrameItem*>(aResult.getItem())); + SfxFrame* pFrame = pItem ? pItem->GetFrame() : nullptr; + SfxViewFrame* pViewFrame = pFrame ? pFrame->GetCurrentViewFrame() : nullptr; + pNewView = pViewFrame ? dynamic_cast<SwView*>( pViewFrame->GetViewShell() ) : nullptr; + } + + return pNewView; +} + +class SwMailMergeWizardExecutor : public salhelper::SimpleReferenceObject +{ + SwView* m_pView; // never owner + SwView* m_pView2Close; // never owner + VclPtr<AbstractMailMergeWizard> m_pWizard; // always owner + VclPtr<AbstractMailMergeWizard> m_pWizardToDestroyInCallback; + + void EndDialogHdl(sal_Int32 nResponse); + DECL_LINK( DestroyDialogHdl, void*, void ); + DECL_LINK( DestroyWizardHdl, void*, void ); + DECL_LINK( CancelHdl, void*, void ); + DECL_LINK( CloseFrameHdl, void*, void ); + + void ExecutionFinished(); + void ExecuteWizard(); + +public: + SwMailMergeWizardExecutor(); + virtual ~SwMailMergeWizardExecutor() override; + + void ExecuteMailMergeWizard( const SfxItemSet * pArgs ); +}; + +SwMailMergeWizardExecutor::SwMailMergeWizardExecutor() + : m_pView( nullptr ), + m_pView2Close( nullptr ), + m_pWizard( nullptr ) +{ +} + +SwMailMergeWizardExecutor::~SwMailMergeWizardExecutor() +{ + OSL_ENSURE( m_pWizard == nullptr, "SwMailMergeWizardExecutor: m_pWizard must be Null!" ); +} + +bool lcl_hasAllComponentsAvailable() +{ + try + { + return css::sdb::TextConnectionSettings::create(comphelper::getProcessComponentContext()).is(); + } + catch (const css::uno::Exception &) + { + TOOLS_INFO_EXCEPTION( + "sw.core", "assuming Base to be missing; caught "); + return false; + } +} + +void SwMailMergeWizardExecutor::ExecuteMailMergeWizard( const SfxItemSet * pArgs ) +{ + if(!lcl_hasAllComponentsAvailable()) + { + if (officecfg::Office::Common::PackageKit::EnableBaseInstallation::get()) + { + try + { + using namespace org::freedesktop::PackageKit; + using namespace svtools; + css::uno::Reference< XSyncDbusSessionHelper > xSyncDbusSessionHelper(SyncDbusSessionHelper::create(comphelper::getProcessComponentContext())); + const css::uno::Sequence< OUString > vPackages{ "libreoffice-base" }; + xSyncDbusSessionHelper->InstallPackageNames(vPackages, OUString()); + SolarMutexGuard aGuard; + executeRestartDialog(comphelper::getProcessComponentContext(), nullptr, RESTART_REASON_MAILMERGE_INSTALL); + } + catch (const css::uno::Exception &) + { + TOOLS_INFO_EXCEPTION( + "sw.core", + "trying to install LibreOffice Base, caught"); + auto xRestartManager + = css::task::OfficeRestartManager::get(comphelper::getProcessComponentContext()); + if (!xRestartManager->isRestartRequested(false)) + { + // Base is absent, and could not initiate its install - ask user to do that manually + // Only show the dialog if restart is not initiated yet + std::unique_ptr<weld::MessageDialog> xWarnBox(Application::CreateMessageDialog( + nullptr, VclMessageType::Info, VclButtonsType::Ok, + SwResId(STR_NO_BASE_FOR_MERGE))); + xWarnBox->run(); + } + } + } else { + auto xRestartManager + = css::task::OfficeRestartManager::get(comphelper::getProcessComponentContext()); + if (!xRestartManager->isRestartRequested(false)) + { + // Base is absent, and could not initiate its install - ask user to do that manually + // Only show the dialog if restart is not initiated yet + std::unique_ptr<weld::MessageDialog> xWarnBox(Application::CreateMessageDialog( + nullptr, VclMessageType::Info, VclButtonsType::Ok, + SwResId(STR_NO_BASE_FOR_MERGE))); + xWarnBox->run(); + } + } + return; + } + if ( m_pView ) + { + OSL_FAIL("SwMailMergeWizardExecutor::ExecuteMailMergeWizard: Already executing the wizard!" ); + return; + } + + m_pView = ::GetActiveView(); + if (!m_pView) + return; + + // keep self alive until done. + acquire(); + + // create if it does not exist yet + std::shared_ptr<SwMailMergeConfigItem> xMMConfig = m_pView->EnsureMailMergeConfigItem(pArgs); + + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + m_pWizard = pFact->CreateMailMergeWizard(*m_pView, xMMConfig); + + ExecuteWizard(); +} + +void SwMailMergeWizardExecutor::ExecutionFinished() +{ + std::shared_ptr<SwMailMergeConfigItem> xMMConfig = m_pView->GetMailMergeConfigItem(); + if (xMMConfig) + xMMConfig->Commit(); + + SwDoc* pDoc = m_pView->GetDocShell()->GetDoc(); + if (pDoc) + { + SwDBManager* pDbManager = pDoc->GetDBManager(); + if (pDbManager) + pDbManager->CommitLastRegistrations(); + + // Show the toolbar + m_pView->ShowUIElement("private:resource/toolbar/mailmerge"); + + // Update Mail Merge controls + const sal_uInt16 slotIds[] = { FN_MAILMERGE_FIRST_ENTRY, + FN_MAILMERGE_PREV_ENTRY, + FN_MAILMERGE_NEXT_ENTRY, + FN_MAILMERGE_LAST_ENTRY, + FN_MAILMERGE_CURRENT_ENTRY, + FN_MAILMERGE_EXCLUDE_ENTRY, + FN_MAILMERGE_CREATE_DOCUMENTS, + FN_MAILMERGE_SAVE_DOCUMENTS, + FN_MAILMERGE_PRINT_DOCUMENTS, + FN_MAILMERGE_EMAIL_DOCUMENTS, + 0 }; + m_pView->GetViewFrame().GetBindings().Invalidate(slotIds); + } + + // release/destroy asynchronously + Application::PostUserEvent( LINK( this, SwMailMergeWizardExecutor, DestroyDialogHdl ) ); +} + +void SwMailMergeWizardExecutor::ExecuteWizard() +{ + m_pWizard->StartExecuteAsync([this](sal_Int32 nResult){ + EndDialogHdl(nResult); + }); +} + +void SwMailMergeWizardExecutor::EndDialogHdl(sal_Int32 nRet) +{ + sal_uInt16 nRestartPage = m_pWizard->GetRestartPage(); + + switch ( nRet ) + { + case RET_LOAD_DOC: + { + SwView* pNewView = lcl_LoadDoc(m_pView, m_pWizard->GetReloadDocument()); + + // Destroy wizard asynchronously, since we are deep inside the wizard and dialog + // machinery code here + m_pWizardToDestroyInCallback = m_pWizard; + Application::PostUserEvent( + LINK( this, SwMailMergeWizardExecutor, DestroyWizardHdl ), nullptr ); + + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + std::shared_ptr<SwMailMergeConfigItem> xMMConfig = m_pView->GetMailMergeConfigItem(); + if (pNewView) + { + pNewView->SetMailMergeConfigItem(xMMConfig); + m_pView = pNewView; + xMMConfig->DocumentReloaded(); + //new source view! + xMMConfig->SetSourceView( m_pView ); + m_pWizard = pFact->CreateMailMergeWizard(*m_pView, xMMConfig); + m_pWizard->ShowPage( nRestartPage ); + } + else + { + m_pWizard = pFact->CreateMailMergeWizard(*m_pView, xMMConfig); + } + + // execute the wizard again + ExecuteWizard(); + break; + } + case RET_TARGET_CREATED: + { + std::shared_ptr<SwMailMergeConfigItem> xMMConfig = m_pView->GetMailMergeConfigItem(); + SwView* pTargetView = xMMConfig->GetTargetView(); + OSL_ENSURE(pTargetView, "No target view has been created"); + if(pTargetView) + { + // destroy wizard asynchronously + m_pWizardToDestroyInCallback = m_pWizard; + Application::PostUserEvent( + LINK( this, SwMailMergeWizardExecutor, DestroyWizardHdl ), nullptr ); + + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + m_pWizard = pFact->CreateMailMergeWizard(*pTargetView, xMMConfig); + m_pWizard->ShowPage( nRestartPage ); + + // execute the wizard again + ExecuteWizard(); + } + else + { + // should not happen - just in case no target view has been created + ExecutionFinished(); + } + break; + } + case RET_REMOVE_TARGET: + { + std::shared_ptr<SwMailMergeConfigItem> xMMConfig = m_pView->GetMailMergeConfigItem(); + SwView* pTargetView = xMMConfig->GetTargetView(); + SwView* pSourceView = xMMConfig->GetSourceView(); + OSL_ENSURE(pTargetView && pSourceView, "source or target view not available" ); + if(pTargetView && pSourceView) + { + m_pView2Close = pTargetView; + pTargetView->GetViewFrame().GetTopViewFrame()->GetWindow().Hide(); + pSourceView->GetViewFrame().GetFrame().AppearWithUpdate(); + // the current view has be set when the target is destroyed + m_pView = pSourceView; + xMMConfig->SetTargetView(nullptr); + + // destroy wizard asynchronously + m_pWizardToDestroyInCallback = m_pWizard; + Application::PostUserEvent( + LINK( this, SwMailMergeWizardExecutor, CloseFrameHdl ), m_pWizard ); + + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + m_pWizard = pFact->CreateMailMergeWizard(*pSourceView, xMMConfig); + m_pWizard->ShowPage( nRestartPage ); + + // execute the wizard again + ExecuteWizard(); + } + else + { + // should not happen - just in case no target view has been created + ExecutionFinished(); + } + break; + } + case RET_CANCEL: + { + // close frame and destroy wizard asynchronously + Application::PostUserEvent( + LINK( this, SwMailMergeWizardExecutor, CancelHdl ), m_pWizard ); + break; + } + default: // finish + { + std::shared_ptr<SwMailMergeConfigItem> xMMConfig = m_pView->GetMailMergeConfigItem(); + SwView* pSourceView = xMMConfig ? xMMConfig->GetSourceView() : nullptr; + if(pSourceView) + { + xMMConfig->GetSourceView()->GetViewFrame().GetFrame().Appear(); + } + ExecutionFinished(); + break; + } + + } // switch +} + +IMPL_LINK_NOARG(SwMailMergeWizardExecutor, DestroyDialogHdl, void*, void) +{ + m_pWizard.disposeAndClear(); + + release(); +} + +IMPL_LINK_NOARG(SwMailMergeWizardExecutor, DestroyWizardHdl, void*, void) +{ + m_pWizardToDestroyInCallback.disposeAndClear(); +} + +IMPL_LINK_NOARG(SwMailMergeWizardExecutor, CancelHdl, void*, void) +{ + std::shared_ptr<SwMailMergeConfigItem> xMMConfig = m_pView->GetMailMergeConfigItem(); + if (xMMConfig) + { + if (xMMConfig->GetTargetView()) + { + xMMConfig->GetTargetView()->GetViewFrame().DoClose(); + xMMConfig->SetTargetView(nullptr); + } + if (xMMConfig->GetSourceView()) + { + auto& rViewFrame(xMMConfig->GetSourceView()->GetViewFrame()); + rViewFrame.GetFrame().AppearWithUpdate(); + } + xMMConfig->Commit(); + } + + // Revoke created connections + SwDoc* pDoc = m_pView->GetDocShell()->GetDoc(); + SwDBManager* pDbManager = pDoc->GetDBManager(); + if (pDbManager) + pDbManager->RevokeLastRegistrations(); + + m_pWizard.disposeAndClear(); + release(); +} + +IMPL_LINK_NOARG(SwMailMergeWizardExecutor, CloseFrameHdl, void*, void) +{ + if ( m_pView2Close ) + { + m_pView2Close->GetViewFrame().DoClose(); + m_pView2Close = nullptr; + } + m_pWizardToDestroyInCallback.disposeAndClear(); +} +} // namespace + +#endif // HAVE_FEATURE_DBCONNECTIVITY + +void SwModule::ExecOther(SfxRequest& rReq) +{ + const SfxItemSet *pArgs = rReq.GetArgs(); + const SfxPoolItem* pItem = nullptr; + + sal_uInt16 nWhich = rReq.GetSlot(); + switch (nWhich) + { + case FN_ENVELOP: + InsertEnv( rReq ); + break; + + case FN_BUSINESS_CARD: + case FN_LABEL: + InsertLab(rReq, nWhich == FN_LABEL); + break; + + case FN_XFORMS_INIT: + NewXForms( rReq ); + break; + + case SID_ATTR_METRIC: + if(pArgs && SfxItemState::SET == pArgs->GetItemState(nWhich, false, &pItem)) + { + FieldUnit eUnit = static_cast<FieldUnit>(static_cast<const SfxUInt16Item*>(pItem)->GetValue()); + switch( eUnit ) + { + case FieldUnit::MM: + case FieldUnit::CM: + case FieldUnit::INCH: + case FieldUnit::PICA: + case FieldUnit::POINT: + { + SwView* pActView = ::GetActiveView(); + bool bWebView = dynamic_cast<SwWebView*>( pActView ) != nullptr; + ::SetDfltMetric(eUnit, bWebView); + } + break; + default:;//prevent warning + } + } + break; + + case FN_SET_MODOPT_TBLNUMFMT: + { + bool bWebView = dynamic_cast<SwWebView*>( ::GetActiveView() )!= nullptr , + bSet; + + if( pArgs && SfxItemState::SET == pArgs->GetItemState( + nWhich, false, &pItem )) + bSet = static_cast<const SfxBoolItem*>(pItem)->GetValue(); + else + bSet = !m_pModuleConfig->IsInsTableFormatNum( bWebView ); + + m_pModuleConfig->SetInsTableFormatNum( bWebView, bSet ); + } + break; +#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS + case FN_MAILMERGE_WIZARD: + { + // show the mailmerge wizard + rtl::Reference< SwMailMergeWizardExecutor > xEx( new SwMailMergeWizardExecutor ); + xEx->ExecuteMailMergeWizard( pArgs ); + } + break; + case FN_MAILMERGE_FIRST_ENTRY: + case FN_MAILMERGE_PREV_ENTRY: + case FN_MAILMERGE_NEXT_ENTRY: + case FN_MAILMERGE_LAST_ENTRY: + case FN_MAILMERGE_CURRENT_ENTRY: + { + SwView* pView = ::GetActiveView(); + if (!pView) + return; + + const std::shared_ptr<SwMailMergeConfigItem>& xConfigItem = pView->GetMailMergeConfigItem(); + if (!xConfigItem) + return; + + const bool bHadConnection + = xConfigItem->GetConnection().is() && !xConfigItem->GetConnection()->isClosed(); + + sal_Int32 nPos = xConfigItem->GetResultSetPosition(); + switch (nWhich) + { + case FN_MAILMERGE_FIRST_ENTRY: xConfigItem->MoveResultSet(1); break; + case FN_MAILMERGE_PREV_ENTRY: xConfigItem->MoveResultSet(nPos - 1); break; + case FN_MAILMERGE_NEXT_ENTRY: xConfigItem->MoveResultSet(nPos + 1); break; + case FN_MAILMERGE_LAST_ENTRY: xConfigItem->MoveResultSet(-1); break; + case FN_MAILMERGE_CURRENT_ENTRY: /* don't move the result set, just update the document */ break; + default: break; + } + + // now the record has to be merged into the source document + // TODO can we re-use PerformMailMerge() here somehow? + const SwDBData& rDBData = xConfigItem->GetCurrentDBData(); + uno::Sequence<uno::Any> vSelection({ uno::Any(xConfigItem->GetResultSetPosition()) }); + svx::ODataAccessDescriptor aDescriptor(::comphelper::InitPropertySequence({ + {"Selection", uno::Any(vSelection)}, + {"DataSourceName", uno::Any(rDBData.sDataSource)}, + {"Command", uno::Any(rDBData.sCommand)}, + {"CommandType", uno::Any(rDBData.nCommandType)}, + {"ActiveConnection", uno::Any(xConfigItem->GetConnection().getTyped())}, + {"Filter", uno::Any(xConfigItem->GetFilter())}, + {"Cursor", uno::Any(xConfigItem->GetResultSet())} + })); + + SwWrtShell& rSh = pView->GetWrtShell(); + SwMergeDescriptor aMergeDesc(DBMGR_MERGE, rSh, aDescriptor); + rSh.GetDBManager()->Merge(aMergeDesc); + + // update enabled / disabled status of the buttons in the toolbar + SfxBindings& rBindings = rSh.GetView().GetViewFrame().GetBindings(); + rBindings.Invalidate(FN_MAILMERGE_FIRST_ENTRY); + rBindings.Invalidate(FN_MAILMERGE_PREV_ENTRY); + rBindings.Invalidate(FN_MAILMERGE_NEXT_ENTRY); + rBindings.Invalidate(FN_MAILMERGE_LAST_ENTRY); + rBindings.Invalidate(FN_MAILMERGE_CURRENT_ENTRY); + rBindings.Invalidate(FN_MAILMERGE_EXCLUDE_ENTRY); + if (!bHadConnection && xConfigItem->GetConnection().is() + && !xConfigItem->GetConnection()->isClosed()) + { + // The connection has been activated. Update controls that were disabled + rBindings.Invalidate(FN_MAILMERGE_CREATE_DOCUMENTS); + rBindings.Invalidate(FN_MAILMERGE_SAVE_DOCUMENTS); + rBindings.Invalidate(FN_MAILMERGE_PRINT_DOCUMENTS); + rBindings.Invalidate(FN_MAILMERGE_EMAIL_DOCUMENTS); + } + rBindings.Update(); + } + break; + case FN_MAILMERGE_CREATE_DOCUMENTS: + case FN_MAILMERGE_SAVE_DOCUMENTS: + case FN_MAILMERGE_PRINT_DOCUMENTS: + case FN_MAILMERGE_EMAIL_DOCUMENTS: + { + SwView* pView = ::GetActiveView(); + if (!pView) + return; + + std::shared_ptr<SwMailMergeConfigItem> xConfigItem = pView->GetMailMergeConfigItem(); + assert(xConfigItem); + if (!xConfigItem->GetResultSet().is()) + { + // The connection has been attempted, but failed or no results found, + // so invalidate the toolbar buttons in case they need to be disabled. + SfxBindings& rBindings + = pView->GetWrtShell().GetView().GetViewFrame().GetBindings(); + rBindings.Invalidate(FN_MAILMERGE_CREATE_DOCUMENTS); + rBindings.Invalidate(FN_MAILMERGE_SAVE_DOCUMENTS); + rBindings.Invalidate(FN_MAILMERGE_PRINT_DOCUMENTS); + rBindings.Invalidate(FN_MAILMERGE_EMAIL_DOCUMENTS); + rBindings.Invalidate(FN_MAILMERGE_FIRST_ENTRY); + rBindings.Invalidate(FN_MAILMERGE_PREV_ENTRY); + rBindings.Invalidate(FN_MAILMERGE_NEXT_ENTRY); + rBindings.Invalidate(FN_MAILMERGE_LAST_ENTRY); + rBindings.Update(); + return; + } + + if (nWhich == FN_MAILMERGE_CREATE_DOCUMENTS) + { + xConfigItem = SwDBManager::PerformMailMerge(pView); + + if (xConfigItem && xConfigItem->GetTargetView()) + xConfigItem->GetTargetView()->GetViewFrame().GetFrame().Appear(); + } + else + { + xConfigItem->SetTargetView(nullptr); + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + if (nWhich == FN_MAILMERGE_SAVE_DOCUMENTS) + pFact->ExecuteMMResultSaveDialog(rReq.GetFrameWeld()); + else if (nWhich == FN_MAILMERGE_PRINT_DOCUMENTS) + pFact->ExecuteMMResultPrintDialog(rReq.GetFrameWeld()); + else if (nWhich == FN_MAILMERGE_EMAIL_DOCUMENTS) + pFact->ExecuteMMResultEmailDialog(rReq.GetFrameWeld()); + } + } + break; +#endif + } +} + +// Catch notifications + +// Catch hint for DocInfo +void SwModule::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint ) +{ + if (rHint.GetId() == SfxHintId::ThisIsAnSfxEventHint) + { + const SfxEventHint& rEvHint = static_cast<const SfxEventHint&>(rHint); + SwDocShell* pDocSh = dynamic_cast<SwDocShell*>(rEvHint.GetObjShell()); + if( pDocSh ) + { + SwWrtShell* pWrtSh = pDocSh->GetWrtShell(); + switch (rEvHint.GetEventId()) + { + case SfxEventHintId::LoadFinished: + // if it is a new document created from a template, + // update fixed fields + if (pDocSh->GetMedium()) + { + const SfxBoolItem* pTemplateItem = pDocSh->GetMedium()->GetItemSet().GetItem(SID_TEMPLATE, false); + if (pTemplateItem && pTemplateItem->GetValue()) + { + // assume that not calling via SwEditShell::SetFixFields + // is allowed, because the shell hasn't been created yet + assert(!pWrtSh || pWrtSh->GetView().GetViewFrame().GetFrame().IsClosing_Impl()); + pDocSh->GetDoc()->getIDocumentFieldsAccess().SetFixFields(nullptr); + } + } + break; + case SfxEventHintId::CreateDoc: + // Update all FIX-Date/Time fields + if( pWrtSh ) + { + const SfxUInt16Item* pUpdateDocItem = pDocSh->GetMedium()->GetItemSet().GetItem(SID_UPDATEDOCMODE, false); + bool bUpdateFields = true; + if( pUpdateDocItem && pUpdateDocItem->GetValue() == document::UpdateDocMode::NO_UPDATE) + bUpdateFields = false; + if(bUpdateFields) + { + comphelper::dispatchCommand(".uno:UpdateInputFields", {}); + + // Are database fields contained? + // Get all used databases for the first time + SwDoc *pDoc = pDocSh->GetDoc(); + std::vector<OUString> aDBNameList; + pDoc->GetAllUsedDB( aDBNameList ); + if(!aDBNameList.empty()) + { // Open database beamer + ShowDBObj(pWrtSh->GetView(), pDoc->GetDBData()); + } + } + } + break; + default: break; + } + } + } + else + { + if (rHint.GetId() == SfxHintId::Deinitializing) + { + m_pWebUsrPref.reset(); + m_pUsrPref.reset(); + m_pModuleConfig.reset(); + m_pPrintOptions.reset(); + m_pWebPrintOptions.reset(); + m_pChapterNumRules.reset(); + m_pStdFontConfig.reset(); + m_pNavigationConfig.reset(); + m_pToolbarConfig.reset(); + m_pWebToolbarConfig.reset(); + m_pDBConfig.reset(); + if( m_pColorConfig ) + { + m_pColorConfig->RemoveListener(this); + m_pColorConfig.reset(); + } + if( m_pAccessibilityOptions ) + { + m_pAccessibilityOptions->RemoveListener(this); + m_pAccessibilityOptions.reset(); + } + if( m_pCTLOptions ) + { + m_pCTLOptions->RemoveListener(this); + m_pCTLOptions.reset(); + } + if( m_pUserOptions ) + { + m_pUserOptions->RemoveListener(this); + m_pUserOptions.reset(); + } + } + } +} + +void SwModule::ConfigurationChanged(utl::ConfigurationBroadcaster* pBrdCst, ConfigurationHints eHints) +{ + if( pBrdCst == m_pUserOptions.get() ) + { + m_bAuthorInitialised = false; + } + else if ( pBrdCst == m_pColorConfig.get() ) + { + //invalidate only the current view in tiled rendering mode, or all views otherwise + const bool bKit = comphelper::LibreOfficeKit::isActive(); + SfxViewShell* pViewShell = bKit ? SfxViewShell::Current() : SfxViewShell::GetFirst(); + while(pViewShell) + { + if(pViewShell->GetWindow()) + { + auto pSwView = dynamic_cast<SwView *>(pViewShell); + if (pSwView) + { + SwViewOption aNewOptions = *pSwView->GetWrtShell().GetViewOptions(); + aNewOptions.SetThemeName(svtools::ColorConfig::GetCurrentSchemeName()); + SwViewColors aViewColors(*m_pColorConfig); + aNewOptions.SetColorConfig(aViewColors); + const bool bChanged(aNewOptions != *pSwView->GetWrtShell().GetViewOptions()); + if (bChanged) + pSwView->GetWrtShell().ApplyViewOptions(aNewOptions); + else if (bKit) + { + SwXTextDocument* pModel = comphelper::getFromUnoTunnel<SwXTextDocument>(pViewShell->GetCurrentDocument()); + SfxLokHelper::notifyViewRenderState(pViewShell, pModel); + } + + if (bKit) + { + pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_APPLICATION_BACKGROUND_COLOR, + aViewColors.m_aAppBackgroundColor.AsRGBHexString().toUtf8()); + pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_DOCUMENT_BACKGROUND_COLOR, + aViewColors.m_aAppBackgroundColor.AsRGBHexString().toUtf8()); + } + + // if nothing changed, and the hint was OnlyCurrentDocumentColorScheme we can skip invalidate + const bool bSkipInvalidate = !bChanged && bKit && eHints == ConfigurationHints::OnlyCurrentDocumentColorScheme; + if (!bSkipInvalidate) + pViewShell->GetWindow()->Invalidate(); + } + else if (dynamic_cast< const SwPagePreview *>( pViewShell ) != nullptr || + dynamic_cast< const SwSrcView *>( pViewShell ) != nullptr) + { + pViewShell->GetWindow()->Invalidate(); + } + } + if (bKit) + break; + pViewShell = SfxViewShell::GetNext( *pViewShell ); + } + } +#if !ENABLE_WASM_STRIP_ACCESSIBILITY + else if ( pBrdCst == m_pAccessibilityOptions.get() ) + { + //set Accessibility options + SfxViewShell* pViewShell = SfxViewShell::GetFirst(); + while(pViewShell) + { + if(pViewShell->GetWindow()) + { + auto pSwView = dynamic_cast<SwView *>( pViewShell ); + auto pPagePreview = dynamic_cast<SwPagePreview *>( pViewShell ); + + if(pSwView) + pSwView->ApplyAccessibilityOptions(); + else if(pPagePreview) + pPagePreview->ApplyAccessibilityOptions(); + + if(pSwView || pPagePreview || dynamic_cast< const SwSrcView *>( pViewShell ) != nullptr) + { + pViewShell->GetWindow()->Invalidate(); + } + } + pViewShell = SfxViewShell::GetNext( *pViewShell ); + } + } +#endif + else if( pBrdCst == m_pCTLOptions.get() ) + { + const SfxObjectShell* pObjSh = SfxObjectShell::GetFirst(); + while( pObjSh ) + { + if( auto pDocShell = dynamic_cast<const SwDocShell*>(pObjSh) ) + { + SwDoc* pDoc = const_cast<SwDocShell*>(pDocShell)->GetDoc(); + SwViewShell* pVSh = pDoc->getIDocumentLayoutAccess().GetCurrentViewShell(); + if ( pVSh ) + pVSh->ChgNumberDigits(); + } + pObjSh = SfxObjectShell::GetNext(*pObjSh); + } + } + +} + +SwDBConfig* SwModule::GetDBConfig() +{ + if(!m_pDBConfig) + m_pDBConfig.reset(new SwDBConfig); + return m_pDBConfig.get(); +} + +svtools::ColorConfig& SwModule::GetColorConfig() +{ + if(!m_pColorConfig) + { + m_pColorConfig.reset(new svtools::ColorConfig); + SwViewOption::SetInitialColorConfig(*m_pColorConfig); + m_pColorConfig->AddListener(this); + } + return *m_pColorConfig; +} + +SvtUserOptions& SwModule::GetUserOptions() +{ + if(!m_pUserOptions) + { + m_pUserOptions.reset(new SvtUserOptions); + m_pUserOptions->AddListener(this); + } + return *m_pUserOptions; +} + +const SwMasterUsrPref *SwModule::GetUsrPref(bool bWeb) const +{ + SwModule* pNonConstModule = const_cast<SwModule*>(this); + if(bWeb && !m_pWebUsrPref) + { + // The SpellChecker is needed in SwMasterUsrPref's Load, but it must not + // be created there #58256# + pNonConstModule->m_pWebUsrPref.reset(new SwMasterUsrPref(true)); + } + else if(!bWeb && !m_pUsrPref) + { + pNonConstModule->m_pUsrPref.reset(new SwMasterUsrPref(false)); + } + return bWeb ? m_pWebUsrPref.get() : m_pUsrPref.get(); +} + +void NewXForms( SfxRequest& rReq ) +{ + // copied & excerpted from SwModule::InsertLab(..) + + // create new document + SwDocShellRef xDocSh( new SwDocShell( SfxObjectCreateMode::STANDARD) ); + xDocSh->DoInitNew(); + + // initialize XForms + xDocSh->GetDoc()->initXForms(true); + + // load document into frame + SfxViewFrame::DisplayNewDocument( *xDocSh, rReq ); + + // set return value + rReq.SetReturnValue( SfxVoidItem( rReq.GetSlot() ) ); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/app/applab.cxx b/sw/source/uibase/app/applab.cxx new file mode 100644 index 0000000000..f440fefe86 --- /dev/null +++ b/sw/source/uibase/app/applab.cxx @@ -0,0 +1,397 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <config_features.h> +#include <config_fuzzers.h> + +#include <hintids.hxx> + +#include <comphelper/string.hxx> +#include <svl/voiditem.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/printer.hxx> +#include <sfx2/request.hxx> +#include <sfx2/linkmgr.hxx> +#include <sfx2/viewfrm.hxx> +#include <editeng/pbinitem.hxx> +#include <editeng/ulspitem.hxx> +#include <editeng/lrspitem.hxx> +#include <com/sun/star/frame/XModel.hpp> +#include <osl/diagnose.h> +#include <fmthdft.hxx> +#include <fmtanchr.hxx> +#include <fmtfsize.hxx> +#include <fmtornt.hxx> +#include <swwait.hxx> +#include <gloshdl.hxx> +#include <swmodule.hxx> +#include <view.hxx> +#include <docsh.hxx> +#include <fldbas.hxx> +#include <wrtsh.hxx> +#include <cmdid.h> +#include <dbmgr.hxx> +#include <fldmgr.hxx> +#include <labimg.hxx> +#include <section.hxx> +#include <pagedesc.hxx> +#include <poolfmt.hxx> + +#include <strings.hrc> +#include <swabstdlg.hxx> + +#include <IDocumentDeviceAccess.hxx> + +#include "appenv.hxx" +#include <memory> + +using namespace ::com::sun::star; + +constexpr OUString MASTER_LABEL = u"MasterLabel"_ustr; + +static const SwFrameFormat *lcl_InsertBCText( SwWrtShell& rSh, const SwLabItem& rItem, + SwFrameFormat &rFormat, + sal_uInt16 nCol, sal_uInt16 nRow ) +{ + SfxItemSetFixed<RES_VERT_ORIENT, RES_ANCHOR> aSet( rSh.GetAttrPool() ); + sal_uInt16 nPhyPageNum, nVirtPageNum; + rSh.GetPageNum( nPhyPageNum, nVirtPageNum ); + + //anchor frame to page + aSet.Put( SwFormatAnchor( RndStdIds::FLY_AT_PAGE, nPhyPageNum ) ); + aSet.Put( SwFormatHoriOrient( rItem.m_lLeft + static_cast<SwTwips>(nCol) * rItem.m_lHDist, + text::HoriOrientation::NONE, text::RelOrientation::PAGE_FRAME ) ); + aSet.Put( SwFormatVertOrient( rItem.m_lUpper + static_cast<SwTwips>(nRow) * rItem.m_lVDist, + text::VertOrientation::NONE, text::RelOrientation::PAGE_FRAME ) ); + const SwFrameFormat *pFormat = rSh.NewFlyFrame(aSet, true, &rFormat ); // Insert Fly + OSL_ENSURE( pFormat, "Fly not inserted" ); + + rSh.UnSelectFrame(); //Frame was selected automatically + + rSh.SetTextFormatColl( rSh.GetTextCollFromPool( RES_POOLCOLL_STANDARD ) ); + + if(!rItem.m_bSynchron || !(nCol|nRow)) + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ::GlossarySetActGroup fnSetActGroup = pFact->SetGlossaryActGroupFunc(); + if ( fnSetActGroup ) + (*fnSetActGroup)( rItem.m_sGlossaryGroup ); + SwGlossaryHdl* pGlosHdl = rSh.GetView().GetGlosHdl(); + pGlosHdl->SetCurGroup(rItem.m_sGlossaryGroup, true); + pGlosHdl->InsertGlossary( rItem.m_sGlossaryBlockName ); + } + + return pFormat; +} + +static const SwFrameFormat *lcl_InsertLabText( SwWrtShell& rSh, const SwLabItem& rItem, + SwFrameFormat &rFormat, SwFieldMgr& rFieldMgr, + sal_uInt16 nCol, sal_uInt16 nRow, bool bLast ) +{ + SfxItemSetFixed<RES_VERT_ORIENT, RES_ANCHOR> aSet( rSh.GetAttrPool() ); + sal_uInt16 nPhyPageNum, nVirtPageNum; + rSh.GetPageNum( nPhyPageNum, nVirtPageNum ); + + //anchor frame to page + aSet.Put( SwFormatAnchor( RndStdIds::FLY_AT_PAGE, nPhyPageNum ) ); + aSet.Put( SwFormatHoriOrient( rItem.m_lLeft + static_cast<SwTwips>(nCol) * rItem.m_lHDist, + text::HoriOrientation::NONE, text::RelOrientation::PAGE_FRAME ) ); + aSet.Put( SwFormatVertOrient( rItem.m_lUpper + static_cast<SwTwips>(nRow) * rItem.m_lVDist, + text::VertOrientation::NONE, text::RelOrientation::PAGE_FRAME ) ); + const SwFrameFormat *pFormat = rSh.NewFlyFrame(aSet, true, &rFormat ); // Insert Fly + OSL_ENSURE( pFormat, "Fly not inserted" ); + + rSh.UnSelectFrame(); //Frame was selected automatically + + rSh.SetTextFormatColl( rSh.GetTextCollFromPool( RES_POOLCOLL_STANDARD ) ); + + // If applicable "next dataset" + OUString sDBName; + if( (!rItem.m_bSynchron || !(nCol|nRow)) && !(sDBName = InsertLabEnvText( rSh, rFieldMgr, rItem.m_aWriting )).isEmpty() && !bLast ) + { + sDBName = comphelper::string::setToken(sDBName, 3, DB_DELIM, u"True"); + SwInsertField_Data aData(SwFieldTypesEnum::DatabaseNextSet, 0, sDBName, OUString(), 0, &rSh); + rFieldMgr.InsertField( aData ); + } + + return pFormat; +} + +void SwModule::InsertLab(SfxRequest& rReq, bool bLabel) +{ + static sal_uInt16 nLabelTitleNo = 0; + static sal_uInt16 nBCTitleNo = 0; + +#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS + // Create DB-Manager + std::unique_ptr<SwDBManager> pDBManager(new SwDBManager(nullptr)); +#endif + + // Read SwLabItem from Config + SwLabCfgItem aLabCfg(bLabel); + + // Move up Dialog + SfxItemSetFixed<FN_LABEL, FN_LABEL> aSet( GetPool() ); + aSet.Put( aLabCfg.GetItem() ); + + SwAbstractDialogFactory* pDialogFactory = SwAbstractDialogFactory::Create(); + + ScopedVclPtr<AbstractSwLabDlg> pDlg(pDialogFactory->CreateSwLabDlg(rReq.GetFrameWeld(), aSet, +#if HAVE_FEATURE_DBCONNECTIVITY && !ENABLE_FUZZERS + pDBManager.get(), +#else + NULL, +#endif + bLabel)); + + if ( RET_OK != pDlg->Execute() ) + return; + + // Read dialog, store item in config + const SwLabItem& rItem = static_cast<const SwLabItem&>( pDlg-> + GetOutputItemSet()->Get(FN_LABEL)); + aLabCfg.GetItem() = rItem; + aLabCfg.Commit(); + + // Create new document + SfxObjectShellLock xDocSh( new SwDocShell( SfxObjectCreateMode::STANDARD)); + xDocSh->DoInitNew(); + + // Printer + Printer *pPrt = pDlg->GetPrt(); + if (pPrt) + { + SwDocShell *pDocSh = static_cast<SwDocShell*>(&*xDocSh); + pDocSh->getIDocumentDeviceAccess().setJobsetup(pPrt->GetJobSetup()); + } + + SfxViewFrame* pViewFrame = SfxViewFrame::DisplayNewDocument( *xDocSh, rReq ); + if (!pViewFrame) + return; + + SwView *pNewView = static_cast<SwView*>( pViewFrame->GetViewShell()); + pNewView->AttrChangedNotify(nullptr);// So that SelectShell is being called. + + // Set document title + OUString aTmp; + if(bLabel) + { + aTmp = SwResId( STR_LAB_TITLE) + + OUString::number(++nLabelTitleNo ); + } + else + { + aTmp = pDlg->GetBusinessCardStr() + + OUString::number( ++nBCTitleNo ); + } + xDocSh->SetTitle( aTmp ); + + pViewFrame->GetFrame().Appear(); + + // Determine Shell + SwWrtShell *pSh = pNewView->GetWrtShellPtr(); + OSL_ENSURE( pSh, "missing WrtShell" ); + + if (pSh) + { // block for locks the dispatcher!! + + SwWait aWait( static_cast<SwDocShell&>(*xDocSh), true ); + + CurrShell aCurr(pSh); + pSh->SetLabelDoc(rItem.m_bSynchron); + pSh->DoUndo( false ); + pSh->StartAllAction(); + + pSh->SetNewDoc(); // Avoid performance problems + + SwPageDesc aDesc = pSh->GetPageDesc( 0 ); + SwFrameFormat& rFormat = aDesc.GetMaster(); + + // Borders + SvxLRSpaceItem aLRMargin( RES_LR_SPACE ); + SvxULSpaceItem aULMargin( RES_UL_SPACE ); + aLRMargin.SetLeft (o3tl::narrowing<sal_uInt16>(rItem.m_lLeft) ); + aULMargin.SetUpper(o3tl::narrowing<sal_uInt16>(rItem.m_lUpper)); + aLRMargin.SetRight( 0 ); + aULMargin.SetLower( 0 ); + rFormat.SetFormatAttr(aLRMargin); + rFormat.SetFormatAttr(aULMargin); + + // Header and footer + rFormat.SetFormatAttr(SwFormatHeader(false)); + aDesc.ChgHeaderShare(false); + rFormat.SetFormatAttr(SwFormatFooter(false)); + aDesc.ChgFooterShare(false); + + aDesc.SetUseOn(UseOnPage::All); // Site numbering + + // Set page size + tools::Long lPgWidth, lPgHeight; + lPgWidth = std::max<sal_Int32>(rItem.m_lPWidth, MINLAY); + lPgHeight = std::max<sal_Int32>(rItem.m_lPHeight, MINLAY); + rFormat.SetFormatAttr( SwFormatFrameSize( SwFrameSize::Fixed, lPgWidth, lPgHeight )); + // Numbering type + SvxNumberType aType; + aType.SetNumberingType(SVX_NUM_NUMBER_NONE); + aDesc.SetNumType( aType ); + + // Followup template + const SwPageDesc &rFollow = pSh->GetPageDesc( pSh->GetCurPageDesc() ); + aDesc.SetFollow( &rFollow ); + + pPrt = pSh->getIDocumentDeviceAccess().getPrinter( true ); + SvxPaperBinItem aItem( RES_PAPER_BIN ); + aItem.SetValue(static_cast<sal_Int8>(pPrt->GetPaperBin())); + rFormat.SetFormatAttr(aItem); + + // Determine orientation of the resulting page + aDesc.SetLandscape(rItem.m_lPWidth > rItem.m_lPHeight); + + pSh->ChgPageDesc( 0, aDesc ); + + // Insert frame + std::optional<SwFieldMgr> pFieldMgr; + pFieldMgr.emplace(); + pFieldMgr->SetEvalExpFields(false); + + // Prepare border template + SwFrameFormat* pFormat = pSh->GetFrameFormatFromPool( RES_POOLFRM_LABEL ); + sal_Int32 iResultWidth = rItem.m_lLeft + (rItem.m_nCols - 1) * rItem.m_lHDist + rItem.m_lWidth - rItem.m_lPWidth; + sal_Int32 iResultHeight = rItem.m_lUpper + (rItem.m_nRows - 1) * rItem.m_lVDist + rItem.m_lHeight - rItem.m_lPHeight; + sal_Int32 iWidth = (iResultWidth > 0 ? rItem.m_lWidth - (iResultWidth / rItem.m_nCols) - 1 : rItem.m_lWidth); + sal_Int32 iHeight = (iResultHeight > 0 ? rItem.m_lHeight - (iResultHeight / rItem.m_nRows) - 1 : rItem.m_lHeight); + SwFormatFrameSize aFrameSize( SwFrameSize::Fixed, iWidth, iHeight ); + pFormat->SetFormatAttr( aFrameSize ); + + //frame represents label itself, no border space + SvxULSpaceItem aFrameNoULSpace( 0, 0, RES_UL_SPACE ); + SvxLRSpaceItem aFrameNoLRSpace( 0, 0, 0, RES_LR_SPACE ); + pFormat->SetFormatAttr( aFrameNoULSpace ); + pFormat->SetFormatAttr( aFrameNoLRSpace ); + + const SwFrameFormat *pFirstFlyFormat = nullptr; + if ( rItem.m_bPage ) + { + SwFormatVertOrient aFrameVertOrient( pFormat->GetVertOrient() ); + aFrameVertOrient.SetVertOrient( text::VertOrientation::TOP ); + pFormat->SetFormatAttr(aFrameVertOrient); + + for ( sal_Int32 i = 0; i < rItem.m_nRows; ++i ) + { + for ( sal_Int32 j = 0; j < rItem.m_nCols; ++j ) + { + pSh->Push(); + const SwFrameFormat *pTmp = ( bLabel ? + lcl_InsertLabText( *pSh, rItem, *pFormat, *pFieldMgr, j, i, + i == rItem.m_nRows - 1 && j == rItem.m_nCols - 1 ) : + lcl_InsertBCText( *pSh, rItem, *pFormat, j, i ) ); + if (!(i|j)) + { + pFirstFlyFormat = pTmp; + + if (rItem.m_bSynchron) + { + // if there is no content in the fly then + // don't leave the fly!!! + pSh->Push(); + pSh->StartOfSection(); + bool bInFly = nullptr != pSh->WizardGetFly(); + pSh->Pop(bInFly ? SwCursorShell::PopMode::DeleteStack : SwCursorShell::PopMode::DeleteCurrent); + + if( bInFly ) + pSh->EndOfSection(true); // select all content + // in the fly + else + pSh->SetMark(); // set only the mark + + SwSectionData aSect(SectionType::Content, MASTER_LABEL); + pSh->InsertSection(aSect); + } + } + else if (rItem.m_bSynchron) + { + SwSectionData aSect(SectionType::FileLink, + pSh->GetUniqueSectionName()); + OUString sLinkName = + OUStringChar(sfx2::cTokenSeparator) + + OUStringChar(sfx2::cTokenSeparator) + + MASTER_LABEL; + aSect.SetLinkFileName(sLinkName); + aSect.SetProtectFlag(true); + pSh->Insert("."); // Dummytext to allocate the Section + pSh->StartOfSection(); + pSh->EndOfSection(true); // Select everything in the frame + pSh->InsertSection(aSect); + } + pSh->Pop(SwCursorShell::PopMode::DeleteCurrent); + } + } + } + else + { + pFirstFlyFormat = bLabel ? + lcl_InsertLabText( *pSh, rItem, *pFormat, *pFieldMgr, + static_cast< sal_uInt16 >(rItem.m_nCol - 1), + static_cast< sal_uInt16 >(rItem.m_nRow - 1), true ) : + lcl_InsertBCText(*pSh, rItem, *pFormat, + static_cast< sal_uInt16 >(rItem.m_nCol - 1), + static_cast< sal_uInt16 >(rItem.m_nRow - 1)); + } + + //fill the user fields + if(!bLabel) + { + uno::Reference< frame::XModel > xModel = pSh->GetView().GetDocShell()->GetBaseModel(); + OSL_ENSURE(pDialogFactory, "SwAbstractDialogFactory fail!"); + SwLabDlgMethod SwLabDlgUpdateFieldInformation = pDialogFactory->GetSwLabDlgStaticMethod (); + SwLabDlgUpdateFieldInformation(xModel, rItem); + } + + pFieldMgr->SetEvalExpFields(true); + pFieldMgr->EvalExpFields(pSh); + + pFieldMgr.reset(); + + if (pFirstFlyFormat) + pSh->GotoFly(pFirstFlyFormat->GetName(), FLYCNTTYPE_ALL, false); + + if (pSh->IsAnyDatabaseFieldInDoc()) + pSh->GetView().ShowUIElement("private:resource/toolbar/mailmerge"); + + pSh->EndAllAction(); + pSh->DoUndo(); + } + + if (pSh && rItem.m_aWriting.indexOf('<') >= 0) + { + // Open database browser on recently used database + ShowDBObj( *pNewView, pSh->GetDBData() ); + } + + if( rItem.m_bSynchron ) + { + SfxDispatcher* pDisp = pViewFrame->GetDispatcher(); + assert(pDisp && "No dispatcher in frame?"); + pDisp->Execute(FN_SYNC_LABELS, SfxCallMode::ASYNCHRON); + } + rReq.SetReturnValue(SfxVoidItem(bLabel ? FN_LABEL : FN_BUSINESS_CARD)); + +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/app/appopt.cxx b/sw/source/uibase/app/appopt.cxx new file mode 100644 index 0000000000..7be59a1dab --- /dev/null +++ b/sw/source/uibase/app/appopt.cxx @@ -0,0 +1,527 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <memory> +#include <cmdid.h> + +#include <com/sun/star/i18n/ScriptType.hpp> + +#include <sal/log.hxx> +#include <hintids.hxx> +#include <svl/eitem.hxx> +#include <sfx2/app.hxx> +#include <sfx2/printer.hxx> +#include <sfx2/htmlmode.hxx> +#include <sfx2/bindings.hxx> +#include <editeng/brushitem.hxx> +#include <editeng/tstpitem.hxx> +#include <svx/optgrid.hxx> +#include <svx/dialogs.hrc> +#include <tools/UnitConversion.hxx> +#include <i18nlangtag/mslangid.hxx> +#include <i18nlangtag/languagetag.hxx> +#include <fontcfg.hxx> +#include <swmodule.hxx> +#include <view.hxx> +#include <doc.hxx> +#include <wrtsh.hxx> +#include <IDocumentDeviceAccess.hxx> +#include <IDocumentSettingAccess.hxx> +#include <uitool.hxx> +#include <wview.hxx> +#include <cfgitems.hxx> +#include <prtopt.hxx> +#include <pview.hxx> +#include <usrpref.hxx> +#include <uiitems.hxx> +#include <editeng/langitem.hxx> +#include <unotools/lingucfg.hxx> +#include <globals.hrc> +#include <swabstdlg.hxx> +#include <swwrtshitem.hxx> + +#include <sfx2/dispatch.hxx> + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; + +std::optional<SfxItemSet> SwModule::CreateItemSet( sal_uInt16 nId ) +{ + bool bTextDialog = (nId == SID_SW_EDITOPTIONS); + + // the options for the Web- and Textdialog are put together here + SwViewOption aViewOpt = *GetUsrPref(!bTextDialog); + SwMasterUsrPref* pPref = bTextDialog ? m_pUsrPref.get() : m_pWebUsrPref.get(); + // no MakeUsrPref, because only options from textdoks can be used here + SwView* pAppView = GetView(); + if(pAppView && &pAppView->GetViewFrame() != SfxViewFrame::Current()) + pAppView = nullptr; + if(pAppView) + { + bool bWebView = dynamic_cast<SwWebView*>( pAppView ) != nullptr; + // if Text then no WebView and vice versa + if (bWebView != bTextDialog) + { + aViewOpt = *pAppView->GetWrtShell().GetViewOptions(); + } + else + pAppView = nullptr; // with View, there's nothing to win here + } + + // Options/Edit + SfxItemSetFixed< + RES_BACKGROUND, RES_BACKGROUND, + XATTR_FILL_FIRST, XATTR_FILL_LAST, + SID_PRINTPREVIEW, SID_PRINTPREVIEW, + SID_ATTR_GRID_OPTIONS, SID_ATTR_GRID_OPTIONS, + SID_HTML_MODE, SID_HTML_MODE, + SID_ATTR_CHAR_CJK_LANGUAGE, SID_ATTR_CHAR_CJK_LANGUAGE, + SID_ATTR_CHAR_CTL_LANGUAGE, SID_ATTR_CHAR_CTL_LANGUAGE, + SID_ATTR_LANGUAGE, SID_ATTR_METRIC, + SID_ATTR_DEFTABSTOP, SID_ATTR_DEFTABSTOP, + SID_ATTR_APPLYCHARUNIT, SID_ATTR_APPLYCHARUNIT, + FN_HSCROLL_METRIC, FN_VSCROLL_METRIC, + FN_PARAM_ADDPRINTER, FN_PARAM_ADDPRINTER, + FN_PARAM_DOCDISP, FN_PARAM_ELEM, + FN_PARAM_PRINTER, FN_PARAM_STDFONTS, + FN_PARAM_WRTSHELL, FN_PARAM_WRTSHELL, + FN_PARAM_SHADOWCURSOR, FN_PARAM_SHADOWCURSOR, + FN_PARAM_CRSR_IN_PROTECTED, FN_PARAM_CRSR_IN_PROTECTED> + aRet(GetPool()); + + aRet.Put( SwDocDisplayItem( aViewOpt ) ); + aRet.Put( SwElemItem( aViewOpt ) ); + if( bTextDialog ) + { + aRet.Put( SwShadowCursorItem( aViewOpt )); + aRet.Put( SfxBoolItem(FN_PARAM_CRSR_IN_PROTECTED, aViewOpt.IsCursorInProtectedArea())); + } + + if( pAppView ) + { + SwWrtShell& rWrtShell = pAppView->GetWrtShell(); + + SfxPrinter* pPrt = rWrtShell.getIDocumentDeviceAccess().getPrinter( false ); + if( pPrt ) + aRet.Put(SwPtrItem(FN_PARAM_PRINTER, pPrt)); + aRet.Put(SwPtrItem(FN_PARAM_WRTSHELL, &rWrtShell)); + + aRet.Put(rWrtShell.GetDefault(RES_CHRATR_LANGUAGE).CloneSetWhich(SID_ATTR_LANGUAGE)); + aRet.Put(rWrtShell.GetDefault(RES_CHRATR_CJK_LANGUAGE).CloneSetWhich(SID_ATTR_CHAR_CJK_LANGUAGE)); + aRet.Put(rWrtShell.GetDefault(RES_CHRATR_CTL_LANGUAGE).CloneSetWhich(SID_ATTR_CHAR_CTL_LANGUAGE)); + } + else + { + SvtLinguConfig aLinguCfg; + css::lang::Locale aLocale; + LanguageType nLang; + + using namespace ::com::sun::star::i18n::ScriptType; + + Any aLang = aLinguCfg.GetProperty(u"DefaultLocale"); + aLang >>= aLocale; + nLang = MsLangId::resolveSystemLanguageByScriptType(LanguageTag::convertToLanguageType( aLocale, false), LATIN); + aRet.Put(SvxLanguageItem(nLang, SID_ATTR_LANGUAGE)); + + aLang = aLinguCfg.GetProperty(u"DefaultLocale_CJK"); + aLang >>= aLocale; + nLang = MsLangId::resolveSystemLanguageByScriptType(LanguageTag::convertToLanguageType( aLocale, false), ASIAN); + aRet.Put(SvxLanguageItem(nLang, SID_ATTR_CHAR_CJK_LANGUAGE)); + + aLang = aLinguCfg.GetProperty(u"DefaultLocale_CTL"); + aLang >>= aLocale; + nLang = MsLangId::resolveSystemLanguageByScriptType(LanguageTag::convertToLanguageType( aLocale, false), COMPLEX); + aRet.Put(SvxLanguageItem(nLang, SID_ATTR_CHAR_CTL_LANGUAGE)); + } + if(bTextDialog) + aRet.Put(SwPtrItem(FN_PARAM_STDFONTS, GetStdFontConfig())); + if( dynamic_cast<SwPagePreview*>( SfxViewShell::Current())!=nullptr ) + { + SfxBoolItem aBool(SfxBoolItem(SID_PRINTPREVIEW, true)); + aRet.Put(aBool); + } + + FieldUnit eUnit = pPref->GetHScrollMetric(); + if(pAppView) + pAppView->GetHRulerMetric(eUnit); + aRet.Put(SfxUInt16Item( FN_HSCROLL_METRIC, static_cast< sal_uInt16 >(eUnit))); + + eUnit = pPref->GetVScrollMetric(); + if(pAppView) + pAppView->GetVRulerMetric(eUnit); + aRet.Put(SfxUInt16Item( FN_VSCROLL_METRIC, static_cast< sal_uInt16 >(eUnit) )); + aRet.Put(SfxUInt16Item( SID_ATTR_METRIC, static_cast< sal_uInt16 >(pPref->GetMetric()) )); + aRet.Put(SfxBoolItem(SID_ATTR_APPLYCHARUNIT, pPref->IsApplyCharUnit())); + if(bTextDialog) + { + if(pAppView) + { + const SvxTabStopItem& rDefTabs = + pAppView->GetWrtShell().GetDefault(RES_PARATR_TABSTOP); + aRet.Put( SfxUInt16Item( SID_ATTR_DEFTABSTOP, o3tl::narrowing<sal_uInt16>(::GetTabDist(rDefTabs)))); + } + else + aRet.Put(SfxUInt16Item( SID_ATTR_DEFTABSTOP, o3tl::toTwips(pPref->GetDefTabInMm100(), o3tl::Length::mm100))); + } + + // Options for GridTabPage + SvxGridItem aGridItem( SID_ATTR_GRID_OPTIONS); + + aGridItem.SetUseGridSnap( aViewOpt.IsSnap()); + aGridItem.SetSynchronize( aViewOpt.IsSynchronize()); + aGridItem.SetGridVisible( aViewOpt.IsGridVisible()); + + const Size& rSnapSize = aViewOpt.GetSnapSize(); + aGridItem.SetFieldDrawX( o3tl::narrowing<sal_uInt16>(rSnapSize.Width() )); + aGridItem.SetFieldDrawY( o3tl::narrowing<sal_uInt16>(rSnapSize.Height())); + + aGridItem.SetFieldDivisionX( aViewOpt.GetDivisionX()); + aGridItem.SetFieldDivisionY( aViewOpt.GetDivisionY()); + + aRet.Put(aGridItem); + + // Options for PrintTabPage + const SwPrintData* pOpt = GetPrtOptions(!bTextDialog); + SwAddPrinterItem aAddPrinterItem(*pOpt ); + aRet.Put(aAddPrinterItem); + + // Options for Web + if(!bTextDialog) + { + aRet.Put(SvxBrushItem(aViewOpt.GetRetoucheColor(), RES_BACKGROUND)); + aRet.Put(SfxUInt16Item(SID_HTML_MODE, HTMLMODE_ON)); + } + + return aRet; +} + +void SwModule::ApplyItemSet( sal_uInt16 nId, const SfxItemSet& rSet ) +{ + bool bTextDialog = nId == SID_SW_EDITOPTIONS; + SwView* pAppView = GetView(); + if(pAppView && &pAppView->GetViewFrame() != SfxViewFrame::Current()) + pAppView = nullptr; + if(pAppView) + { + // the text dialog mustn't apply data to the web view and vice versa + bool bWebView = dynamic_cast<SwWebView*>( pAppView ) != nullptr; + if(bWebView == bTextDialog) + pAppView = nullptr; + } + + SwViewOption aViewOpt = *GetUsrPref(!bTextDialog); + SwMasterUsrPref* pPref = bTextDialog ? m_pUsrPref.get() : m_pWebUsrPref.get(); + + SfxBindings *pBindings = pAppView ? &pAppView->GetViewFrame().GetBindings() + : nullptr; + + // Interpret the page Documentview + if( const SwDocDisplayItem* pDocDispItem = rSet.GetItemIfSet( FN_PARAM_DOCDISP, false )) + { + if(!aViewOpt.IsViewMetaChars()) + { + if( (!aViewOpt.IsTab( true ) && pDocDispItem->m_bTab) || + (!aViewOpt.IsBlank( true ) && pDocDispItem->m_bSpace) || + (!aViewOpt.IsShowBookmarks(true) && pDocDispItem->m_bBookmarks) || + (!aViewOpt.IsParagraph( true ) && pDocDispItem->m_bParagraphEnd) || + (!aViewOpt.IsLineBreak( true ) && pDocDispItem->m_bManualBreak) ) + { + aViewOpt.SetViewMetaChars(true); + if(pBindings) + pBindings->Invalidate(FN_VIEW_META_CHARS); + } + + } + pDocDispItem->FillViewOptions( aViewOpt ); + if(pBindings) + { + pBindings->Invalidate(FN_VIEW_GRAPHIC); + pBindings->Invalidate(FN_VIEW_HIDDEN_PARA); + } + } + + // Elements - interpret Item + bool bReFoldOutlineFolding = false; + if( const SwElemItem* pElemItem = rSet.GetItemIfSet( FN_PARAM_ELEM, false ) ) + { + pElemItem->FillViewOptions( aViewOpt ); + + // Outline-folding options + if (SwWrtShell* pWrtShell = GetActiveWrtShell()) + { + bool bIsOutlineFoldingOn = pWrtShell->GetViewOptions()->IsShowOutlineContentVisibilityButton(); + bool bTreatSubsChanged = aViewOpt.IsTreatSubOutlineLevelsAsContent() + != pWrtShell->GetViewOptions()->IsTreatSubOutlineLevelsAsContent(); + if (bIsOutlineFoldingOn && + (!aViewOpt.IsShowOutlineContentVisibilityButton() || bTreatSubsChanged)) + { + // Outline-folding options have change which require to show all content. + // Either outline-folding is being switched off or outline-folding is currently on + // and the treat subs option has changed. + pWrtShell->GetView().GetViewFrame().GetDispatcher()->Execute(FN_SHOW_OUTLINECONTENTVISIBILITYBUTTON); + if (bTreatSubsChanged) + bReFoldOutlineFolding = true; // folding method changed, set flag to refold below + } + else + { + // Refold needs to be done when outline-folding is being turned on or off + bReFoldOutlineFolding = + pWrtShell->GetViewOptions()->IsShowOutlineContentVisibilityButton() != + aViewOpt.IsShowOutlineContentVisibilityButton(); + } + } + } + + if( const SfxUInt16Item* pMetricItem = rSet.GetItemIfSet(SID_ATTR_METRIC, false ) ) + { + SfxApplication::SetOptions(rSet); + PutItem(*pMetricItem); + ::SetDfltMetric(static_cast<FieldUnit>(pMetricItem->GetValue()), !bTextDialog); + } + if( const SfxBoolItem* pCharItem = rSet.GetItemIfSet(SID_ATTR_APPLYCHARUNIT, + false ) ) + { + SfxApplication::SetOptions(rSet); + ::SetApplyCharUnit(pCharItem->GetValue(), !bTextDialog); + } + + if( const SfxUInt16Item* pMetricItem = rSet.GetItemIfSet(FN_HSCROLL_METRIC, false ) ) + { + FieldUnit eUnit = static_cast<FieldUnit>(pMetricItem->GetValue()); + pPref->SetHScrollMetric(eUnit); + if(pAppView) + pAppView->ChangeTabMetric(eUnit); + } + + if( const SfxUInt16Item* pMetricItem = rSet.GetItemIfSet(FN_VSCROLL_METRIC, false ) ) + { + FieldUnit eUnit = static_cast<FieldUnit>(pMetricItem->GetValue()); + pPref->SetVScrollMetric(eUnit); + if(pAppView) + pAppView->ChangeVRulerMetric(eUnit); + } + + if( const SfxUInt16Item* pItem = rSet.GetItemIfSet(SID_ATTR_DEFTABSTOP, false ) ) + { + sal_uInt16 nTabDist = pItem->GetValue(); + pPref->SetDefTabInMm100(convertTwipToMm100(nTabDist)); + if(pAppView) + { + SvxTabStopItem aDefTabs( 0, 0, SvxTabAdjust::Default, RES_PARATR_TABSTOP ); + MakeDefTabs( nTabDist, aDefTabs ); + pAppView->GetWrtShell().SetDefault( aDefTabs ); + } + } + + // Background only in WebDialog + if(SfxItemState::SET == rSet.GetItemState(RES_BACKGROUND)) + { + const SvxBrushItem& rBrushItem = rSet.Get(RES_BACKGROUND); + aViewOpt.SetRetoucheColor( rBrushItem.GetColor() ); + } + + // Interpret page Grid Settings + if( const SvxGridItem* pGridItem = rSet.GetItemIfSet( SID_ATTR_GRID_OPTIONS, false )) + { + aViewOpt.SetSnap( pGridItem->GetUseGridSnap() ); + aViewOpt.SetSynchronize(pGridItem->GetSynchronize()); + if( aViewOpt.IsGridVisible() != pGridItem->GetGridVisible() ) + aViewOpt.SetGridVisible( pGridItem->GetGridVisible()); + Size aSize( pGridItem->GetFieldDrawX(), pGridItem->GetFieldDrawY() ); + if( aViewOpt.GetSnapSize() != aSize ) + aViewOpt.SetSnapSize( aSize ); + short nDiv = static_cast<short>(pGridItem->GetFieldDivisionX()) ; + if( aViewOpt.GetDivisionX() != nDiv ) + aViewOpt.SetDivisionX( nDiv ); + nDiv = static_cast<short>(pGridItem->GetFieldDivisionY()); + if( aViewOpt.GetDivisionY() != nDiv ) + aViewOpt.SetDivisionY( nDiv ); + + if(pBindings) + { + pBindings->Invalidate(SID_GRID_VISIBLE); + pBindings->Invalidate(SID_GRID_USE); + } + } + + // Interpret Writer Printer Options + if( const SwAddPrinterItem* pAddPrinterAttr = rSet.GetItemIfSet( FN_PARAM_ADDPRINTER, false ) ) + { + SwPrintOptions* pOpt = GetPrtOptions(!bTextDialog); + if (pOpt) + { + *pOpt = *pAddPrinterAttr; + } + } + + if( const SwShadowCursorItem* pItem = rSet.GetItemIfSet( FN_PARAM_SHADOWCURSOR, false )) + { + pItem->FillViewOptions( aViewOpt ); + if(pBindings) + pBindings->Invalidate(FN_SHADOWCURSOR); + } + + if( pAppView ) + { + SwWrtShell &rWrtSh = pAppView->GetWrtShell(); + const bool bAlignFormulas = rWrtSh.GetDoc()->getIDocumentSettingAccess().get( DocumentSettingId::MATH_BASELINE_ALIGNMENT ); + pPref->SetAlignMathObjectsToBaseline( bAlignFormulas ); + + // don't align formulas in documents that are currently loading + if (bAlignFormulas && !rWrtSh.GetDoc()->IsInReading()) + rWrtSh.AlignAllFormulasToBaseline(); + } + + if( const SfxBoolItem* pItem = rSet.GetItemIfSet( FN_PARAM_CRSR_IN_PROTECTED, false )) + { + aViewOpt.SetCursorInProtectedArea(pItem->GetValue()); + } + + // set elements for the current view and shell + ApplyUsrPref( aViewOpt, pAppView, bTextDialog? SvViewOpt::DestText : SvViewOpt::DestWeb); + + // must be done after ApplyUsrPref + if (SfxItemState::SET != rSet.GetItemState(FN_PARAM_ELEM, false)) + return; + + if (bReFoldOutlineFolding) + { + if (SwWrtShell* pWrtShell = GetActiveWrtShell()) + { + pWrtShell->GetView().GetViewFrame().GetDispatcher()->Execute(FN_SHOW_OUTLINECONTENTVISIBILITYBUTTON); + pWrtShell->GetView().GetViewFrame().GetDispatcher()->Execute(FN_SHOW_OUTLINECONTENTVISIBILITYBUTTON); + } + } +} + +std::unique_ptr<SfxTabPage> SwModule::CreateTabPage( sal_uInt16 nId, weld::Container* pPage, weld::DialogController* pController, const SfxItemSet& rSet ) +{ + std::unique_ptr<SfxTabPage> xRet; + SfxAllItemSet aSet(*(rSet.GetPool())); + switch( nId ) + { + case RID_SW_TP_CONTENT_OPT: + case RID_SW_TP_HTML_CONTENT_OPT: + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( nId ); + xRet = (*fnCreatePage)( pPage, pController, &rSet ); + break; + } + case RID_SW_TP_HTML_OPTGRID_PAGE: + case RID_SVXPAGE_GRID: + xRet = SvxGridTabPage::Create(pPage, pController, rSet); + break; + + case RID_SW_TP_STD_FONT: + case RID_SW_TP_STD_FONT_CJK: + case RID_SW_TP_STD_FONT_CTL: + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( nId ); + xRet = (*fnCreatePage)( pPage, pController, &rSet ); + if(RID_SW_TP_STD_FONT != nId) + { + aSet.Put (SfxUInt16Item(SID_FONTMODE_TYPE, RID_SW_TP_STD_FONT_CJK == nId ? FONT_GROUP_CJK : FONT_GROUP_CTL)); + xRet->PageCreated(aSet); + } + } + break; + case RID_SW_TP_HTML_OPTPRINT_PAGE: + case RID_SW_TP_OPTPRINT_PAGE: + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( nId ); + xRet = (*fnCreatePage)( pPage, pController, &rSet ); + aSet.Put (SfxBoolItem(SID_FAX_LIST, true)); + xRet->PageCreated(aSet); + } + break; + case RID_SW_TP_HTML_OPTTABLE_PAGE: + case RID_SW_TP_OPTTABLE_PAGE: + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( nId ); + xRet = (*fnCreatePage)( pPage, pController, &rSet ); + SwView* pCurrView = GetView(); + if(pCurrView) + { + // if text then not WebView and vice versa + bool bWebView = dynamic_cast<SwWebView*>( pCurrView ) != nullptr; + if( (bWebView && RID_SW_TP_HTML_OPTTABLE_PAGE == nId) || + (!bWebView && RID_SW_TP_HTML_OPTTABLE_PAGE != nId) ) + { + aSet.Put (SwWrtShellItem(pCurrView->GetWrtShellPtr())); + xRet->PageCreated(aSet); + } + } + } + break; + case RID_SW_TP_OPTSHDWCRSR: + case RID_SW_TP_HTML_OPTSHDWCRSR: + case RID_SW_TP_REDLINE_OPT: + case RID_SW_TP_COMPARISON_OPT: + case RID_SW_TP_OPTLOAD_PAGE: + case RID_SW_TP_OPTCOMPATIBILITY_PAGE: + case RID_SW_TP_MAILCONFIG: + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( nId ); + xRet = (*fnCreatePage)( pPage, pController, &rSet ); + if (nId == RID_SW_TP_OPTSHDWCRSR || nId == RID_SW_TP_HTML_OPTSHDWCRSR) + { + SwView* pCurrView = GetView(); + if(pCurrView) + { + aSet.Put( SwWrtShellItem( pCurrView->GetWrtShellPtr() ) ); + xRet->PageCreated(aSet); + } + } + } + break; + case RID_SW_TP_OPTTEST_PAGE: + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( nId ); + xRet = (*fnCreatePage)( pPage, pController, &rSet ); + break; + } + case RID_SW_TP_BACKGROUND: + { + SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); + ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( RID_SVXPAGE_BKG ); + xRet = (*fnCreatePage)( pPage, pController, &rSet ); + xRet->PageCreated( rSet ); + break; + } + case RID_SW_TP_OPTCAPTION_PAGE: + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ::CreateTabPage fnCreatePage = pFact->GetTabPageCreatorFunc( RID_SW_TP_OPTCAPTION_PAGE ); + xRet = (*fnCreatePage)( pPage, pController, &rSet ); + } + break; + } + + if(!xRet) + SAL_WARN( "sw", "SwModule::CreateTabPage(): Unknown tabpage id " << nId ); + return xRet; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/app/docsh.cxx b/sw/source/uibase/app/docsh.cxx new file mode 100644 index 0000000000..1cddf3070b --- /dev/null +++ b/sw/source/uibase/app/docsh.cxx @@ -0,0 +1,1433 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <config_features.h> + +#include <officecfg/Office/Common.hxx> +#include <vcl/weld.hxx> +#include <vcl/svapp.hxx> +#include <vcl/syswin.hxx> +#include <vcl/jobset.hxx> +#include <svl/numformat.hxx> +#include <svl/whiter.hxx> +#include <svl/eitem.hxx> +#include <svl/stritem.hxx> +#include <svl/PasswordHelper.hxx> +#include <unotools/moduleoptions.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/docfilt.hxx> +#include <sfx2/notebookbar/SfxNotebookBar.hxx> +#include <sfx2/printer.hxx> +#include <sfx2/linkmgr.hxx> +#include <editeng/flstitem.hxx> +#include <comphelper/lok.hxx> +#include <comphelper/classids.hxx> +#include <basic/sbmod.hxx> +#include <osl/diagnose.h> +#include <node.hxx> +#include <swwait.hxx> +#include <printdata.hxx> +#include <view.hxx> +#include <edtwin.hxx> +#include <PostItMgr.hxx> +#include <wrtsh.hxx> +#include <docsh.hxx> +#include <viewopt.hxx> +#include <wdocsh.hxx> +#include <swmodule.hxx> +#include <globdoc.hxx> +#include <usrpref.hxx> +#include <shellio.hxx> +#include <docstyle.hxx> +#include <doc.hxx> +#include <docfunc.hxx> +#include <IDocumentUndoRedo.hxx> +#include <IDocumentSettingAccess.hxx> +#include <IDocumentLinksAdministration.hxx> +#include <IDocumentDeviceAccess.hxx> +#include <IDocumentDrawModelAccess.hxx> +#include <IDocumentRedlineAccess.hxx> +#include <IDocumentStatistics.hxx> +#include <IDocumentState.hxx> +#include <pview.hxx> +#include <srcview.hxx> +#include <ndindex.hxx> +#include <ndole.hxx> +#include <txtftn.hxx> +#include <ftnidx.hxx> +#include <fldbas.hxx> +#include <docary.hxx> +#include <swerror.h> +#include <cmdid.h> +#include <strings.hrc> + +#include <unotools/fltrcfg.hxx> +#include <sfx2/viewfrm.hxx> +#include <sfx2/objface.hxx> + +#define ShellClass_SwDocShell +#include <sfx2/msg.hxx> +#include <swslots.hxx> +#include <com/sun/star/document/UpdateDocMode.hpp> + +#include <com/sun/star/script/XLibraryContainer.hpp> +#include <com/sun/star/document/XDocumentProperties.hpp> +#include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> +#include <com/sun/star/sdb/DatabaseContext.hpp> +#include <com/sun/star/sdb/XDocumentDataSource.hpp> +#include <com/sun/star/uri/UriReferenceFactory.hpp> +#include <com/sun/star/uri/VndSunStarPkgUrlReferenceFactory.hpp> +#include <com/sun/star/frame/XStorable.hpp> +#include <ooo/vba/XSinkCaller.hpp> + +#include <unotextrange.hxx> + +#include <dbmgr.hxx> +#include <iodetect.hxx> + +#include <comphelper/processfactory.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::script; +using namespace ::com::sun::star::container; + +SFX_IMPL_SUPERCLASS_INTERFACE(SwDocShell, SfxObjectShell) + +void SwDocShell::InitInterface_Impl() +{ +} + + +SFX_IMPL_OBJECTFACTORY(SwDocShell, SvGlobalName(SO3_SW_CLASSID), "swriter" ) + +bool SwDocShell::InsertGeneratedStream(SfxMedium & rMedium, + uno::Reference<text::XTextRange> const& xInsertPosition) +{ + SwUnoInternalPaM aPam(*GetDoc()); // must have doc since called from SwView + if (!::sw::XTextRangeToSwPaM(aPam, xInsertPosition)) + return false; + // similar to SwView::InsertMedium + SwReaderPtr pReader; + Reader *const pRead = StartConvertFrom(rMedium, pReader, nullptr, &aPam); + if (!pRead) + return false; + ErrCodeMsg const nError = pReader->Read(*pRead); + return ERRCODE_NONE == nError; +} + +// Prepare loading +Reader* SwDocShell::StartConvertFrom(SfxMedium& rMedium, SwReaderPtr& rpRdr, + SwCursorShell const *pCursorShell, + SwPaM* pPaM ) +{ + bool bAPICall = false; + if( const SfxBoolItem* pApiItem = rMedium.GetItemSet().GetItemIfSet( FN_API_CALL ) ) + bAPICall = pApiItem->GetValue(); + + std::shared_ptr<const SfxFilter> pFlt = rMedium.GetFilter(); + if( !pFlt ) + { + if(!bAPICall) + { + std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(nullptr, + VclMessageType::Info, VclButtonsType::Ok, + SwResId(STR_CANTOPEN))); + xInfoBox->run(); + } + return nullptr; + } + OUString aFileName( rMedium.GetName() ); + Reader* pRead = SwReaderWriter::GetReader( pFlt->GetUserData() ); + if( !pRead ) + return nullptr; + + if( rMedium.IsStorage() + ? SwReaderType::Storage & pRead->GetReaderType() + : SwReaderType::Stream & pRead->GetReaderType() ) + { + if (pPaM) + rpRdr.reset(new SwReader( rMedium, aFileName, *pPaM )); + else if (pCursorShell) + rpRdr.reset(new SwReader( rMedium, aFileName, *pCursorShell->GetCursor() )); + else + rpRdr.reset(new SwReader( rMedium, aFileName, m_xDoc.get() )); + } + else + return nullptr; + + // #i30171# set the UpdateDocMode at the SwDocShell + const SfxUInt16Item* pUpdateDocItem = rMedium.GetItemSet().GetItem(SID_UPDATEDOCMODE, false); + m_nUpdateDocMode = pUpdateDocItem ? pUpdateDocItem->GetValue() : document::UpdateDocMode::NO_UPDATE; + + if (!pFlt->GetDefaultTemplate().isEmpty()) + pRead->SetTemplateName( pFlt->GetDefaultTemplate() ); + + if( pRead == ReadAscii && nullptr != rMedium.GetInStream() && + pFlt->GetUserData() == FILTER_TEXT_DLG ) + { + SwAsciiOptions aOpt; + if( const SfxStringItem* pItem = rMedium.GetItemSet().GetItemIfSet( SID_FILE_FILTEROPTIONS ) ) + aOpt.ReadUserData( pItem->GetValue() ); + + pRead->GetReaderOpt().SetASCIIOpts( aOpt ); + } + + return pRead; +} + +// Loading +bool SwDocShell::ConvertFrom( SfxMedium& rMedium ) +{ + SwReaderPtr pRdr; + Reader* pRead = StartConvertFrom(rMedium, pRdr); + if (!pRead) + return false; // #129881# return if no reader is found + tools::SvRef<SotStorage> pStg=pRead->getSotStorageRef(); // #i45333# save sot storage ref in case of recursive calls + + m_xDoc->setDocAccTitle(OUString()); + if (const auto pFrame1 = SfxViewFrame::GetFirst(this)) + { + if (auto pSysWin = pFrame1->GetWindow().GetSystemWindow()) + { + pSysWin->SetAccessibleName(OUString()); + } + } + SwWait aWait( *this, true ); + + // Suppress SfxProgress, when we are Embedded + SW_MOD()->SetEmbeddedLoadSave( + SfxObjectCreateMode::EMBEDDED == GetCreateMode() ); + + pRdr->GetDoc().getIDocumentSettingAccess().set(DocumentSettingId::HTML_MODE, dynamic_cast< const SwWebDocShell *>( this ) != nullptr); + + // Restore the pool default if reading a saved document. + m_xDoc->RemoveAllFormatLanguageDependencies(); + + ErrCodeMsg nErr = pRdr->Read( *pRead ); + + // Maybe put away one old Doc + if (m_xDoc.get() != &pRdr->GetDoc()) + { + RemoveLink(); + m_xDoc = &pRdr->GetDoc(); + + AddLink(); + + if (!m_xBasePool.is()) + m_xBasePool = new SwDocStyleSheetPool( *m_xDoc, SfxObjectCreateMode::ORGANIZER == GetCreateMode() ); + } + + UpdateFontList(); + InitDrawModelAndDocShell(this, m_xDoc ? m_xDoc->getIDocumentDrawModelAccess().GetDrawModel() : nullptr); + + pRdr.reset(); + + SW_MOD()->SetEmbeddedLoadSave( false ); + + SetError(nErr); + bool bOk = !nErr.IsError(); + + if (bOk && !m_xDoc->IsInLoadAsynchron()) + { + LoadingFinished(); + } + + pRead->setSotStorageRef(pStg); // #i45333# save sot storage ref in case of recursive calls + + return bOk; +} + +// Saving the Default-Format, Stg present +bool SwDocShell::Save() +{ + //#i3370# remove quick help to prevent saving of autocorrection suggestions + if (m_pView) + m_pView->GetEditWin().StopQuickHelp(); + SwWait aWait( *this, true ); + + CalcLayoutForOLEObjects(); // format for OLE objects + // #i62875# + // reset compatibility flag <DoNotCaptureDrawObjsOnPage>, if possible + if (m_pWrtShell && m_xDoc && + m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE) && + docfunc::AllDrawObjsOnPage(*m_xDoc)) + { + m_xDoc->getIDocumentSettingAccess().set(DocumentSettingId::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE, false); + } + + ErrCodeMsg nErr = ERR_SWG_WRITE_ERROR; + ErrCode nVBWarning = ERRCODE_NONE; + if( SfxObjectShell::Save() ) + { + switch( GetCreateMode() ) + { + case SfxObjectCreateMode::INTERNAL: + nErr = ERRCODE_NONE; + break; + + case SfxObjectCreateMode::ORGANIZER: + { + WriterRef xWrt; + ::GetXMLWriter(std::u16string_view(), GetMedium()->GetBaseURL(true), xWrt); + xWrt->SetOrganizerMode( true ); + SwWriter aWrt( *GetMedium(), *m_xDoc ); + nErr = aWrt.Write( xWrt ); + xWrt->SetOrganizerMode( false ); + } + break; + + case SfxObjectCreateMode::EMBEDDED: + // Suppress SfxProgress, if we are Embedded + SW_MOD()->SetEmbeddedLoadSave( true ); + [[fallthrough]]; + + case SfxObjectCreateMode::STANDARD: + default: + { + if (m_xDoc->ContainsMSVBasic()) + { + if( SvtFilterOptions::Get().IsLoadWordBasicStorage() ) + nVBWarning = GetSaveWarningOfMSVBAStorage( static_cast<SfxObjectShell&>(*this) ); + m_xDoc->SetContainsMSVBasic( false ); + } + + // End TableBox Edit! + if (m_pWrtShell) + m_pWrtShell->EndAllTableBoxEdit(); + + WriterRef xWrt; + ::GetXMLWriter(std::u16string_view(), GetMedium()->GetBaseURL(true), xWrt); + + bool bLockedView(false); + if (m_pWrtShell) + { + bLockedView = m_pWrtShell->IsViewLocked(); + m_pWrtShell->LockView( true ); //lock visible section + } + + SwWriter aWrt( *GetMedium(), *m_xDoc ); + nErr = aWrt.Write( xWrt ); + + if (m_pWrtShell) + m_pWrtShell->LockView( bLockedView ); + } + break; + } + SW_MOD()->SetEmbeddedLoadSave( false ); + } + SetError(nErr ? nErr : nVBWarning); + + SfxViewFrame *const pFrame = + m_pWrtShell ? &m_pWrtShell->GetView().GetViewFrame() : nullptr; + if( pFrame ) + { + pFrame->GetBindings().SetState(SfxBoolItem(SID_DOC_MODIFIED, false)); + } + return !nErr.IsError(); +} + +SwDocShell::LockAllViewsGuard_Impl::LockAllViewsGuard_Impl(SwViewShell* pViewShell) +{ + if (!pViewShell) + return; + for (SwViewShell& rShell : pViewShell->GetRingContainer()) + { + if (!rShell.IsViewLocked()) + { + m_aViewWasUnLocked.push_back(&rShell); + rShell.LockView(true); + } + } +} + +SwDocShell::LockAllViewsGuard_Impl::~LockAllViewsGuard_Impl() +{ + for (SwViewShell* pShell : m_aViewWasUnLocked) + pShell->LockView(false); +} + +std::unique_ptr<SfxObjectShell::LockAllViewsGuard> SwDocShell::LockAllViews() +{ + return std::make_unique<LockAllViewsGuard_Impl>(GetEditShell()); +} + +// Save using the Defaultformat +bool SwDocShell::SaveAs( SfxMedium& rMedium ) +{ + SwWait aWait( *this, true ); + //#i3370# remove quick help to prevent saving of autocorrection suggestions + if (m_pView) + m_pView->GetEditWin().StopQuickHelp(); + + //#i91811# mod if we have an active margin window, write back the text + if (m_pView && + m_pView->GetPostItMgr() && + m_pView->GetPostItMgr()->HasActiveSidebarWin()) + { + m_pView->GetPostItMgr()->UpdateDataOnActiveSidebarWin(); + } + + if (m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::GLOBAL_DOCUMENT) && + !m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::GLOBAL_DOCUMENT_SAVE_LINKS)) + RemoveOLEObjects(); + + if (GetMedium()) + { + // Task 75666 - is the Document imported by our Microsoft-Filters? + std::shared_ptr<const SfxFilter> pOldFilter = GetMedium()->GetFilter(); + if( pOldFilter && + ( pOldFilter->GetUserData() == FILTER_WW8 || + pOldFilter->GetUserData() == "CWW6" || + pOldFilter->GetUserData() == "WW6" ) ) + { + // when saving it in our own fileformat, then remove the template + // name from the docinfo. + uno::Reference<document::XDocumentPropertiesSupplier> xDPS( + GetModel(), uno::UNO_QUERY_THROW); + uno::Reference<document::XDocumentProperties> xDocProps + = xDPS->getDocumentProperties(); + xDocProps->setTemplateName(OUString()); + xDocProps->setTemplateURL(OUString()); + xDocProps->setTemplateDate(::util::DateTime()); + } + } + + CalcLayoutForOLEObjects(); // format for OLE objects + + const bool bURLChanged = GetMedium() && GetMedium()->GetURLObject() != rMedium.GetURLObject(); + const SwDBManager* const pMgr = m_xDoc->GetDBManager(); + const bool bHasEmbedded = pMgr && !pMgr->getEmbeddedName().isEmpty(); + bool bSaveDS = bHasEmbedded && bURLChanged; + if (bSaveDS) + { + // Don't save data source in case a temporary is being saved for preview in MM wizard + if (const SfxBoolItem* pNoEmbDS + = rMedium.GetItemSet().GetItem(SID_NO_EMBEDDED_DS, false)) + bSaveDS = !pNoEmbDS->GetValue(); + } + if (bSaveDS) + { + // We have an embedded data source definition, need to re-store it, + // otherwise relative references will break when the new file is in a + // different directory. + + OUString aURL(GetMedium()->GetURLObject().GetMainURL(INetURLObject::DecodeMechanism::NONE)); + if (aURL.isEmpty()) + { + // No old URL - is this a new document created from a template with embedded DS? + // Try to get the template URL to reconstruct the embedded data source URL + const css::beans::PropertyValues& rArgs = GetMedium()->GetArgs(); + const auto aURLIter = std::find_if(rArgs.begin(), rArgs.end(), + [](const auto& v) { return v.Name == "URL"; }); + if (aURLIter != rArgs.end()) + aURLIter->Value >>= aURL; + } + + if (!aURL.isEmpty()) + { + auto xContext(comphelper::getProcessComponentContext()); + auto xUri = css::uri::UriReferenceFactory::create(xContext)->parse(aURL); + assert(xUri.is()); + xUri = css::uri::VndSunStarPkgUrlReferenceFactory::create(xContext) + ->createVndSunStarPkgUrlReference(xUri); + assert(xUri.is()); + aURL = xUri->getUriReference() + "/" + + INetURLObject::encode(pMgr->getEmbeddedName(), INetURLObject::PART_FPATH, + INetURLObject::EncodeMechanism::All); + + bool bCopyTo = GetCreateMode() == SfxObjectCreateMode::EMBEDDED; + if (!bCopyTo) + { + if (const SfxBoolItem* pSaveToItem + = rMedium.GetItemSet().GetItem(SID_SAVETO, false)) + bCopyTo = pSaveToItem->GetValue(); + } + + auto xDatabaseContext = sdb::DatabaseContext::create(xContext); + uno::Reference<sdb::XDocumentDataSource> xDataSource(xDatabaseContext->getByName(aURL), + uno::UNO_QUERY); + if (xDataSource) + { + uno::Reference<frame::XStorable> xStorable(xDataSource->getDatabaseDocument(), + uno::UNO_QUERY); + SwDBManager::StoreEmbeddedDataSource(xStorable, rMedium.GetOutputStorage(), + pMgr->getEmbeddedName(), rMedium.GetName(), + bCopyTo); + } + } + } + + // #i62875# + // reset compatibility flag <DoNotCaptureDrawObjsOnPage>, if possible + if (m_pWrtShell && + m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE) && + docfunc::AllDrawObjsOnPage(*m_xDoc)) + { + m_xDoc->getIDocumentSettingAccess().set(DocumentSettingId::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE, false); + } + + ErrCodeMsg nErr = ERR_SWG_WRITE_ERROR; + ErrCode nVBWarning = ERRCODE_NONE; + uno::Reference < embed::XStorage > xStor = rMedium.GetOutputStorage(); + if( SfxObjectShell::SaveAs( rMedium ) ) + { + if( GetDoc()->getIDocumentSettingAccess().get(DocumentSettingId::GLOBAL_DOCUMENT) && dynamic_cast< const SwGlobalDocShell *>( this ) == nullptr ) + { + // The document is closed explicitly, but using SfxObjectShellLock is still more correct here + SfxObjectShellLock xDocSh = + new SwGlobalDocShell( SfxObjectCreateMode::INTERNAL ); + // the global document can not be a template + xDocSh->SetupStorage( xStor, SotStorage::GetVersion( xStor ), false ); + xDocSh->DoClose(); + } + + if (m_xDoc->ContainsMSVBasic()) + { + if( SvtFilterOptions::Get().IsLoadWordBasicStorage() ) + nVBWarning = GetSaveWarningOfMSVBAStorage( static_cast<SfxObjectShell&>(*this) ); + m_xDoc->SetContainsMSVBasic( false ); + } + + if (m_pWrtShell) + { + // End TableBox Edit! + m_pWrtShell->EndAllTableBoxEdit(); + + // Remove invalid signatures. + m_pWrtShell->ValidateAllParagraphSignatures(false); + + m_pWrtShell->ClassifyDocPerHighestParagraphClass(); + } + + // Remember and preserve Modified-Flag without calling the Link + // (for OLE; after Statement from MM) + const bool bIsModified = m_xDoc->getIDocumentState().IsModified(); + m_xDoc->GetIDocumentUndoRedo().LockUndoNoModifiedPosition(); + Link<bool,void> aOldOLELnk( m_xDoc->GetOle2Link() ); + m_xDoc->SetOle2Link( Link<bool,void>() ); + + // Suppress SfxProgress when we are Embedded + SW_MOD()->SetEmbeddedLoadSave( + SfxObjectCreateMode::EMBEDDED == GetCreateMode() ); + + WriterRef xWrt; + ::GetXMLWriter(std::u16string_view(), rMedium.GetBaseURL(true), xWrt); + + bool bLockedView(false); + if (m_pWrtShell) + { + bLockedView = m_pWrtShell->IsViewLocked(); + m_pWrtShell->LockView( true ); //lock visible section + } + + SwWriter aWrt( rMedium, *m_xDoc ); + nErr = aWrt.Write( xWrt ); + + if (m_pWrtShell) + m_pWrtShell->LockView( bLockedView ); + + if( bIsModified ) + { + m_xDoc->getIDocumentState().SetModified(); + m_xDoc->GetIDocumentUndoRedo().UnLockUndoNoModifiedPosition(); + } + m_xDoc->SetOle2Link( aOldOLELnk ); + + SW_MOD()->SetEmbeddedLoadSave( false ); + + // Increase RSID + m_xDoc->setRsid( m_xDoc->getRsid() ); + + m_xDoc->cleanupUnoCursorTable(); + } + SetError(nErr ? nErr : nVBWarning); + + return !nErr.IsError(); +} + +// Save all Formats +static SwSrcView* lcl_GetSourceView( SwDocShell const * pSh ) +{ + // are we in SourceView? + SfxViewFrame* pVFrame = SfxViewFrame::GetFirst( pSh ); + SfxViewShell* pViewShell = pVFrame ? pVFrame->GetViewShell() : nullptr; + return dynamic_cast<SwSrcView*>( pViewShell ); +} + +bool SwDocShell::ConvertTo( SfxMedium& rMedium ) +{ + std::shared_ptr<const SfxFilter> pFlt = rMedium.GetFilter(); + if( !pFlt ) + return false; + + WriterRef xWriter; + SwReaderWriter::GetWriter( pFlt->GetUserData(), rMedium.GetBaseURL( true ), xWriter ); + if( !xWriter.is() ) + { // Filter not available + std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(nullptr, + VclMessageType::Info, VclButtonsType::Ok, + SwResId(STR_DLLNOTFOUND))); + xInfoBox->run(); + return false; + } + + //#i3370# remove quick help to prevent saving of autocorrection suggestions + if (m_pView) + m_pView->GetEditWin().StopQuickHelp(); + + //#i91811# mod if we have an active margin window, write back the text + if (m_pView && + m_pView->GetPostItMgr() && + m_pView->GetPostItMgr()->HasActiveSidebarWin()) + { + m_pView->GetPostItMgr()->UpdateDataOnActiveSidebarWin(); + } + + ErrCode nVBWarning = ERRCODE_NONE; + + if (m_xDoc->ContainsMSVBasic()) + { + bool bSave = pFlt->GetUserData() == "CWW8" + && SvtFilterOptions::Get().IsLoadWordBasicStorage(); + + if ( bSave ) + { + tools::SvRef<SotStorage> xStg = new SotStorage( rMedium.GetOutStream(), false ); + OSL_ENSURE( !xStg->GetError(), "No storage available for storing VBA macros!" ); + if ( !xStg->GetError() ) + { + nVBWarning = SaveOrDelMSVBAStorage( static_cast<SfxObjectShell&>(*this), *xStg, bSave, "Macros" ); + xStg->Commit(); + m_xDoc->SetContainsMSVBasic( true ); + } + } + } + + // End TableBox Edit! + if (m_pWrtShell) + m_pWrtShell->EndAllTableBoxEdit(); + + if( pFlt->GetUserData() == "HTML" ) + { +#if HAVE_FEATURE_SCRIPTING + if( !officecfg::Office::Common::Filter::HTML::Export::Basic::get() + && officecfg::Office::Common::Filter::HTML::Export::Warning::get() + && HasBasic() ) + { + uno::Reference< XLibraryContainer > xLibCont = GetBasicContainer(); + uno::Reference< XNameAccess > xLib; + const Sequence<OUString> aNames = xLibCont->getElementNames(); + for(const OUString& rName : aNames) + { + Any aLib = xLibCont->getByName(rName); + aLib >>= xLib; + if(xLib.is()) + { + Sequence<OUString> aModNames = xLib->getElementNames(); + if(aModNames.hasElements()) + { + SetError(WARN_SWG_HTML_NO_MACROS); + break; + } + } + } + } +#endif + } + + // #i76360# Update document statistics + if ( !rMedium.IsSkipImages() ) + m_xDoc->getIDocumentStatistics().UpdateDocStat( false, true ); + + CalcLayoutForOLEObjects(); // format for OLE objects + // #i62875# + // reset compatibility flag <DoNotCaptureDrawObjsOnPage>, if possible + if (m_pWrtShell && + m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE) && + docfunc::AllDrawObjsOnPage(*m_xDoc)) + { + m_xDoc->getIDocumentSettingAccess().set(DocumentSettingId::DO_NOT_CAPTURE_DRAW_OBJS_ON_PAGE, false); + } + + if( xWriter->IsStgWriter() && + ( pFlt->GetUserData() == FILTER_XML || + pFlt->GetUserData() == FILTER_XMLV || + pFlt->GetUserData() == FILTER_XMLVW ) ) + { + // determine the own Type + sal_uInt8 nMyType = 0; + if( dynamic_cast< const SwWebDocShell *>( this ) != nullptr ) + nMyType = 1; + else if( dynamic_cast< const SwGlobalDocShell *>( this ) != nullptr ) + nMyType = 2; + + // determine the desired Type + sal_uInt8 nSaveType = 0; + SotClipboardFormatId nSaveClipId = pFlt->GetFormat(); + if( SotClipboardFormatId::STARWRITERWEB_8 == nSaveClipId || + SotClipboardFormatId::STARWRITERWEB_60 == nSaveClipId || + SotClipboardFormatId::STARWRITERWEB_50 == nSaveClipId || + SotClipboardFormatId::STARWRITERWEB_40 == nSaveClipId ) + nSaveType = 1; + else if( SotClipboardFormatId::STARWRITERGLOB_8 == nSaveClipId || + SotClipboardFormatId::STARWRITERGLOB_8_TEMPLATE == nSaveClipId || + SotClipboardFormatId::STARWRITERGLOB_60 == nSaveClipId || + SotClipboardFormatId::STARWRITERGLOB_50 == nSaveClipId || + SotClipboardFormatId::STARWRITERGLOB_40 == nSaveClipId ) + nSaveType = 2; + + // Change Flags of the Document accordingly + bool bIsHTMLModeSave = GetDoc()->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE); + bool bIsGlobalDocSave = GetDoc()->getIDocumentSettingAccess().get(DocumentSettingId::GLOBAL_DOCUMENT); + bool bIsGlblDocSaveLinksSave = GetDoc()->getIDocumentSettingAccess().get(DocumentSettingId::GLOBAL_DOCUMENT_SAVE_LINKS); + if( nMyType != nSaveType ) + { + GetDoc()->getIDocumentSettingAccess().set(DocumentSettingId::HTML_MODE, 1 == nSaveType); + GetDoc()->getIDocumentSettingAccess().set(DocumentSettingId::GLOBAL_DOCUMENT, 2 == nSaveType); + if( 2 != nSaveType ) + GetDoc()->getIDocumentSettingAccess().set(DocumentSettingId::GLOBAL_DOCUMENT_SAVE_LINKS, false); + } + + // if the target format is storage based, then the output storage must be already created + if ( rMedium.IsStorage() ) + { + // set MediaType on target storage + // (MediaType will be queried during SaveAs) + try + { + // TODO/MBA: testing + uno::Reference < beans::XPropertySet > xSet( rMedium.GetStorage(), uno::UNO_QUERY ); + if ( xSet.is() ) + xSet->setPropertyValue("MediaType", uno::Any( SotExchange::GetFormatMimeType( nSaveClipId ) ) ); + } + catch (const uno::Exception&) + { + } + } + + // Now normally save the Document + bool bRet = SaveAs( rMedium ); + + if( nMyType != nSaveType ) + { + GetDoc()->getIDocumentSettingAccess().set(DocumentSettingId::HTML_MODE, bIsHTMLModeSave ); + GetDoc()->getIDocumentSettingAccess().set(DocumentSettingId::GLOBAL_DOCUMENT, bIsGlobalDocSave); + GetDoc()->getIDocumentSettingAccess().set(DocumentSettingId::GLOBAL_DOCUMENT_SAVE_LINKS, bIsGlblDocSaveLinksSave); + } + + return bRet; + } + + if( pFlt->GetUserData() == FILTER_TEXT_DLG && + (m_pWrtShell || !::lcl_GetSourceView(this))) + { + SwAsciiOptions aOpt; + OUString sItemOpt; + if( const SfxStringItem* pItem = rMedium.GetItemSet().GetItemIfSet( SID_FILE_FILTEROPTIONS ) ) + sItemOpt = pItem->GetValue(); + if(!sItemOpt.isEmpty()) + aOpt.ReadUserData( sItemOpt ); + + xWriter->SetAsciiOptions( aOpt ); + } + + // Suppress SfxProgress when we are Embedded + SW_MOD()->SetEmbeddedLoadSave( + SfxObjectCreateMode::EMBEDDED == GetCreateMode()); + + // Span Context in order to suppress the Selection's View + ErrCodeMsg nErrno; + const OUString aFileName( rMedium.GetName() ); + + bool bSelection = false; + if (m_pWrtShell) + { + const SfxBoolItem* pSelectionItem = rMedium.GetItemSet().GetItemIfSet(SID_SELECTION); + bSelection = pSelectionItem && pSelectionItem->GetValue(); + } + + // No View, so the whole Document! (unless SID_SELECTION explicitly set) + if (m_pWrtShell && (!Application::IsHeadlessModeEnabled() || bSelection)) + { + + SwWait aWait( *this, true ); + // #i106906# + const bool bFormerLockView = m_pWrtShell->IsViewLocked(); + m_pWrtShell->LockView( true ); + m_pWrtShell->StartAllAction(); + m_pWrtShell->Push(); + SwWriter aWrt( rMedium, *m_pWrtShell, !bSelection ); + nErrno = aWrt.Write( xWriter, &aFileName ); + //JP 16.05.97: In case the SFX revokes the View while saving + if (m_pWrtShell) + { + m_pWrtShell->Pop(SwCursorShell::PopMode::DeleteCurrent); + m_pWrtShell->EndAllAction(); + // #i106906# + m_pWrtShell->LockView( bFormerLockView ); + } + } + else + { + // are we in SourceView? + SwSrcView* pSrcView = ::lcl_GetSourceView( this ); + if( pSrcView ) + { + pSrcView->SaveContentTo(rMedium); + nErrno = ERRCODE_NONE; + } + else + { + SwWriter aWrt( rMedium, *m_xDoc ); + nErrno = aWrt.Write( xWriter, &aFileName ); + } + } + + SW_MOD()->SetEmbeddedLoadSave( false ); + SetError(nErrno ? nErrno : nVBWarning); + if( !rMedium.IsStorage() ) + rMedium.CloseOutStream(); + + return ! nErrno.IsError(); +} + +// Hands off +// do not yet activate, must deliver TRUE +bool SwDocShell::SaveCompleted( const uno::Reference < embed::XStorage >& xStor ) +{ + bool bRet = SfxObjectShell::SaveCompleted( xStor ); + if( bRet ) + { + // Do not decide until here, whether Saving was successful or not + if( IsModified() ) + m_xDoc->getIDocumentState().SetModified(); + else + m_xDoc->getIDocumentState().ResetModified(); + } + + if (m_pOLEChildList) + { + bool bResetModified = IsEnableSetModified(); + if( bResetModified ) + EnableSetModified( false ); + + uno::Sequence < OUString > aNames = m_pOLEChildList->GetObjectNames(); + for( sal_Int32 n = aNames.getLength(); n; n-- ) + { + if (!m_pOLEChildList->MoveEmbeddedObject(aNames[n-1], GetEmbeddedObjectContainer())) + { + OSL_FAIL("Copying of objects didn't work!" ); + } + } + + m_pOLEChildList.reset(); + if( bResetModified ) + EnableSetModified(); + } + return bRet; +} + +// Draw()-Override for OLE2 (Sfx) +void SwDocShell::Draw( OutputDevice* pDev, const JobSetup& rSetup, + sal_uInt16 nAspect, bool bOutputForScreen ) +{ + //fix #25341# Draw should not affect the Modified + bool bResetModified = IsEnableSetModified(); + if ( bResetModified ) + EnableSetModified( false ); + + // When there is a JobSetup connected to the Document, we copy it to + // reconnect it after PrtOle2. We don't use an empty JobSetup because + // that would only lead to questionable results after expensive + // reformatting (Preview!) + std::unique_ptr<JobSetup> pOrig; + if ( !rSetup.GetPrinterName().isEmpty() && ASPECT_THUMBNAIL != nAspect ) + { + const JobSetup* pCurrentJobSetup = m_xDoc->getIDocumentDeviceAccess().getJobsetup(); + if( pCurrentJobSetup ) // then we copy that + pOrig.reset(new JobSetup( *pCurrentJobSetup )); + m_xDoc->getIDocumentDeviceAccess().setJobsetup( rSetup ); + } + + tools::Rectangle aRect( nAspect == ASPECT_THUMBNAIL ? + GetVisArea( nAspect ) : GetVisArea( ASPECT_CONTENT ) ); + + pDev->Push(); + pDev->SetFillColor(); + pDev->SetLineColor(); + pDev->SetBackground(); + const bool bWeb = dynamic_cast< const SwWebDocShell *>( this ) != nullptr; + SwPrintData aOpts; + SwViewShell::PrtOle2(m_xDoc.get(), SW_MOD()->GetUsrPref(bWeb), aOpts, *pDev, aRect, bOutputForScreen); + pDev->Pop(); + + if( pOrig ) + { + m_xDoc->getIDocumentDeviceAccess().setJobsetup( *pOrig ); + } + if ( bResetModified ) + EnableSetModified(); +} + +void SwDocShell::SetVisArea( const tools::Rectangle &rRect ) +{ + tools::Rectangle aRect( rRect ); + if (m_pView) + { + Size aSz( m_pView->GetDocSz() ); + aSz.AdjustWidth(DOCUMENTBORDER ); aSz.AdjustHeight(DOCUMENTBORDER ); + tools::Long nMoveX = 0, nMoveY = 0; + if ( aRect.Right() > aSz.Width() ) + nMoveX = aSz.Width() - aRect.Right(); + if ( aRect.Bottom() > aSz.Height() ) + nMoveY = aSz.Height() - aRect.Bottom(); + aRect.Move( nMoveX, nMoveY ); + nMoveX = aRect.Left() < 0 ? -aRect.Left() : 0; + nMoveY = aRect.Top() < 0 ? -aRect.Top() : 0; + aRect.Move( nMoveX, nMoveY ); + + // Calls SfxInPlaceObject::SetVisArea()! + m_pView->SetVisArea( aRect ); + } + else + SfxObjectShell::SetVisArea( aRect ); +} + +tools::Rectangle SwDocShell::GetVisArea( sal_uInt16 nAspect ) const +{ + if ( nAspect == ASPECT_THUMBNAIL ) + { + // Preview: set VisArea to the first page. + SwNodeIndex aIdx( m_xDoc->GetNodes().GetEndOfExtras(), 1 ); + SwContentNode* pNd = m_xDoc->GetNodes().GoNext( &aIdx ); + + const SwRect aPageRect = pNd->FindPageFrameRect(); + if (aPageRect.IsEmpty()) + return tools::Rectangle(); + tools::Rectangle aRect(aPageRect.SVRect()); + + // tdf#81219 sanitize - nobody is interested in a thumbnail where's + // nothing visible + if (aRect.GetHeight() > 2*aRect.GetWidth()) + aRect.SetSize(Size(aRect.GetWidth(), 2*aRect.GetWidth())); + else if (aRect.GetWidth() > 2*aRect.GetHeight()) + aRect.SetSize(Size(2*aRect.GetHeight(), aRect.GetHeight())); + + return aRect; + } + return SfxObjectShell::GetVisArea( nAspect ); +} + +Printer *SwDocShell::GetDocumentPrinter() +{ + return m_xDoc->getIDocumentDeviceAccess().getPrinter( false ); +} + +OutputDevice* SwDocShell::GetDocumentRefDev() +{ + return m_xDoc->getIDocumentDeviceAccess().getReferenceDevice( false ); +} + +void SwDocShell::OnDocumentPrinterChanged( Printer * pNewPrinter ) +{ + if ( pNewPrinter ) + GetDoc()->getIDocumentDeviceAccess().setJobsetup( pNewPrinter->GetJobSetup() ); + else + GetDoc()->getIDocumentDeviceAccess().setPrinter( nullptr, true, true ); +} + +// #i20883# Digital Signatures and Encryption +HiddenInformation SwDocShell::GetHiddenInformationState( HiddenInformation nStates ) +{ + // get global state like HiddenInformation::DOCUMENTVERSIONS + HiddenInformation nState = SfxObjectShell::GetHiddenInformationState( nStates ); + + if ( nStates & HiddenInformation::RECORDEDCHANGES ) + { + if ( !GetDoc()->getIDocumentRedlineAccess().GetRedlineTable().empty() ) + nState |= HiddenInformation::RECORDEDCHANGES; + } + if ( nStates & HiddenInformation::NOTES ) + { + OSL_ENSURE( GetWrtShell(), "No SwWrtShell, no information" ); + if(GetWrtShell() && GetWrtShell()->GetFieldType(SwFieldIds::Postit, OUString())->HasHiddenInformationNotes()) + nState |= HiddenInformation::NOTES; + } + + return nState; +} + +void SwDocShell::GetState(SfxItemSet& rSet) +{ + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + + while (nWhich) + { + switch (nWhich) + { + case SID_PRINTPREVIEW: + { + bool bDisable = IsInPlaceActive(); + // Disable "multiple layout" + if ( !bDisable ) + { + SfxViewFrame *pTmpFrame = SfxViewFrame::GetFirst(this); + while (pTmpFrame) // Look for Preview + { + if ( auto pSwView = dynamic_cast<SwView*>( pTmpFrame->GetViewShell() ) ) + if (pSwView->GetWrtShell().GetViewOptions()->getBrowseMode()) + { + bDisable = true; + break; + } + pTmpFrame = SfxViewFrame::GetNext(*pTmpFrame, this); + } + } + // End of disabled "multiple layout" + if ( bDisable ) + rSet.DisableItem( SID_PRINTPREVIEW ); + else + { + SfxBoolItem aBool( SID_PRINTPREVIEW, false ); + if( dynamic_cast<SwPagePreview*>( SfxViewShell::Current()) ) + aBool.SetValue( true ); + rSet.Put( aBool ); + } + } + break; + case SID_AUTO_CORRECT_DLG: + if ( comphelper::LibreOfficeKit::isActive() ) + rSet.DisableItem( SID_AUTO_CORRECT_DLG ); + break; + case SID_SOURCEVIEW: + { + SfxViewShell* pCurrView = GetView() ? static_cast<SfxViewShell*>(GetView()) + : SfxViewShell::Current(); + bool bSourceView = dynamic_cast<SwSrcView*>( pCurrView ) != nullptr; + rSet.Put(SfxBoolItem(SID_SOURCEVIEW, bSourceView)); + } + break; + case SID_HTML_MODE: + rSet.Put(SfxUInt16Item(SID_HTML_MODE, ::GetHtmlMode(this))); + break; + + case FN_ABSTRACT_STARIMPRESS: + case FN_OUTLINE_TO_IMPRESS: + { + SvtModuleOptions aMOpt; + if (!aMOpt.IsImpress() || GetObjectShell()->isExportLocked()) + rSet.DisableItem( nWhich ); + } + [[fallthrough]]; + case FN_ABSTRACT_NEWDOC: + case FN_OUTLINE_TO_CLIPBOARD: + { + if ( GetDoc()->GetNodes().GetOutLineNds().empty() ) + rSet.DisableItem( nWhich ); + } + break; + case SID_BROWSER_MODE: + case FN_PRINT_LAYOUT: + { + bool bState = GetDoc()->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE); + if(FN_PRINT_LAYOUT == nWhich) + bState = !bState; + rSet.Put( SfxBoolItem( nWhich, bState)); + } + break; + + case FN_NEW_GLOBAL_DOC: + if (dynamic_cast<const SwGlobalDocShell*>(this) != nullptr + || GetObjectShell()->isExportLocked()) + rSet.DisableItem( nWhich ); + break; + + case FN_NEW_HTML_DOC: + if (dynamic_cast<const SwWebDocShell*>(this) != nullptr + || GetObjectShell()->isExportLocked()) + rSet.DisableItem( nWhich ); + break; + + case FN_OPEN_FILE: + if( dynamic_cast< const SwWebDocShell *>( this ) != nullptr ) + rSet.DisableItem( nWhich ); + break; + + case SID_ATTR_YEAR2000: + { + const SvNumberFormatter* pFormatr = m_xDoc->GetNumberFormatter(false); + rSet.Put( SfxUInt16Item( nWhich, + static_cast< sal_uInt16 >( + pFormatr ? pFormatr->GetYear2000() + : officecfg::Office::Common::DateFormat::TwoDigitYear::get())) ); + } + break; + case SID_ATTR_CHAR_FONTLIST: + { + rSet.Put( SvxFontListItem(m_pFontList.get(), SID_ATTR_CHAR_FONTLIST) ); + } + break; + case SID_MAIL_PREPAREEXPORT: + { + //check if linked content or possibly hidden content is available + //m_xDoc->UpdateFields( NULL, false ); + sfx2::LinkManager& rLnkMgr = m_xDoc->getIDocumentLinksAdministration().GetLinkManager(); + const ::sfx2::SvBaseLinks& rLnks = rLnkMgr.GetLinks(); + bool bRet = false; + if( !rLnks.empty() ) + bRet = true; + else + { + //sections with hidden flag, hidden character attribute, hidden paragraph/text or conditional text fields + bRet = m_xDoc->HasInvisibleContent(); + } + rSet.Put( SfxBoolItem( nWhich, bRet ) ); + } + break; + case SID_NOTEBOOKBAR: + { + SfxViewShell* pViewShell = GetView()? GetView(): SfxViewShell::Current(); + bool bVisible = sfx2::SfxNotebookBar::StateMethod(pViewShell->GetViewFrame().GetBindings(), + u"modules/swriter/ui/"); + rSet.Put( SfxBoolItem( SID_NOTEBOOKBAR, bVisible ) ); + } + break; + case FN_REDLINE_ACCEPT_ALL: + case FN_REDLINE_REJECT_ALL: + { + if (GetDoc()->getIDocumentRedlineAccess().GetRedlineTable().empty() || + HasChangeRecordProtection()) // tdf#128229 Disable Accept / Reject all if redlines are password protected + rSet.DisableItem(nWhich); + } + break; + + default: OSL_ENSURE(false,"You cannot get here!"); + + } + nWhich = aIter.NextWhich(); + } +} + +// OLE-Hdls +IMPL_LINK( SwDocShell, Ole2ModifiedHdl, bool, bNewStatus, void ) +{ + if (m_pWrtShell) + { + SwOLENode* pOLENode = nullptr; + if (!m_pWrtShell->IsTableMode()) + { + pOLENode = m_pWrtShell->GetCursor()->GetPointNode().GetOLENode(); + } + if (pOLENode) + { + if (pOLENode->GetOLEObj().IsProtected()) + { + return; + } + } + } + + if( IsEnableSetModified() ) + SetModified( bNewStatus ); +} + +// return Pool here, because virtual +SfxStyleSheetBasePool* SwDocShell::GetStyleSheetPool() +{ + return m_xBasePool.get(); +} + +sfx2::StyleManager* SwDocShell::GetStyleManager() +{ + return m_pStyleManager.get(); +} + +void SwDocShell::SetView(SwView* pVw) +{ + SetViewShell_Impl(pVw); + m_pView = pVw; + if (m_pView) + { + m_pWrtShell = &m_pView->GetWrtShell(); + + // Set view-specific redline author. + const OUString& rRedlineAuthor = m_pView->GetRedlineAuthor(); + if (!rRedlineAuthor.isEmpty()) + SW_MOD()->SetRedlineAuthor(m_pView->GetRedlineAuthor()); + } + else + m_pWrtShell = nullptr; +} + +// #i59688# +// linked graphics are now loaded on demand. +// Thus, loading of linked graphics no longer needed and necessary for +// the load of document being finished. +void SwDocShell::LoadingFinished() +{ + // #i38810# + // Original fix fails after integration of cws xmlsec11: + // interface <SfxObjectShell::EnableSetModified(..)> no longer works, because + // <SfxObjectShell::FinishedLoading(..)> doesn't care about its status and + // enables the document modification again. + // Thus, manual modify the document, if it's modified and its links are updated + // before <FinishedLoading(..)> is called. + const bool bHasDocToStayModified( m_xDoc->getIDocumentState().IsModified() && m_xDoc->getIDocumentLinksAdministration().LinksUpdated() ); + + FinishedLoading(); + SfxViewFrame* pVFrame = SfxViewFrame::GetFirst(this); + if(pVFrame) + { + SfxViewShell* pShell = pVFrame->GetViewShell(); + if(auto pSrcView = dynamic_cast<SwSrcView*>( pShell) ) + pSrcView->Load(this); + } + + // #i38810# + if ( bHasDocToStayModified && !m_xDoc->getIDocumentState().IsModified() ) + { + m_xDoc->getIDocumentState().SetModified(); + } +} + +// a Transfer is cancelled (is called from SFX) +void SwDocShell::CancelTransfers() +{ + // Cancel all links from LinkManager + m_xDoc->getIDocumentLinksAdministration().GetLinkManager().CancelTransfers(); + SfxObjectShell::CancelTransfers(); +} + +SwEditShell * SwDocShell::GetEditShell() +{ + return m_pWrtShell; +} + +SwFEShell* SwDocShell::GetFEShell() +{ + return m_pWrtShell; +} + +void SwDocShell::RemoveOLEObjects() +{ + SwIterator<SwContentNode,SwFormatColl> aIter( *m_xDoc->GetDfltGrfFormatColl() ); + for( SwContentNode* pNd = aIter.First(); pNd; pNd = aIter.Next() ) + { + SwOLENode* pOLENd = pNd->GetOLENode(); + if( pOLENd && ( pOLENd->IsOLEObjectDeleted() || + pOLENd->IsInGlobalDocSection() ) ) + { + if (!m_pOLEChildList) + m_pOLEChildList.reset( new comphelper::EmbeddedObjectContainer ); + + OUString aObjName = pOLENd->GetOLEObj().GetCurrentPersistName(); + GetEmbeddedObjectContainer().MoveEmbeddedObject( aObjName, *m_pOLEChildList ); + } + } +} + +// When a document is loaded, SwDoc::PrtOLENotify is called to update +// the sizes of math objects. However, for objects that do not have a +// SwFrame at this time, only a flag is set (bIsOLESizeInvalid) and the +// size change takes place later, while calculating the layout in the +// idle handler. If this document is saved now, it is saved with invalid +// sizes. For this reason, the layout has to be calculated before a document is +// saved, but of course only id there are OLE objects with bOLESizeInvalid set. +void SwDocShell::CalcLayoutForOLEObjects() +{ + if (!m_pWrtShell) + return; + + if (m_pView && m_pView->GetIPClient()) + { + // We have an active OLE edit: allow link updates, so an up to date replacement graphic can + // be created. + comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = getEmbeddedObjectContainer(); + rEmbeddedObjectContainer.setUserAllowsLinkUpdate(true); + } + + SwIterator<SwContentNode,SwFormatColl> aIter( *m_xDoc->GetDfltGrfFormatColl() ); + for( SwContentNode* pNd = aIter.First(); pNd; pNd = aIter.Next() ) + { + SwOLENode* pOLENd = pNd->GetOLENode(); + if( pOLENd && pOLENd->IsOLESizeInvalid() ) + { + m_pWrtShell->CalcLayout(); + break; + } + } +} + +// #i42634# Overwrites SfxObjectShell::UpdateLinks +// This new function is necessary to trigger update of links in docs +// read by the binary filter: +void SwDocShell::UpdateLinks() +{ + GetDoc()->getIDocumentLinksAdministration().UpdateLinks(); + // #i50703# Update footnote numbers + SwTextFootnote::SetUniqueSeqRefNo( *GetDoc() ); + SwNodeIndex aTmp( GetDoc()->GetNodes() ); + GetDoc()->GetFootnoteIdxs().UpdateFootnote( aTmp.GetNode() ); +} + +uno::Reference< frame::XController > + SwDocShell::GetController() +{ + css::uno::Reference< css::frame::XController > aRet; + // #i82346# No view in page preview + if ( GetView() ) + aRet = GetView()->GetController(); + return aRet; +} + +static const char* s_EventNames[] = +{ + "OnPageCountChange", + "OnMailMerge", + "OnMailMergeFinished", + "OnFieldMerge", + "OnFieldMergeFinished", + "OnLayoutFinished" +}; +sal_Int32 const s_nEvents(SAL_N_ELEMENTS(s_EventNames)); + +Sequence< OUString > SwDocShell::GetEventNames() +{ + Sequence< OUString > aRet = SfxObjectShell::GetEventNames(); + sal_Int32 nLen = aRet.getLength(); + aRet.realloc(nLen + 6); + OUString* pNames = aRet.getArray(); + pNames[nLen++] = GetEventName(0); + pNames[nLen++] = GetEventName(1); + pNames[nLen++] = GetEventName(2); + pNames[nLen++] = GetEventName(3); + pNames[nLen++] = GetEventName(4); + pNames[nLen] = GetEventName(5); + + return aRet; +} + +OUString SwDocShell::GetEventName( sal_Int32 nIndex ) +{ + if (nIndex < s_nEvents) + { + return OUString::createFromAscii(s_EventNames[nIndex]); + } + return OUString(); +} + +const ::sfx2::IXmlIdRegistry* SwDocShell::GetXmlIdRegistry() const +{ + return m_xDoc ? &m_xDoc->GetXmlIdRegistry() : nullptr; +} + +bool SwDocShell::IsChangeRecording() const +{ + if (!m_pWrtShell) + return false; + return bool(m_pWrtShell->GetRedlineFlags() & RedlineFlags::On); +} + +bool SwDocShell::HasChangeRecordProtection() const +{ + if (!m_pWrtShell) + return false; + return m_pWrtShell->getIDocumentRedlineAccess().GetRedlinePassword().hasElements(); +} + +void SwDocShell::SetChangeRecording( bool bActivate, bool bLockAllViews ) +{ + RedlineFlags nOn = bActivate ? RedlineFlags::On : RedlineFlags::NONE; + RedlineFlags nMode = m_pWrtShell->GetRedlineFlags(); + if (bLockAllViews) + { + // tdf#107870: prevent jumping to cursor + auto aViewGuard(LockAllViews()); + m_pWrtShell->SetRedlineFlagsAndCheckInsMode( (nMode & ~RedlineFlags::On) | nOn ); + } + else + { + m_pWrtShell->SetRedlineFlagsAndCheckInsMode( (nMode & ~RedlineFlags::On) | nOn ); + } +} + +void SwDocShell::SetProtectionPassword( const OUString &rNewPassword ) +{ + const SfxAllItemSet aSet( GetPool() ); + + IDocumentRedlineAccess& rIDRA = m_pWrtShell->getIDocumentRedlineAccess(); + Sequence< sal_Int8 > aPasswd = rIDRA.GetRedlinePassword(); + const SfxBoolItem* pRedlineProtectItem = aSet.GetItemIfSet(FN_REDLINE_PROTECT, false); + if (pRedlineProtectItem + && pRedlineProtectItem->GetValue() == aPasswd.hasElements()) + return; + + if (!rNewPassword.isEmpty()) + { + // when password protection is applied change tracking must always be active + SetChangeRecording( true ); + + Sequence< sal_Int8 > aNewPasswd; + SvPasswordHelper::GetHashPassword( aNewPasswd, rNewPassword ); + rIDRA.SetRedlinePassword( aNewPasswd ); + } + else + { + rIDRA.SetRedlinePassword( Sequence< sal_Int8 >() ); + } +} + +bool SwDocShell::GetProtectionHash( /*out*/ css::uno::Sequence< sal_Int8 > &rPasswordHash ) +{ + bool bRes = false; + + const SfxAllItemSet aSet( GetPool() ); + + IDocumentRedlineAccess& rIDRA = m_pWrtShell->getIDocumentRedlineAccess(); + const Sequence< sal_Int8 >& aPasswdHash( rIDRA.GetRedlinePassword() ); + const SfxBoolItem* pRedlineProtectItem = aSet.GetItemIfSet(FN_REDLINE_PROTECT, false); + if (pRedlineProtectItem + && pRedlineProtectItem->GetValue() == aPasswdHash.hasElements()) + return false; + rPasswordHash = aPasswdHash; + bRes = true; + + return bRes; +} + +void SwDocShell::RegisterAutomationDocumentEventsCaller(css::uno::Reference< ooo::vba::XSinkCaller > const& xCaller) +{ + mxAutomationDocumentEventsCaller = xCaller; +} + +void SwDocShell::CallAutomationDocumentEventSinks(const OUString& Method, css::uno::Sequence< css::uno::Any >& Arguments) +{ + if (mxAutomationDocumentEventsCaller.is()) + mxAutomationDocumentEventsCaller->CallSinks(Method, Arguments); +} + +void SwDocShell::RegisterAutomationDocumentObject(css::uno::Reference< ooo::vba::word::XDocument > const& xDocument) +{ + mxAutomationDocumentObject = xDocument; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/app/docsh2.cxx b/sw/source/uibase/app/docsh2.cxx new file mode 100644 index 0000000000..47c8a3ec65 --- /dev/null +++ b/sw/source/uibase/app/docsh2.cxx @@ -0,0 +1,1805 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; fill-column: 100 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <config_features.h> + +#include <osl/diagnose.h> +#include <com/sun/star/drawing/ModuleDispatcher.hpp> +#include <com/sun/star/frame/DispatchHelper.hpp> +#include <ooo/vba/word/XDocument.hpp> +#include <comphelper/fileformat.h> +#include <comphelper/processfactory.hxx> +#include <comphelper/propertyvalue.hxx> +#include <comphelper/string.hxx> + +#include <sal/log.hxx> +#include <edtwin.hxx> +#include <tools/urlobj.hxx> +#include <unotools/tempfile.hxx> +#include <unotools/configmgr.hxx> +#include <vcl/errinf.hxx> +#include <vcl/svapp.hxx> +#include <vcl/weld.hxx> +#include <svl/eitem.hxx> +#include <svl/macitem.hxx> +#include <unotools/pathoptions.hxx> +#include <vcl/transfer.hxx> +#include <sfx2/dinfdlg.hxx> +#include <sfx2/request.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/new.hxx> +#include <sfx2/notebookbar/SfxNotebookBar.hxx> +#include <sfx2/filedlghelper.hxx> +#include <sfx2/printer.hxx> +#include <sfx2/evntconf.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/docfilt.hxx> +#include <svx/dialogs.hrc> +#include <svx/drawitem.hxx> +#include <editeng/svxacorr.hxx> +#include <svx/fmshell.hxx> +#include <sfx2/linkmgr.hxx> +#include <sfx2/classificationhelper.hxx> +#include <sfx2/watermarkitem.hxx> + +#include <svx/ofaitem.hxx> +#include <SwSmartTagMgr.hxx> +#include <sfx2/app.hxx> +#include <basic/sbstar.hxx> +#include <basic/basmgr.hxx> +#include <comphelper/classids.hxx> +#include <fmtcol.hxx> +#include <istype.hxx> +#include <view.hxx> +#include <docsh.hxx> +#include <docary.hxx> +#include <wrtsh.hxx> +#include <rootfrm.hxx> +#include <fldbas.hxx> +#include <viewopt.hxx> +#include <globdoc.hxx> +#include <fldwrap.hxx> +#include <redlndlg.hxx> +#include <doc.hxx> +#include <IDocumentUndoRedo.hxx> +#include <IDocumentSettingAccess.hxx> +#include <IDocumentDeviceAccess.hxx> +#include <IDocumentLinksAdministration.hxx> +#include <IDocumentFieldsAccess.hxx> +#include <IDocumentStatistics.hxx> +#include <IDocumentLayoutAccess.hxx> +#include <IDocumentRedlineAccess.hxx> +#include <IDocumentState.hxx> +#include <shellio.hxx> +#include <pview.hxx> +#include <srcview.hxx> +#include <wdocsh.hxx> +#include <unotxdoc.hxx> +#include <acmplwrd.hxx> +#include <swmodule.hxx> +#include <unobaseclass.hxx> +#include <swwait.hxx> +#include <swcli.hxx> + +#include <cmdid.h> +#include <helpids.h> +#include <strings.hrc> +#include <com/sun/star/ui/dialogs/XFilePicker3.hpp> +#include <com/sun/star/ui/dialogs/XFilePickerControlAccess.hpp> +#include <com/sun/star/ui/dialogs/ExtendedFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/ListboxControlActions.hpp> +#include <com/sun/star/ui/dialogs/CommonFilePickerElementIds.hpp> +#include <com/sun/star/ui/dialogs/TemplateDescription.hpp> +#include <com/sun/star/script/vba/XVBAEventProcessor.hpp> +#include <com/sun/star/script/vba/VBAEventId.hpp> +#include <editeng/acorrcfg.hxx> +#include <officecfg/Office/Security.hxx> +#include <officecfg/Office/Common.hxx> + +#include <sfx2/fcontnr.hxx> +#include <svx/ClassificationDialog.hxx> +#include <svtools/embedhlp.hxx> + +#include <swabstdlg.hxx> +#include <watermarkdialog.hxx> + +#include <ndtxt.hxx> +#include <iodetect.hxx> + +#include <memory> + +using namespace ::com::sun::star::ui::dialogs; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star; +using namespace ::sfx2; + +// create DocInfo (virtual) +std::shared_ptr<SfxDocumentInfoDialog> SwDocShell::CreateDocumentInfoDialog(weld::Window* pParent, const SfxItemSet &rSet) +{ + std::shared_ptr<SfxDocumentInfoDialog> xDlg = std::make_shared<SfxDocumentInfoDialog>(pParent, rSet); + //only with statistics, when this document is being shown, not + //from within the Doc-Manager + SwDocShell* pDocSh = static_cast<SwDocShell*>( SfxObjectShell::Current()); + if( pDocSh == this ) + { + //Not for SourceView. + SfxViewShell *pVSh = SfxViewShell::Current(); + if ( pVSh && dynamic_cast< const SwSrcView *>( pVSh ) == nullptr ) + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + xDlg->AddFontTabPage(); + xDlg->AddTabPage("writerstats", SwResId(STR_DOC_STAT), pFact->GetTabPageCreatorFunc(RID_SW_TP_DOC_STAT)); + } + } + return xDlg; +} + +void SwDocShell::ToggleLayoutMode(SwView* pView) +{ + OSL_ENSURE( pView, "SwDocShell::ToggleLayoutMode, pView is null." ); + + const SwViewOption& rViewOptions = *pView->GetWrtShell().GetViewOptions(); + + //TODO: Should HideWhitespace flag be saved in the document settings? + GetDoc()->getIDocumentSettingAccess().set(DocumentSettingId::BROWSE_MODE, rViewOptions.getBrowseMode()); + UpdateFontList(); // Why is this necessary here? + + pView->GetViewFrame().GetBindings().Invalidate(FN_SHADOWCURSOR); + if( !GetDoc()->getIDocumentDeviceAccess().getPrinter( false ) ) + pView->SetPrinter( GetDoc()->getIDocumentDeviceAccess().getPrinter( false ), SfxPrinterChangeFlags::PRINTER | SfxPrinterChangeFlags::JOBSETUP ); + GetDoc()->CheckDefaultPageFormat(); + SfxViewFrame *pTmpFrame = SfxViewFrame::GetFirst(this, false); + while (pTmpFrame) + { + if( pTmpFrame != &pView->GetViewFrame() ) + { + pTmpFrame->DoClose(); + pTmpFrame = SfxViewFrame::GetFirst(this, false); + } + else + pTmpFrame = SfxViewFrame::GetNext(*pTmpFrame, this, false); + } + + pView->GetWrtShell().InvalidateLayout(true); + + pView->RecheckBrowseMode(); + + pView->SetNewWindowAllowed(!rViewOptions.getBrowseMode()); +} + +// update text fields on document properties changes +void SwDocShell::DoFlushDocInfo() +{ + if (!m_xDoc) + return; + + bool bUnlockView(true); + if (m_pWrtShell) + { + bUnlockView = !m_pWrtShell->IsViewLocked(); + m_pWrtShell->LockView( true ); // lock visible section + m_pWrtShell->StartAllAction(); + } + + m_xDoc->getIDocumentStatistics().DocInfoChgd(IsEnableSetModified()); + + if (m_pWrtShell) + { + m_pWrtShell->EndAllAction(); + if (bUnlockView) + { + m_pWrtShell->LockView( false ); + } + } +} + +static void lcl_processCompatibleSfxHint( const uno::Reference< script::vba::XVBAEventProcessor >& xVbaEvents, const SfxHint& rHint ) +{ + using namespace com::sun::star::script::vba::VBAEventId; + if (rHint.GetId() != SfxHintId::ThisIsAnSfxEventHint) + return; + + uno::Sequence< uno::Any > aArgs; + switch (static_cast<const SfxEventHint&>(rHint).GetEventId()) + { + case SfxEventHintId::CreateDoc: + xVbaEvents->processVbaEvent(AUTO_NEW, aArgs); + xVbaEvents->processVbaEvent(DOCUMENT_NEW, aArgs); + break; + case SfxEventHintId::OpenDoc: + xVbaEvents->processVbaEvent(AUTO_OPEN, aArgs); + xVbaEvents->processVbaEvent(DOCUMENT_OPEN, aArgs); + break; + default: break; + } +} + +// Notification on DocInfo changes +void SwDocShell::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if (!m_xDoc) + { + return ; + } + + uno::Reference< script::vba::XVBAEventProcessor > const xVbaEvents = + m_xDoc->GetVbaEventProcessor(); + if( xVbaEvents.is() ) + lcl_processCompatibleSfxHint( xVbaEvents, rHint ); + + if (rHint.GetId() == SfxHintId::ThisIsAnSfxEventHint) + { + switch (static_cast<const SfxEventHint&>(rHint).GetEventId()) + { + case SfxEventHintId::ActivateDoc: + case SfxEventHintId::CreateDoc: + case SfxEventHintId::OpenDoc: + { + uno::Sequence< css::uno::Any > aArgs; + SW_MOD()->CallAutomationApplicationEventSinks( "DocumentChange", aArgs ); + break; + } + default: + break; + } + + switch (static_cast<const SfxEventHint&>(rHint).GetEventId()) + { + case SfxEventHintId::CreateDoc: + { + uno::Any aDocument; + aDocument <<= mxAutomationDocumentObject; + uno::Sequence< uno::Any > aArgs{ aDocument }; + SW_MOD()->CallAutomationApplicationEventSinks( "NewDocument", aArgs ); + } + break; + case SfxEventHintId::OpenDoc: + { + uno::Any aDocument; + aDocument <<= mxAutomationDocumentObject; + uno::Sequence< uno::Any > aArgs{ aDocument }; + SW_MOD()->CallAutomationApplicationEventSinks( "DocumentOpen", aArgs ); + } + break; + default: + break; + } + } + + sal_uInt16 nAction = 0; + if (rHint.GetId() == SfxHintId::ThisIsAnSfxEventHint && + static_cast<const SfxEventHint&>(rHint).GetEventId() == SfxEventHintId::LoadFinished) + { + // #i38126# - own action id + nAction = 3; + } + else + { + // switch for more actions + if( rHint.GetId() == SfxHintId::TitleChanged) + { + if( GetMedium() ) + nAction = 2; + } + } + + if( !nAction ) + return; + + bool bUnlockView = true; //initializing prevents warning + if (m_pWrtShell) + { + bUnlockView = !m_pWrtShell->IsViewLocked(); + m_pWrtShell->LockView( true ); //lock visible section + m_pWrtShell->StartAllAction(); + } + switch( nAction ) + { + case 2: + m_xDoc->getIDocumentFieldsAccess().GetSysFieldType( SwFieldIds::Filename )->UpdateFields(); + break; + // #i38126# - own action for event LOADFINISHED + // in order to avoid a modified document. + // #i41679# - Also for the instance of <SwDoc> + // it has to be assured, that it's not modified. + // Perform the same as for action id 1, but disable <SetModified>. + case 3: + { + const bool bResetModified = IsEnableSetModified(); + if ( bResetModified ) + EnableSetModified( false ); + // #i41679# + const bool bIsDocModified = m_xDoc->getIDocumentState().IsModified(); + // TODO: is the ResetModified() below because of only the direct call from DocInfoChgd, or does UpdateFields() set it too? + + m_xDoc->getIDocumentStatistics().DocInfoChgd(false); + + // #i41679# + if ( !bIsDocModified ) + m_xDoc->getIDocumentState().ResetModified(); + if ( bResetModified ) + EnableSetModified(); + } + break; + } + + if (m_pWrtShell) + { + m_pWrtShell->EndAllAction(); + if( bUnlockView ) + m_pWrtShell->LockView( false ); + } +} + +// Notification Close Doc +bool SwDocShell::PrepareClose( bool bUI ) +{ + bool bRet = SfxObjectShell::PrepareClose( bUI ); + + // If we are going to close it at this point, let potential DocumentBeforeClose event handlers + // in Automation clients veto it. + if (bRet && m_xDoc && IsInPrepareClose()) + { + uno::Any aDocument; + aDocument <<= mxAutomationDocumentObject; + + uno::Sequence<uno::Any> aArgs{ // Arg 0: Document + aDocument, + // Arg 1: Cancel + uno::Any(false) + }; + + SW_MOD()->CallAutomationApplicationEventSinks( "DocumentBeforeClose", aArgs ); + + // If the Cancel argument was set to True by an event handler, return false. + bool bCancel(false); + aArgs[1] >>= bCancel; + if (bCancel) + bRet = false; + } + + if( bRet ) + EndListening( *this ); + + if (m_xDoc && IsInPrepareClose()) + { + uno::Reference< script::vba::XVBAEventProcessor > const xVbaEvents = + m_xDoc->GetVbaEventProcessor(); + if( xVbaEvents.is() ) + { + using namespace com::sun::star::script::vba::VBAEventId; + uno::Sequence< uno::Any > aNoArgs; + xVbaEvents->processVbaEvent(AUTO_CLOSE, aNoArgs); + xVbaEvents->processVbaEvent(DOCUMENT_CLOSE, aNoArgs); + } + } + return bRet; +} + +void SwDocShell::Execute(SfxRequest& rReq) +{ + const SfxItemSet* pArgs = rReq.GetArgs(); + const SfxPoolItem* pItem; + sal_uInt16 nWhich = rReq.GetSlot(); + bool bDone = false; + switch ( nWhich ) + { + case SID_AUTO_CORRECT_DLG: + { + SvxSwAutoFormatFlags* pAFlags = &SvxAutoCorrCfg::Get().GetAutoCorrect()->GetSwFlags(); + SwAutoCompleteWord& rACW = SwDoc::GetAutoCompleteWords(); + + bool bOldLocked = rACW.IsLockWordLstLocked(), + bOldAutoCmpltCollectWords = pAFlags->bAutoCmpltCollectWords; + + rACW.SetLockWordLstLocked( true ); + + editeng::SortedAutoCompleteStrings aTmpLst( rACW.GetWordList().createNonOwningCopy() ); + pAFlags->m_pAutoCompleteList = &aTmpLst; + + SfxApplication* pApp = SfxGetpApp(); + SfxRequest aAppReq(SID_AUTO_CORRECT_DLG, SfxCallMode::SYNCHRON, pApp->GetPool()); + SfxBoolItem aSwOptions( SID_AUTO_CORRECT_DLG, true ); + aAppReq.AppendItem(aSwOptions); + + pAFlags->pSmartTagMgr = &SwSmartTagMgr::Get(); + + SfxItemSetFixed<SID_AUTO_CORRECT_DLG, SID_AUTO_CORRECT_DLG, SID_OPEN_SMARTTAGOPTIONS, SID_OPEN_SMARTTAGOPTIONS> aSet( pApp->GetPool() ); + aSet.Put( aSwOptions ); + + const SfxBoolItem* pOpenSmartTagOptionsItem = nullptr; + if( pArgs && (pOpenSmartTagOptionsItem = pArgs->GetItemIfSet( SID_OPEN_SMARTTAGOPTIONS, false )) ) + aSet.Put( *pOpenSmartTagOptionsItem ); + + SfxAbstractDialogFactory* pFact = SfxAbstractDialogFactory::Create(); + VclPtr<SfxAbstractTabDialog> pDlg = pFact->CreateAutoCorrTabDialog(GetView()->GetFrameWeld(), &aSet); + pDlg->Execute(); + pDlg.disposeAndClear(); + + + rACW.SetLockWordLstLocked( bOldLocked ); + + SwEditShell::SetAutoFormatFlags( pAFlags ); + rACW.SetMinWordLen( pAFlags->nAutoCmpltWordLen ); + rACW.SetMaxCount( pAFlags->nAutoCmpltListLen ); + if (pAFlags->m_pAutoCompleteList) // any changes? + { + rACW.CheckChangedList( aTmpLst ); + // clear the temp WordList pointer + pAFlags->m_pAutoCompleteList = nullptr; + } + + if( !bOldAutoCmpltCollectWords && bOldAutoCmpltCollectWords != + pAFlags->bAutoCmpltCollectWords ) + { + // call on all Docs the idle formatter to start + // the collection of Words + for( SwDocShell *pDocSh = static_cast<SwDocShell*>(SfxObjectShell::GetFirst(checkSfxObjectShell<SwDocShell>)); + pDocSh; + pDocSh = static_cast<SwDocShell*>(SfxObjectShell::GetNext( *pDocSh, checkSfxObjectShell<SwDocShell> )) ) + { + SwDoc* pTmp = pDocSh->GetDoc(); + if ( pTmp->getIDocumentLayoutAccess().GetCurrentViewShell() ) + pTmp->InvalidateAutoCompleteFlag(); + } + } + } + break; + + case SID_PRINTPREVIEW: + { + bool bSet = false; + bool bFound = false, bOnly = true; + SfxViewFrame *pTmpFrame = SfxViewFrame::GetFirst(this); + SfxViewShell* pViewShell = SfxViewShell::Current(); + SwView* pCurrView = dynamic_cast< SwView *> ( pViewShell ); + bool bCurrent = isType<SwPagePreview>( pViewShell ); + + while( pTmpFrame ) // search Preview + { + if( isType<SwView>( pTmpFrame->GetViewShell()) ) + bOnly = false; + else if( isType<SwPagePreview>( pTmpFrame->GetViewShell())) + { + pTmpFrame->GetFrame().Appear(); + bFound = true; + } + if( bFound && !bOnly ) + break; + pTmpFrame = SfxViewFrame::GetNext(*pTmpFrame, this); + } + + if( pArgs && SfxItemState::SET == + pArgs->GetItemState( SID_PRINTPREVIEW, false, &pItem )) + bSet = static_cast<const SfxBoolItem*>(pItem)->GetValue(); + else + bSet = !bCurrent; + + sal_uInt16 nSlotId = 0; + if( bSet && !bFound ) // Nothing found, so create new Preview + nSlotId = SID_VIEWSHELL1; + else if( bFound && !bSet ) + nSlotId = bOnly ? SID_VIEWSHELL0 : SID_VIEWSHELL1; + + if( nSlotId ) + { + // PagePreview in the WebDocShell + // is found under Id VIEWSHELL2. + if( dynamic_cast< const SwWebDocShell *>( this ) != nullptr && SID_VIEWSHELL1 == nSlotId ) + nSlotId = SID_VIEWSHELL2; + + if( pCurrView && pCurrView->GetDocShell() == this ) + pTmpFrame = &pCurrView->GetViewFrame(); + else + pTmpFrame = SfxViewFrame::GetFirst( this ); + + if (pTmpFrame) + pTmpFrame->GetDispatcher()->Execute( nSlotId, SfxCallMode::ASYNCHRON ); + } + + rReq.SetReturnValue(SfxBoolItem(SID_PRINTPREVIEW, bSet )); + } + break; + case SID_TEMPLATE_LOAD: + { + OUString aFileName; + static bool bText = true; + static bool bFrame = false; + static bool bPage = false; + static bool bNum = false; + static bool bMerge = false; + + SfxTemplateFlags nFlags = bFrame ? SfxTemplateFlags::LOAD_FRAME_STYLES : SfxTemplateFlags::NONE; + if(bPage) + nFlags |= SfxTemplateFlags::LOAD_PAGE_STYLES; + if(bNum) + nFlags |= SfxTemplateFlags::LOAD_NUM_STYLES; + if(nFlags == SfxTemplateFlags::NONE || bText) + nFlags |= SfxTemplateFlags::LOAD_TEXT_STYLES; + if(bMerge) + nFlags |= SfxTemplateFlags::MERGE_STYLES; + + if ( pArgs ) + { + const SfxStringItem* pTemplateItem = rReq.GetArg<SfxStringItem>(SID_TEMPLATE_NAME); + if ( pTemplateItem ) + { + aFileName = pTemplateItem->GetValue(); + const SfxInt32Item* pFlagsItem = rReq.GetArg<SfxInt32Item>(SID_TEMPLATE_LOAD); + if ( pFlagsItem ) + nFlags = static_cast<SfxTemplateFlags>(o3tl::narrowing<sal_uInt16>(pFlagsItem->GetValue())); + } + } + + if ( aFileName.isEmpty() ) + { + SfxNewFileDialog aNewFileDlg(GetView()->GetFrameWeld(), SfxNewFileDialogMode::LoadTemplate); + aNewFileDlg.SetTemplateFlags(nFlags); + + sal_uInt16 nRet = aNewFileDlg.run(); + if(RET_TEMPLATE_LOAD == nRet) + { + FileDialogHelper aDlgHelper(TemplateDescription::FILEOPEN_SIMPLE, + FileDialogFlags::NONE, GetView()->GetFrameWeld()); + aDlgHelper.SetContext(FileDialogHelper::WriterLoadTemplate); + uno::Reference < XFilePicker3 > xFP = aDlgHelper.GetFilePicker(); + + SfxObjectFactory &rFact = GetFactory(); + SfxFilterMatcher aMatcher( rFact.GetFactoryName() ); + SfxFilterMatcherIter aIter( aMatcher ); + std::shared_ptr<const SfxFilter> pFlt = aIter.First(); + while( pFlt ) + { + // --> OD #i117339# + if( pFlt && pFlt->IsAllowedAsTemplate() && + ( pFlt->GetUserData() == "CXML" || + pFlt->GetUserData() == "CXMLV" ) ) + { + const OUString sWild = pFlt->GetWildcard().getGlob(); + xFP->appendFilter( pFlt->GetUIName(), sWild ); + } + pFlt = aIter.Next(); + } + bool bWeb = dynamic_cast< SwWebDocShell *>( this ) != nullptr; + std::shared_ptr<const SfxFilter> pOwnFlt = + SwDocShell::Factory().GetFilterContainer()-> + GetFilter4FilterName("writer8"); + + // make sure the default file format is also available + if(bWeb) + { + const OUString sWild = pOwnFlt->GetWildcard().getGlob(); + xFP->appendFilter( pOwnFlt->GetUIName(), sWild ); + } + + bool bError = false; + // catch exception if wrong filter is selected - should not happen anymore + try + { + xFP->setCurrentFilter( pOwnFlt->GetUIName() ); + } + catch (const uno::Exception&) + { + bError = true; + } + + if( !bError && ERRCODE_NONE == aDlgHelper.Execute() ) + { + aFileName = xFP->getSelectedFiles().getConstArray()[0]; + } + } + else if( RET_OK == nRet) + { + aFileName = aNewFileDlg.GetTemplateFileName(); + } + + nFlags = aNewFileDlg.GetTemplateFlags(); + rReq.AppendItem( SfxStringItem( SID_TEMPLATE_NAME, aFileName ) ); + rReq.AppendItem( SfxInt32Item( SID_TEMPLATE_LOAD, static_cast<tools::Long>(nFlags) ) ); + } + + if( !aFileName.isEmpty() ) + { + SwgReaderOption aOpt; + bText = bool(nFlags & SfxTemplateFlags::LOAD_TEXT_STYLES ); + aOpt.SetTextFormats(bText); + bFrame = bool(nFlags & SfxTemplateFlags::LOAD_FRAME_STYLES); + aOpt.SetFrameFormats(bFrame); + bPage = bool(nFlags & SfxTemplateFlags::LOAD_PAGE_STYLES ); + aOpt.SetPageDescs(bPage); + bNum = bool(nFlags & SfxTemplateFlags::LOAD_NUM_STYLES ); + aOpt.SetNumRules(bNum); + //different meaning between SFX_MERGE_STYLES and aOpt.SetMerge! + bMerge = bool(nFlags & SfxTemplateFlags::MERGE_STYLES); + aOpt.SetMerge( !bMerge ); + + SetError(LoadStylesFromFile(aFileName, aOpt, false)); + if ( !GetErrorIgnoreWarning() ) + rReq.Done(); + } + } + break; + case SID_SOURCEVIEW: + { + SfxViewShell* pViewShell = GetView() + ? static_cast<SfxViewShell*>(GetView()) + : SfxViewShell::Current(); + SfxViewFrame& rViewFrame = pViewShell->GetViewFrame(); + SwSrcView* pSrcView = dynamic_cast< SwSrcView *>( pViewShell ); + if(!pSrcView) + { + // 3 possible state: + // 1 - file unsaved -> save as HTML + // 2 - file modified and HTML filter active -> save + // 3 - file saved in non-HTML -> QueryBox to save as HTML + std::shared_ptr<const SfxFilter> pHtmlFlt = + SwIoSystem::GetFilterOfFormat( + u"HTML", + SwWebDocShell::Factory().GetFilterContainer() ); + bool bLocalHasName = HasName(); + if(bLocalHasName) + { + //check for filter type + std::shared_ptr<const SfxFilter> pFlt = GetMedium()->GetFilter(); + if(!pFlt || pFlt->GetUserData() != pHtmlFlt->GetUserData()) + { + std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(rViewFrame.GetFrameWeld(), "modules/swriter/ui/saveashtmldialog.ui")); + std::unique_ptr<weld::MessageDialog> xQuery(xBuilder->weld_message_dialog("SaveAsHTMLDialog")); + if (RET_YES == xQuery->run()) + bLocalHasName = false; + else + break; + } + } + if(!bLocalHasName) + { + FileDialogHelper aDlgHelper(TemplateDescription::FILESAVE_AUTOEXTENSION, + FileDialogFlags::NONE, + GetView()->GetFrameWeld()); + aDlgHelper.SetContext(FileDialogHelper::WriterSaveHTML); + aDlgHelper.AddFilter( pHtmlFlt->GetFilterName(), pHtmlFlt->GetDefaultExtension() ); + aDlgHelper.SetCurrentFilter( pHtmlFlt->GetFilterName() ); + if( ERRCODE_NONE != aDlgHelper.Execute()) + { + break; + } + OUString sPath = aDlgHelper.GetPath(); + SfxStringItem aName(SID_FILE_NAME, sPath); + SfxStringItem aFilter(SID_FILTER_NAME, pHtmlFlt->GetName()); + const SfxPoolItemHolder aResult( + rViewFrame.GetDispatcher()->ExecuteList( + SID_SAVEASDOC, SfxCallMode::SYNCHRON, + { &aName, &aFilter })); + const SfxBoolItem* pBool(static_cast<const SfxBoolItem*>(aResult.getItem())); + if(!pBool || !pBool->GetValue()) + break; + } + } + + assert(dynamic_cast<SwWebDocShell*>(this) && "SourceView only in WebDocShell"); + + // the SourceView is not the 1 for SwWebDocShell + sal_uInt16 nSlot = SID_VIEWSHELL1; + bool bSetModified = false; + VclPtr<SfxPrinter> pSavePrinter; + if( nullptr != pSrcView) + { + SfxPrinter* pTemp = GetDoc()->getIDocumentDeviceAccess().getPrinter( false ); + if(pTemp) + pSavePrinter = VclPtr<SfxPrinter>::Create(*pTemp); + bSetModified = IsModified() || pSrcView->IsModified(); + if(pSrcView->IsModified()||pSrcView->HasSourceSaved()) + { + utl::TempFileNamed aTempFile; + aTempFile.EnableKillingFile(); + pSrcView->SaveContent(aTempFile.GetURL()); + bDone = true; + SvxMacro aMac(OUString(), OUString(), STARBASIC); + SfxEventConfiguration::ConfigureEvent(GlobalEventConfig::GetEventName( GlobalEventId::OPENDOC ), aMac, this); + SfxEventConfiguration::ConfigureEvent(GlobalEventConfig::GetEventName( GlobalEventId::PREPARECLOSEDOC ), aMac, this); + SfxEventConfiguration::ConfigureEvent(GlobalEventConfig::GetEventName( GlobalEventId::ACTIVATEDOC ), aMac, this); + SfxEventConfiguration::ConfigureEvent(GlobalEventConfig::GetEventName( GlobalEventId::DEACTIVATEDOC ), aMac, this); + ReloadFromHtml(aTempFile.GetURL(), pSrcView); + nSlot = 0; + } + else + { + nSlot = SID_VIEWSHELL0; + } + } + if (nSlot) + rViewFrame.GetDispatcher()->Execute(nSlot, SfxCallMode::SYNCHRON); + if(bSetModified) + GetDoc()->getIDocumentState().SetModified(); + if(pSavePrinter) + { + GetDoc()->getIDocumentDeviceAccess().setPrinter( pSavePrinter, true, true); + //pSavePrinter must not be deleted again + } + rViewFrame.GetBindings().SetState(SfxBoolItem(SID_SOURCEVIEW, false)); // not SID_VIEWSHELL2 + rViewFrame.GetBindings().Invalidate( SID_NEWWINDOW ); + rViewFrame.GetBindings().Invalidate( SID_BROWSER_MODE ); + rViewFrame.GetBindings().Invalidate( FN_PRINT_LAYOUT ); + } + break; + case SID_GET_COLORLIST: + { + const SvxColorListItem* pColItem = GetItem(SID_COLOR_TABLE); + const XColorListRef& pList = pColItem->GetColorList(); + rReq.SetReturnValue(OfaXColorListItem(SID_GET_COLORLIST, pList)); + } + break; + case FN_ABSTRACT_STARIMPRESS: + case FN_ABSTRACT_NEWDOC: + { + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + ScopedVclPtr<AbstractSwInsertAbstractDlg> pDlg(pFact->CreateSwInsertAbstractDlg(GetView()->GetFrameWeld())); + if(RET_OK == pDlg->Execute()) + { + sal_uInt8 nLevel = pDlg->GetLevel(); + sal_uInt8 nPara = pDlg->GetPara(); + SwDoc* pSmryDoc = new SwDoc(); + SfxObjectShellLock xDocSh(new SwDocShell(*pSmryDoc, SfxObjectCreateMode::STANDARD)); + xDocSh->DoInitNew(); + + bool bImpress = FN_ABSTRACT_STARIMPRESS == nWhich; + m_xDoc->Summary(*pSmryDoc, nLevel, nPara, bImpress); + if( bImpress ) + { + WriterRef xWrt; + // mba: looks as if relative URLs don't make sense here + ::GetRTFWriter(std::u16string_view(), OUString(), xWrt); + SvMemoryStream *pStrm = new SvMemoryStream(); + pStrm->SetBufferSize( 16348 ); + SwWriter aWrt( *pStrm, *pSmryDoc ); + ErrCodeMsg eErr = aWrt.Write( xWrt ); + if( !eErr.IgnoreWarning() ) + { + uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext(); + uno::Reference< frame::XDispatchProvider > xProv = drawing::ModuleDispatcher::create( xContext ); + + uno::Reference< frame::XDispatchHelper > xHelper( frame::DispatchHelper::create(xContext) ); + pStrm->Seek( STREAM_SEEK_TO_END ); + pStrm->WriteChar( '\0' ); + pStrm->Seek( STREAM_SEEK_TO_BEGIN ); + + // Transfer ownership of stream to a lockbytes object + SvLockBytes aLockBytes( pStrm, true ); + SvLockBytesStat aStat; + if ( aLockBytes.Stat( &aStat ) == ERRCODE_NONE ) + { + sal_uInt32 nLen = aStat.nSize; + std::size_t nRead = 0; + uno::Sequence< sal_Int8 > aSeq( nLen ); + aLockBytes.ReadAt( 0, aSeq.getArray(), nLen, &nRead ); + + uno::Sequence< beans::PropertyValue > aArgs{ + comphelper::makePropertyValue("RtfOutline", aSeq) + }; + xHelper->executeDispatch( xProv, "SendOutlineToImpress", OUString(), 0, aArgs ); + } + } + else + ErrorHandler::HandleError( eErr ); + } + else + { + // Create new document + SfxViewFrame *pFrame = SfxViewFrame::LoadDocument( *xDocSh, SFX_INTERFACE_NONE ); + SwView *pCurrView = static_cast<SwView*>( pFrame->GetViewShell()); + + // Set document's title + OUString aTmp = SwResId(STR_ABSTRACT_TITLE) + GetTitle(); + xDocSh->SetTitle( aTmp ); + pCurrView->GetWrtShell().SetNewDoc(); + pFrame->Show(); + pSmryDoc->getIDocumentState().SetModified(); + } + + } + } + break; + case FN_OUTLINE_TO_CLIPBOARD: + case FN_OUTLINE_TO_IMPRESS: + { + bool bEnable = IsEnableSetModified(); + EnableSetModified( false ); + WriterRef xWrt; + // mba: looks as if relative URLs don't make sense here + ::GetRTFWriter( u"O", OUString(), xWrt ); + std::unique_ptr<SvMemoryStream> pStrm (new SvMemoryStream()); + pStrm->SetBufferSize( 16348 ); + SwWriter aWrt( *pStrm, *GetDoc() ); + ErrCodeMsg eErr = aWrt.Write( xWrt ); + EnableSetModified( bEnable ); + if( !eErr.IgnoreWarning() ) + { + pStrm->Seek( STREAM_SEEK_TO_END ); + pStrm->WriteChar( '\0' ); + pStrm->Seek( STREAM_SEEK_TO_BEGIN ); + if ( nWhich == FN_OUTLINE_TO_IMPRESS ) + { + uno::Reference< uno::XComponentContext > xContext = ::comphelper::getProcessComponentContext(); + uno::Reference< frame::XDispatchProvider > xProv = drawing::ModuleDispatcher::create( xContext ); + + uno::Reference< frame::XDispatchHelper > xHelper( frame::DispatchHelper::create(xContext) ); + pStrm->Seek( STREAM_SEEK_TO_END ); + pStrm->WriteChar( '\0' ); + pStrm->Seek( STREAM_SEEK_TO_BEGIN ); + + // Transfer ownership of stream to a lockbytes object + SvLockBytes aLockBytes( pStrm.release(), true ); + SvLockBytesStat aStat; + if ( aLockBytes.Stat( &aStat ) == ERRCODE_NONE ) + { + sal_uInt32 nLen = aStat.nSize; + std::size_t nRead = 0; + uno::Sequence< sal_Int8 > aSeq( nLen ); + aLockBytes.ReadAt( 0, aSeq.getArray(), nLen, &nRead ); + + uno::Sequence< beans::PropertyValue > aArgs{ + comphelper::makePropertyValue("RtfOutline", aSeq) + }; + xHelper->executeDispatch( xProv, "SendOutlineToImpress", OUString(), 0, aArgs ); + } + } + else + { + rtl::Reference<TransferDataContainer> pClipCntnr = new TransferDataContainer; + + pClipCntnr->CopyAnyData( SotClipboardFormatId::RTF, static_cast<char const *>( + pStrm->GetData()), pStrm->GetEndOfData() ); + pClipCntnr->CopyToClipboard( + GetView()? &GetView()->GetEditWin() : nullptr ); + } + } + else + ErrorHandler::HandleError( eErr ); + } + break; + case SID_SPELLCHECKER_CHANGED: + { + //! false, true, true is on the save side but a probably overdone + SwModule::CheckSpellChanges(false, true, true, false ); + Broadcast(SfxHint(SfxHintId::LanguageChanged)); + } + break; + + case SID_MAIL_PREPAREEXPORT: + { + const SfxBoolItem* pNoUpdate = pArgs ? + pArgs->GetItem<SfxBoolItem>(FN_NOUPDATE, false) : + nullptr; + + //pWrtShell is not set in page preview + if (m_pWrtShell) + m_pWrtShell->StartAllAction(); + + if (!pNoUpdate || !pNoUpdate->GetValue()) + { + m_xDoc->getIDocumentFieldsAccess().UpdateFields( false ); + m_xDoc->getIDocumentLinksAdministration().EmbedAllLinks(); + } + + m_IsRemovedInvisibleContent + = officecfg::Office::Security::HiddenContent::RemoveHiddenContent::get(); + if (m_IsRemovedInvisibleContent) + m_xDoc->RemoveInvisibleContent(); + if (m_pWrtShell) + m_pWrtShell->EndAllAction(); + } + break; + + case SID_MAIL_EXPORT_FINISHED: + { + if (m_pWrtShell) + m_pWrtShell->StartAllAction(); + //try to undo the removal of invisible content + if (m_IsRemovedInvisibleContent) + m_xDoc->RestoreInvisibleContent(); + if (m_pWrtShell) + m_pWrtShell->EndAllAction(); + } + break; + case FN_NEW_HTML_DOC: + case FN_NEW_GLOBAL_DOC: + { + bDone = false; + bool bCreateHtml = FN_NEW_HTML_DOC == nWhich; + + bool bCreateByOutlineLevel = false; + sal_Int32 nTemplateOutlineLevel = 0; + + OUString aFileName, aTemplateName; + if( pArgs && SfxItemState::SET == pArgs->GetItemState( nWhich, false, &pItem ) ) + { + aFileName = static_cast<const SfxStringItem*>(pItem)->GetValue(); + const SfxStringItem* pTemplItem = SfxItemSet::GetItem<SfxStringItem>(pArgs, SID_TEMPLATE_NAME, false); + if ( pTemplItem ) + aTemplateName = pTemplItem->GetValue(); + } + if ( aFileName.isEmpty() ) + { + bool bError = false; + + FileDialogHelper aDlgHelper(TemplateDescription::FILESAVE_AUTOEXTENSION_TEMPLATE, FileDialogFlags::NONE, + GetView()->GetFrameWeld()); + aDlgHelper.SetContext(FileDialogHelper::WriterNewHTMLGlobalDoc); + + const sal_Int16 nControlIds[] = { + CommonFilePickerElementIds::PUSHBUTTON_OK, + CommonFilePickerElementIds::PUSHBUTTON_CANCEL, + CommonFilePickerElementIds::LISTBOX_FILTER, + CommonFilePickerElementIds::CONTROL_FILEVIEW, + CommonFilePickerElementIds::EDIT_FILEURL, + ExtendedFilePickerElementIds::CHECKBOX_AUTOEXTENSION, + ExtendedFilePickerElementIds::LISTBOX_TEMPLATE, + 0 + }; + + if (bCreateHtml) + { + const char* aHTMLHelpIds[] = + { + HID_SEND_HTML_CTRL_PUSHBUTTON_OK, + HID_SEND_HTML_CTRL_PUSHBUTTON_CANCEL, + HID_SEND_HTML_CTRL_LISTBOX_FILTER, + HID_SEND_HTML_CTRL_CONTROL_FILEVIEW, + HID_SEND_HTML_CTRL_EDIT_FILEURL, + HID_SEND_HTML_CTRL_CHECKBOX_AUTOEXTENSION, + HID_SEND_HTML_CTRL_LISTBOX_TEMPLATE, + "" + }; + aDlgHelper.SetControlHelpIds( nControlIds, aHTMLHelpIds ); + } + else + { + const char* aMasterHelpIds[] = + { + HID_SEND_MASTER_CTRL_PUSHBUTTON_OK, + HID_SEND_MASTER_CTRL_PUSHBUTTON_CANCEL, + HID_SEND_MASTER_CTRL_LISTBOX_FILTER, + HID_SEND_MASTER_CTRL_CONTROL_FILEVIEW, + HID_SEND_MASTER_CTRL_EDIT_FILEURL, + HID_SEND_MASTER_CTRL_CHECKBOX_AUTOEXTENSION, + HID_SEND_MASTER_CTRL_LISTBOX_TEMPLATE, + "" + }; + aDlgHelper.SetControlHelpIds( nControlIds, aMasterHelpIds ); + } + uno::Reference < XFilePicker3 > xFP = aDlgHelper.GetFilePicker(); + + std::shared_ptr<const SfxFilter> pFlt; + TranslateId pStrId; + + if( bCreateHtml ) + { + // for HTML there is only one filter!! + pFlt = SwIoSystem::GetFilterOfFormat( + u"HTML", + SwWebDocShell::Factory().GetFilterContainer() ); + pStrId = STR_LOAD_HTML_DOC; + } + else + { + // for Global-documents we now only offer the current one. + pFlt = SwGlobalDocShell::Factory().GetFilterContainer()-> + GetFilter4Extension( "odm" ); + pStrId = STR_LOAD_GLOBAL_DOC; + } + + if( pFlt ) + { + const OUString sWild = pFlt->GetWildcard().getGlob(); + xFP->appendFilter( pFlt->GetUIName(), sWild ); + try + { + xFP->setCurrentFilter( pFlt->GetUIName() ) ; + } + catch (const uno::Exception&) + { + bError = true; + } + } + if(!bError) + { + uno::Reference<XFilePickerControlAccess> xCtrlAcc(xFP, UNO_QUERY); + + bool bOutline[MAXLEVEL] = {false}; + const SwOutlineNodes& rOutlNds = m_xDoc->GetNodes().GetOutLineNds(); + for( size_t n = 0; n < rOutlNds.size(); ++n ) + { + const int nLevel = rOutlNds[n]->GetTextNode()->GetAttrOutlineLevel(); + if( nLevel > 0 && ! bOutline[nLevel-1] ) + { + bOutline[nLevel-1] = true; + } + } + + const sal_uInt16 nStyleCount = m_xDoc->GetTextFormatColls()->size(); + Sequence<OUString> aListBoxEntries( MAXLEVEL + nStyleCount); + OUString* pEntries = aListBoxEntries.getArray(); + sal_Int32 nIdx = 0 ; + + OUString sOutline( SwResId(STR_FDLG_OUTLINE_LEVEL) ); + for( sal_uInt16 i = 0; i < MAXLEVEL; ++i ) + { + if( bOutline[i] ) + pEntries[nIdx++] = sOutline + OUString::number( i+1 ); + } + + OUString sStyle( SwResId(STR_FDLG_STYLE) ); + for(sal_uInt16 i = 0; i < nStyleCount; ++i) + { + SwTextFormatColl &rTextColl = *(*m_xDoc->GetTextFormatColls())[ i ]; + if( !rTextColl.IsDefault() && rTextColl.IsAtDocNodeSet() ) + { + pEntries[nIdx++] = sStyle + rTextColl.GetName(); + } + } + + aListBoxEntries.realloc(nIdx); + sal_Int16 nSelect = 0; + + try + { + Any aTemplates(&aListBoxEntries, cppu::UnoType<decltype(aListBoxEntries)>::get()); + + xCtrlAcc->setValue( ExtendedFilePickerElementIds::LISTBOX_TEMPLATE, + ListboxControlActions::ADD_ITEMS , aTemplates ); + Any aSelectPos(&nSelect, cppu::UnoType<decltype(nSelect)>::get()); + xCtrlAcc->setValue( ExtendedFilePickerElementIds::LISTBOX_TEMPLATE, + ListboxControlActions::SET_SELECT_ITEM, aSelectPos ); + xCtrlAcc->setLabel( ExtendedFilePickerElementIds::LISTBOX_TEMPLATE, + SwResId( STR_FDLG_TEMPLATE_NAME )); + } + catch (const Exception&) + { + OSL_FAIL("control access failed"); + } + + xFP->setTitle(SwResId(pStrId)); + SvtPathOptions aPathOpt; + xFP->setDisplayDirectory( aPathOpt.GetWorkPath() ); + if( ERRCODE_NONE == aDlgHelper.Execute()) + { + aFileName = xFP->getSelectedFiles().getConstArray()[0]; + Any aTemplateValue = xCtrlAcc->getValue( + ExtendedFilePickerElementIds::LISTBOX_TEMPLATE, + ListboxControlActions::GET_SELECTED_ITEM ); + OUString sTmpl; + aTemplateValue >>= sTmpl; + + OUString aStyle(SwResId(STR_FDLG_STYLE)); + OUString aOutline(SwResId(STR_FDLG_OUTLINE_LEVEL)); + + if ( sTmpl.startsWith(aStyle) ) + { + aTemplateName = sTmpl.copy( aStyle.getLength() ); //get string behind "Style: " + } + else if ( sTmpl.startsWith(aOutline) ) + { + nTemplateOutlineLevel = o3tl::toInt32(sTmpl.subView(aOutline.getLength())); //get string behind "Outline: Level "; + bCreateByOutlineLevel = true; + } + + if ( !aFileName.isEmpty() ) + { + rReq.AppendItem( SfxStringItem( nWhich, aFileName ) ); + if( !aTemplateName.isEmpty() ) + rReq.AppendItem( SfxStringItem( SID_TEMPLATE_NAME, aTemplateName ) ); + } + } + } + } + + if( !aFileName.isEmpty() ) + { + if( PrepareClose( false ) ) + { + SwWait aWait( *this, true ); + + if ( bCreateByOutlineLevel ) + { + bDone = bCreateHtml + ? m_xDoc->GenerateHTMLDoc( aFileName, nTemplateOutlineLevel ) + : m_xDoc->GenerateGlobalDoc( aFileName, nTemplateOutlineLevel ); + } + else + { + const SwTextFormatColl* pSplitColl = nullptr; + if ( !aTemplateName.isEmpty() ) + pSplitColl = m_xDoc->FindTextFormatCollByName(aTemplateName); + bDone = bCreateHtml + ? m_xDoc->GenerateHTMLDoc( aFileName, pSplitColl ) + : m_xDoc->GenerateGlobalDoc( aFileName, pSplitColl ); + } + if( bDone ) + { + SfxStringItem aName( SID_FILE_NAME, aFileName ); + SfxStringItem aReferer(SID_REFERER, OUString()); + SfxViewShell* pViewShell = SfxViewShell::GetFirst(); + while(pViewShell) + { + //search for the view that created the call + if(pViewShell->GetObjectShell() == this && pViewShell->GetDispatcher()) + { + SfxFrameItem aFrameItem(SID_DOCFRAME, &pViewShell->GetViewFrame()); + SfxDispatcher* pDispatch = pViewShell->GetDispatcher(); + pDispatch->ExecuteList(SID_OPENDOC, + SfxCallMode::ASYNCHRON, + { &aName, &aReferer, &aFrameItem }); + break; + } + pViewShell = SfxViewShell::GetNext(*pViewShell); + } + } + } + if( !bDone && !rReq.IsAPI() ) + { + std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(nullptr, + VclMessageType::Info, VclButtonsType::Ok, + SwResId(STR_CANTCREATE))); + xInfoBox->run(); + } + } + } + rReq.SetReturnValue(SfxBoolItem( nWhich, bDone )); + if (bDone) + rReq.Done(); + else + rReq.Ignore(); + break; + + case SID_ATTR_YEAR2000: + if ( pArgs && SfxItemState::SET == pArgs->GetItemState( nWhich , false, &pItem )) + { + assert(dynamic_cast< const SfxUInt16Item *>( pItem ) && "wrong Item"); + sal_uInt16 nYear2K = static_cast<const SfxUInt16Item*>(pItem)->GetValue(); + // iterate over Views and put the State to FormShells + + SfxViewFrame* pVFrame = SfxViewFrame::GetFirst( this ); + SfxViewShell* pViewShell = pVFrame ? pVFrame->GetViewShell() : nullptr; + SwView* pCurrView = dynamic_cast< SwView* >( pViewShell ); + while(pCurrView) + { + FmFormShell* pFormShell = pCurrView->GetFormShell(); + if(pFormShell) + pFormShell->SetY2KState(nYear2K); + pVFrame = SfxViewFrame::GetNext( *pVFrame, this ); + pViewShell = pVFrame ? pVFrame->GetViewShell() : nullptr; + pCurrView = dynamic_cast<SwView*>( pViewShell ); + } + m_xDoc->GetNumberFormatter()->SetYear2000(nYear2K); + } + break; + case FN_OPEN_FILE: + { + SfxViewShell* pViewShell = GetView(); + if (!pViewShell) + pViewShell = SfxViewShell::Current(); + + if (!pViewShell) + // Ok. I did my best. + break; + + if (SfxDispatcher* pDispatch = pViewShell->GetDispatcher()) + { + SfxStringItem aApp(SID_DOC_SERVICE, "com.sun.star.text.TextDocument"); + SfxStringItem aTarget(SID_TARGETNAME, "_blank"); + pDispatch->ExecuteList(SID_OPENDOC, SfxCallMode::API|SfxCallMode::SYNCHRON, { &aApp, &aTarget }); + } + } + break; + case SID_CLASSIFICATION_APPLY: + { + if (pArgs && pArgs->GetItemState(nWhich, false, &pItem) == SfxItemState::SET) + { + SwWrtShell* pSh = GetWrtShell(); + const OUString& rValue = static_cast<const SfxStringItem*>(pItem)->GetValue(); + auto eType = SfxClassificationPolicyType::IntellectualProperty; + if (const SfxStringItem* pTypeNameItem = pArgs->GetItemIfSet(SID_TYPE_NAME, false)) + { + const OUString& rType = pTypeNameItem->GetValue(); + eType = SfxClassificationHelper::stringToPolicyType(rType); + } + pSh->SetClassification(rValue, eType); + } + else + SAL_WARN("sw.ui", "missing parameter for SID_CLASSIFICATION_APPLY"); + } + break; + case SID_CLASSIFICATION_DIALOG: + if (SfxObjectShell* pObjSh = SfxObjectShell::Current()) + { + auto xDialog = std::make_shared<svx::ClassificationDialog>(GetView()->GetFrameWeld(), pObjSh->getDocProperties(), false); + + SwWrtShell* pShell = GetWrtShell(); + std::vector<svx::ClassificationResult> aInput = pShell->CollectAdvancedClassification(); + xDialog->setupValues(std::move(aInput)); + + weld::DialogController::runAsync(xDialog, [xDialog, pShell](sal_Int32 nResult){ + if (RET_OK == nResult) + pShell->ApplyAdvancedClassification(xDialog->getResult()); + }); + } + break; + case SID_PARAGRAPH_SIGN_CLASSIFY_DLG: + if (SfxObjectShell* pObjSh = SfxObjectShell::Current()) + { + SwWrtShell* pShell = GetWrtShell(); + auto xDialog = std::make_shared<svx::ClassificationDialog>(GetView()->GetFrameWeld(), pObjSh->getDocProperties(), true, [pShell]() + { + pShell->SignParagraph(); + }); + + std::vector<svx::ClassificationResult> aInput = pShell->CollectParagraphClassification(); + xDialog->setupValues(std::move(aInput)); + + weld::DialogController::runAsync(xDialog, [xDialog, pShell](sal_Int32 nResult){ + if (RET_OK == nResult) + pShell->ApplyParagraphClassification(xDialog->getResult()); + }); + } + break; + case SID_WATERMARK: + { + SwWrtShell* pSh = GetWrtShell(); + if ( pSh ) + { + if (pArgs && pArgs->GetItemState( SID_WATERMARK, false, &pItem ) == SfxItemState::SET) + { + SfxWatermarkItem aItem; + aItem.SetText( static_cast<const SfxStringItem*>( pItem )->GetValue() ); + + if ( const SfxStringItem* pFontItem = pArgs->GetItemIfSet( SID_WATERMARK_FONT, false ) ) + aItem.SetFont( pFontItem->GetValue() ); + if ( const SfxInt16Item* pAngleItem = pArgs->GetItemIfSet( SID_WATERMARK_ANGLE, false ) ) + aItem.SetAngle( pAngleItem->GetValue() ); + if ( const SfxInt16Item* pTransItem = pArgs->GetItemIfSet( SID_WATERMARK_TRANSPARENCY, false ) ) + aItem.SetTransparency( pTransItem->GetValue() ); + if ( const SfxUInt32Item* pColorItem = pArgs->GetItemIfSet( SID_WATERMARK_COLOR, false ) ) + aItem.SetColor( Color(ColorTransparency, pColorItem->GetValue()) ); + + pSh->SetWatermark( aItem ); + } + else + { + SfxViewShell* pViewShell = GetView() ? GetView() : SfxViewShell::Current(); + SfxBindings& rBindings( pViewShell->GetViewFrame().GetBindings() ); + auto xDlg = std::make_shared<SwWatermarkDialog>(pViewShell->GetViewFrame().GetFrameWeld(), + rBindings); + weld::DialogController::runAsync(xDlg, [](sal_Int32 /*nResult*/){}); + } + } + } + break; + case SID_NOTEBOOKBAR: + { + const SfxStringItem* pFile = rReq.GetArg<SfxStringItem>( SID_NOTEBOOKBAR ); + SfxViewShell* pViewShell = GetView()? GetView(): SfxViewShell::Current(); + SfxBindings& rBindings( pViewShell->GetViewFrame().GetBindings() ); + + if ( SfxNotebookBar::IsActive() ) + sfx2::SfxNotebookBar::ExecMethod( rBindings, pFile ? pFile->GetValue() : "" ); + else + { + sfx2::SfxNotebookBar::CloseMethod( rBindings ); + } + } + break; + case FN_REDLINE_ACCEPT_ALL: + case FN_REDLINE_REJECT_ALL: + { + IDocumentRedlineAccess& rRedlineAccess = GetDoc()->getIDocumentRedlineAccess(); + SwWrtShell *pWrtShell = dynamic_cast<SwWrtShell*>(GetDoc()->getIDocumentLayoutAccess().GetCurrentViewShell()); + + if (rRedlineAccess.GetRedlineTable().empty()) + { + break; + } + + // tables with tracked deletion need Show Changes + bool bHideChanges = pWrtShell && pWrtShell->GetLayout() && + pWrtShell->GetLayout()->IsHideRedlines(); + bool bChangedHideChanges = false; + if ( bHideChanges ) + { + SwTableNode* pOldTableNd = nullptr; + const SwRedlineTable& aRedlineTable = rRedlineAccess.GetRedlineTable(); + for (SwRedlineTable::size_type n = 0; n < aRedlineTable.size(); ++n) + { + const SwRangeRedline* pRedline = aRedlineTable[n]; + if ( pRedline->GetType() == RedlineType::Delete ) + { + SwTableNode* pTableNd = + pRedline->GetPoint()->GetNode().FindTableNode(); + if ( pTableNd && pTableNd != + pOldTableNd && pTableNd->GetTable().HasDeletedRowOrCell() ) + { + SfxBoolItem aShow(FN_REDLINE_SHOW, true); + SfxViewShell* pViewShell = GetView() + ? GetView() + : SfxViewShell::Current(); + pViewShell->GetViewFrame().GetDispatcher()->ExecuteList( + FN_REDLINE_SHOW, SfxCallMode::SYNCHRON|SfxCallMode::RECORD, + { &aShow }); + bChangedHideChanges = true; + break; + } + pOldTableNd = pTableNd; + } + } + } + + if (pWrtShell) + { + pWrtShell->StartAllAction(); + } + + rRedlineAccess.AcceptAllRedline(nWhich == FN_REDLINE_ACCEPT_ALL); + + if (pWrtShell) + { + pWrtShell->EndAllAction(); + } + + if ( bChangedHideChanges ) + { + SfxBoolItem aShow(FN_REDLINE_SHOW, false); + SfxViewShell* pViewShell = GetView()? GetView(): SfxViewShell::Current(); + pViewShell->GetViewFrame().GetDispatcher()->ExecuteList( + FN_REDLINE_SHOW, SfxCallMode::SYNCHRON|SfxCallMode::RECORD, { &aShow }); + } + + Broadcast(SfxHint(SfxHintId::RedlineChanged)); + rReq.Done(); + } + break; + + default: OSL_FAIL("wrong Dispatcher"); + } +} + +#if defined(_WIN32) +bool SwDocShell::DdeGetData( const OUString& rItem, const OUString& rMimeType, + uno::Any & rValue ) +{ + return m_xDoc->getIDocumentLinksAdministration().GetData( rItem, rMimeType, rValue ); +} + +bool SwDocShell::DdeSetData( const OUString& rItem, const OUString& /*rMimeType*/, + const uno::Any & /*rValue*/ ) +{ + m_xDoc->getIDocumentLinksAdministration().SetData( rItem ); + return false; +} + +#endif + +::sfx2::SvLinkSource* SwDocShell::DdeCreateLinkSource( const OUString& rItem ) +{ + if(officecfg::Office::Common::Security::Scripting::DisableActiveContent::get()) + return nullptr; + return m_xDoc->getIDocumentLinksAdministration().CreateLinkSource( rItem ); +} + +void SwDocShell::ReconnectDdeLink(SfxObjectShell& rServer) +{ + if (m_xDoc) + { + ::sfx2::LinkManager& rLinkManager = m_xDoc->getIDocumentLinksAdministration().GetLinkManager(); + rLinkManager.ReconnectDdeLink(rServer); + } +} + +void SwDocShell::FillClass( SvGlobalName * pClassName, + SotClipboardFormatId * pClipFormat, + OUString * pLongUserName, + sal_Int32 nVersion, + bool bTemplate /* = false */) const +{ + if (nVersion == SOFFICE_FILEFORMAT_60) + { + *pClassName = SvGlobalName( SO3_SW_CLASSID_60 ); + *pClipFormat = SotClipboardFormatId::STARWRITER_60; + *pLongUserName = SwResId(STR_WRITER_DOCUMENT_FULLTYPE); + } + else if (nVersion == SOFFICE_FILEFORMAT_8) + { + *pClassName = SvGlobalName( SO3_SW_CLASSID_60 ); + *pClipFormat = bTemplate ? SotClipboardFormatId::STARWRITER_8_TEMPLATE : SotClipboardFormatId::STARWRITER_8; + *pLongUserName = SwResId(STR_WRITER_DOCUMENT_FULLTYPE); + } +// #FIXME check with new Event handling +#if 0 + uno::Reference< document::XVbaEventsHelper > xVbaEventsHelper = m_xDoc->GetVbaEventsHelper(); + if( xVbaEventsHelper.is() ) + lcl_processCompatibleSfxHint( xVbaEventsHelper, rHint ); +#endif +} + +void SwDocShell::SetModified( bool bSet ) +{ + if (utl::ConfigManager::IsFuzzing()) + return; + SfxObjectShell::SetModified( bSet ); + if( !IsEnableSetModified()) + return; + + if (!m_xDoc->getIDocumentState().IsInCallModified()) + { + EnableSetModified( false ); + if( bSet ) + { + bool const bOld = m_xDoc->getIDocumentState().IsModified(); + m_xDoc->getIDocumentState().SetModified(); + if( !bOld ) + { + m_xDoc->GetIDocumentUndoRedo().SetUndoNoResetModified(); + } + } + else + m_xDoc->getIDocumentState().ResetModified(); + + EnableSetModified(); + } + + UpdateChildWindows(); + Broadcast(SfxHint(SfxHintId::DocChanged)); +} + +void SwDocShell::UpdateChildWindows() +{ + // if necessary newly initialize Fielddlg (i.e. for TYP_SETVAR) + if(!GetView()) + return; + SfxViewFrame& rVFrame = GetView()->GetViewFrame(); + SwFieldDlgWrapper *pWrp = static_cast<SwFieldDlgWrapper*>(rVFrame. + GetChildWindow( SwFieldDlgWrapper::GetChildWindowId() )); + if( pWrp ) + pWrp->ReInitDlg( this ); + + // if necessary newly initialize RedlineDlg + SwRedlineAcceptChild *pRed = static_cast<SwRedlineAcceptChild*>(rVFrame. + GetChildWindow( SwRedlineAcceptChild::GetChildWindowId() )); + if( pRed ) + pRed->ReInitDlg( this ); +} + +namespace { + +// #i48748# +class SwReloadFromHtmlReader : public SwReader +{ + public: + SwReloadFromHtmlReader( SfxMedium& _rTmpMedium, + const OUString& _rFilename, + SwDoc* _pDoc ) + : SwReader( _rTmpMedium, _rFilename, _pDoc ) + { + SetBaseURL( _rFilename ); + } +}; + +} + +void SwDocShell::ReloadFromHtml( const OUString& rStreamName, SwSrcView* pSrcView ) +{ + bool bModified = IsModified(); + + // The HTTP-Header fields have to be removed, otherwise + // there are some from Meta-Tags duplicated or triplicated afterwards. + ClearHeaderAttributesForSourceViewHack(); + +#if HAVE_FEATURE_SCRIPTING + // The Document-Basic also bites the dust ... + // A EnterBasicCall is not needed here, because nothing is called and + // there can't be any Dok-Basic, that has not yet been loaded inside + // of an HTML document. + //#59620# HasBasic() shows, that there already is a BasicManager at the DocShell. + // That was always generated in HTML-Import, when there are + // Macros in the source code. + if( officecfg::Office::Common::Filter::HTML::Export::Basic::get() && HasBasic()) + { + BasicManager *pBasicMan = GetBasicManager(); + if( pBasicMan && (pBasicMan != SfxApplication::GetBasicManager()) ) + { + sal_uInt16 nLibCount = pBasicMan->GetLibCount(); + while( nLibCount ) + { + StarBASIC *pBasic = pBasicMan->GetLib( --nLibCount ); + if( pBasic ) + { + // Notify the IDE + SfxUnoAnyItem aShellItem( SID_BASICIDE_ARG_DOCUMENT_MODEL, Any( GetModel() ) ); + OUString aLibName( pBasic->GetName() ); + SfxStringItem aLibNameItem( SID_BASICIDE_ARG_LIBNAME, aLibName ); + pSrcView->GetViewFrame().GetDispatcher()->ExecuteList( + SID_BASICIDE_LIBREMOVED, + SfxCallMode::SYNCHRON, + { &aShellItem, &aLibNameItem }); + + // Only the modules are deleted from the standard-lib + if( nLibCount ) + pBasicMan->RemoveLib( nLibCount, true ); + else + pBasic->Clear(); + } + } + + OSL_ENSURE( pBasicMan->GetLibCount() <= 1, + "Deleting Basics didn't work" ); + } + } +#endif + bool bWasBrowseMode = m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::BROWSE_MODE); + RemoveLink(); + + // now also the UNO-Model has to be informed about the new Doc #51535# + uno::Reference<text::XTextDocument> xDoc(GetBaseModel(), uno::UNO_QUERY); + text::XTextDocument* pxDoc = xDoc.get(); + static_cast<SwXTextDocument*>(pxDoc)->InitNewDoc(); + + AddLink(); + //#116402# update font list when new document is created + UpdateFontList(); + m_xDoc->getIDocumentSettingAccess().set(DocumentSettingId::BROWSE_MODE, bWasBrowseMode); + pSrcView->SetPool(&GetPool()); + + const OUString& rMedname = GetMedium()->GetName(); + + // The HTML template still has to be set + SetHTMLTemplate( *GetDoc() ); //Styles from HTML.vor + + SfxViewShell* pViewShell = GetView() ? static_cast<SfxViewShell*>(GetView()) + : SfxViewShell::Current(); + SfxViewFrame& rViewFrame = pViewShell->GetViewFrame(); + rViewFrame.GetDispatcher()->Execute( SID_VIEWSHELL0, SfxCallMode::SYNCHRON ); + + SubInitNew(); + + SfxMedium aMed( rStreamName, StreamMode::READ ); + // #i48748# - use class <SwReloadFromHtmlReader>, because + // the base URL has to be set to the filename of the document <rMedname> + // and not to the base URL of the temporary file <aMed> in order to get + // the URLs of the linked graphics correctly resolved. + SwReloadFromHtmlReader aReader( aMed, rMedname, m_xDoc.get() ); + + aReader.Read( *ReadHTML ); + + const SwView* pCurrView = GetView(); + //in print layout the first page(s) may have been formatted as a mix of browse + //and print layout + if(!bWasBrowseMode && pCurrView) + { + SwWrtShell& rWrtSh = pCurrView->GetWrtShell(); + if( rWrtSh.GetLayout()) + rWrtSh.InvalidateLayout( true ); + } + + // Take HTTP-Header-Attributes over into the DocInfo again. + // The Base-URL doesn't matter here because TLX uses the one from the document + // for absolutization. + SetHeaderAttributesForSourceViewHack(); + + if(bModified && !IsReadOnly()) + SetModified(); + else + m_xDoc->getIDocumentState().ResetModified(); +} + +ErrCodeMsg SwDocShell::LoadStylesFromFile(const OUString& rURL, SwgReaderOption& rOpt, bool bUnoCall) +{ + ErrCodeMsg nErr = ERRCODE_NONE; + + // Set filter: + SfxFilterMatcher aMatcher( SwDocShell::Factory().GetFactoryName() ); + + // search for filter in WebDocShell, too + SfxMedium aMed( rURL, StreamMode::STD_READ ); + if (rURL == "private:stream") + aMed.setStreamToLoadFrom(rOpt.GetInputStream(), true); + std::shared_ptr<const SfxFilter> pFlt; + aMatcher.DetectFilter( aMed, pFlt ); + if(!pFlt) + { + SfxFilterMatcher aWebMatcher( SwWebDocShell::Factory().GetFactoryName() ); + aWebMatcher.DetectFilter( aMed, pFlt ); + } + // --> OD #i117339# - trigger import only for own formats + bool bImport( false ); + if ( aMed.IsStorage() ) + { + // As <SfxMedium.GetFilter().IsOwnFormat() resp. IsOwnTemplateFormat() + // does not work correct (e.g., MS Word 2007 XML Template), + // use workaround provided by MAV. + uno::Reference< embed::XStorage > xStorage = aMed.GetStorage(); + if ( xStorage.is() ) + { + // use <try-catch> on retrieving <MediaType> in order to check, + // if the storage is one of our own ones. + try + { + uno::Reference< beans::XPropertySet > xProps( xStorage, uno::UNO_QUERY_THROW ); + xProps->getPropertyValue( "MediaType" ); + bImport = true; + } + catch (const uno::Exception&) + { + bImport = false; + } + } + } + if ( bImport ) + { + Reader* pRead = ReadXML; + SwReaderPtr pReader; + std::optional<SwPaM> pPam; + // the SW3IO - Reader need the pam/wrtshell, because only then he + // insert the styles! + if( bUnoCall ) + { + SwNodeIndex aIdx( m_xDoc->GetNodes().GetEndOfContent(), -1 ); + pPam.emplace( aIdx ); + pReader.reset(new SwReader( aMed, rURL, *pPam )); + } + else + { + pReader.reset(new SwReader( aMed, rURL, *m_pWrtShell->GetCursor() )); + } + + pRead->GetReaderOpt().SetTextFormats( rOpt.IsTextFormats() ); + pRead->GetReaderOpt().SetFrameFormats( rOpt.IsFrameFormats() ); + pRead->GetReaderOpt().SetPageDescs( rOpt.IsPageDescs() ); + pRead->GetReaderOpt().SetNumRules( rOpt.IsNumRules() ); + pRead->GetReaderOpt().SetMerge( rOpt.IsMerge() ); + + if( bUnoCall ) + { + UnoActionContext aAction( m_xDoc.get() ); + nErr = pReader->Read( *pRead ); + } + else + { + m_pWrtShell->StartAllAction(); + nErr = pReader->Read( *pRead ); + m_pWrtShell->EndAllAction(); + } + } + + return nErr; +} + +// Get a client for an embedded object if possible. +SfxInPlaceClient* SwDocShell::GetIPClient( const ::svt::EmbeddedObjectRef& xObjRef ) +{ + SfxInPlaceClient* pResult = nullptr; + + SwWrtShell* pShell = GetWrtShell(); + if ( pShell ) + { + pResult = pShell->GetView().FindIPClient( xObjRef.GetObject(), &pShell->GetView().GetEditWin() ); + if ( !pResult ) + pResult = new SwOleClient( &pShell->GetView(), &pShell->GetView().GetEditWin(), xObjRef ); + } + + return pResult; +} + +int SwFindDocShell( SfxObjectShellRef& xDocSh, + SfxObjectShellLock& xLockRef, + std::u16string_view rFileName, + const OUString& rPasswd, + const OUString& rFilter, + sal_Int16 nVersion, + SwDocShell* pDestSh ) +{ + if ( rFileName.empty() ) + return 0; + + // 1. Does the file already exist in the list of all Documents? + INetURLObject aTmpObj( rFileName ); + aTmpObj.SetMark( u"" ); + + // Iterate over the DocShell and get the ones with the name + + SfxObjectShell* pShell = pDestSh; + bool bFirst = nullptr != pShell; + + if( !bFirst ) + // No DocShell passed, starting with the first from the DocShell list + pShell = SfxObjectShell::GetFirst( checkSfxObjectShell<SwDocShell> ); + + while( pShell ) + { + // We want this one + SfxMedium* pMed = pShell->GetMedium(); + if( pMed && pMed->GetURLObject() == aTmpObj ) + { + const SfxPoolItem* pItem; + if( ( SfxItemState::SET == pMed->GetItemSet().GetItemState( + SID_VERSION, false, &pItem ) ) + ? (nVersion == static_cast<const SfxInt16Item*>(pItem)->GetValue()) + : !nVersion ) + { + // Found, thus return + xDocSh = pShell; + return 1; + } + } + + if( bFirst ) + { + bFirst = false; + pShell = SfxObjectShell::GetFirst( checkSfxObjectShell<SwDocShell> ); + } + else + pShell = SfxObjectShell::GetNext( *pShell, checkSfxObjectShell<SwDocShell> ); + } + + // 2. Open the file ourselves + std::unique_ptr<SfxMedium> xMed(new SfxMedium( aTmpObj.GetMainURL( + INetURLObject::DecodeMechanism::NONE ), StreamMode::READ )); + if( INetProtocol::File == aTmpObj.GetProtocol() ) + xMed->Download(); // Touch the medium (download it) + + std::shared_ptr<const SfxFilter> pSfxFlt; + if (!xMed->GetErrorIgnoreWarning()) + { + SfxFilterMatcher aMatcher( rFilter == "writerglobal8" + ? SwGlobalDocShell::Factory().GetFactoryName() + : SwDocShell::Factory().GetFactoryName() ); + + // No Filter, so search for it. Else test if the one passed is a valid one + if( !rFilter.isEmpty() ) + { + pSfxFlt = aMatcher.GetFilter4FilterName( rFilter ); + } + + if( nVersion ) + xMed->GetItemSet().Put( SfxInt16Item( SID_VERSION, nVersion )); + + if( !rPasswd.isEmpty() ) + xMed->GetItemSet().Put( SfxStringItem( SID_PASSWORD, rPasswd )); + + if( !pSfxFlt ) + aMatcher.DetectFilter( *xMed, pSfxFlt ); + + if( pSfxFlt ) + { + // We cannot do anything without a Filter + xMed->SetFilter( pSfxFlt ); + + // If the new shell is created, SfxObjectShellLock should be used to let it be closed later for sure + SwDocShell *const pNew(new SwDocShell(SfxObjectCreateMode::INTERNAL)); + xLockRef = pNew; + xDocSh = static_cast<SfxObjectShell*>(xLockRef); + if (xDocSh->DoLoad(xMed.release())) + { + return 2; + } + } + } + + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/app/docshdrw.cxx b/sw/source/uibase/app/docshdrw.cxx new file mode 100644 index 0000000000..f767191fbd --- /dev/null +++ b/sw/source/uibase/app/docshdrw.cxx @@ -0,0 +1,100 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <svx/svxids.hrc> +#include <svx/drawitem.hxx> +#include <svx/svdoutl.hxx> +#include <svx/xtable.hxx> +#include <unotools/configmgr.hxx> +#include <docsh.hxx> +#include <drawdoc.hxx> +#include <swtypes.hxx> + +using namespace ::com::sun::star; + +// Load Document +void InitDrawModelAndDocShell(SwDocShell* pSwDocShell, SwDrawModel* pSwDrawDocument) +{ + if(pSwDrawDocument) + { + if(pSwDocShell == pSwDrawDocument->GetObjectShell()) + { + // association already done, nothing to do + } + else + { + // set object shell (mainly for FormControl stuff), maybe zero + pSwDrawDocument->SetObjectShell(pSwDocShell); + + // set persist, maybe zero + pSwDrawDocument->SetPersist(pSwDocShell); + + // get and decide on the color table to use + if(pSwDocShell) + { + const SvxColorListItem* pColItemFromDocShell = pSwDocShell->GetItem(SID_COLOR_TABLE); + + if(pColItemFromDocShell) + { + // the DocShell has a ColorTable, use it also in DrawingLayer + const XColorListRef& xCol(pColItemFromDocShell->GetColorList()); + pSwDrawDocument->SetPropertyList(static_cast<XPropertyList*>(xCol.get())); + } + else + { + // Use the ColorTable which is used at the DrawingLayer's SdrModel + XColorListRef xColorList = pSwDrawDocument->GetColorList(); + if (xColorList.is()) + { + pSwDocShell->PutItem(SvxColorListItem(xColorList, SID_COLOR_TABLE)); + } + else if (!utl::ConfigManager::IsFuzzing()) + { + // there wasn't one, get the standard and set to the + // docshell and then to the drawdocument + xColorList = XColorList::GetStdColorList(); + pSwDocShell->PutItem(SvxColorListItem(xColorList, SID_COLOR_TABLE)); + pSwDrawDocument->SetPropertyList(xColorList); + } + } + + // add other tables in SfxItemSet of the DocShell + pSwDocShell->PutItem(SvxGradientListItem(pSwDrawDocument->GetGradientList(), SID_GRADIENT_LIST)); + pSwDocShell->PutItem(SvxHatchListItem(pSwDrawDocument->GetHatchList(), SID_HATCH_LIST)); + pSwDocShell->PutItem(SvxBitmapListItem(pSwDrawDocument->GetBitmapList(), SID_BITMAP_LIST)); + pSwDocShell->PutItem(SvxPatternListItem(pSwDrawDocument->GetPatternList(), SID_PATTERN_LIST)); + pSwDocShell->PutItem(SvxDashListItem(pSwDrawDocument->GetDashList(), SID_DASH_LIST)); + pSwDocShell->PutItem(SvxLineEndListItem(pSwDrawDocument->GetLineEndList(), SID_LINEEND_LIST)); + } + + // init hyphenator for DrawingLayer outliner + uno::Reference<linguistic2::XHyphenator> xHyphenator(::GetHyphenator()); + Outliner& rOutliner = pSwDrawDocument->GetDrawOutliner(); + + rOutliner.SetHyphenator(xHyphenator); + } + } + else if(pSwDocShell) + { + // fallback: add the default color list to have one when someone requests it from the DocShell + pSwDocShell->PutItem(SvxColorListItem(XColorList::GetStdColorList(), SID_COLOR_TABLE)); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/app/docshini.cxx b/sw/source/uibase/app/docshini.cxx new file mode 100644 index 0000000000..5acee759db --- /dev/null +++ b/sw/source/uibase/app/docshini.cxx @@ -0,0 +1,711 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <hintids.hxx> + +#include <osl/diagnose.h> +#include <sal/log.hxx> +#include <i18nlangtag/languagetag.hxx> +#include <i18nlangtag/mslangid.hxx> +#include <svtools/ctrltool.hxx> +#include <unotools/configmgr.hxx> +#include <unotools/lingucfg.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/sfxmodelfactory.hxx> +#include <sfx2/printer.hxx> +#include <svl/asiancfg.hxx> +#include <svl/intitem.hxx> +#include <editeng/adjustitem.hxx> +#include <editeng/autokernitem.hxx> +#include <com/sun/star/document/UpdateDocMode.hpp> +#include <com/sun/star/i18n/ScriptType.hpp> +#include <svx/compatflags.hxx> +#include <svx/svxids.hrc> +#include <editeng/fhgtitem.hxx> +#include <editeng/fontitem.hxx> +#include <editeng/flstitem.hxx> +#include <editeng/tstpitem.hxx> +#include <editeng/langitem.hxx> +#include <editeng/colritem.hxx> +#include <editeng/orphitem.hxx> +#include <editeng/widwitem.hxx> +#include <editeng/hyphenzoneitem.hxx> +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> +#include <prtopt.hxx> +#include <fmtcol.hxx> +#include <docsh.hxx> +#include <wdocsh.hxx> +#include <swmodule.hxx> +#include <doc.hxx> +#include <IDocumentSettingAccess.hxx> +#include <IDocumentDeviceAccess.hxx> +#include <IDocumentDrawModelAccess.hxx> +#include <IDocumentStylePoolAccess.hxx> +#include <IDocumentChartDataProviderAccess.hxx> +#include <IDocumentState.hxx> +#include <docfac.hxx> +#include <docstyle.hxx> +#include <shellio.hxx> +#include <swdtflvr.hxx> +#include <usrpref.hxx> +#include <fontcfg.hxx> +#include <poolfmt.hxx> +#include <globdoc.hxx> +#include <unotxdoc.hxx> +#include <linkenum.hxx> +#include <swwait.hxx> +#include <swerror.h> +#include <unochart.hxx> +#include <drawdoc.hxx> + +#include <svx/CommonStyleManager.hxx> + +#include <memory> + +#include <officecfg/Office/Common.hxx> + +using namespace ::com::sun::star::i18n; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star; + +// Load Document +bool SwDocShell::InitNew( const uno::Reference < embed::XStorage >& xStor ) +{ + bool bRet = SfxObjectShell::InitNew( xStor ); + OSL_ENSURE( GetMapUnit() == MapUnit::MapTwip, "map unit is not twip!" ); + bool bHTMLTemplSet = false; + if( bRet ) + { + AddLink(); // create m_xDoc / pIo if applicable + + bool bWeb = dynamic_cast< const SwWebDocShell *>( this ) != nullptr; + if ( bWeb ) + bHTMLTemplSet = SetHTMLTemplate( *GetDoc() );// Styles from HTML.vor + else if( dynamic_cast< const SwGlobalDocShell *>( this ) != nullptr ) + GetDoc()->getIDocumentSettingAccess().set(DocumentSettingId::GLOBAL_DOCUMENT, true); // Globaldokument + + if ( GetCreateMode() == SfxObjectCreateMode::EMBEDDED ) + SwTransferable::InitOle( this ); + + // set forbidden characters if necessary + const bool bFuzzing = utl::ConfigManager::IsFuzzing(); + if (!bFuzzing) + { + SvxAsianConfig aAsian; + const Sequence<lang::Locale> aLocales = aAsian.GetStartEndCharLocales(); + for(const lang::Locale& rLocale : aLocales) + { + ForbiddenCharacters aForbidden; + aAsian.GetStartEndChars( rLocale, aForbidden.beginLine, aForbidden.endLine); + LanguageType eLang = LanguageTag::convertToLanguageType(rLocale); + m_xDoc->getIDocumentSettingAccess().setForbiddenCharacters( eLang, aForbidden); + } + m_xDoc->getIDocumentSettingAccess().set(DocumentSettingId::KERN_ASIAN_PUNCTUATION, + !aAsian.IsKerningWesternTextOnly()); + m_xDoc->getIDocumentSettingAccess().setCharacterCompressionType(aAsian.GetCharDistanceCompression()); + m_xDoc->getIDocumentDeviceAccess().setPrintData(*SW_MOD()->GetPrtOptions(bWeb)); + } + + SubInitNew(); + + // for all + + SwStdFontConfig* pStdFont = SW_MOD()->GetStdFontConfig(); + SfxPrinter* pPrt = m_xDoc->getIDocumentDeviceAccess().getPrinter( false ); + + OUString sEntry; + static const sal_uInt16 aFontWhich[] = + { RES_CHRATR_FONT, + RES_CHRATR_CJK_FONT, + RES_CHRATR_CTL_FONT + }; + static const sal_uInt16 aFontHeightWhich[] = + { + RES_CHRATR_FONTSIZE, + RES_CHRATR_CJK_FONTSIZE, + RES_CHRATR_CTL_FONTSIZE + }; + static const sal_uInt16 aFontIds[] = + { + FONT_STANDARD, + FONT_STANDARD_CJK, + FONT_STANDARD_CTL + }; + static const DefaultFontType nFontTypes[] = + { + DefaultFontType::LATIN_TEXT, + DefaultFontType::CJK_TEXT, + DefaultFontType::CTL_TEXT + }; + static const sal_uInt16 aLangTypes[] = + { + RES_CHRATR_LANGUAGE, + RES_CHRATR_CJK_LANGUAGE, + RES_CHRATR_CTL_LANGUAGE + }; + + for(sal_uInt8 i = 0; i < 3; i++) + { + sal_uInt16 nFontWhich = aFontWhich[i]; + sal_uInt16 nFontId = aFontIds[i]; + std::unique_ptr<SvxFontItem> pFontItem; + const SvxLanguageItem& rLang = static_cast<const SvxLanguageItem&>(m_xDoc->GetDefault( aLangTypes[i] )); + LanguageType eLanguage = rLang.GetLanguage(); + if(!pStdFont->IsFontDefault(nFontId)) + { + sEntry = pStdFont->GetFontFor(nFontId); + + vcl::Font aFont( sEntry, Size( 0, 10 ) ); + if( pPrt ) + { + aFont = pPrt->GetFontMetric( aFont ); + } + + pFontItem.reset(new SvxFontItem(aFont.GetFamilyType(), aFont.GetFamilyName(), + OUString(), aFont.GetPitch(), aFont.GetCharSet(), nFontWhich)); + } + else + { + // #107782# OJ use korean language if latin was used + if ( i == 0 ) + { + LanguageType eUiLanguage = Application::GetSettings().GetUILanguageTag().getLanguageType(); + if (MsLangId::isKorean(eUiLanguage)) + eLanguage = eUiLanguage; + } + + vcl::Font aLangDefFont = OutputDevice::GetDefaultFont( + nFontTypes[i], + eLanguage, + GetDefaultFontFlags::OnlyOne ); + pFontItem.reset(new SvxFontItem(aLangDefFont.GetFamilyType(), aLangDefFont.GetFamilyName(), + OUString(), aLangDefFont.GetPitch(), aLangDefFont.GetCharSet(), nFontWhich)); + } + m_xDoc->SetDefault(*pFontItem); + if( !bHTMLTemplSet ) + { + SwTextFormatColl *pColl = m_xDoc->getIDocumentStylePoolAccess().GetTextCollFromPool(RES_POOLCOLL_STANDARD); + pColl->ResetFormatAttr(nFontWhich); + } + pFontItem.reset(); + sal_Int32 nFontHeight = pStdFont->GetFontHeight( FONT_STANDARD, i, eLanguage ); + if(nFontHeight <= 0) + nFontHeight = SwStdFontConfig::GetDefaultHeightFor( nFontId, eLanguage ); + m_xDoc->SetDefault(SvxFontHeightItem( nFontHeight, 100, aFontHeightWhich[i] )); + if( !bHTMLTemplSet ) + { + SwTextFormatColl *pColl = m_xDoc->getIDocumentStylePoolAccess().GetTextCollFromPool(RES_POOLCOLL_STANDARD); + pColl->ResetFormatAttr(aFontHeightWhich[i]); + } + + } + sal_uInt16 aFontIdPoolId[] = + { + FONT_OUTLINE, RES_POOLCOLL_HEADLINE_BASE, + FONT_LIST, RES_POOLCOLL_NUMBER_BULLET_BASE, + FONT_CAPTION, RES_POOLCOLL_LABEL, + FONT_INDEX, RES_POOLCOLL_REGISTER_BASE, + FONT_OUTLINE_CJK, RES_POOLCOLL_HEADLINE_BASE, + FONT_LIST_CJK, RES_POOLCOLL_NUMBER_BULLET_BASE, + FONT_CAPTION_CJK, RES_POOLCOLL_LABEL, + FONT_INDEX_CJK, RES_POOLCOLL_REGISTER_BASE, + FONT_OUTLINE_CTL, RES_POOLCOLL_HEADLINE_BASE, + FONT_LIST_CTL, RES_POOLCOLL_NUMBER_BULLET_BASE, + FONT_CAPTION_CTL, RES_POOLCOLL_LABEL, + FONT_INDEX_CTL, RES_POOLCOLL_REGISTER_BASE + }; + + TypedWhichId<SvxFontItem> nFontWhich = RES_CHRATR_FONT; + TypedWhichId<SvxFontHeightItem> nFontHeightWhich = RES_CHRATR_FONTSIZE; + LanguageType eLanguage = m_xDoc->GetDefault( RES_CHRATR_LANGUAGE ).GetLanguage(); + bool bDisableBuiltinStyles = !bFuzzing && officecfg::Office::Common::Load::DisableBuiltinStyles::get(); + sal_uInt8 nLimit = bDisableBuiltinStyles ? 0 : 24; + for(sal_uInt8 nIdx = 0; nIdx < nLimit; nIdx += 2) + { + if(nIdx == 8) + { + nFontWhich = RES_CHRATR_CJK_FONT; + nFontHeightWhich = RES_CHRATR_CJK_FONTSIZE; + eLanguage = m_xDoc->GetDefault( RES_CHRATR_CJK_LANGUAGE ).GetLanguage(); + } + else if(nIdx == 16) + { + nFontWhich = RES_CHRATR_CTL_FONT; + nFontHeightWhich = RES_CHRATR_CTL_FONTSIZE; + eLanguage = m_xDoc->GetDefault( RES_CHRATR_CTL_LANGUAGE ).GetLanguage(); + } + SwTextFormatColl *pColl = nullptr; + if(!pStdFont->IsFontDefault(aFontIdPoolId[nIdx])) + { + sEntry = pStdFont->GetFontFor(aFontIdPoolId[nIdx]); + + vcl::Font aFont( sEntry, Size( 0, 10 ) ); + if( pPrt ) + aFont = pPrt->GetFontMetric( aFont ); + + pColl = m_xDoc->getIDocumentStylePoolAccess().GetTextCollFromPool(aFontIdPoolId[nIdx + 1]); + if( !bHTMLTemplSet || + SfxItemState::SET != pColl->GetAttrSet().GetItemState( + nFontWhich, false ) ) + { + pColl->SetFormatAttr(SvxFontItem(aFont.GetFamilyType(), aFont.GetFamilyName(), + OUString(), aFont.GetPitch(), aFont.GetCharSet(), nFontWhich)); + } + } + sal_Int32 nFontHeight = pStdFont->GetFontHeight( static_cast< sal_Int8 >(aFontIdPoolId[nIdx]), 0, eLanguage ); + if(nFontHeight <= 0) + nFontHeight = SwStdFontConfig::GetDefaultHeightFor( aFontIdPoolId[nIdx], eLanguage ); + if(!pColl) + pColl = m_xDoc->getIDocumentStylePoolAccess().GetTextCollFromPool(aFontIdPoolId[nIdx + 1]); + SvxFontHeightItem aFontHeight( pColl->GetFormatAttr( nFontHeightWhich ) ); + if(aFontHeight.GetHeight() != sal::static_int_cast<sal_uInt32, sal_Int32>(nFontHeight)) + { + aFontHeight.SetHeight(nFontHeight); + pColl->SetFormatAttr( aFontHeight ); + } + } + + // the default for documents created via 'File/New' should be 'on' + // (old documents, where this property was not yet implemented, will get the + // value 'false' in the SwDoc c-tor) + m_xDoc->getIDocumentSettingAccess().set( DocumentSettingId::MATH_BASELINE_ALIGNMENT, + SW_MOD()->GetUsrPref( bWeb )->IsAlignMathObjectsToBaseline() ); + m_xDoc->getIDocumentSettingAccess().set( DocumentSettingId::FOOTNOTE_IN_COLUMN_TO_PAGEEND, true); + } + + /* #106748# If the default frame direction of a document is RTL + the default adjustment is to the right. */ + if( !bHTMLTemplSet && + SvxFrameDirection::Horizontal_RL_TB == GetDefaultFrameDirection(GetAppLanguage()) ) + { + m_xDoc->SetDefault( SvxAdjustItem(SvxAdjust::Right, RES_PARATR_ADJUST ) ); + } + +// #i29550# + m_xDoc->SetDefault( SfxBoolItem( RES_COLLAPSING_BORDERS, true ) ); +// <-- collapsing + + //#i16874# AutoKerning as default for new documents + m_xDoc->SetDefault( SvxAutoKernItem( true, RES_CHRATR_AUTOKERN ) ); + + // #i42080# - Due to the several calls of method <SetDefault(..)> + // at the document instance, the document is modified. Thus, reset this + // status here. Note: In method <SubInitNew()> this is also done. + m_xDoc->getIDocumentState().ResetModified(); + + return bRet; +} + +// Ctor with SfxCreateMode ????? +SwDocShell::SwDocShell( SfxObjectCreateMode const eMode ) + : SfxObjectShell(eMode) + , m_IsInUpdateFontList(false) + , m_pStyleManager(new svx::CommonStyleManager(*this)) + , m_pView(nullptr) + , m_pWrtShell(nullptr) + , m_nUpdateDocMode(document::UpdateDocMode::ACCORDING_TO_CONFIG) + , m_IsATemplate(false) + , m_IsRemovedInvisibleContent(false) +{ + Init_Impl(); +} + +// Ctor / Dtor +SwDocShell::SwDocShell( const SfxModelFlags i_nSfxCreationFlags ) + : SfxObjectShell ( i_nSfxCreationFlags ) + , m_IsInUpdateFontList(false) + , m_pStyleManager(new svx::CommonStyleManager(*this)) + , m_pView(nullptr) + , m_pWrtShell(nullptr) + , m_nUpdateDocMode(document::UpdateDocMode::ACCORDING_TO_CONFIG) + , m_IsATemplate(false) + , m_IsRemovedInvisibleContent(false) +{ + Init_Impl(); +} + +// Ctor / Dtor +SwDocShell::SwDocShell( SwDoc& rD, SfxObjectCreateMode const eMode ) + : SfxObjectShell(eMode) + , m_xDoc(&rD) + , m_IsInUpdateFontList(false) + , m_pStyleManager(new svx::CommonStyleManager(*this)) + , m_pView(nullptr) + , m_pWrtShell(nullptr) + , m_nUpdateDocMode(document::UpdateDocMode::ACCORDING_TO_CONFIG) + , m_IsATemplate(false) + , m_IsRemovedInvisibleContent(false) +{ + Init_Impl(); +} + +// Dtor +SwDocShell::~SwDocShell() +{ + // disable chart related objects now because in ~SwDoc it may be too late for this + if (m_xDoc) + { + m_xDoc->getIDocumentChartDataProviderAccess().GetChartControllerHelper().Disconnect(); + SwChartDataProvider *pPCD = m_xDoc->getIDocumentChartDataProviderAccess().GetChartDataProvider(); + if (pPCD) + pPCD->dispose(); + } + + RemoveLink(); + m_pFontList.reset(); + + // we, as BroadCaster also become our own Listener + // (for DocInfo/FileNames/...) + EndListening( *this ); + + m_pOLEChildList.reset(); +} + +void SwDocShell::Init_Impl() +{ + SetPool(&SW_MOD()->GetPool()); + SetBaseModel(new SwXTextDocument(this)); + // we, as BroadCaster also become our own Listener + // (for DocInfo/FileNames/...) + StartListening( *this ); + //position of the "Automatic" style filter for the stylist (app.src) + SetAutoStyleFilterIndex(3); + + // set map unit to twip + SetMapUnit( MapUnit::MapTwip ); +} + +void SwDocShell::AddLink() +{ + if (!m_xDoc) + { + SwDocFac aFactory; + m_xDoc = &aFactory.GetDoc(); + m_xDoc->getIDocumentSettingAccess().set(DocumentSettingId::HTML_MODE, dynamic_cast< const SwWebDocShell *>( this ) != nullptr ); + } + m_xDoc->SetDocShell( this ); // set the DocShell-Pointer for Doc + uno::Reference< text::XTextDocument > xDoc(GetBaseModel(), uno::UNO_QUERY); + static_cast<SwXTextDocument*>(xDoc.get())->Reactivate(this); + + SetPool(&m_xDoc->GetAttrPool()); + + // most suitably not until a sdbcx::View is created!!! + m_xDoc->SetOle2Link(LINK(this, SwDocShell, Ole2ModifiedHdl)); +} + +// create new FontList Change Printer +void SwDocShell::UpdateFontList() +{ + if (!m_IsInUpdateFontList) + { + m_IsInUpdateFontList = true; + OSL_ENSURE(m_xDoc, "No Doc no FontList"); + if (m_xDoc) + { + m_pFontList.reset( new FontList( m_xDoc->getIDocumentDeviceAccess().getReferenceDevice(true) ) ); + PutItem( SvxFontListItem( m_pFontList.get(), SID_ATTR_CHAR_FONTLIST ) ); + } + m_IsInUpdateFontList = false; + } +} + +void SwDocShell::RemoveLink() +{ + // disconnect Uno-Object + uno::Reference< text::XTextDocument > xDoc(GetBaseModel(), uno::UNO_QUERY); + static_cast<SwXTextDocument*>(xDoc.get())->Invalidate(); + if (m_xDoc) + { + if (m_xBasePool.is()) + { + m_xBasePool->dispose(); + m_xBasePool.clear(); + } + m_xDoc->SetOle2Link(Link<bool,void>()); + m_xDoc->SetDocShell( nullptr ); + m_xDoc.clear(); // we don't have the Doc anymore!! + } +} +void SwDocShell::InvalidateModel() +{ + // disconnect Uno-Object + uno::Reference< text::XTextDocument > xDoc(GetBaseModel(), uno::UNO_QUERY); + static_cast<SwXTextDocument*>(xDoc.get())->Invalidate(); +} +void SwDocShell::ReactivateModel() +{ + // disconnect Uno-Object + uno::Reference< text::XTextDocument > xDoc(GetBaseModel(), uno::UNO_QUERY); + static_cast<SwXTextDocument*>(xDoc.get())->Reactivate(this); +} + +// Load, Default-Format +bool SwDocShell::Load( SfxMedium& rMedium ) +{ + bool bRet = false; + + if (SfxObjectShell::Load(rMedium)) + { + comphelper::EmbeddedObjectContainer& rEmbeddedObjectContainer = getEmbeddedObjectContainer(); + rEmbeddedObjectContainer.setUserAllowsLinkUpdate(false); + + SAL_INFO( "sw.ui", "after SfxInPlaceObject::Load" ); + if (m_xDoc) // for last version!! + RemoveLink(); // release the existing + + AddLink(); // set Link and update Data!! + + // Define some settings for legacy ODF files that have different default values now + // (if required, they will be overridden later when settings will be read) + if (IsOwnStorageFormat(rMedium)) + { + SwDrawModel* pDrawModel = m_xDoc->getIDocumentDrawModelAccess().GetDrawModel(); + if (pDrawModel) + { + pDrawModel->SetCompatibilityFlag(SdrCompatibilityFlag::AnchoredTextOverflowLegacy, + true); // legacy processing for tdf#99729 + pDrawModel->SetCompatibilityFlag(SdrCompatibilityFlag::LegacyFontwork, + true); // legacy processing for tdf#148000 + } + } + + // Loading + // for MD + OSL_ENSURE( !m_xBasePool.is(), "who hasn't destroyed their Pool?" ); + m_xBasePool = new SwDocStyleSheetPool( *m_xDoc, SfxObjectCreateMode::ORGANIZER == GetCreateMode() ); + if(GetCreateMode() != SfxObjectCreateMode::ORGANIZER) + { + const SfxUInt16Item* pUpdateDocItem = rMedium.GetItemSet().GetItem(SID_UPDATEDOCMODE, false); + m_nUpdateDocMode = pUpdateDocItem ? pUpdateDocItem->GetValue() : document::UpdateDocMode::NO_UPDATE; + } + + SwWait aWait( *this, true ); + ErrCodeMsg nErr = ERR_SWG_READ_ERROR; + switch( GetCreateMode() ) + { + case SfxObjectCreateMode::ORGANIZER: + { + if( ReadXML ) + { + ReadXML->SetOrganizerMode( true ); + SwReader aRdr(rMedium, OUString(), m_xDoc.get()); + nErr = aRdr.Read( *ReadXML ); + ReadXML->SetOrganizerMode( false ); + } + } + break; + + case SfxObjectCreateMode::INTERNAL: + case SfxObjectCreateMode::EMBEDDED: + { + SwTransferable::InitOle( this ); + } + // suppress SfxProgress, when we are Embedded + SW_MOD()->SetEmbeddedLoadSave( true ); + [[fallthrough]]; + + case SfxObjectCreateMode::STANDARD: + { + Reader *pReader = ReadXML; + if( pReader ) + { + // set Doc's DocInfo at DocShell-Medium + SAL_INFO( "sw.ui", "before ReadDocInfo" ); + SwReader aRdr(rMedium, OUString(), m_xDoc.get()); + SAL_INFO( "sw.ui", "before Read" ); + nErr = aRdr.Read( *pReader ); + SAL_INFO( "sw.ui", "after Read" ); + // If a XML document is loaded, the global doc/web doc + // flags have to be set, because they aren't loaded + // by this formats. + if( dynamic_cast< const SwWebDocShell *>( this ) != nullptr ) + { + if (!m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE)) + m_xDoc->getIDocumentSettingAccess().set(DocumentSettingId::HTML_MODE, true); + } + if( dynamic_cast< const SwGlobalDocShell *>( this ) != nullptr ) + { + if (!m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::GLOBAL_DOCUMENT)) + m_xDoc->getIDocumentSettingAccess().set(DocumentSettingId::GLOBAL_DOCUMENT, true); + } + } + } + break; + + default: + OSL_ENSURE( false, "Load: new CreateMode?" ); + } + + UpdateFontList(); + InitDrawModelAndDocShell(this, m_xDoc ? m_xDoc->getIDocumentDrawModelAccess().GetDrawModel() + : nullptr); + + SetError(nErr); + bRet = !nErr.IsError(); + + if (bRet && !m_xDoc->IsInLoadAsynchron() && + GetCreateMode() == SfxObjectCreateMode::STANDARD) + { + LoadingFinished(); + } + + // suppress SfxProgress, when we are Embedded + SW_MOD()->SetEmbeddedLoadSave( false ); + } + + return bRet; +} + +bool SwDocShell::LoadFrom( SfxMedium& rMedium ) +{ + bool bRet = false; + if (m_xDoc) + RemoveLink(); + + AddLink(); // set Link and update Data!! + + do { // middle check loop + ErrCodeMsg nErr = ERR_SWG_READ_ERROR; + OUString aStreamName = "styles.xml"; + uno::Reference < container::XNameAccess > xAccess = rMedium.GetStorage(); + if ( xAccess->hasByName( aStreamName ) && rMedium.GetStorage()->isStreamElement( aStreamName ) ) + { + // Loading + SwWait aWait( *this, true ); + { + OSL_ENSURE( !m_xBasePool.is(), "who hasn't destroyed their Pool?" ); + m_xBasePool = new SwDocStyleSheetPool( *m_xDoc, SfxObjectCreateMode::ORGANIZER == GetCreateMode() ); + if( ReadXML ) + { + ReadXML->SetOrganizerMode( true ); + SwReader aRdr(rMedium, OUString(), m_xDoc.get()); + nErr = aRdr.Read( *ReadXML ); + ReadXML->SetOrganizerMode( false ); + } + } + } + else + { + OSL_FAIL("Code removed!"); + } + + SetError(nErr); + bRet = !nErr.IsError(); + + } while( false ); + + SfxObjectShell::LoadFrom( rMedium ); + m_xDoc->getIDocumentState().ResetModified(); + return bRet; +} + +void SwDocShell::SubInitNew() +{ + OSL_ENSURE( !m_xBasePool.is(), "who hasn't destroyed their Pool?" ); + m_xBasePool = new SwDocStyleSheetPool( *m_xDoc, SfxObjectCreateMode::ORGANIZER == GetCreateMode() ); + UpdateFontList(); + InitDrawModelAndDocShell(this, m_xDoc ? m_xDoc->getIDocumentDrawModelAccess().GetDrawModel() : nullptr); + + m_xDoc->getIDocumentSettingAccess().setLinkUpdateMode( GLOBALSETTING ); + m_xDoc->getIDocumentSettingAccess().setFieldUpdateFlags( AUTOUPD_GLOBALSETTING ); + + bool bWeb = dynamic_cast< const SwWebDocShell *>( this ) != nullptr; + + static const WhichRangesContainer nRange1(svl::Items< + RES_CHRATR_COLOR, RES_CHRATR_COLOR, + RES_CHRATR_LANGUAGE, RES_CHRATR_LANGUAGE, + RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, + RES_CHRATR_CTL_LANGUAGE, RES_CHRATR_CTL_LANGUAGE, + RES_PARATR_ADJUST, RES_PARATR_ADJUST + >); + static const WhichRangesContainer nRange2(svl::Items< + RES_CHRATR_COLOR, RES_CHRATR_COLOR, + RES_CHRATR_LANGUAGE, RES_CHRATR_LANGUAGE, + RES_CHRATR_CJK_LANGUAGE, RES_CHRATR_CJK_LANGUAGE, + RES_CHRATR_CTL_LANGUAGE, RES_CHRATR_CTL_LANGUAGE, + RES_PARATR_ADJUST, RES_PARATR_ADJUST, + RES_PARATR_TABSTOP, RES_PARATR_HYPHENZONE + >); + SfxItemSet aDfltSet( m_xDoc->GetAttrPool(), bWeb ? nRange1 : nRange2 ); + + //! get lingu options without loading lingu DLL + SvtLinguOptions aLinguOpt; + + const bool bFuzzing = utl::ConfigManager::IsFuzzing(); + if (!bFuzzing) + SvtLinguConfig().GetOptions(aLinguOpt); + + LanguageType nVal = MsLangId::resolveSystemLanguageByScriptType(aLinguOpt.nDefaultLanguage, css::i18n::ScriptType::LATIN), + eCJK = MsLangId::resolveSystemLanguageByScriptType(aLinguOpt.nDefaultLanguage_CJK, css::i18n::ScriptType::ASIAN), + eCTL = MsLangId::resolveSystemLanguageByScriptType(aLinguOpt.nDefaultLanguage_CTL, css::i18n::ScriptType::COMPLEX); + aDfltSet.Put( SvxLanguageItem( nVal, RES_CHRATR_LANGUAGE ) ); + aDfltSet.Put( SvxLanguageItem( eCJK, RES_CHRATR_CJK_LANGUAGE ) ); + aDfltSet.Put( SvxLanguageItem( eCTL, RES_CHRATR_CTL_LANGUAGE ) ); + + if(!bWeb) + { + SvxHyphenZoneItem aHyp( m_xDoc->GetDefault(RES_PARATR_HYPHENZONE) ); + aHyp.GetMinLead() = static_cast< sal_uInt8 >(aLinguOpt.nHyphMinLeading); + aHyp.GetMinTrail() = static_cast< sal_uInt8 >(aLinguOpt.nHyphMinTrailing); + aHyp.GetMinWordLength() = static_cast< sal_uInt8 >(aLinguOpt.nHyphMinWordLength); + + aDfltSet.Put( aHyp ); + + sal_uInt16 nNewPos = o3tl::toTwips(SW_MOD()->GetUsrPref(false)->GetDefTabInMm100(), o3tl::Length::mm100); + if( nNewPos ) + aDfltSet.Put( SvxTabStopItem( 1, nNewPos, + SvxTabAdjust::Default, RES_PARATR_TABSTOP ) ); + } + aDfltSet.Put( SvxColorItem( COL_AUTO, RES_CHRATR_COLOR ) ); + + m_xDoc->SetDefault( aDfltSet ); + + //default page mode for text grid + if(!bWeb) + { + bool bSquaredPageMode = SW_MOD()->GetUsrPref(false)->IsSquaredPageMode(); + m_xDoc->SetDefaultPageMode( bSquaredPageMode ); + + // only set Widow/Orphan defaults on a new, non-web document - not an opened one + if (GetMedium() && GetMedium()->GetOrigURL().isEmpty() && !bFuzzing) + { + m_xDoc->SetDefault( SvxWidowsItem( sal_uInt8(2), RES_PARATR_WIDOWS) ); + m_xDoc->SetDefault( SvxOrphansItem( sal_uInt8(2), RES_PARATR_ORPHANS) ); + } + } + + m_xDoc->getIDocumentState().ResetModified(); +} + +/* + * Document Interface Access + */ +IDocumentDeviceAccess& SwDocShell::getIDocumentDeviceAccess() +{ + return m_xDoc->getIDocumentDeviceAccess(); +} + +IDocumentChartDataProviderAccess& SwDocShell::getIDocumentChartDataProviderAccess() +{ + return m_xDoc->getIDocumentChartDataProviderAccess(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/app/docst.cxx b/sw/source/uibase/app/docst.cxx new file mode 100644 index 0000000000..ba6c850a86 --- /dev/null +++ b/sw/source/uibase/app/docst.cxx @@ -0,0 +1,1693 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <config_wasm_strip.h> + +#include <memory> + +#include <com/sun/star/style/XStyleFamiliesSupplier.hpp> +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <comphelper/flagguard.hxx> +#include <o3tl/any.hxx> +#include <sal/log.hxx> +#include <osl/diagnose.h> +#include <hintids.hxx> +#include <sfx2/styledlg.hxx> +#include <svl/whiter.hxx> +#include <sfx2/tplpitem.hxx> +#include <sfx2/request.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/newstyle.hxx> +#include <sfx2/printer.hxx> +#include <sfx2/viewfrm.hxx> +#include <svl/stritem.hxx> +#include <svl/ctloptions.hxx> +#include <sfx2/htmlmode.hxx> +#include <swmodule.hxx> +#include <fchrfmt.hxx> +#include <svx/xdef.hxx> +#include <SwStyleNameMapper.hxx> +#include <SwRewriter.hxx> +#include <numrule.hxx> +#include <swundo.hxx> +#include <svx/drawitem.hxx> +#include <utility> +#include <view.hxx> +#include <wrtsh.hxx> +#include <docsh.hxx> +#include <uitool.hxx> +#include <cmdid.h> +#include <viewopt.hxx> +#include <doc.hxx> +#include <drawdoc.hxx> +#include <IDocumentDrawModelAccess.hxx> +#include <IDocumentUndoRedo.hxx> +#include <IDocumentSettingAccess.hxx> +#include <IDocumentDeviceAccess.hxx> +#include <IDocumentFieldsAccess.hxx> +#include <IDocumentState.hxx> +#include <frmfmt.hxx> +#include <charfmt.hxx> +#include <poolfmt.hxx> +#include <pagedesc.hxx> +#include <docstyle.hxx> +#include <uiitems.hxx> +#include <fmtcol.hxx> +#include <edtwin.hxx> +#include <unochart.hxx> +#include <swabstdlg.hxx> +#include <tblafmt.hxx> +#include <sfx2/watermarkitem.hxx> +#include <svl/grabbagitem.hxx> +#include <PostItMgr.hxx> +#include <AnnotationWin.hxx> +#include <SwUndoFmt.hxx> +#include <strings.hrc> +#include <AccessibilityCheck.hxx> +#include <docmodel/theme/Theme.hxx> +#include <svx/svdpage.hxx> +#include <officecfg/Office/Common.hxx> + +using namespace ::com::sun::star; + +void SwDocShell::StateStyleSheet(SfxItemSet& rSet, SwWrtShell* pSh) +{ + SfxWhichIter aIter(rSet); + sal_uInt16 nWhich = aIter.FirstWhich(); + SfxStyleFamily nActualFamily = SfxStyleFamily(USHRT_MAX); + + SwWrtShell* pShell = pSh ? pSh : GetWrtShell(); + if(!pShell) + { + while (nWhich) + { + rSet.DisableItem(nWhich); + nWhich = aIter.NextWhich(); + } + return; + } + else + { + SfxViewFrame& rFrame = pShell->GetView().GetViewFrame(); + std::unique_ptr<SfxUInt16Item> pFamilyItem; + rFrame.GetBindings().QueryState(SID_STYLE_FAMILY, pFamilyItem); + if (pFamilyItem) + { + nActualFamily = static_cast<SfxStyleFamily>(pFamilyItem->GetValue()); + } + } + + while (nWhich) + { + // determine current template to every family + OUString aName; + SwTableAutoFormat aTableAutoFormat("dummy"); // needed to check if can take a table auto format at current cursor position + switch (nWhich) + { + case SID_STYLE_APPLY: + {// here the template and its family are passed to the StyleBox + // so that this family is being showed + if(pShell->IsFrameSelected()) + { + SwFrameFormat* pFormat = pShell->GetSelectedFrameFormat(); + if( pFormat ) + aName = pFormat->GetName(); + } + else if (pShell->GetSelectionType() == SelectionType::PostIt) + { + auto pStyle = pShell->GetPostItMgr()->GetActiveSidebarWin()->GetOutlinerView()->GetStyleSheet(); + if (pStyle) + aName = pStyle->GetName(); + } + else + { + SwTextFormatColl* pColl = pShell->GetCurTextFormatColl(); + if(pColl) + aName = pColl->GetName(); + } + rSet.Put(SfxTemplateItem(nWhich, aName)); + } + break; + case SID_STYLE_FAMILY1: + if( !pShell->IsFrameSelected() ) + { + SwCharFormat* pFormat = pShell->GetCurCharFormat(); + if(pFormat) + aName = pFormat->GetName(); + else + aName = SwResId(STR_POOLCHR_STANDARD); + rSet.Put(SfxTemplateItem(nWhich, aName)); + } + break; + + case SID_STYLE_FAMILY2: + if(!pShell->IsFrameSelected()) + { + OUString aProgName; + if (pShell->GetSelectionType() == SelectionType::PostIt) + { + if (auto pStyle = pShell->GetPostItMgr()->GetActiveSidebarWin()->GetOutlinerView()->GetStyleSheet()) + { + aName = pStyle->GetName(); + aProgName = SwStyleNameMapper::GetProgName(aName, SwGetPoolIdFromName::TxtColl); + } + } + else if (auto pColl = pShell->GetCurTextFormatColl()) + { + aName = pColl->GetName(); + sal_uInt16 nId = pColl->GetPoolFormatId(); + SwStyleNameMapper::FillProgName(nId, aProgName); + } + + SfxTemplateItem aItem(nWhich, aName, aProgName); + + SfxStyleSearchBits nMask = SfxStyleSearchBits::Auto; + if (m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE)) + nMask = SfxStyleSearchBits::SwHtml; + else + { + const FrameTypeFlags nSelection = pShell->GetFrameType(nullptr,true); + if(pShell->GetCurTOX()) + nMask = SfxStyleSearchBits::SwIndex ; + else if(nSelection & FrameTypeFlags::HEADER || + nSelection & FrameTypeFlags::FOOTER || + nSelection & FrameTypeFlags::TABLE || + nSelection & FrameTypeFlags::FLY_ANY || + nSelection & FrameTypeFlags::FOOTNOTE || + nSelection & FrameTypeFlags::FTNPAGE) + nMask = SfxStyleSearchBits::SwExtra; + else + nMask = SfxStyleSearchBits::SwText; + } + + aItem.SetValue(nMask); + rSet.Put(aItem); + } + + break; + + case SID_STYLE_FAMILY3: + + if (m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE)) + rSet.DisableItem( nWhich ); + else + { + SwFrameFormat* pFormat = pShell->GetSelectedFrameFormat(); + if(pFormat && pShell->IsFrameSelected()) + { + aName = pFormat->GetName(); + rSet.Put(SfxTemplateItem(nWhich, aName)); + } + } + break; + + case SID_STYLE_FAMILY4: + { + if (m_xDoc->getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) && !officecfg::Office::Common::Filter::HTML::Export::PrintLayout::get()) + rSet.DisableItem( nWhich ); + else + { + size_t n = pShell->GetCurPageDesc( false ); + if( n < pShell->GetPageDescCnt() ) + aName = pShell->GetPageDesc( n ).GetName(); + + rSet.Put(SfxTemplateItem(nWhich, aName)); + } + } + break; + case SID_STYLE_FAMILY5: + { + const SwNumRule* pRule = pShell->GetNumRuleAtCurrCursorPos(); + if( pRule ) + aName = pRule->GetName(); + + rSet.Put(SfxTemplateItem(nWhich, aName)); + } + break; + case SID_STYLE_FAMILY6: + { + const SwTableNode *pTableNd = pShell->IsCursorInTable(); + if( pTableNd ) + aName = pTableNd->GetTable().GetTableStyleName(); + + rSet.Put(SfxTemplateItem(nWhich, aName)); + } + break; + + case SID_STYLE_WATERCAN: + { + SwEditWin& rEdtWin = pShell->GetView().GetEditWin(); + SwApplyTemplate* pApply = rEdtWin.GetApplyTemplate(); + rSet.Put(SfxBoolItem(nWhich, pApply && pApply->eType != SfxStyleFamily(0))); + } + break; + case SID_STYLE_UPDATE_BY_EXAMPLE: + if( pShell->IsFrameSelected() + ? SfxStyleFamily::Frame != nActualFamily + : ( SfxStyleFamily::Frame == nActualFamily || + SfxStyleFamily::Page == nActualFamily || + (SfxStyleFamily::Pseudo == nActualFamily && !pShell->GetNumRuleAtCurrCursorPos()) || + (SfxStyleFamily::Table == nActualFamily && !pShell->GetTableAutoFormat(aTableAutoFormat))) ) + { + rSet.DisableItem( nWhich ); + } + break; + + case SID_STYLE_NEW_BY_EXAMPLE: + if( (pShell->IsFrameSelected() + ? SfxStyleFamily::Frame != nActualFamily + : SfxStyleFamily::Frame == nActualFamily) || + (SfxStyleFamily::Pseudo == nActualFamily && !pShell->GetNumRuleAtCurrCursorPos()) || + (SfxStyleFamily::Table == nActualFamily && !pShell->GetTableAutoFormat(aTableAutoFormat)) ) + { + rSet.DisableItem( nWhich ); + } + break; + + case SID_CLASSIFICATION_APPLY: + // Just trigger ClassificationCategoriesController::statusChanged(). + rSet.InvalidateItem(nWhich); + break; + case SID_CLASSIFICATION_DIALOG: + rSet.InvalidateItem(nWhich); + break; + case SID_STYLE_EDIT: + break; + case SID_WATERMARK: + if (pSh) + { + SfxWatermarkItem aItem = pSh->GetWatermark(); + rSet.Put(aItem); + } + break; + default: + OSL_FAIL("Invalid SlotId"); + } + nWhich = aIter.NextWhich(); + } +} + +// evaluate StyleSheet-Requests +void SwDocShell::ExecStyleSheet( SfxRequest& rReq ) +{ + sal_uInt16 nSlot = rReq.GetSlot(); + + const SfxItemSet* pArgs = rReq.GetArgs(); + const SfxPoolItem* pItem; + switch (nSlot) + { + case SID_STYLE_NEW: + if( pArgs && SfxItemState::SET == pArgs->GetItemState( SID_STYLE_FAMILY, + false, &pItem )) + { + const SfxStyleFamily nFamily = static_cast<SfxStyleFamily>(static_cast<const SfxUInt16Item*>(pItem)->GetValue()); + + OUString sName; + SfxStyleSearchBits nMask = SfxStyleSearchBits::Auto; + if( SfxItemState::SET == pArgs->GetItemState( SID_STYLE_NEW, + false, &pItem )) + sName = static_cast<const SfxStringItem*>(pItem)->GetValue(); + if( SfxItemState::SET == pArgs->GetItemState( SID_STYLE_MASK, + false, &pItem )) + nMask = static_cast<SfxStyleSearchBits>(static_cast<const SfxUInt16Item*>(pItem)->GetValue()); + OUString sParent; + if( SfxItemState::SET == pArgs->GetItemState( SID_STYLE_REFERENCE, + false, &pItem )) + sParent = static_cast<const SfxStringItem*>(pItem)->GetValue(); + + if (sName.isEmpty() && m_xBasePool) + sName = SfxStyleDialogController::GenerateUnusedName(*m_xBasePool, nFamily); + + Edit(rReq.GetFrameWeld(), sName, sParent, nFamily, nMask, true, {}, nullptr, &rReq, nSlot); + } + break; + + case SID_STYLE_APPLY: + if( !pArgs ) + { + GetView()->GetViewFrame().GetDispatcher()->Execute(SID_STYLE_DESIGNER); + break; + } + else + { + // convert internal StyleName to DisplayName (slot implementation uses the latter) + const SfxStringItem* pNameItem = rReq.GetArg<SfxStringItem>(SID_APPLY_STYLE); + const SfxStringItem* pFamilyItem = rReq.GetArg<SfxStringItem>(SID_STYLE_FAMILYNAME); + if ( pFamilyItem && pNameItem ) + { + uno::Reference< style::XStyleFamiliesSupplier > xModel(GetModel(), uno::UNO_QUERY); + try + { + uno::Reference< container::XNameAccess > xStyles; + uno::Reference< container::XNameAccess > xCont = xModel->getStyleFamilies(); + xCont->getByName(pFamilyItem->GetValue()) >>= xStyles; + uno::Reference< beans::XPropertySet > xInfo; + xStyles->getByName( pNameItem->GetValue() ) >>= xInfo; + OUString aUIName; + xInfo->getPropertyValue("DisplayName") >>= aUIName; + if ( !aUIName.isEmpty() ) + rReq.AppendItem( SfxStringItem( SID_STYLE_APPLY, aUIName ) ); + } + catch (const uno::Exception&) + { + } + } + } + + [[fallthrough]]; + + case SID_STYLE_EDIT: + case SID_STYLE_FONT: + case SID_STYLE_DELETE: + case SID_STYLE_HIDE: + case SID_STYLE_SHOW: + case SID_STYLE_WATERCAN: + case SID_STYLE_FAMILY: + case SID_STYLE_UPDATE_BY_EXAMPLE: + case SID_STYLE_NEW_BY_EXAMPLE: + { + OUString aParam; + SfxStyleFamily nFamily = SfxStyleFamily::Para; + SfxStyleSearchBits nMask = SfxStyleSearchBits::Auto; + SwWrtShell* pActShell = nullptr; + + if( !pArgs ) + { + switch (nSlot) + { + case SID_STYLE_NEW_BY_EXAMPLE: + { + SfxStyleSheetBasePool& rPool = *GetStyleSheetPool(); + SfxNewStyleDlg aDlg(GetView()->GetFrameWeld(), rPool, nFamily); + if (aDlg.run() == RET_OK) + { + aParam = aDlg.GetName(); + rReq.AppendItem(SfxStringItem(nSlot, aParam)); + } + } + break; + + case SID_STYLE_UPDATE_BY_EXAMPLE: + case SID_STYLE_EDIT: + { + if (GetWrtShell()->GetSelectionType() == SelectionType::PostIt) + { + auto pOLV = GetWrtShell()->GetPostItMgr()->GetActiveSidebarWin()->GetOutlinerView(); + if (auto pStyle = pOLV->GetStyleSheet()) + aParam = pStyle->GetName(); + } + else if (auto pColl = GetWrtShell()->GetCurTextFormatColl()) + aParam = pColl->GetName(); + + if (!aParam.isEmpty()) + rReq.AppendItem(SfxStringItem(nSlot, aParam)); + } + break; + } + } + else + { + SAL_WARN_IF( !pArgs->Count(), "sw.ui", "SfxBug ItemSet is empty" ); + + SwWrtShell* pShell = GetWrtShell(); + if( SfxItemState::SET == pArgs->GetItemState(nSlot, false, &pItem )) + aParam = static_cast<const SfxStringItem*>(pItem)->GetValue(); + + if( SfxItemState::SET == pArgs->GetItemState(SID_STYLE_FAMILY, + false, &pItem )) + nFamily = static_cast<SfxStyleFamily>(static_cast<const SfxUInt16Item*>(pItem)->GetValue()); + + if( SfxItemState::SET == pArgs->GetItemState(SID_STYLE_FAMILYNAME, false, &pItem )) + { + OUString aFamily = static_cast<const SfxStringItem*>(pItem)->GetValue(); + if(aFamily == "CharacterStyles") + nFamily = SfxStyleFamily::Char; + else + if(aFamily == "ParagraphStyles") + nFamily = SfxStyleFamily::Para; + else + if(aFamily == "PageStyles") + nFamily = SfxStyleFamily::Page; + else + if(aFamily == "FrameStyles") + nFamily = SfxStyleFamily::Frame; + else + if(aFamily == "NumberingStyles") + nFamily = SfxStyleFamily::Pseudo; + else + if(aFamily == "TableStyles") + nFamily = SfxStyleFamily::Table; + } + + if( SfxItemState::SET == pArgs->GetItemState(SID_STYLE_MASK, + false, &pItem )) + nMask = static_cast<SfxStyleSearchBits>(static_cast<const SfxUInt16Item*>(pItem)->GetValue()); + if( const SwPtrItem* pShellItem = pArgs->GetItemIfSet(FN_PARAM_WRTSHELL, false )) + pActShell = pShell = static_cast<SwWrtShell*>(pShellItem->GetValue()); + + if( nSlot == SID_STYLE_UPDATE_BY_EXAMPLE && aParam.isEmpty() ) + { + switch( nFamily ) + { + case SfxStyleFamily::Para: + { + SwTextFormatColl* pColl = pShell->GetCurTextFormatColl(); + if(pColl) + aParam = pColl->GetName(); + } + break; + case SfxStyleFamily::Frame: + { + SwFrameFormat* pFrame = m_pWrtShell->GetSelectedFrameFormat(); + if( pFrame ) + aParam = pFrame->GetName(); + } + break; + case SfxStyleFamily::Char: + { + SwCharFormat* pChar = m_pWrtShell->GetCurCharFormat(); + if( pChar ) + aParam = pChar->GetName(); + } + break; + case SfxStyleFamily::Pseudo: + if(const SfxStringItem* pExName = pArgs->GetItemIfSet(SID_STYLE_UPD_BY_EX_NAME, false)) + { + aParam = pExName->GetValue(); + } + break; + case SfxStyleFamily::Table: + if(const SfxStringItem* pExName = pArgs->GetItemIfSet(SID_STYLE_UPD_BY_EX_NAME, false)) + { + aParam = pExName->GetValue(); + } + break; + default: break; + } + rReq.AppendItem(SfxStringItem(nSlot, aParam)); + } + } + if (!aParam.isEmpty() || nSlot == SID_STYLE_WATERCAN ) + { + sal_uInt16 nRet = 0xffff; + bool bReturns = false; + + switch(nSlot) + { + case SID_STYLE_EDIT: + case SID_STYLE_FONT: + Edit(rReq.GetFrameWeld(), aParam, {}, nFamily, nMask, false, (nSlot == SID_STYLE_FONT) ? "font" : OUString(), pActShell); + break; + case SID_STYLE_DELETE: + Delete(aParam, nFamily); + break; + case SID_STYLE_HIDE: + case SID_STYLE_SHOW: + Hide(aParam, nFamily, nSlot == SID_STYLE_HIDE); + break; + case SID_STYLE_APPLY: + // Shell-switch in ApplyStyles + nRet = static_cast<sal_uInt16>(ApplyStyles(aParam, nFamily, pActShell, rReq.GetModifier() )); + bReturns = true; + break; + case SID_STYLE_WATERCAN: + nRet = static_cast<sal_uInt16>(DoWaterCan(aParam, nFamily)); + bReturns = true; + break; + case SID_STYLE_UPDATE_BY_EXAMPLE: + UpdateStyle(aParam, nFamily, pActShell); + break; + case SID_STYLE_NEW_BY_EXAMPLE: + MakeByExample(aParam, nFamily, nMask, pActShell); + break; + + default: + OSL_FAIL("Invalid SlotId"); + } + + // Update formatting toolbar buttons status + if (GetWrtShell()->GetSelectionType() == SelectionType::PostIt) + GetView()->GetViewFrame().GetBindings().InvalidateAll(false); + + if (bReturns) + { + if(rReq.IsAPI()) // Basic only gets TRUE or FALSE + rReq.SetReturnValue(SfxUInt16Item(nSlot, sal_uInt16(nRet !=0))); + else + rReq.SetReturnValue(SfxUInt16Item(nSlot, nRet)); + } + + rReq.Done(); + } + + break; + } + } +} + +namespace { + +class ApplyStyle +{ +public: + ApplyStyle(SwDocShell &rDocSh, bool bNew, + rtl::Reference< SwDocStyleSheet > xTmp, + SfxStyleFamily nFamily, SfxAbstractApplyTabDialog *pDlg, + rtl::Reference< SfxStyleSheetBasePool > xBasePool, + bool bModified) + : m_pDlg(pDlg) + , m_rDocSh(rDocSh) + , m_bNew(bNew) + , m_xTmp(std::move(xTmp)) + , m_nFamily(nFamily) + , m_xBasePool(std::move(xBasePool)) + , m_bModified(bModified) + { + } + DECL_LINK( ApplyHdl, LinkParamNone*, void ); + void apply() + { + ApplyHdl(nullptr); + } + VclPtr<SfxAbstractApplyTabDialog> m_pDlg; + // true if the document was initially modified before ApplyStyle was created + // or if ApplyStyle:::apply was called + bool DocIsModified() const + { + return m_bModified; + } +private: + SwDocShell &m_rDocSh; + bool m_bNew; + rtl::Reference< SwDocStyleSheet > m_xTmp; + SfxStyleFamily m_nFamily; + rtl::Reference< SfxStyleSheetBasePool > m_xBasePool; + bool m_bModified; +}; + +} + +IMPL_LINK_NOARG(ApplyStyle, ApplyHdl, LinkParamNone*, void) +{ + SwWrtShell* pWrtShell = m_rDocSh.GetWrtShell(); + SwDoc* pDoc = m_rDocSh.GetDoc(); + SwView* pView = m_rDocSh.GetView(); + + pWrtShell->StartAllAction(); + + if( SfxStyleFamily::Para == m_nFamily ) + { + SfxItemSet aSet( *m_pDlg->GetOutputItemSet() ); + ::ConvertAttrGenToChar(aSet, m_xTmp->GetItemSet(), /*bIsPara=*/true); + ::SfxToSwPageDescAttr( *pWrtShell, aSet ); + // reset indent attributes at paragraph style, if a list style + // will be applied and no indent attributes will be applied. + m_xTmp->SetItemSet( aSet, false, true ); + } + else + { + if(SfxStyleFamily::Page == m_nFamily || SfxStyleFamily::Frame == m_nFamily) + { + static const sal_uInt16 aInval[] = { + SID_IMAGE_ORIENTATION, + SID_ATTR_CHAR_FONT, + FN_INSERT_CTRL, FN_INSERT_OBJ_CTRL, + FN_TABLE_INSERT_COL_BEFORE, + FN_TABLE_INSERT_COL_AFTER, 0}; + pView->GetViewFrame().GetBindings().Invalidate(aInval); + } + SfxItemSet aTmpSet( *m_pDlg->GetOutputItemSet() ); + if( SfxStyleFamily::Char == m_nFamily ) + { + ::ConvertAttrGenToChar(aTmpSet, m_xTmp->GetItemSet()); + } + + m_xTmp->SetItemSet( aTmpSet, false ); + + if( SfxStyleFamily::Page == m_nFamily && SvtCTLOptions::IsCTLFontEnabled() ) + { + const SfxPoolItem *pItem = nullptr; + if( aTmpSet.GetItemState( m_rDocSh.GetPool().GetTrueWhich( SID_ATTR_FRAMEDIRECTION, false ) , true, &pItem ) == SfxItemState::SET ) + SwChartHelper::DoUpdateAllCharts( pDoc ); + } + + if (m_nFamily == SfxStyleFamily::Page) + { + if (const SfxGrabBagItem* pGrabBagItem = aTmpSet.GetItemIfSet(SID_ATTR_CHAR_GRABBAG)) + { + bool bGutterAtTop{}; + auto it = pGrabBagItem->GetGrabBag().find("GutterAtTop"); + if (it != pGrabBagItem->GetGrabBag().end()) + { + it->second >>= bGutterAtTop; + } + bool bOldGutterAtTop + = pDoc->getIDocumentSettingAccess().get(DocumentSettingId::GUTTER_AT_TOP); + if (bOldGutterAtTop != bGutterAtTop) + { + pDoc->getIDocumentSettingAccess().set(DocumentSettingId::GUTTER_AT_TOP, + bGutterAtTop); + pWrtShell->InvalidateLayout(/*bSizeChanged=*/true); + } + } + } + + if (m_nFamily == SfxStyleFamily::Frame) + { + if (const SfxBoolItem* pBoolItem = aTmpSet.GetItemIfSet(FN_KEEP_ASPECT_RATIO)) + { + const SwViewOption* pVOpt = pWrtShell->GetViewOptions(); + SwViewOption aUsrPref(*pVOpt); + aUsrPref.SetKeepRatio(pBoolItem->GetValue()); + if (pBoolItem->GetValue() != pVOpt->IsKeepRatio()) + { + SW_MOD()->ApplyUsrPref(aUsrPref, &pWrtShell->GetView()); + } + } + } + } + + if(m_bNew) + { + if(SfxStyleFamily::Frame == m_nFamily || SfxStyleFamily::Para == m_nFamily) + { + // clear FillStyle so that it works as a derived attribute + SfxItemSet aTmpSet(*m_pDlg->GetOutputItemSet()); + + aTmpSet.ClearItem(XATTR_FILLSTYLE); + m_xTmp->SetItemSet(aTmpSet, false); + } + } + + if(SfxStyleFamily::Page == m_nFamily) + pView->InvalidateRulerPos(); + + if( m_bNew ) + m_xBasePool->Broadcast(SfxStyleSheetHint(SfxHintId::StyleSheetCreated, *m_xTmp)); + else + m_xBasePool->Broadcast(SfxStyleSheetHint(SfxHintId::StyleSheetModified, *m_xTmp)); + + pDoc->getIDocumentState().SetModified(); + if( !m_bModified ) + { + pDoc->GetIDocumentUndoRedo().SetUndoNoResetModified(); + m_bModified = true; + } + + pWrtShell->EndAllAction(); +} + +namespace +{ +/// Checks if there is an Endnote page style in use, and makes sure it has the same orientation +/// with the Default (Standard) page style. +void syncEndnoteOrientation(const uno::Reference< style::XStyleFamiliesSupplier >& xStyleFamSupp) +{ + if (!xStyleFamSupp.is()) + { + SAL_WARN("sw.ui", "Ref to XStyleFamiliesSupplier is null."); + return; + } + uno::Reference<container::XNameAccess> xStyleFamilies = xStyleFamSupp->getStyleFamilies(); + + if (!xStyleFamilies.is()) + return; + + uno::Reference<container::XNameAccess> xPageStyles(xStyleFamilies->getByName("PageStyles"), + uno::UNO_QUERY); + + if (!xPageStyles.is()) + return; + + uno::Reference<css::style::XStyle> xEndnotePageStyle(xPageStyles->getByName("Endnote"), + uno::UNO_QUERY); + + if (!xEndnotePageStyle.is()) + return; + + // Language-independent name of the "Default Style" is "Standard" + uno::Reference<css::style::XStyle> xDefaultPageStyle(xPageStyles->getByName("Standard"), + uno::UNO_QUERY); + if (!xDefaultPageStyle.is()) + return; + + if (xEndnotePageStyle->isUserDefined() || !xEndnotePageStyle->isInUse()) + return; + + uno::Reference<beans::XPropertySet> xEndnotePagePropSet(xPageStyles->getByName("Endnote"), uno::UNO_QUERY); + uno::Reference<beans::XPropertySet> xDefaultPagePropSet(xPageStyles->getByName("Standard"), uno::UNO_QUERY); + + if (!xEndnotePagePropSet.is() || !xDefaultPagePropSet.is()) + { + SAL_WARN("sw.ui", "xEndnotePagePropSet or xDefaultPagePropSet is null."); + return; + } + + auto const bIsDefLandScape = *o3tl::doAccess<bool>( + xDefaultPagePropSet->getPropertyValue("IsLandscape")); + auto const bIsEndLandScape = *o3tl::doAccess<bool>( + xEndnotePagePropSet->getPropertyValue("IsLandscape")); + + if (bIsDefLandScape == bIsEndLandScape) + return; + + auto const nWidth = xEndnotePagePropSet->getPropertyValue("Width"); + auto const nHeight = xEndnotePagePropSet->getPropertyValue("Height"); + + xEndnotePagePropSet->setPropertyValue("IsLandscape", css::uno::toAny(bIsDefLandScape)); + xEndnotePagePropSet->setPropertyValue("Width", nHeight); + xEndnotePagePropSet->setPropertyValue("Height", nWidth); +} +} + +void SwDocShell::Edit( + weld::Window* pDialogParent, + const OUString &rName, + const OUString &rParent, + const SfxStyleFamily nFamily, + SfxStyleSearchBits nMask, + const bool bNew, + const OUString& sPage, + SwWrtShell* pActShell, + SfxRequest* pReq, + sal_uInt16 nSlot) +{ + assert( GetWrtShell() ); + const bool bBasic = pReq && pReq->IsAPI(); + SfxStyleSheetBase *pStyle = nullptr; + + bool bModified = m_xDoc->getIDocumentState().IsModified(); + + SwUndoId nNewStyleUndoId(SwUndoId::EMPTY); + + if( bNew ) + { + if (!bBasic) + { + // start undo action in order to get only one undo action for the + // UI new style + change style operations + m_pWrtShell->StartUndo(); + } + + if( SfxStyleSearchBits::All != nMask && SfxStyleSearchBits::AllVisible != nMask && SfxStyleSearchBits::Used != nMask ) + nMask |= SfxStyleSearchBits::UserDefined; + else + nMask = SfxStyleSearchBits::UserDefined; + + if ( nFamily == SfxStyleFamily::Para || nFamily == SfxStyleFamily::Char || nFamily == SfxStyleFamily::Frame ) + { + // Prevent undo append from being done during paragraph, character, and frame style Make + // Do it after ok return from style dialog when derived from style is known + ::sw::UndoGuard const undoGuard(GetDoc()->GetIDocumentUndoRedo()); + pStyle = &m_xBasePool->Make( rName, nFamily, nMask ); + } + else + { + pStyle = &m_xBasePool->Make( rName, nFamily, nMask ); + } + + // set the current one as Parent + SwDocStyleSheet* pDStyle = static_cast<SwDocStyleSheet*>(pStyle); + switch( nFamily ) + { + case SfxStyleFamily::Para: + { + if(!rParent.isEmpty()) + { + SwTextFormatColl* pColl = m_pWrtShell->FindTextFormatCollByName( rParent ); + if(!pColl) + { + sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(rParent, SwGetPoolIdFromName::TxtColl); + if(USHRT_MAX != nId) + pColl = m_pWrtShell->GetTextCollFromPool( nId ); + } + pDStyle->GetCollection()->SetDerivedFrom( pColl ); + pDStyle->PresetParent( rParent ); + } + else + { + SwTextFormatColl* pColl = m_pWrtShell->GetCurTextFormatColl(); + pDStyle->GetCollection()->SetDerivedFrom( pColl ); + if( pColl ) + pDStyle->PresetParent( pColl->GetName() ); + } + } + break; + case SfxStyleFamily::Char: + { + if(!rParent.isEmpty()) + { + SwCharFormat* pCFormat = m_pWrtShell->FindCharFormatByName(rParent); + if(!pCFormat) + { + sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(rParent, SwGetPoolIdFromName::ChrFmt); + if(USHRT_MAX != nId) + pCFormat = m_pWrtShell->GetCharFormatFromPool( nId ); + } + + pDStyle->GetCharFormat()->SetDerivedFrom( pCFormat ); + pDStyle->PresetParent( rParent ); + } + else + { + SwCharFormat* pCFormat = m_pWrtShell->GetCurCharFormat(); + pDStyle->GetCharFormat()->SetDerivedFrom( pCFormat ); + if( pCFormat ) + pDStyle->PresetParent( pCFormat->GetName() ); + } + } + break; + case SfxStyleFamily::Frame : + { + if(!rParent.isEmpty()) + { + SwFrameFormat* pFFormat = m_pWrtShell->GetDoc()->FindFrameFormatByName( rParent ); + if(!pFFormat) + { + sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(rParent, SwGetPoolIdFromName::FrmFmt); + if(USHRT_MAX != nId) + pFFormat = m_pWrtShell->GetFrameFormatFromPool( nId ); + } + pDStyle->GetFrameFormat()->SetDerivedFrom( pFFormat ); + pDStyle->PresetParent( rParent ); + } + } + break; + default: break; + } + + if (!bBasic) + { + //Get the undo id for the type of style that was created in order to re-use that comment for the grouped + //create style + change style operations + m_pWrtShell->GetLastUndoInfo(nullptr, &nNewStyleUndoId); + } + } + else + { + pStyle = m_xBasePool->Find( rName, nFamily ); + SAL_WARN_IF( !pStyle, "sw.ui", "Style not found" ); + } + + if(!pStyle) + return; + + // put dialogues together + rtl::Reference< SwDocStyleSheet > xTmp( new SwDocStyleSheet( *static_cast<SwDocStyleSheet*>(pStyle) ) ); + if( SfxStyleFamily::Para == nFamily ) + { + SfxItemSet& rSet = xTmp->GetItemSet(); + ::SwToSfxPageDescAttr( rSet ); + // merge list level indent attributes into the item set if needed + xTmp->MergeIndentAttrsOfListStyle( rSet ); + + ::ConvertAttrCharToGen(xTmp->GetItemSet(), /*bIsPara=*/true); + } + else if( SfxStyleFamily::Char == nFamily ) + { + ::ConvertAttrCharToGen(xTmp->GetItemSet()); + } + + if(SfxStyleFamily::Page == nFamily || SfxStyleFamily::Para == nFamily) + { + // create needed items for XPropertyList entries from the DrawModel so that + // the Area TabPage can access them + SfxItemSet& rSet = xTmp->GetItemSet(); + const SwDrawModel* pDrawModel = GetDoc()->getIDocumentDrawModelAccess().GetDrawModel(); + + rSet.Put(SvxColorListItem(pDrawModel->GetColorList(), SID_COLOR_TABLE)); + rSet.Put(SvxGradientListItem(pDrawModel->GetGradientList(), SID_GRADIENT_LIST)); + rSet.Put(SvxHatchListItem(pDrawModel->GetHatchList(), SID_HATCH_LIST)); + rSet.Put(SvxBitmapListItem(pDrawModel->GetBitmapList(), SID_BITMAP_LIST)); + rSet.Put(SvxPatternListItem(pDrawModel->GetPatternList(), SID_PATTERN_LIST)); + + std::optional<SfxGrabBagItem> oGrabBag; + if (SfxGrabBagItem const* pItem = rSet.GetItemIfSet(SID_ATTR_CHAR_GRABBAG)) + { + oGrabBag.emplace(*pItem); + } + else + { + oGrabBag.emplace(SID_ATTR_CHAR_GRABBAG); + } + bool bGutterAtTop + = GetDoc()->getIDocumentSettingAccess().get(DocumentSettingId::GUTTER_AT_TOP); + oGrabBag->GetGrabBag()["GutterAtTop"] <<= bGutterAtTop; + rSet.Put(*oGrabBag); + } + + SwWrtShell* pCurrShell = pActShell ? pActShell : m_pWrtShell; + if (nFamily == SfxStyleFamily::Frame) + { + SfxItemSet& rSet = xTmp->GetItemSet(); + const SwViewOption* pVOpt = pCurrShell->GetViewOptions(); + rSet.Put(SfxBoolItem(FN_KEEP_ASPECT_RATIO, pVOpt->IsKeepRatio())); + } + + if (!bBasic) + { + // prior to the dialog the HtmlMode at the DocShell is being sunk + sal_uInt16 nHtmlMode = ::GetHtmlMode(this); + + // In HTML mode, we do not always have a printer. In order to show + // the correct page size in the Format - Page dialog, we have to + // get one here. + if( ( HTMLMODE_ON & nHtmlMode ) && + !pCurrShell->getIDocumentDeviceAccess().getPrinter( false ) ) + pCurrShell->InitPrt( pCurrShell->getIDocumentDeviceAccess().getPrinter( true ) ); + + PutItem(SfxUInt16Item(SID_HTML_MODE, nHtmlMode)); + FieldUnit eMetric = ::GetDfltMetric(0 != (HTMLMODE_ON&nHtmlMode)); + SW_MOD()->PutItem(SfxUInt16Item(SID_ATTR_METRIC, static_cast< sal_uInt16 >(eMetric))); + SwAbstractDialogFactory* pFact = SwAbstractDialogFactory::Create(); + if (!pDialogParent) + { + SAL_WARN("sw.ui", "no parent for dialog supplied, assuming document frame is good enough"); + pDialogParent = GetView()->GetFrameWeld(); + } + VclPtr<SfxAbstractApplyTabDialog> pDlg(pFact->CreateTemplateDialog(pDialogParent, + *xTmp, nFamily, sPage, pCurrShell, bNew)); + auto pApplyStyleHelper = std::make_shared<ApplyStyle>(*this, bNew, xTmp, nFamily, pDlg.get(), m_xBasePool, bModified); + pDlg->SetApplyHdl(LINK(pApplyStyleHelper.get(), ApplyStyle, ApplyHdl)); + + std::shared_ptr<SfxRequest> pRequest; + if (pReq) + { + pRequest = std::make_shared<SfxRequest>(*pReq); + pReq->Ignore(); // the 'old' request is not relevant any more + } + + bool bIsDefaultPage = nFamily == SfxStyleFamily::Page + && rName == SwResId(STR_POOLPAGE_STANDARD) + && pStyle->IsUsed() + && !pStyle->IsUserDefined(); + + pDlg->StartExecuteAsync([bIsDefaultPage, bNew, nFamily, nSlot, nNewStyleUndoId, pApplyStyleHelper, pRequest, xTmp, this](sal_Int32 nResult){ + if (RET_OK == nResult) + pApplyStyleHelper->apply(); + + if (bNew) + { + switch( nFamily ) + { + case SfxStyleFamily::Para: + { + if(!xTmp->GetParent().isEmpty()) + { + SwTextFormatColl* pColl = m_pWrtShell->FindTextFormatCollByName(xTmp->GetParent()); + if (GetDoc()->GetIDocumentUndoRedo().DoesUndo()) + { + GetDoc()->GetIDocumentUndoRedo().AppendUndo( + std::make_unique<SwUndoTextFormatCollCreate>(xTmp->GetCollection(), pColl, *GetDoc())); + } + } + } + break; + case SfxStyleFamily::Char: + { + if(!xTmp->GetParent().isEmpty()) + { + SwCharFormat* pCFormat = m_pWrtShell->FindCharFormatByName(xTmp->GetParent()); + if (GetDoc()->GetIDocumentUndoRedo().DoesUndo()) + { + GetDoc()->GetIDocumentUndoRedo().AppendUndo( + std::make_unique<SwUndoCharFormatCreate>(xTmp->GetCharFormat(), pCFormat, *GetDoc())); + } + } + } + break; + case SfxStyleFamily::Frame: + { + if(!xTmp->GetParent().isEmpty()) + { + SwFrameFormat* pFFormat = m_pWrtShell->GetDoc()->FindFrameFormatByName(xTmp->GetParent()); + if (GetDoc()->GetIDocumentUndoRedo().DoesUndo()) + { + GetDoc()->GetIDocumentUndoRedo().AppendUndo( + std::make_unique<SwUndoFrameFormatCreate>(xTmp->GetFrameFormat(), pFFormat, *GetDoc())); + } + } + } + break; + default: break; + } + + SwRewriter aRewriter; + aRewriter.AddRule(UndoArg1, xTmp->GetName()); + //Group the create style and change style operations together under the + //one "create style" comment + m_pWrtShell->EndUndo(nNewStyleUndoId, &aRewriter); + } + + bool bDocModified = pApplyStyleHelper->DocIsModified(); + + if (RET_OK != nResult) + { + if (bNew) + { + GetWrtShell()->Undo(); + m_xDoc->GetIDocumentUndoRedo().ClearRedo(); + } + + if (!bDocModified) + m_xDoc->getIDocumentState().ResetModified(); + } + + // Update Watermark if new page style was created + if (nSlot == SID_STYLE_NEW && nFamily == SfxStyleFamily::Page) + { + SwWrtShell* pShell = GetWrtShell(); + const SfxWatermarkItem aWatermark = pShell->GetWatermark(); + pShell->SetWatermark(aWatermark); + } + + pApplyStyleHelper->m_pDlg.disposeAndClear(); + if (pRequest) + pRequest->Done(); + + if (bIsDefaultPage && bDocModified) + { + uno::Reference< style::XStyleFamiliesSupplier > xStyleFamSupp(GetModel(), uno::UNO_QUERY); + + if (!xStyleFamSupp.is()) + { + SAL_WARN("sw.ui", "Ref to XStyleFamiliesSupplier is null."); + return; + } + + syncEndnoteOrientation(xStyleFamSupp); + } + }); + } + else + { + // prior to the dialog the HtmlMode at the DocShell is being sunk + PutItem(SfxUInt16Item(SID_HTML_MODE, ::GetHtmlMode(this))); + + GetWrtShell()->StartAllAction(); + + if( SfxStyleFamily::Para == nFamily ) + { + ::SfxToSwPageDescAttr( *GetWrtShell(), xTmp->GetItemSet() ); + ::ConvertAttrGenToChar(xTmp->GetItemSet(), xTmp->GetItemSet(), /*bIsPara=*/true); + } + else + { + ::ConvertAttrGenToChar(xTmp->GetItemSet(), xTmp->GetItemSet()); + } + if(SfxStyleFamily::Page == nFamily) + m_pView->InvalidateRulerPos(); + + if( bNew ) + m_xBasePool->Broadcast(SfxStyleSheetHint(SfxHintId::StyleSheetCreated, *xTmp)); + + m_xDoc->getIDocumentState().SetModified(); + if( !bModified ) // Bug 57028 + { + m_xDoc->GetIDocumentUndoRedo().SetUndoNoResetModified(); + } + GetWrtShell()->EndAllAction(); + } +} + +void SwDocShell::Delete(const OUString &rName, SfxStyleFamily nFamily) +{ + SfxStyleSheetBase *pStyle = m_xBasePool->Find(rName, nFamily); + + if(pStyle) + { + assert( GetWrtShell() ); + + GetWrtShell()->StartAllAction(); + m_xBasePool->Remove(pStyle); + GetWrtShell()->EndAllAction(); + } +} + +void SwDocShell::Hide(const OUString &rName, SfxStyleFamily nFamily, bool bHidden) +{ + SfxStyleSheetBase *pStyle = m_xBasePool->Find(rName, nFamily); + + if(pStyle) + { + assert( GetWrtShell() ); + + GetWrtShell()->StartAllAction(); + rtl::Reference< SwDocStyleSheet > xTmp( new SwDocStyleSheet( *static_cast<SwDocStyleSheet*>(pStyle) ) ); + xTmp->SetHidden( bHidden ); + GetWrtShell()->EndAllAction(); + } +} + +// apply template +SfxStyleFamily SwDocShell::ApplyStyles(const OUString &rName, SfxStyleFamily nFamily, + SwWrtShell* pShell, const sal_uInt16 nMode ) +{ + SwDocStyleSheet* pStyle = static_cast<SwDocStyleSheet*>( m_xBasePool->Find( rName, nFamily ) ); + + SAL_WARN_IF( !pStyle, "sw.ui", "Style not found" ); + + if(!pStyle) + return SfxStyleFamily::None; + + SwWrtShell *pSh = pShell ? pShell : GetWrtShell(); + + assert( pSh ); + + pSh->StartAllAction(); + + switch (nFamily) + { + case SfxStyleFamily::Char: + { + SwFormatCharFormat aFormat(pStyle->GetCharFormat()); + pSh->SetAttrItem( aFormat, (nMode & KEY_SHIFT) ? + SetAttrMode::DONTREPLACE : SetAttrMode::DEFAULT ); + break; + } + case SfxStyleFamily::Para: + { + if (pSh->GetPostItMgr() && pSh->GetPostItMgr()->HasActiveSidebarWin()) + { + pSh->GetPostItMgr()->GetActiveSidebarWin()->GetOutlinerView()->SetStyleSheet(rName); + } + else + { + // When outline-folding is enabled, MakeAllOutlineContentTemporarilyVisible makes + // application of a paragraph style that has an outline-level greater than the previous + // outline node become folded content of the previous outline node if the previous + // outline node's content is folded. + MakeAllOutlineContentTemporarilyVisible a(GetDoc()); + // #i62675# + // clear also list attributes at affected text nodes, if paragraph + // style has the list style attribute set. + pSh->SetTextFormatColl( pStyle->GetCollection(), true ); + } + break; + } + case SfxStyleFamily::Frame: + { + if ( pSh->IsFrameSelected() ) + pSh->SetFrameFormat( pStyle->GetFrameFormat() ); + break; + } + case SfxStyleFamily::Page: + { + pSh->SetPageStyle(pStyle->GetPageDesc()->GetName()); + break; + } + case SfxStyleFamily::Pseudo: + { + // reset indent attribute on applying list style + // continue list of list style + const SwNumRule* pNumRule = pStyle->GetNumRule(); + if (pNumRule->GetName() == SwResId(STR_POOLNUMRULE_NOLIST)) + { + if (SfxViewFrame* pViewFrm = SfxViewFrame::Current()) + pViewFrm->GetDispatcher()->Execute(FN_NUM_BULLET_OFF); + break; + } + const OUString sListIdForStyle =pNumRule->GetDefaultListId(); + pSh->SetCurNumRule( *pNumRule, false, sListIdForStyle, true ); + break; + } + case SfxStyleFamily::Table: + { + pSh->SetTableStyle(pStyle->GetName()); + break; + } + default: + OSL_FAIL("Unknown family"); + } + pSh->EndAllAction(); + + return nFamily; +} + +// start watering-can +SfxStyleFamily SwDocShell::DoWaterCan(const OUString &rName, SfxStyleFamily nFamily) +{ + assert( GetWrtShell() ); + + SwEditWin& rEdtWin = m_pView->GetEditWin(); + SwApplyTemplate* pApply = rEdtWin.GetApplyTemplate(); + bool bWaterCan = !(pApply && pApply->eType != SfxStyleFamily(0)); + + if( rName.isEmpty() ) + bWaterCan = false; + + SwApplyTemplate aTemplate; + aTemplate.eType = nFamily; + + if(bWaterCan) + { + SwDocStyleSheet* pStyle = + static_cast<SwDocStyleSheet*>( m_xBasePool->Find(rName, nFamily) ); + + SAL_WARN_IF( !pStyle, "sw.ui", "Where's the StyleSheet" ); + + if(!pStyle) return nFamily; + + switch(nFamily) + { + case SfxStyleFamily::Char: + aTemplate.aColl.pCharFormat = pStyle->GetCharFormat(); + break; + case SfxStyleFamily::Para: + aTemplate.aColl.pTextColl = pStyle->GetCollection(); + break; + case SfxStyleFamily::Frame: + aTemplate.aColl.pFrameFormat = pStyle->GetFrameFormat(); + break; + case SfxStyleFamily::Page: + aTemplate.aColl.pPageDesc = const_cast<SwPageDesc*>(pStyle->GetPageDesc()); + break; + case SfxStyleFamily::Pseudo: + aTemplate.aColl.pNumRule = const_cast<SwNumRule*>(pStyle->GetNumRule()); + break; + + default: + OSL_FAIL("Unknown family"); + } + } + else + aTemplate.eType = SfxStyleFamily(0); + + m_pView->GetEditWin().SetApplyTemplate(aTemplate); + + return nFamily; +} + +// update template +void SwDocShell::UpdateStyle(const OUString &rName, SfxStyleFamily nFamily, SwWrtShell* pShell) +{ + SwWrtShell* pCurrWrtShell = pShell ? pShell : GetWrtShell(); + assert( pCurrWrtShell ); + + SwDocStyleSheet* pStyle = + static_cast<SwDocStyleSheet*>( m_xBasePool->Find(rName, nFamily) ); + + if (!pStyle) + return; + + switch(nFamily) + { + case SfxStyleFamily::Para: + { + SwTextFormatColl* pColl = pStyle->GetCollection(); + if(pColl && !pColl->IsDefault()) + { + GetWrtShell()->StartAllAction(); + + SwRewriter aRewriter; + aRewriter.AddRule(UndoArg1, pColl->GetName()); + + GetWrtShell()->StartUndo(SwUndoId::INSFMTATTR, &aRewriter); + GetWrtShell()->FillByEx(pColl); + // also apply template to remove hard set attributes + GetWrtShell()->SetTextFormatColl( pColl ); + GetWrtShell()->EndUndo(); + GetWrtShell()->EndAllAction(); + } + break; + } + case SfxStyleFamily::Frame: + { + SwFrameFormat* pFrame = pStyle->GetFrameFormat(); + if( pCurrWrtShell->IsFrameSelected() && pFrame && !pFrame->IsDefault() ) + { + SfxItemSet aSet( GetPool(), aFrameFormatSetRange ); + pCurrWrtShell->StartAllAction(); + pCurrWrtShell->GetFlyFrameAttr( aSet ); + + // #i105535# + // no update of anchor attribute + aSet.ClearItem( RES_ANCHOR ); + + pFrame->SetFormatAttr( aSet ); + + // also apply template to remove hard set attributes + pCurrWrtShell->SetFrameFormat( pFrame, true ); + pCurrWrtShell->EndAllAction(); + } + } + break; + case SfxStyleFamily::Char: + { + SwCharFormat* pChar = pStyle->GetCharFormat(); + if( pChar && !pChar->IsDefault() ) + { + pCurrWrtShell->StartAllAction(); + pCurrWrtShell->FillByEx(pChar); + // also apply template to remove hard set attributes + pCurrWrtShell->EndAllAction(); + } + + } + break; + case SfxStyleFamily::Pseudo: + { + const SwNumRule* pCurRule; + if( pStyle->GetNumRule() && + nullptr != ( pCurRule = pCurrWrtShell->GetNumRuleAtCurrCursorPos() )) + { + SwNumRule aRule( *pCurRule ); + // #i91400# + aRule.SetName( pStyle->GetNumRule()->GetName(), + pCurrWrtShell->GetDoc()->getIDocumentListsAccess() ); + pCurrWrtShell->ChgNumRuleFormats( aRule ); + } + } + break; + case SfxStyleFamily::Table: + { + if (SwFEShell* pFEShell = GetFEShell()) + { + if(pFEShell->IsTableMode()) + { + pFEShell->TableCursorToCursor(); + } + } + SwTableAutoFormat aFormat(rName); + if (pCurrWrtShell->GetTableAutoFormat(aFormat)) + { + pCurrWrtShell->StartAllAction(); + pCurrWrtShell->GetDoc()->ChgTableStyle(rName, aFormat); + pCurrWrtShell->EndAllAction(); + } + + } + break; + default: break; + } + + m_xDoc->BroadcastStyleOperation(rName, nFamily, SfxHintId::StyleSheetModified); +} + +// NewByExample +void SwDocShell::MakeByExample( const OUString &rName, SfxStyleFamily nFamily, + SfxStyleSearchBits nMask, SwWrtShell* pShell ) +{ + SwWrtShell* pCurrWrtShell = pShell ? pShell : GetWrtShell(); + SwDocStyleSheet* pStyle = static_cast<SwDocStyleSheet*>( m_xBasePool->Find( + rName, nFamily ) ); + if(!pStyle) + { + // preserve the current mask of PI, then the new one is + // immediately merged with the viewable area + if( SfxStyleSearchBits::All == nMask || SfxStyleSearchBits::Used == nMask ) + nMask = SfxStyleSearchBits::UserDefined; + else + nMask |= SfxStyleSearchBits::UserDefined; + + if (nFamily == SfxStyleFamily::Para || nFamily == SfxStyleFamily::Char || nFamily == SfxStyleFamily::Frame) + { + // Prevent undo append from being done during paragraph, character, and frame style Make. Do it later + ::sw::UndoGuard const undoGuard(GetDoc()->GetIDocumentUndoRedo()); + pStyle = static_cast<SwDocStyleSheet*>(&m_xBasePool->Make(rName, nFamily, nMask)); + } + else + { + pStyle = static_cast<SwDocStyleSheet*>(&m_xBasePool->Make(rName, nFamily, nMask)); + } + } + + switch(nFamily) + { + case SfxStyleFamily::Para: + { + SwTextFormatColl* pColl = pStyle->GetCollection(); + if(pColl && !pColl->IsDefault()) + { + pCurrWrtShell->StartAllAction(); + pCurrWrtShell->FillByEx(pColl); + // also apply template to remove hard set attributes + SwTextFormatColl * pDerivedFrom = pCurrWrtShell->GetCurTextFormatColl(); + pColl->SetDerivedFrom(pDerivedFrom); + + // set the mask at the Collection: + sal_uInt16 nId = pColl->GetPoolFormatId() & 0x87ff; + switch( nMask & static_cast<SfxStyleSearchBits>(0x0fff) ) + { + case SfxStyleSearchBits::SwText: + nId |= COLL_TEXT_BITS; + break; + case SfxStyleSearchBits::SwChapter: + nId |= COLL_DOC_BITS; + break; + case SfxStyleSearchBits::SwList: + nId |= COLL_LISTS_BITS; + break; + case SfxStyleSearchBits::SwIndex: + nId |= COLL_REGISTER_BITS; + break; + case SfxStyleSearchBits::SwExtra: + nId |= COLL_EXTRA_BITS; + break; + case SfxStyleSearchBits::SwHtml: + nId |= COLL_HTML_BITS; + break; + default: break; + } + pColl->SetPoolFormatId(nId); + + if (GetDoc()->GetIDocumentUndoRedo().DoesUndo()) + { + GetDoc()->GetIDocumentUndoRedo().AppendUndo( + std::make_unique<SwUndoTextFormatCollCreate>(pColl, pDerivedFrom, *GetDoc())); + } + pCurrWrtShell->SetTextFormatColl(pColl); + pCurrWrtShell->EndAllAction(); + } + } + break; + case SfxStyleFamily::Frame: + { + SwFrameFormat* pFrame = pStyle->GetFrameFormat(); + if(pCurrWrtShell->IsFrameSelected() && pFrame && !pFrame->IsDefault()) + { + pCurrWrtShell->StartAllAction(); + + SfxItemSet aSet(GetPool(), aFrameFormatSetRange ); + pCurrWrtShell->GetFlyFrameAttr( aSet ); + aSet.ClearItem(RES_ANCHOR); // tdf#112574 no anchor in styles + + SwFrameFormat* pFFormat = pCurrWrtShell->GetSelectedFrameFormat(); + pFrame->SetDerivedFrom( pFFormat ); + pFrame->SetFormatAttr( aSet ); + if (GetDoc()->GetIDocumentUndoRedo().DoesUndo()) + { + GetDoc()->GetIDocumentUndoRedo().AppendUndo( + std::make_unique<SwUndoFrameFormatCreate>(pFrame, pFFormat, *GetDoc())); + } + // also apply template to remove hard set attributes + pCurrWrtShell->SetFrameFormat(pFrame); + pCurrWrtShell->EndAllAction(); + } + } + break; + case SfxStyleFamily::Char: + { + SwCharFormat* pChar = pStyle->GetCharFormat(); + if(pChar && !pChar->IsDefault()) + { + pCurrWrtShell->StartAllAction(); + pCurrWrtShell->FillByEx( pChar ); + SwCharFormat * pDerivedFrom = pCurrWrtShell->GetCurCharFormat(); + pChar->SetDerivedFrom( pDerivedFrom ); + SwFormatCharFormat aFormat( pChar ); + + if (GetDoc()->GetIDocumentUndoRedo().DoesUndo()) + { + // Looks like sometimes pDerivedFrom can be null and this is not supported by redo code + // So use default format as a derived from in such situations + GetDoc()->GetIDocumentUndoRedo().AppendUndo( + std::make_unique<SwUndoCharFormatCreate>( + pChar, pDerivedFrom ? pDerivedFrom : GetDoc()->GetDfltCharFormat(), + *GetDoc())); + } + pCurrWrtShell->SetAttrItem(aFormat); + pCurrWrtShell->EndAllAction(); + } + } + break; + + case SfxStyleFamily::Page: + { + pCurrWrtShell->StartAllAction(); + size_t nPgDsc = pCurrWrtShell->GetCurPageDesc(); + SwPageDesc& rSrc = const_cast<SwPageDesc&>(pCurrWrtShell->GetPageDesc( nPgDsc )); + SwPageDesc& rDest = *const_cast<SwPageDesc*>(pStyle->GetPageDesc()); + + sal_uInt16 nPoolId = rDest.GetPoolFormatId(); + sal_uInt16 nHId = rDest.GetPoolHelpId(); + sal_uInt8 nHFId = rDest.GetPoolHlpFileId(); + + pCurrWrtShell->GetDoc()->CopyPageDesc( rSrc, rDest ); + + // PoolId must NEVER be copied! + rDest.SetPoolFormatId( nPoolId ); + rDest.SetPoolHelpId( nHId ); + rDest.SetPoolHlpFileId( nHFId ); + + // when Headers/Footers are created, there is no Undo anymore! + pCurrWrtShell->GetDoc()->GetIDocumentUndoRedo().DelAllUndoObj(); + + pCurrWrtShell->EndAllAction(); + } + break; + + case SfxStyleFamily::Pseudo: + { + const SwNumRule* pCurRule = pCurrWrtShell->GetNumRuleAtCurrCursorPos(); + + if (pCurRule) + { + pCurrWrtShell->StartAllAction(); + + SwNumRule aRule( *pCurRule ); + OUString sOrigRule( aRule.GetName() ); + // #i91400# + aRule.SetName( pStyle->GetNumRule()->GetName(), + pCurrWrtShell->GetDoc()->getIDocumentListsAccess() ); + pCurrWrtShell->ChgNumRuleFormats( aRule ); + + pCurrWrtShell->ReplaceNumRule( sOrigRule, aRule.GetName() ); + + pCurrWrtShell->EndAllAction(); + } + } + break; + + case SfxStyleFamily::Table: + { + SwTableAutoFormat* pFormat = pStyle->GetTableFormat(); + if (pCurrWrtShell->GetTableAutoFormat(*pFormat)) + { + pCurrWrtShell->StartAllAction(); + + pCurrWrtShell->SetTableStyle(rName); + + pCurrWrtShell->EndAllAction(); + } + } + break; + + default: break; + } + + m_xDoc->BroadcastStyleOperation(rName, nFamily, SfxHintId::StyleSheetCreated); +} + +sfx::AccessibilityIssueCollection SwDocShell::runAccessibilityCheck() +{ +#if !ENABLE_WASM_STRIP_ACCESSIBILITY + sw::AccessibilityCheck aCheck(m_xDoc.get()); + aCheck.check(); + return aCheck.getIssueCollection(); +#else + return sfx::AccessibilityIssueCollection(); +#endif +} + +std::set<Color> SwDocShell::GetDocColors() +{ + return m_xDoc->GetDocColors(); +} + +std::shared_ptr<model::ColorSet> SwDocShell::GetThemeColors() +{ + SdrModel* pModel = m_xDoc->getIDocumentDrawModelAccess().GetDrawModel(); + if (!pModel) + return {}; + auto const& pTheme = pModel->getTheme(); + if (!pTheme) + return {}; + return pTheme->getColorSet(); +} + +void SwDocShell::LoadStyles( SfxObjectShell& rSource ) +{ + LoadStyles_(rSource, false); +} + +// bPreserveCurrentDocument determines whether SetFixFields() is called +// This call modifies the source document. This mustn't happen when the source +// is a document the user is working on. +// Calls of ::LoadStyles() normally use files especially loaded for the purpose +// of importing styles. +void SwDocShell::LoadStyles_( SfxObjectShell& rSource, bool bPreserveCurrentDocument ) +{ +/* [Description] + + This method is called by SFx if Styles have to be reloaded from a + document-template. Existing Styles should be overwritten by that. + That's why the document has to be reformatted. Therefore applications + will usually override this method and call the baseclass' implementation + in their implementation. +*/ + // When the source is our document, we do the checking ourselves + // (much quicker and doesn't use the crutch StxStylePool). + if( dynamic_cast<const SwDocShell*>( &rSource) != nullptr) + { + // in order for the Headers/Footers not to get the fixed content + // of the template, update all the Source's + // FixFields once. + if(!bPreserveCurrentDocument) + static_cast<SwDocShell&>(rSource).m_xDoc->getIDocumentFieldsAccess().SetFixFields(nullptr); + if (m_pWrtShell) + { + // rhbz#818557, fdo#58893: EndAllAction will call SelectShell(), + // which pushes a bunch of SfxShells that are not cleared + // (for unknown reasons) when closing the document, causing crash; + // setting g_bNoInterrupt appears to avoid the problem. + ::comphelper::FlagRestorationGuard g(g_bNoInterrupt, true); + m_pWrtShell->StartAllAction(); + m_xDoc->ReplaceStyles( *static_cast<SwDocShell&>(rSource).m_xDoc ); + m_pWrtShell->EndAllAction(); + } + else + { + bool bModified = m_xDoc->getIDocumentState().IsModified(); + m_xDoc->ReplaceStyles( *static_cast<SwDocShell&>(rSource).m_xDoc ); + if (!bModified && m_xDoc->getIDocumentState().IsModified() && !m_pView) + { + // the View is created later, but overwrites the Modify-Flag. + // Undo doesn't work anymore anyways. + m_xDoc->GetIDocumentUndoRedo().SetUndoNoResetModified(); + } + } + } + else + SfxObjectShell::LoadStyles( rSource ); +} + +void SwDocShell::FormatPage( + weld::Window* pDialogParent, + const OUString& rPage, + const OUString& rPageId, + SwWrtShell& rActShell, + SfxRequest* pRequest) +{ + Edit(pDialogParent, rPage, OUString(), SfxStyleFamily::Page, SfxStyleSearchBits::Auto, false, rPageId, &rActShell, pRequest); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/app/docstyle.cxx b/sw/source/uibase/app/docstyle.cxx new file mode 100644 index 0000000000..a715bef70d --- /dev/null +++ b/sw/source/uibase/app/docstyle.cxx @@ -0,0 +1,3380 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <memory> +#include <sal/config.h> +#include <sal/log.hxx> +#include <osl/diagnose.h> + +#include <cstdlib> + +#include <hintids.hxx> +#include <rtl/ustrbuf.hxx> +#include <svl/itemiter.hxx> +#include <svl/eitem.hxx> +#include <unotools/syslocale.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/numitem.hxx> +#include <editeng/lrspitem.hxx> +#include <drawdoc.hxx> +#include <fmtcol.hxx> +#include <uitool.hxx> +#include <wrtsh.hxx> +#include <docsh.hxx> +#include <frmfmt.hxx> +#include <charfmt.hxx> +#include <tblafmt.hxx> +#include <poolfmt.hxx> +#include <pagedesc.hxx> +#include <docstyle.hxx> +#include <docary.hxx> +#include <ccoll.hxx> +#include <doc.hxx> +#include <IDocumentUndoRedo.hxx> +#include <IDocumentStylePoolAccess.hxx> +#include <IDocumentSettingAccess.hxx> +#include <IDocumentDrawModelAccess.hxx> +#include <IDocumentState.hxx> +#include <cmdid.h> +#include <strings.hrc> +#include <paratr.hxx> +#include <SwStyleNameMapper.hxx> +#include <svl/cjkoptions.hxx> +#include <svl/ctloptions.hxx> +#include <unotools/intlwrapper.hxx> +#include <numrule.hxx> +#include <svx/xdef.hxx> +#include <SwRewriter.hxx> +#include <hints.hxx> +#include <frameformats.hxx> +#include <editeng/brushitem.hxx> +#include <editeng/colritem.hxx> +#include <editeng/eeitem.hxx> +#include <svx/xfillit0.hxx> +#include <svx/xflftrit.hxx> +#include <svx/drawitem.hxx> + +using namespace com::sun::star; + +// At the names' publication, this character is removed again and the +// family is newly generated. + +// In addition now there is the Bit bPhysical. In case this Bit is +// TRUE, the Pool-Formatnames are not being submitted. + +namespace { + +class EEStyleSheet : public SfxStyleSheet +{ +public: + using SfxStyleSheet::SfxStyleSheet; + bool IsUsed() const override + { + bool bResult = false; + ForAllListeners( + [&bResult] (SfxListener* pListener) + { + auto pUser(dynamic_cast<svl::StyleSheetUser*>(pListener)); + bResult = pUser && pUser->isUsedByModel(); + return bResult; + }); + return bResult; + } + void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override + { + if (rHint.GetId() == SfxHintId::DataChanged) + Broadcast(rHint); + else + SfxStyleSheet::Notify(rBC, rHint); + } + bool SetParent(const OUString& rName) override + { + if (SfxStyleSheet::SetParent(rName)) + { + auto pStyle = m_pPool->Find(rName, nFamily); + pSet->SetParent(pStyle ? &pStyle->GetItemSet() : nullptr); + return true; + } + return false; + } +}; + +class EEStyleSheetPool : public SfxStyleSheetPool, public SfxListener +{ + SfxStyleSheetBasePool* m_pOwner; + +public: + explicit EEStyleSheetPool(SfxStyleSheetBasePool* pOwner) + : SfxStyleSheetPool(pOwner->GetPool()) + , m_pOwner(pOwner) + { + StartListening(*m_pOwner); + } + + using SfxStyleSheetPool::Create; + rtl::Reference<SfxStyleSheetBase> Create(const OUString& rName, SfxStyleFamily eFamily, + SfxStyleSearchBits nMask) override + { + return new EEStyleSheet(rName, *this, eFamily, nMask); + } + + void Notify(SfxBroadcaster&, const SfxHint& rHint) override + { + auto pHint = dynamic_cast<const SfxStyleSheetHint*>(&rHint); + if (!pHint) + return; + + auto nId = pHint->GetId(); + auto pDocStyleSheet = pHint->GetStyleSheet(); + auto pExtendedHint = dynamic_cast<const SfxStyleSheetModifiedHint*>(&rHint); + const OUString aName = pExtendedHint ? pExtendedHint->GetOldName() : pDocStyleSheet->GetName(); + auto pStyleSheet = SfxStyleSheetPool::Find(aName, pDocStyleSheet->GetFamily()); + if (!pStyleSheet) + return; + + if (nId == SfxHintId::StyleSheetModified) + { + pStyleSheet->SetName(pDocStyleSheet->GetName()); + UpdateStyleHierarchyFrom(pStyleSheet, pDocStyleSheet); + static_cast<SfxStyleSheet*>(pStyleSheet)->Broadcast(SfxHint(SfxHintId::DataChanged)); + } + else if (nId == SfxHintId::StyleSheetErased) + Remove(pStyleSheet); + } + + SfxStyleSheetBase* Find(const OUString& rName, SfxStyleFamily eFamily, + SfxStyleSearchBits = SfxStyleSearchBits::All) override + { + auto pStyleSheet = SfxStyleSheetPool::Find(rName, eFamily); + + if (auto pDocStyleSheet = pStyleSheet ? nullptr : m_pOwner->Find(rName, eFamily)) + { + pStyleSheet = &Make(pDocStyleSheet->GetName(), pDocStyleSheet->GetFamily()); + UpdateStyleHierarchyFrom(pStyleSheet, pDocStyleSheet); + } + + return pStyleSheet; + } + + void UpdateStyleHierarchyFrom(SfxStyleSheetBase* pStyleSheet, SfxStyleSheetBase* pDocStyleSheet) + { + FillItemSet(pStyleSheet, pDocStyleSheet); + + // Remember now, as the next calls will invalidate pDocStyleSheet. + const OUString aParent = pDocStyleSheet->GetParent(); + const OUString aFollow = pDocStyleSheet->GetFollow(); + + if (pStyleSheet->GetParent() != aParent) + pStyleSheet->SetParent(aParent); + + if (pStyleSheet->GetFollow() != aFollow) + pStyleSheet->SetFollow(aFollow); + } + + void FillItemSet(SfxStyleSheetBase* pDestSheet, SfxStyleSheetBase* pSourceSheet) + { + auto& rItemSet = pDestSheet->GetItemSet(); + rItemSet.ClearItem(); + + auto pCol = static_cast<SwDocStyleSheet*>(pSourceSheet)->GetCollection(); + SfxItemIter aIter(pCol->GetAttrSet()); + std::optional<SvxLRSpaceItem> oLRSpaceItem; + + for (auto pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem()) + { + if (aIter.GetItemState(false) != SfxItemState::SET) + continue; + + auto nWhich = pItem->Which(); + auto nSlotId = rPool.GetSlotId(nWhich); + auto nNewWhich = rPool.GetSecondaryPool()->GetWhich(nSlotId); + if (nNewWhich != nSlotId) + rItemSet.Put(pItem->CloneSetWhich(nNewWhich)); + else if (nWhich == RES_MARGIN_FIRSTLINE) + { + if (!oLRSpaceItem) + oLRSpaceItem.emplace(EE_PARA_LRSPACE); + auto pFirstLineItem = static_cast<const SvxFirstLineIndentItem*>(pItem); + (*oLRSpaceItem).SetTextFirstLineOffsetValue(pFirstLineItem->GetTextFirstLineOffset()); + (*oLRSpaceItem).SetAutoFirst(pFirstLineItem->IsAutoFirst()); + } + else if (nWhich == RES_MARGIN_TEXTLEFT) + { + if (!oLRSpaceItem) + oLRSpaceItem.emplace(EE_PARA_LRSPACE); + (*oLRSpaceItem).SetTextLeft(static_cast<const SvxTextLeftMarginItem*>(pItem)->GetTextLeft()); + } + else if (nWhich == RES_MARGIN_RIGHT) + { + if (!oLRSpaceItem) + oLRSpaceItem.emplace(EE_PARA_LRSPACE); + (*oLRSpaceItem).SetRight(static_cast<const SvxRightMarginItem*>(pItem)->GetRight()); + } + else if (nWhich == RES_CHRATR_BACKGROUND) + { + auto pBrushItem = static_cast<const SvxBrushItem*>(pItem); + rItemSet.Put(SvxColorItem(pBrushItem->GetColor(), EE_CHAR_BKGCOLOR)); + } + } + if (oLRSpaceItem) + rItemSet.Put(*oLRSpaceItem); + } +}; + +class SwImplShellAction +{ + SwWrtShell* m_pSh; + std::unique_ptr<CurrShell> m_pCurrSh; +public: + explicit SwImplShellAction( SwDoc& rDoc ); + ~SwImplShellAction() COVERITY_NOEXCEPT_FALSE; + SwImplShellAction(const SwImplShellAction&) = delete; + SwImplShellAction& operator=(const SwImplShellAction&) = delete; +}; + +} + +SwImplShellAction::SwImplShellAction( SwDoc& rDoc ) +{ + if( rDoc.GetDocShell() ) + m_pSh = rDoc.GetDocShell()->GetWrtShell(); + else + m_pSh = nullptr; + + if( m_pSh ) + { + m_pCurrSh.reset( new CurrShell( m_pSh ) ); + m_pSh->StartAllAction(); + } +} + +SwImplShellAction::~SwImplShellAction() COVERITY_NOEXCEPT_FALSE +{ + if( m_pCurrSh ) + { + m_pSh->EndAllAction(); + m_pCurrSh.reset(); + } +} + +// find/create SwCharFormate +// possibly fill Style +static SwCharFormat* lcl_FindCharFormat( SwDoc& rDoc, + const OUString& rName, + SwDocStyleSheet* pStyle = nullptr, + bool bCreate = true ) +{ + SwCharFormat* pFormat = nullptr; + if (!rName.isEmpty()) + { + pFormat = rDoc.FindCharFormatByName( rName ); + if( !pFormat && rName == SwResId(STR_POOLCHR_STANDARD)) + { + // Standard-Character template + pFormat = rDoc.GetDfltCharFormat(); + } + + if( !pFormat && bCreate ) + { // explore Pool + const sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(rName, SwGetPoolIdFromName::ChrFmt); + if(nId != USHRT_MAX) + pFormat = rDoc.getIDocumentStylePoolAccess().GetCharFormatFromPool(nId); + } + } + if(pStyle) + { + if(pFormat) + { + pStyle->SetPhysical(true); + SwFormat* p = pFormat->DerivedFrom(); + if( p && !p->IsDefault() ) + pStyle->PresetParent( p->GetName() ); + else + pStyle->PresetParent( OUString() ); + } + else + pStyle->SetPhysical(false); + } + return pFormat; +} + +// find/create ParaFormats +// fill Style +static SwTextFormatColl* lcl_FindParaFormat( SwDoc& rDoc, + const OUString& rName, + SwDocStyleSheet* pStyle = nullptr, + bool bCreate = true ) +{ + SwTextFormatColl* pColl = nullptr; + + if (!rName.isEmpty()) + { + pColl = rDoc.FindTextFormatCollByName( rName ); + if( !pColl && bCreate ) + { // explore Pool + const sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(rName, SwGetPoolIdFromName::TxtColl); + if(nId != USHRT_MAX) + pColl = rDoc.getIDocumentStylePoolAccess().GetTextCollFromPool(nId); + } + } + + if(pStyle) + { + if(pColl) + { + pStyle->SetPhysical(true); + if( pColl->DerivedFrom() && !pColl->DerivedFrom()->IsDefault() ) + pStyle->PresetParent( pColl->DerivedFrom()->GetName() ); + else + pStyle->PresetParent( OUString() ); + + SwTextFormatColl& rNext = pColl->GetNextTextFormatColl(); + pStyle->PresetFollow(rNext.GetName()); + } + else + pStyle->SetPhysical(false); + } + return pColl; +} + +// Border formats +static SwFrameFormat* lcl_FindFrameFormat( SwDoc& rDoc, + const OUString& rName, + SwDocStyleSheet* pStyle = nullptr, + bool bCreate = true ) +{ + SwFrameFormat* pFormat = nullptr; + if( !rName.isEmpty() ) + { + pFormat = rDoc.FindFrameFormatByName( rName ); + if( !pFormat && bCreate ) + { // explore Pool + const sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(rName, SwGetPoolIdFromName::FrmFmt); + if(nId != USHRT_MAX) + pFormat = rDoc.getIDocumentStylePoolAccess().GetFrameFormatFromPool(nId); + } + } + + if(pStyle) + { + if(pFormat) + { + pStyle->SetPhysical(true); + if( pFormat->DerivedFrom() && !pFormat->DerivedFrom()->IsDefault() ) + pStyle->PresetParent( pFormat->DerivedFrom()->GetName() ); + else + pStyle->PresetParent( OUString() ); + } + else + pStyle->SetPhysical(false); + } + return pFormat; +} + +// Page descriptors +static const SwPageDesc* lcl_FindPageDesc( SwDoc& rDoc, + const OUString& rName, + SwDocStyleSheet* pStyle = nullptr, + bool bCreate = true ) +{ + const SwPageDesc* pDesc = nullptr; + + if (!rName.isEmpty()) + { + pDesc = rDoc.FindPageDesc(rName); + if( !pDesc && bCreate ) + { + sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(rName, SwGetPoolIdFromName::PageDesc); + if(nId != USHRT_MAX) + pDesc = rDoc.getIDocumentStylePoolAccess().GetPageDescFromPool(nId); + } + } + + if(pStyle) + { + if(pDesc) + { + pStyle->SetPhysical(true); + if(pDesc->GetFollow()) + pStyle->PresetFollow(pDesc->GetFollow()->GetName()); + else + pStyle->PresetParent( OUString() ); + } + else + pStyle->SetPhysical(false); + } + return pDesc; +} + +static const SwNumRule* lcl_FindNumRule( SwDoc& rDoc, + const OUString& rName, + SwDocStyleSheet* pStyle = nullptr, + bool bCreate = true ) +{ + const SwNumRule* pRule = nullptr; + + if (!rName.isEmpty()) + { + pRule = rDoc.FindNumRulePtr( rName ); + if( !pRule && bCreate ) + { + sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(rName, SwGetPoolIdFromName::NumRule); + if(nId != USHRT_MAX) + pRule = rDoc.getIDocumentStylePoolAccess().GetNumRuleFromPool(nId); + } + } + + if(pStyle) + { + if(pRule) + { + pStyle->SetPhysical(true); + pStyle->PresetParent( OUString() ); + } + else + pStyle->SetPhysical(false); + } + return pRule; +} + +static SwTableAutoFormat* lcl_FindTableStyle(SwDoc& rDoc, const OUString& rName, SwDocStyleSheet *pStyle = nullptr, bool bCreate = true) +{ + SwTableAutoFormat* pFormat = nullptr; + + if (!rName.isEmpty()) + { + pFormat = rDoc.GetTableStyles().FindAutoFormat(rName); + if (!pFormat && bCreate) + { + SwTableAutoFormat aNew(rName); + rDoc.GetTableStyles().AddAutoFormat(aNew); + } + } + + if(pStyle) + { + if(pFormat) + { + pStyle->SetPhysical(true); + pStyle->PresetParent(OUString()); + } + else + pStyle->SetPhysical(false); + } + return pFormat; +} + +static const SwBoxAutoFormat* lcl_FindCellStyle(SwDoc& rDoc, std::u16string_view rName, SwDocStyleSheet *pStyle) +{ + const SwBoxAutoFormat* pFormat = rDoc.GetCellStyles().GetBoxFormat(rName); + + if (!pFormat) + { + const auto& aTableTemplateMap = SwTableAutoFormat::GetTableTemplateMap(); + SwTableAutoFormatTable& rTableStyles = rDoc.GetTableStyles(); + for (size_t i=0; i < rTableStyles.size() && !pFormat; ++i) + { + const SwTableAutoFormat& rTableStyle = rTableStyles[i]; + for (size_t nBoxFormat=0; nBoxFormat < aTableTemplateMap.size() && !pFormat; ++nBoxFormat) + { + const sal_uInt32 nBoxIndex = aTableTemplateMap[nBoxFormat]; + const SwBoxAutoFormat& rBoxFormat = rTableStyle.GetBoxFormat(nBoxIndex); + OUString sBoxFormatName; + SwStyleNameMapper::FillProgName(rTableStyle.GetName(), sBoxFormatName, SwGetPoolIdFromName::TabStyle); + sBoxFormatName += rTableStyle.GetTableTemplateCellSubName(rBoxFormat); + if (rName == sBoxFormatName) + pFormat = &rBoxFormat; + } + } + } + + if(pStyle) + { + if(pFormat) + { + pStyle->SetPhysical(true); + pStyle->PresetParent(OUString()); + } + else + pStyle->SetPhysical(false); + } + return pFormat; +} + +sal_uInt32 SwStyleSheetIterator::SwPoolFormatList::FindName(SfxStyleFamily eFam, + const OUString& rName) +{ + if(!maImpl.empty()) + { + UniqueHash::const_iterator it = maUnique.find(std::pair<SfxStyleFamily,OUString>{eFam, rName}); + if (it != maUnique.end()) + { + sal_uInt32 nIdx = it->second; + assert (nIdx < maImpl.size()); + assert (maImpl.size() == maUnique.size()); + return nIdx; + } + } + return SAL_MAX_UINT32; +} + +void SwStyleSheetIterator::SwPoolFormatList::rehash() +{ + maUnique.clear(); + for (size_t i = 0; i < maImpl.size(); i++) + maUnique[maImpl[i]] = i; + assert (maImpl.size() == maUnique.size()); +} + +void SwStyleSheetIterator::SwPoolFormatList::RemoveName(SfxStyleFamily eFam, + const OUString& rName) +{ + sal_uInt32 nTmpPos = FindName( eFam, rName ); + if (nTmpPos != SAL_MAX_UINT32) + maImpl.erase(maImpl.begin() + nTmpPos); + + // assumption: this seldom occurs, the iterator is built, then emptied. + rehash(); + assert (maImpl.size() == maUnique.size()); +} + +// Add Strings to the list of templates +void SwStyleSheetIterator::SwPoolFormatList::Append( SfxStyleFamily eFam, const OUString& rStr ) +{ + UniqueHash::const_iterator it = maUnique.find(std::pair<SfxStyleFamily,OUString>{eFam, rStr}); + if (it != maUnique.end()) + return; + + maUnique.emplace(std::pair<SfxStyleFamily,OUString>{eFam, rStr}, static_cast<sal_uInt32>(maImpl.size())); + maImpl.push_back(std::pair<SfxStyleFamily,OUString>{eFam, rStr}); +} + +// UI-sided implementation of StyleSheets +// uses the Core-Engine +SwDocStyleSheet::SwDocStyleSheet( SwDoc& rDocument, + SwDocStyleSheetPool& rPool) : + + SfxStyleSheetBase( OUString(), &rPool, SfxStyleFamily::Char, SfxStyleSearchBits::Auto ), + m_pCharFormat(nullptr), + m_pColl(nullptr), + m_pFrameFormat(nullptr), + m_pDesc(nullptr), + m_pNumRule(nullptr), + m_pTableFormat(nullptr), + m_pBoxFormat(nullptr), + m_rDoc(rDocument), + m_aCoreSet( + rPool.GetPool(), + svl::Items< + RES_CHRATR_BEGIN, RES_CHRATR_END - 1, + RES_PARATR_BEGIN, RES_FRMATR_END - 1, + RES_UNKNOWNATR_BEGIN, RES_UNKNOWNATR_END - 1, + // FillAttribute support: + XATTR_FILL_FIRST, XATTR_FILL_LAST, + SID_ATTR_BORDER_INNER, SID_ATTR_BORDER_INNER, + SID_ATTR_PAGE, SID_ATTR_PAGE_EXT1, + SID_ATTR_PAGE_HEADERSET, SID_ATTR_PAGE_FOOTERSET, + SID_ATTR_PARA_MODEL, SID_ATTR_PARA_MODEL, + // Items to hand over XPropertyList things like XColorList, + // XHatchList, XGradientList, and XBitmapList to the Area TabPage: + SID_COLOR_TABLE, SID_PATTERN_LIST, + SID_SWREGISTER_COLLECTION, SID_SWREGISTER_COLLECTION, + SID_ATTR_PARA_PAGENUM, SID_ATTR_PARA_PAGENUM, + SID_SWREGISTER_MODE, SID_SWREGISTER_MODE, + SID_ATTR_BRUSH_CHAR, SID_ATTR_BRUSH_CHAR, + SID_ATTR_NUMBERING_RULE, SID_ATTR_NUMBERING_RULE, + SID_ATTR_CHAR_GRABBAG, SID_ATTR_CHAR_GRABBAG, + SID_ATTR_AUTO_STYLE_UPDATE, SID_ATTR_AUTO_STYLE_UPDATE, + FN_PARAM_FTN_INFO, FN_PARAM_FTN_INFO, + FN_KEEP_ASPECT_RATIO, FN_KEEP_ASPECT_RATIO, + FN_COND_COLL, FN_COND_COLL>), + m_bPhysical(false) +{ + nHelpId = UCHAR_MAX; +} + +SwDocStyleSheet::SwDocStyleSheet( const SwDocStyleSheet& ) = default; + +SwDocStyleSheet::~SwDocStyleSheet() = default; + +void SwDocStyleSheet::Reset() +{ + aName.clear(); + aFollow.clear(); + aParent.clear(); + SetPhysical(false); +} + +void SwDocStyleSheet::SetGrabBagItem(const uno::Any& rVal) +{ + bool bChg = false; + if (!m_bPhysical) + FillStyleSheet(FillPhysical); + + SwFormat* pFormat = nullptr; + switch (nFamily) + { + case SfxStyleFamily::Char: + pFormat = m_rDoc.FindCharFormatByName(aName); + if (pFormat) + { + pFormat->SetGrabBagItem(rVal); + bChg = true; + } + break; + case SfxStyleFamily::Para: + pFormat = m_rDoc.FindTextFormatCollByName(aName); + if (pFormat) + { + pFormat->SetGrabBagItem(rVal); + bChg = true; + } + break; + case SfxStyleFamily::Pseudo: + { + SwNumRule* pRule = m_rDoc.FindNumRulePtr(aName); + if (pRule) + { + pRule->SetGrabBagItem(rVal); + bChg = true; + } + } + break; + default: + break; + } + + if (bChg) + { + dynamic_cast<SwDocStyleSheetPool&>(*m_pPool).InvalidateIterator(); + m_pPool->Broadcast(SfxStyleSheetHint(SfxHintId::StyleSheetModified, *this)); + if (SwEditShell* pSh = m_rDoc.GetEditShell()) + pSh->CallChgLnk(); + } +} + +void SwDocStyleSheet::GetGrabBagItem(uno::Any& rVal) const +{ + SwFormat* pFormat = nullptr; + switch (nFamily) + { + case SfxStyleFamily::Char: + pFormat = m_rDoc.FindCharFormatByName(aName); + if (pFormat) + pFormat->GetGrabBagItem(rVal); + break; + case SfxStyleFamily::Para: + pFormat = m_rDoc.FindTextFormatCollByName(aName); + if (pFormat) + pFormat->GetGrabBagItem(rVal); + break; + case SfxStyleFamily::Pseudo: + { + SwNumRule* pRule = m_rDoc.FindNumRulePtr(aName); + if (pRule) + pRule->GetGrabBagItem(rVal); + } + break; + default: + break; + } +} +// virtual methods +void SwDocStyleSheet::SetHidden( bool bValue ) +{ + bool bChg = false; + if(!m_bPhysical) + FillStyleSheet( FillPhysical ); + + SwFormat* pFormat = nullptr; + switch(nFamily) + { + case SfxStyleFamily::Char: + pFormat = m_rDoc.FindCharFormatByName( aName ); + if ( pFormat ) + { + pFormat->SetHidden( bValue ); + bChg = true; + } + break; + + case SfxStyleFamily::Para: + pFormat = m_rDoc.FindTextFormatCollByName( aName ); + if ( pFormat ) + { + pFormat->SetHidden( bValue ); + bChg = true; + } + break; + + case SfxStyleFamily::Frame: + pFormat = m_rDoc.FindFrameFormatByName( aName ); + if ( pFormat ) + { + pFormat->SetHidden( bValue ); + bChg = true; + } + break; + + case SfxStyleFamily::Page: + { + SwPageDesc* pPgDesc = m_rDoc.FindPageDesc(aName); + if ( pPgDesc ) + { + pPgDesc->SetHidden( bValue ); + bChg = true; + } + } + break; + + case SfxStyleFamily::Pseudo: + { + SwNumRule* pRule = m_rDoc.FindNumRulePtr( aName ); + if ( pRule ) + { + pRule->SetHidden( bValue ); + bChg = true; + } + } + break; + + case SfxStyleFamily::Table: + { + SwTableAutoFormat* pTableAutoFormat = m_rDoc.GetTableStyles().FindAutoFormat( aName ); + if ( pTableAutoFormat ) + { + pTableAutoFormat->SetHidden( bValue ); + bChg = true; + } + } + break; + + default: + break; + } + + if( bChg ) + { + // calling pPool->First() here would be quite slow... + dynamic_cast<SwDocStyleSheetPool&>(*m_pPool).InvalidateIterator(); // internal list has to be updated + m_pPool->Broadcast( SfxStyleSheetHint( SfxHintId::StyleSheetModified, *this ) ); + if (SwEditShell* pSh = m_rDoc.GetEditShell()) + pSh->CallChgLnk(); + } +} + +bool SwDocStyleSheet::IsHidden( ) const +{ + bool bRet = false; + + SwFormat* pFormat = nullptr; + switch(nFamily) + { + case SfxStyleFamily::Char: + pFormat = m_rDoc.FindCharFormatByName( aName ); + bRet = pFormat && pFormat->IsHidden( ); + break; + + case SfxStyleFamily::Para: + pFormat = m_rDoc.FindTextFormatCollByName( aName ); + bRet = pFormat && pFormat->IsHidden( ); + break; + + case SfxStyleFamily::Frame: + pFormat = m_rDoc.FindFrameFormatByName( aName ); + bRet = pFormat && pFormat->IsHidden( ); + break; + + case SfxStyleFamily::Page: + { + SwPageDesc* pPgDesc = m_rDoc.FindPageDesc(aName); + bRet = pPgDesc && pPgDesc->IsHidden( ); + } + break; + case SfxStyleFamily::Pseudo: + { + SwNumRule* pRule = m_rDoc.FindNumRulePtr( aName ); + bRet = pRule && pRule->IsHidden( ); + } + break; + case SfxStyleFamily::Table: + { + SwTableAutoFormat* pTableAutoFormat = m_rDoc.GetTableStyles().FindAutoFormat( aName ); + bRet = pTableAutoFormat && pTableAutoFormat->IsHidden( ); + } + break; + default: + break; + } + + return bRet; +} + +const OUString& SwDocStyleSheet::GetParent() const +{ + if( !m_bPhysical ) + { + // check if it's already in document + SwFormat* pFormat = nullptr; + SwGetPoolIdFromName eGetType; + switch(nFamily) + { + case SfxStyleFamily::Char: + pFormat = m_rDoc.FindCharFormatByName( aName ); + eGetType = SwGetPoolIdFromName::ChrFmt; + break; + + case SfxStyleFamily::Para: + pFormat = m_rDoc.FindTextFormatCollByName( aName ); + eGetType = SwGetPoolIdFromName::TxtColl; + break; + + case SfxStyleFamily::Frame: + pFormat = m_rDoc.FindFrameFormatByName( aName ); + eGetType = SwGetPoolIdFromName::FrmFmt; + break; + + case SfxStyleFamily::Page: + case SfxStyleFamily::Pseudo: + default: + { + static const OUString sEmpty; + return sEmpty; // there's no parent + } + } + + OUString sTmp; + if( !pFormat ) // not yet there, so default Parent + { + sal_uInt16 i = SwStyleNameMapper::GetPoolIdFromUIName( aName, eGetType ); + i = ::GetPoolParent( i ); + if( i && USHRT_MAX != i ) + SwStyleNameMapper::FillUIName( i, sTmp ); + } + else + { + SwFormat* p = pFormat->DerivedFrom(); + if( p && !p->IsDefault() ) + sTmp = p->GetName(); + } + SwDocStyleSheet* pThis = const_cast<SwDocStyleSheet*>(this); + pThis->aParent = sTmp; + } + return aParent; +} + +// Follower +const OUString& SwDocStyleSheet::GetFollow() const +{ + if( !m_bPhysical ) + { + SwDocStyleSheet* pThis = const_cast<SwDocStyleSheet*>(this); + pThis->FillStyleSheet( FillAllInfo ); + } + return aFollow; +} + +void SwDocStyleSheet::SetLink(const OUString& rStr) +{ + SwImplShellAction aTmpSh(m_rDoc); + switch (nFamily) + { + case SfxStyleFamily::Para: + { + if (m_pColl) + { + SwCharFormat* pLink = lcl_FindCharFormat(m_rDoc, rStr); + if (pLink) + { + m_pColl->SetLinkedCharFormat(pLink); + } + } + break; + } + case SfxStyleFamily::Char: + { + if (m_pCharFormat) + { + SwTextFormatColl* pLink = lcl_FindParaFormat(m_rDoc, rStr); + if (pLink) + { + m_pCharFormat->SetLinkedParaFormat(pLink); + } + } + break; + } + default: + break; + } +} + +const OUString& SwDocStyleSheet::GetLink() const +{ + if (!m_bPhysical) + { + SwDocStyleSheet* pThis = const_cast<SwDocStyleSheet*>(this); + pThis->FillStyleSheet(FillAllInfo); + } + + return m_aLink; +} + +// What Linkage is possible +bool SwDocStyleSheet::HasFollowSupport() const +{ + switch(nFamily) + { + case SfxStyleFamily::Para : + case SfxStyleFamily::Page : return true; + case SfxStyleFamily::Frame: + case SfxStyleFamily::Char : + case SfxStyleFamily::Pseudo: return false; + default: + OSL_ENSURE(false, "unknown style family"); + } + return false; +} + +// Parent ? +bool SwDocStyleSheet::HasParentSupport() const +{ + bool bRet = false; + switch(nFamily) + { + case SfxStyleFamily::Char : + case SfxStyleFamily::Para : + case SfxStyleFamily::Frame: bRet = true; + break; + default:; //prevent warning + } + return bRet; +} + +bool SwDocStyleSheet::HasClearParentSupport() const +{ + bool bRet = false; + switch(nFamily) + { + case SfxStyleFamily::Para : + case SfxStyleFamily::Char : + case SfxStyleFamily::Frame: bRet = true; + break; + default:; //prevent warning + } + return bRet; +} + +// determine textual description +OUString SwDocStyleSheet::GetDescription(MapUnit eUnit) +{ + IntlWrapper aIntlWrapper(SvtSysLocale().GetUILanguageTag()); + + static constexpr OUString sPlus(u" + "_ustr); + if ( SfxStyleFamily::Page == nFamily ) + { + if( !pSet ) + GetItemSet(); + + SfxItemIter aIter( *pSet ); + OUStringBuffer aDesc; + + for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem()) + { + if(!IsInvalidItem(pItem)) + { + switch ( pItem->Which() ) + { + case RES_LR_SPACE: + case SID_ATTR_PAGE_SIZE: + case SID_ATTR_PAGE_MAXSIZE: + case SID_ATTR_PAGE_PAPERBIN: + case SID_ATTR_BORDER_INNER: + break; + default: + { + OUString aItemPresentation; + if ( !IsInvalidItem( pItem ) && + m_pPool->GetPool().GetPresentation( + *pItem, eUnit, aItemPresentation, aIntlWrapper ) ) + { + if ( !aDesc.isEmpty() && !aItemPresentation.isEmpty() ) + aDesc.append(sPlus); + aDesc.append(aItemPresentation); + } + } + } + } + } + return aDesc.makeStringAndClear(); + } + + if ( SfxStyleFamily::Frame == nFamily || SfxStyleFamily::Para == nFamily || SfxStyleFamily::Char == nFamily ) + { + if( !pSet ) + GetItemSet(); + + SfxItemIter aIter( *pSet ); + OUStringBuffer aDesc; + OUString sPageNum; + OUString sModel; + OUString sBreak; + bool bHasWesternFontPrefix = false; + bool bHasCJKFontPrefix = false; + bool bHasCTLFontPrefix = false; + SvtCTLOptions aCTLOptions; + + // Get currently used FillStyle and remember, also need the XFillFloatTransparenceItem + // to decide if gradient transparence is used + const drawing::FillStyle eFillStyle(pSet->Get(XATTR_FILLSTYLE).GetValue()); + const bool bUseFloatTransparence(pSet->Get(XATTR_FILLFLOATTRANSPARENCE).IsEnabled()); + + for (const SfxPoolItem* pItem = aIter.GetCurItem(); pItem; pItem = aIter.NextItem()) + { + if(!IsInvalidItem(pItem)) + { + switch ( pItem->Which() ) + { + case SID_ATTR_AUTO_STYLE_UPDATE: + case RES_PAGEDESC: + break; + default: + { + OUString aItemPresentation; + if ( !IsInvalidItem( pItem ) && + m_pPool->GetPool().GetPresentation( + *pItem, eUnit, aItemPresentation, aIntlWrapper ) ) + { + bool bIsDefault = false; + switch ( pItem->Which() ) + { + case XATTR_FILLCOLOR: + { + // only use active FillStyle information + bIsDefault = (drawing::FillStyle_SOLID == eFillStyle); + break; + } + case XATTR_FILLGRADIENT: + { + // only use active FillStyle information + bIsDefault = (drawing::FillStyle_GRADIENT == eFillStyle); + break; + } + case XATTR_FILLHATCH: + { + // only use active FillStyle information + bIsDefault = (drawing::FillStyle_HATCH == eFillStyle); + break; + } + case XATTR_FILLBITMAP: + { + // only use active FillStyle information + bIsDefault = (drawing::FillStyle_BITMAP == eFillStyle); + break; + } + case XATTR_FILLTRANSPARENCE: + { + // only active when not FloatTransparence + bIsDefault = !bUseFloatTransparence; + break; + } + case XATTR_FILLFLOATTRANSPARENCE: + { + // only active when FloatTransparence + bIsDefault = bUseFloatTransparence; + break; + } + + case SID_ATTR_PARA_PAGENUM: + sPageNum = aItemPresentation; + break; + case SID_ATTR_PARA_MODEL: + sModel = aItemPresentation; + break; + case RES_BREAK: + sBreak = aItemPresentation; + break; + case RES_CHRATR_CJK_FONT: + case RES_CHRATR_CJK_FONTSIZE: + case RES_CHRATR_CJK_LANGUAGE: + case RES_CHRATR_CJK_POSTURE: + case RES_CHRATR_CJK_WEIGHT: + if(SvtCJKOptions::IsCJKFontEnabled()) + bIsDefault = true; + if(!bHasCJKFontPrefix) + { + aItemPresentation = SwResId(STR_CJK_FONT) + aItemPresentation; + bHasCJKFontPrefix = true; + } + break; + case RES_CHRATR_CTL_FONT: + case RES_CHRATR_CTL_FONTSIZE: + case RES_CHRATR_CTL_LANGUAGE: + case RES_CHRATR_CTL_POSTURE: + case RES_CHRATR_CTL_WEIGHT: + if(SvtCTLOptions::IsCTLFontEnabled()) + bIsDefault = true; + if(!bHasCTLFontPrefix) + { + aItemPresentation = SwResId(STR_CTL_FONT) + aItemPresentation; + bHasCTLFontPrefix = true; + } + break; + case RES_CHRATR_FONT: + case RES_CHRATR_FONTSIZE: + case RES_CHRATR_LANGUAGE: + case RES_CHRATR_POSTURE: + case RES_CHRATR_WEIGHT: + if(!bHasWesternFontPrefix) + { + aItemPresentation = SwResId(STR_WESTERN_FONT) + aItemPresentation; + bHasWesternFontPrefix = true; + } + [[fallthrough]]; + default: + bIsDefault = true; + } + if(bIsDefault) + { + if ( !aDesc.isEmpty() && !aItemPresentation.isEmpty() ) + aDesc.append(sPlus); + aDesc.append(aItemPresentation); + } + } + } + } + } + } + // Special treatment for Break, Page template and Site offset + if (!sModel.isEmpty()) + { + if (!aDesc.isEmpty()) + aDesc.append(sPlus); + aDesc.append(SwResId(STR_PAGEBREAK) + sPlus + sModel); + if (sPageNum != "0") + { + aDesc.append(sPlus + SwResId(STR_PAGEOFFSET) + sPageNum); + } + } + else if (!sBreak.isEmpty()) // Break can be valid only when NO Model + { + if (!aDesc.isEmpty()) + aDesc.append(sPlus); + aDesc.append(sBreak); + } + return aDesc.makeStringAndClear(); + } + + if( SfxStyleFamily::Pseudo == nFamily ) + { + return OUString(); + } + + return SfxStyleSheetBase::GetDescription(eUnit); +} + +// Set names +bool SwDocStyleSheet::SetName(const OUString& rStr, bool bReindexNow) +{ + if( rStr.isEmpty() ) + return false; + + if( aName != rStr ) + { + if( !SfxStyleSheetBase::SetName(rStr, bReindexNow)) + return false; + } + else if(!m_bPhysical) + FillStyleSheet( FillPhysical ); + + bool bChg = false; + switch(nFamily) + { + case SfxStyleFamily::Char : + { + OSL_ENSURE(m_pCharFormat, "SwCharFormat missing!"); + if( m_pCharFormat && m_pCharFormat->GetName() != rStr ) + { + if (!m_pCharFormat->GetName().isEmpty()) + m_rDoc.RenameFormat(*m_pCharFormat, rStr); + else + m_pCharFormat->SetFormatName(rStr); + + bChg = true; + } + break; + } + case SfxStyleFamily::Para : + { + OSL_ENSURE(m_pColl, "Collection missing!"); + if( m_pColl && m_pColl->GetName() != rStr ) + { + if (!m_pColl->GetName().isEmpty()) + m_rDoc.RenameFormat(*m_pColl, rStr); + else + m_pColl->SetFormatName(rStr); + + bChg = true; + } + break; + } + case SfxStyleFamily::Frame: + { + OSL_ENSURE(m_pFrameFormat, "FrameFormat missing!"); + if( m_pFrameFormat && m_pFrameFormat->GetName() != rStr ) + { + if (!m_pFrameFormat->GetName().isEmpty()) + m_rDoc.RenameFormat(*m_pFrameFormat, rStr); + else + m_pFrameFormat->SetFormatName( rStr ); + + bChg = true; + } + break; + } + case SfxStyleFamily::Page : + OSL_ENSURE(m_pDesc, "PageDesc missing!"); + if( m_pDesc && m_pDesc->GetName() != rStr ) + { + // Set PageDesc - copy with earlier one - probably not + // necessary for setting the name. So here we allow a + // cast. + SwPageDesc aPageDesc(*const_cast<SwPageDesc*>(m_pDesc)); + const OUString aOldName(aPageDesc.GetName()); + + aPageDesc.SetName( rStr ); + bool const bDoesUndo = m_rDoc.GetIDocumentUndoRedo().DoesUndo(); + + m_rDoc.GetIDocumentUndoRedo().DoUndo(!aOldName.isEmpty()); + m_rDoc.ChgPageDesc(aOldName, aPageDesc); + m_rDoc.GetIDocumentUndoRedo().DoUndo(bDoesUndo); + + m_rDoc.getIDocumentState().SetModified(); + bChg = true; + } + break; + case SfxStyleFamily::Pseudo: + OSL_ENSURE(m_pNumRule, "NumRule missing!"); + + if (m_pNumRule) + { + OUString aOldName = m_pNumRule->GetName(); + + if (!aOldName.isEmpty()) + { + if ( aOldName != rStr && + m_rDoc.RenameNumRule(aOldName, rStr)) + { + m_pNumRule = m_rDoc.FindNumRulePtr(rStr); + m_rDoc.getIDocumentState().SetModified(); + + bChg = true; + } + } + else + { + // #i91400# + const_cast<SwNumRule*>(m_pNumRule)->SetName( rStr, m_rDoc.getIDocumentListsAccess() ); + m_rDoc.getIDocumentState().SetModified(); + + bChg = true; + } + } + + break; + + default: + OSL_ENSURE(false, "unknown style family"); + } + + if( bChg ) + { + m_pPool->First(nFamily); // internal list has to be updated + m_pPool->Broadcast( SfxStyleSheetHint( SfxHintId::StyleSheetModified, *this ) ); + if (SwEditShell* pSh = m_rDoc.GetEditShell()) + pSh->CallChgLnk(); + } + return true; +} + +// hierarchy of deduction +bool SwDocStyleSheet::SetParent( const OUString& rStr) +{ + SwFormat* pFormat = nullptr, *pParent = nullptr; + switch(nFamily) + { + case SfxStyleFamily::Char : + OSL_ENSURE( m_pCharFormat, "SwCharFormat missing!" ); + if( nullptr != ( pFormat = m_pCharFormat ) && !rStr.isEmpty() ) + pParent = lcl_FindCharFormat(m_rDoc, rStr); + break; + + case SfxStyleFamily::Para : + OSL_ENSURE( m_pColl, "Collection missing!"); + if( nullptr != ( pFormat = m_pColl ) && !rStr.isEmpty() ) + pParent = lcl_FindParaFormat( m_rDoc, rStr ); + break; + + case SfxStyleFamily::Frame: + OSL_ENSURE(m_pFrameFormat, "FrameFormat missing!"); + if( nullptr != ( pFormat = m_pFrameFormat ) && !rStr.isEmpty() ) + pParent = lcl_FindFrameFormat( m_rDoc, rStr ); + break; + + case SfxStyleFamily::Page: + case SfxStyleFamily::Pseudo: + break; + default: + OSL_ENSURE(false, "unknown style family"); + } + + bool bRet = false; + if( pFormat && pFormat->DerivedFrom() && + pFormat->DerivedFrom()->GetName() != rStr ) + { + { + SwImplShellAction aTmp( m_rDoc ); + bRet = pFormat->SetDerivedFrom( pParent ); + } + + if( bRet ) + { + aParent = rStr; + m_pPool->Broadcast( SfxStyleSheetHint( SfxHintId::StyleSheetModified, + *this ) ); + } + } + + return bRet; +} + +// Set Follower +bool SwDocStyleSheet::SetFollow( const OUString& rStr) +{ + if( !rStr.isEmpty() && !SfxStyleSheetBase::SetFollow( rStr )) + return false; + + SwImplShellAction aTmpSh( m_rDoc ); + switch(nFamily) + { + case SfxStyleFamily::Para : + { + OSL_ENSURE(m_pColl, "Collection missing!"); + if( m_pColl ) + { + SwTextFormatColl* pFollow = m_pColl; + if( !rStr.isEmpty() && nullptr == (pFollow = lcl_FindParaFormat(m_rDoc, rStr) )) + pFollow = m_pColl; + + m_pColl->SetNextTextFormatColl(*pFollow); + } + break; + } + case SfxStyleFamily::Page : + { + OSL_ENSURE(m_pDesc, "PageDesc missing!"); + if( m_pDesc ) + { + const SwPageDesc* pFollowDesc = !rStr.isEmpty() + ? lcl_FindPageDesc(m_rDoc, rStr) + : nullptr; + size_t nId = 0; + if (pFollowDesc != m_pDesc->GetFollow() && m_rDoc.FindPageDesc(m_pDesc->GetName(), &nId)) + { + SwPageDesc aDesc( *m_pDesc ); + aDesc.SetFollow( pFollowDesc ); + m_rDoc.ChgPageDesc( nId, aDesc ); + m_pDesc = &m_rDoc.GetPageDesc( nId ); + } + } + break; + } + case SfxStyleFamily::Char: + case SfxStyleFamily::Frame: + case SfxStyleFamily::Pseudo: + break; + default: + OSL_ENSURE(false, "unknown style family"); + } + + return true; +} + +static +void lcl_SwFormatToFlatItemSet(SwFormat const *const pFormat, std::optional<SfxItemSet>& pRet) +{ + // note: we don't add the odd items that GetItemSet() would add + // because they don't seem relevant for preview + std::vector<SfxItemSet const*> sets; + sets.push_back(&pFormat->GetAttrSet()); + while (SfxItemSet const*const pParent = sets.back()->GetParent()) + { + sets.push_back(pParent); + } + // start by copying top-level parent set + pRet.emplace(*sets.back()); + sets.pop_back(); + for (auto iter = sets.rbegin(); iter != sets.rend(); ++iter) + { // in reverse so child overrides parent + pRet->Put(**iter); + } +} + +std::optional<SfxItemSet> SwDocStyleSheet::GetItemSetForPreview() +{ + if (SfxStyleFamily::Page == nFamily || SfxStyleFamily::Pseudo == nFamily || SfxStyleFamily::Table == nFamily) + { + SAL_WARN("sw.ui", "GetItemSetForPreview not implemented for page or number or table style"); + return std::optional<SfxItemSet>(); + } + if (!m_bPhysical) + { + // because not only this style, but also any number of its parents + // (or follow style) may not actually exist in the document at this + // time, return one "flattened" item set that contains all items from + // all parents. + std::optional<SfxItemSet> pRet; + + bool bModifiedEnabled = m_rDoc.getIDocumentState().IsEnableSetModified(); + m_rDoc.getIDocumentState().SetEnableSetModified(false); + + FillStyleSheet(FillPreview, &pRet); + + m_rDoc.getIDocumentState().SetEnableSetModified(bModifiedEnabled); + + assert(pRet); + return pRet; + } + else + { + std::optional<SfxItemSet> pRet; + switch (nFamily) + { + case SfxStyleFamily::Char: + lcl_SwFormatToFlatItemSet(m_pCharFormat, pRet); + break; + case SfxStyleFamily::Para: + lcl_SwFormatToFlatItemSet(m_pColl, pRet); + break; + case SfxStyleFamily::Frame: + lcl_SwFormatToFlatItemSet(m_pFrameFormat, pRet); + break; + default: + std::abort(); + } + return pRet; + } +} + +// extract ItemSet to Name and Family, Mask + +SfxItemSet& SwDocStyleSheet::GetItemSet() +{ + if(!m_bPhysical) + FillStyleSheet( FillPhysical ); + + switch(nFamily) + { + case SfxStyleFamily::Char: + case SfxStyleFamily::Para: + case SfxStyleFamily::Frame: + { + SvxBoxInfoItem aBoxInfo( SID_ATTR_BORDER_INNER ); + aBoxInfo.SetTable( false ); + aBoxInfo.SetDist( true ); // always show gap field + aBoxInfo.SetMinDist( true );// set minimum size in tables and paragraphs + aBoxInfo.SetDefDist( MIN_BORDER_DIST );// always set Default-Gap + // Single lines can only have DontCare-Status in tables + aBoxInfo.SetValid( SvxBoxInfoItemValidFlags::DISABLE ); + + if( nFamily == SfxStyleFamily::Char ) + { + SAL_WARN_IF(!m_pCharFormat, "sw.ui", "Where's SwCharFormat"); + m_aCoreSet.Put(m_pCharFormat->GetAttrSet()); + m_aCoreSet.Put( aBoxInfo ); + + if(m_pCharFormat->DerivedFrom()) + m_aCoreSet.SetParent(&m_pCharFormat->DerivedFrom()->GetAttrSet()); + } + else if ( nFamily == SfxStyleFamily::Para ) + { + OSL_ENSURE(m_pColl, "Where's Collection"); + m_aCoreSet.Put(m_pColl->GetAttrSet()); + m_aCoreSet.Put( aBoxInfo ); + m_aCoreSet.Put(SfxBoolItem(SID_ATTR_AUTO_STYLE_UPDATE, m_pColl->IsAutoUpdateOnDirectFormat())); + + if(m_pColl->DerivedFrom()) + m_aCoreSet.SetParent(&m_pColl->DerivedFrom()->GetAttrSet()); + } + else + { + OSL_ENSURE(m_pFrameFormat, "Where's FrameFormat"); + m_aCoreSet.Put(m_pFrameFormat->GetAttrSet()); + m_aCoreSet.Put( aBoxInfo ); + m_aCoreSet.Put(SfxBoolItem(SID_ATTR_AUTO_STYLE_UPDATE, m_pFrameFormat->IsAutoUpdateOnDirectFormat())); + + if(m_pFrameFormat->DerivedFrom()) + m_aCoreSet.SetParent(&m_pFrameFormat->DerivedFrom()->GetAttrSet()); + + // create needed items for XPropertyList entries from the DrawModel so that + // the Area TabPage can access them + const SwDrawModel* pDrawModel = m_rDoc.getIDocumentDrawModelAccess().GetDrawModel(); + + m_aCoreSet.Put(SvxColorListItem(pDrawModel->GetColorList(), SID_COLOR_TABLE)); + m_aCoreSet.Put(SvxGradientListItem(pDrawModel->GetGradientList(), SID_GRADIENT_LIST)); + m_aCoreSet.Put(SvxHatchListItem(pDrawModel->GetHatchList(), SID_HATCH_LIST)); + m_aCoreSet.Put(SvxBitmapListItem(pDrawModel->GetBitmapList(), SID_BITMAP_LIST)); + m_aCoreSet.Put(SvxPatternListItem(pDrawModel->GetPatternList(), SID_PATTERN_LIST)); + } + } + break; + + case SfxStyleFamily::Page : + { + // set correct parent to get the drawing::FillStyle_NONE FillStyle as needed + if(!m_aCoreSet.GetParent()) + { + m_aCoreSet.SetParent(&m_rDoc.GetDfltFrameFormat()->GetAttrSet()); + } + + OSL_ENSURE(m_pDesc, "No PageDescriptor"); + ::PageDescToItemSet(*const_cast<SwPageDesc*>(m_pDesc), m_aCoreSet); + } + break; + + case SfxStyleFamily::Pseudo: + { + OSL_ENSURE(m_pNumRule, "No NumRule"); + SvxNumRule aRule = m_pNumRule->MakeSvxNumRule(); + m_aCoreSet.Put(SvxNumBulletItem(std::move(aRule))); + } + break; + + default: + OSL_ENSURE(false, "unknown style family"); + } + // Member of Baseclass + pSet = &m_aCoreSet; + + return m_aCoreSet; +} + +void SwDocStyleSheet::MergeIndentAttrsOfListStyle( SfxItemSet& rSet ) +{ + if ( nFamily != SfxStyleFamily::Para ) + { + return; + } + + OSL_ENSURE( m_pColl, "<SwDocStyleSheet::MergeIndentAttrsOfListStyle(..)> - missing paragraph style"); + ::sw::ListLevelIndents const indents(m_pColl->AreListLevelIndentsApplicable()); + if (indents == ::sw::ListLevelIndents::No) + return; + + OSL_ENSURE( m_pColl->GetItemState( RES_PARATR_NUMRULE ) == SfxItemState::SET, + "<SwDocStyleSheet::MergeIndentAttrsOfListStyle(..)> - list level indents are applicable at paragraph style, but no list style found. Serious defect." ); + const OUString sNumRule = m_pColl->GetNumRule().GetValue(); + if (sNumRule.isEmpty()) + return; + + const SwNumRule* pRule = m_rDoc.FindNumRulePtr( sNumRule ); + if( pRule ) + { + const SwNumFormat& rFormat = pRule->Get( 0 ); + if ( rFormat.GetPositionAndSpaceMode() == SvxNumberFormat::LABEL_ALIGNMENT ) + { + if (indents & ::sw::ListLevelIndents::FirstLine) + { + SvxFirstLineIndentItem const firstLine(static_cast<short>(rFormat.GetFirstLineIndent()), RES_MARGIN_FIRSTLINE); + rSet.Put(firstLine); + } + if (indents & ::sw::ListLevelIndents::LeftMargin) + { + SvxTextLeftMarginItem const leftMargin(rFormat.GetIndentAt(), RES_MARGIN_TEXTLEFT); + rSet.Put(leftMargin); + } + } + } +} + +// handling of parameter <bResetIndentAttrsAtParagraphStyle> +void SwDocStyleSheet::SetItemSet( const SfxItemSet& rSet, const bool bBroadcast, + const bool bResetIndentAttrsAtParagraphStyle ) +{ + // if applicable determine format first + if(!m_bPhysical) + FillStyleSheet( FillPhysical ); + + SwImplShellAction aTmpSh( m_rDoc ); + + OSL_ENSURE( &rSet != &m_aCoreSet, "SetItemSet with own Set is not allowed" ); + + if (m_rDoc.GetIDocumentUndoRedo().DoesUndo()) + { + SwRewriter aRewriter; + aRewriter.AddRule( UndoArg1, GetName() ); + m_rDoc.GetIDocumentUndoRedo().StartUndo( SwUndoId::INSFMTATTR, &aRewriter ); + } + + SwFormat* pFormat = nullptr; + std::vector<sal_uInt16> aWhichIdsToReset; + std::unique_ptr<SwPageDesc> pNewDsc; + size_t nPgDscPos = 0; + + switch(nFamily) + { + case SfxStyleFamily::Char : + { + OSL_ENSURE(m_pCharFormat, "Where's CharFormat"); + pFormat = m_pCharFormat; + } + break; + + case SfxStyleFamily::Para : + { + OSL_ENSURE(m_pColl, "Where's Collection"); + if(const SfxBoolItem* pAutoUpdate = rSet.GetItemIfSet(SID_ATTR_AUTO_STYLE_UPDATE,false)) + { + m_pColl->SetAutoUpdateOnDirectFormat(pAutoUpdate->GetValue()); + } + + const SwCondCollItem* pCondItem = rSet.GetItemIfSet( FN_COND_COLL, false ); + + if( RES_CONDTXTFMTCOLL == m_pColl->Which() && pCondItem ) + { + const CommandStruct* pCmds = SwCondCollItem::GetCmds(); + for(sal_uInt16 i = 0; i < COND_COMMAND_COUNT; i++) + { + SwCollCondition aCond( nullptr, pCmds[ i ].nCnd, pCmds[ i ].nSubCond ); + static_cast<SwConditionTextFormatColl*>(m_pColl)->RemoveCondition( aCond ); + const OUString sStyle = pCondItem->GetStyle( i ); + if (sStyle.isEmpty()) + continue; + SwFormat *const pFindFormat = lcl_FindParaFormat( m_rDoc, sStyle ); + if (pFindFormat) + { + aCond.RegisterToFormat( *pFindFormat ); + static_cast<SwConditionTextFormatColl*>(m_pColl)->InsertCondition( aCond ); + } + } + + m_pColl->GetNotifier().Broadcast(sw::CondCollCondChg(*m_pColl)); + } + else if( pCondItem && !m_pColl->HasWriterListeners() ) + { + // no conditional template, then first create and adopt + // all important values + SwConditionTextFormatColl* pCColl = m_rDoc.MakeCondTextFormatColl( + m_pColl->GetName(), static_cast<SwTextFormatColl*>(m_pColl->DerivedFrom()) ); + if( m_pColl != &m_pColl->GetNextTextFormatColl() ) + pCColl->SetNextTextFormatColl( m_pColl->GetNextTextFormatColl() ); + + if( m_pColl->IsAssignedToListLevelOfOutlineStyle()) + pCColl->AssignToListLevelOfOutlineStyle(m_pColl->GetAssignedOutlineStyleLevel()); + else + pCColl->DeleteAssignmentToListLevelOfOutlineStyle(); + + const CommandStruct* pCmds = SwCondCollItem::GetCmds(); + for( sal_uInt16 i = 0; i < COND_COMMAND_COUNT; ++i ) + { + const OUString sStyle = pCondItem->GetStyle( i ); + if (sStyle.isEmpty()) + continue; + SwTextFormatColl *const pFindFormat = lcl_FindParaFormat( m_rDoc, sStyle ); + if (pFindFormat) + { + pCColl->InsertCondition( SwCollCondition( pFindFormat, + pCmds[ i ].nCnd, pCmds[ i ].nSubCond ) ); + } + } + + m_rDoc.DelTextFormatColl( m_pColl ); + m_pColl = pCColl; + } + if ( bResetIndentAttrsAtParagraphStyle && + rSet.GetItemState( RES_PARATR_NUMRULE, false ) == SfxItemState::SET && + rSet.GetItemState(RES_MARGIN_FIRSTLINE, false) != SfxItemState::SET && + m_pColl->GetItemState(RES_MARGIN_FIRSTLINE, false) == SfxItemState::SET) + { + aWhichIdsToReset.emplace_back(RES_MARGIN_FIRSTLINE); + } + if ( bResetIndentAttrsAtParagraphStyle && + rSet.GetItemState( RES_PARATR_NUMRULE, false ) == SfxItemState::SET && + rSet.GetItemState(RES_MARGIN_TEXTLEFT, false) != SfxItemState::SET && + m_pColl->GetItemState(RES_MARGIN_TEXTLEFT, false) == SfxItemState::SET) + { + aWhichIdsToReset.emplace_back(RES_MARGIN_TEXTLEFT); + } + + // #i56252: If a standard numbering style is assigned to a standard paragraph style + // we have to create a physical instance of the numbering style. If we do not and + // neither the paragraph style nor the numbering style is used in the document + // the numbering style will not be saved with the document and the assignment got lost. + if( const SfxPoolItem* pNumRuleItem = rSet.GetItemIfSet( RES_PARATR_NUMRULE, false ) ) + { // Setting a numbering rule? + const OUString sNumRule = static_cast<const SwNumRuleItem*>(pNumRuleItem)->GetValue(); + if (!sNumRule.isEmpty()) + { + SwNumRule* pRule = m_rDoc.FindNumRulePtr( sNumRule ); + if( !pRule ) + { // Numbering rule not in use yet. + sal_uInt16 nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( sNumRule, SwGetPoolIdFromName::NumRule ); + if( USHRT_MAX != nPoolId ) // It's a standard numbering rule + { + m_rDoc.getIDocumentStylePoolAccess().GetNumRuleFromPool( nPoolId ); // Create numbering rule (physical) + } + } + } + } + + pFormat = m_pColl; + + sal_uInt16 nId = m_pColl->GetPoolFormatId() & + ~ ( COLL_GET_RANGE_BITS | POOLGRP_NOCOLLID ); + switch( GetMask() & ( static_cast<SfxStyleSearchBits>(0x0fff) & ~SfxStyleSearchBits::SwCondColl ) ) + { + case SfxStyleSearchBits::SwText: + nId |= COLL_TEXT_BITS; + break; + case SfxStyleSearchBits::SwChapter: + nId |= COLL_DOC_BITS; + break; + case SfxStyleSearchBits::SwList: + nId |= COLL_LISTS_BITS; + break; + case SfxStyleSearchBits::SwIndex: + nId |= COLL_REGISTER_BITS; + break; + case SfxStyleSearchBits::SwExtra: + nId |= COLL_EXTRA_BITS; + break; + case SfxStyleSearchBits::SwHtml: + nId |= COLL_HTML_BITS; + break; + default: break; + } + m_pColl->SetPoolFormatId( nId ); + break; + } + case SfxStyleFamily::Frame: + { + OSL_ENSURE(m_pFrameFormat, "Where's FrameFormat"); + + if(const SfxPoolItem* pAutoUpdate = rSet.GetItemIfSet(SID_ATTR_AUTO_STYLE_UPDATE,false)) + { + m_pFrameFormat->SetAutoUpdateOnDirectFormat(static_cast<const SfxBoolItem*>(pAutoUpdate)->GetValue()); + } + pFormat = m_pFrameFormat; + } + break; + + case SfxStyleFamily::Page : + { + OSL_ENSURE(m_pDesc, "Where's PageDescriptor"); + + if (m_rDoc.FindPageDesc(m_pDesc->GetName(), &nPgDscPos)) + { + pNewDsc.reset( new SwPageDesc( *m_pDesc ) ); + // #i48949# - no undo actions for the + // copy of the page style + ::sw::UndoGuard const ug(m_rDoc.GetIDocumentUndoRedo()); + m_rDoc.CopyPageDesc(*m_pDesc, *pNewDsc); // #i7983# + + pFormat = &pNewDsc->GetMaster(); + } + } + break; + + case SfxStyleFamily::Pseudo: + { + OSL_ENSURE(m_pNumRule, "Where's NumRule"); + + if (!m_pNumRule) + break; + + const SfxPoolItem* pItem; + switch( rSet.GetItemState( SID_ATTR_NUMBERING_RULE, false, &pItem )) + { + case SfxItemState::SET: + { + SvxNumRule& rSetRule = const_cast<SvxNumRule&>(static_cast<const SvxNumBulletItem*>(pItem)->GetNumRule()); + rSetRule.UnLinkGraphics(); + SwNumRule aSetRule(*m_pNumRule); + aSetRule.SetSvxRule(rSetRule, &m_rDoc); + m_rDoc.ChgNumRuleFormats( aSetRule ); + } + break; + case SfxItemState::DONTCARE: + // set NumRule to default values + // what are the default values? + { + SwNumRule aRule( m_pNumRule->GetName(), + // #i89178# + numfunc::GetDefaultPositionAndSpaceMode() ); + m_rDoc.ChgNumRuleFormats( aRule ); + } + break; + default: break; + } + } + break; + + default: + OSL_ENSURE(false, "unknown style family"); + } + + if( pFormat && rSet.Count()) + { + SfxItemIter aIter( rSet ); + const SfxPoolItem* pItem = aIter.GetCurItem(); + do + { + if( IsInvalidItem( pItem ) ) // Clear + { + // use method <SwDoc::ResetAttrAtFormat(..)> in order to + // create an Undo object for the attribute reset. + aWhichIdsToReset.emplace_back(rSet.GetWhichByOffset(aIter.GetCurPos())); + } + + pItem = aIter.NextItem(); + } while (pItem); + + m_rDoc.ResetAttrAtFormat(aWhichIdsToReset, *pFormat); + + SfxItemSet aSet(rSet); + aSet.ClearInvalidItems(); + + if(SfxStyleFamily::Frame == nFamily) + { + // Need to check for unique item for DrawingLayer items of type NameOrIndex + // and evtl. correct that item to ensure unique names for that type. This call may + // modify/correct entries inside of the given SfxItemSet + m_rDoc.CheckForUniqueItemForLineFillNameOrIndex(aSet); + } + + m_aCoreSet.ClearItem(); + + if( pNewDsc ) + { + ::ItemSetToPageDesc( aSet, *pNewDsc ); + m_rDoc.ChgPageDesc( nPgDscPos, *pNewDsc ); + m_pDesc = &m_rDoc.GetPageDesc( nPgDscPos ); + m_rDoc.PreDelPageDesc(pNewDsc.get()); // #i7983# + pNewDsc.reset(); + } + else + { + m_rDoc.ChgFormat(*pFormat, aSet); // put all that is set + if (bBroadcast) + m_pPool->Broadcast(SfxStyleSheetHint(SfxHintId::StyleSheetModified, *this)); + } + } + else + { + m_aCoreSet.ClearItem(); + if( pNewDsc ) // we still need to delete it + { + m_rDoc.PreDelPageDesc(pNewDsc.get()); // #i7983# + pNewDsc.reset(); + } + } + + if (m_rDoc.GetIDocumentUndoRedo().DoesUndo()) + { + m_rDoc.GetIDocumentUndoRedo().EndUndo(SwUndoId::END, nullptr); + } +} + +static void lcl_SaveStyles( SfxStyleFamily nFamily, std::vector<void*>& rArr, SwDoc& rDoc ) +{ + switch( nFamily ) + { + case SfxStyleFamily::Char: + { + const SwCharFormats& rTable = *rDoc.GetCharFormats(); + for(auto const& rChar: rTable) + { + rArr.push_back(rChar); + } + } + break; + case SfxStyleFamily::Para: + { + const SwTextFormatColls& rTable = *rDoc.GetTextFormatColls(); + for(auto const& rPara : rTable) + { + rArr.push_back(rPara); + } + } + break; + case SfxStyleFamily::Frame: + { + for(auto const& rFrame: *rDoc.GetFrameFormats()) + { + rArr.push_back(rFrame); + } + } + break; + + case SfxStyleFamily::Page: + { + for( size_t n = 0, nCnt = rDoc.GetPageDescCnt(); n < nCnt; ++n ) + { + rArr.push_back( &rDoc.GetPageDesc( n ) ); + } + } + break; + + case SfxStyleFamily::Pseudo: + { + const SwNumRuleTable& rTable = rDoc.GetNumRuleTable(); + for(auto const& rPseudo: rTable) + { + rArr.push_back(rPseudo); + } + } + break; + default: break; + } +} + +static bool lcl_Contains(const std::vector<void*>& rArr, const void* p) +{ + return std::find( rArr.begin(), rArr.end(), p ) != rArr.end(); +} + +static void lcl_DeleteInfoStyles( SfxStyleFamily nFamily, std::vector<void*> const & rArr, SwDoc& rDoc ) +{ + size_t n, nCnt; + switch( nFamily ) + { + case SfxStyleFamily::Char: + { + std::deque<sal_uInt16> aDelArr; + const SwCharFormats& rTable = *rDoc.GetCharFormats(); + for( n = 0, nCnt = rTable.size(); n < nCnt; ++n ) + { + if( !lcl_Contains( rArr, rTable[ n ] )) + aDelArr.push_front( n ); + } + for(auto const& rDelArr: aDelArr) + rDoc.DelCharFormat( rDelArr ); + } + break; + + case SfxStyleFamily::Para : + { + std::deque<sal_uInt16> aDelArr; + const SwTextFormatColls& rTable = *rDoc.GetTextFormatColls(); + for( n = 0, nCnt = rTable.size(); n < nCnt; ++n ) + { + if( !lcl_Contains( rArr, rTable[ n ] )) + aDelArr.push_front( n ); + } + for(auto const& rDelArr: aDelArr) + rDoc.DelTextFormatColl( rDelArr ); + } + break; + + case SfxStyleFamily::Frame: + { + std::deque<SwFrameFormat*> aDelArr; + for(auto const& rFrame: *rDoc.GetFrameFormats()) + { + if( !lcl_Contains( rArr, rFrame )) + aDelArr.push_front( rFrame ); + } + for( auto const& rDelArr: aDelArr) + rDoc.DelFrameFormat( rDelArr ); + } + break; + + case SfxStyleFamily::Page: + { + std::deque<size_t> aDelArr; + for( n = 0, nCnt = rDoc.GetPageDescCnt(); n < nCnt; ++n ) + { + if( !lcl_Contains( rArr, &rDoc.GetPageDesc( n ) )) + aDelArr.push_front( n ); + } + for( auto const& rDelArr: aDelArr ) + rDoc.DelPageDesc( rDelArr); + } + break; + + case SfxStyleFamily::Pseudo: + { + std::deque<SwNumRule*> aDelArr; + const SwNumRuleTable& rTable = rDoc.GetNumRuleTable(); + for( auto const& rPseudo: rTable) + { + if( !lcl_Contains( rArr, rPseudo )) + aDelArr.push_front( rPseudo ); + } + for( auto const& rDelArr: aDelArr) + rDoc.DelNumRule( rDelArr->GetName() ); + } + break; + default: break; + } +} + +// determine the format +bool SwDocStyleSheet::FillStyleSheet( + FillStyleType const eFType, std::optional<SfxItemSet> *const o_ppFlatSet) +{ + bool bRet = false; + sal_uInt16 nPoolId = USHRT_MAX; + SwFormat* pFormat = nullptr; + + bool bCreate = FillPhysical == eFType; + bool bDeleteInfo = false; + bool bFillOnlyInfo = FillAllInfo == eFType || FillPreview == eFType; + std::vector<void*> aDelArr; + bool const isModified(m_rDoc.getIDocumentState().IsModified()); + + switch(nFamily) + { + case SfxStyleFamily::Char: + m_pCharFormat = lcl_FindCharFormat(m_rDoc, aName, this, bCreate ); + m_bPhysical = nullptr != m_pCharFormat; + if( bFillOnlyInfo && !m_bPhysical ) + { + // create style (plus all needed parents) and clean it up + // later - without affecting the undo/redo stack + ::sw::UndoGuard const ug(m_rDoc.GetIDocumentUndoRedo()); + bDeleteInfo = true; + ::lcl_SaveStyles( nFamily, aDelArr, m_rDoc ); + m_pCharFormat = lcl_FindCharFormat(m_rDoc, aName, this ); + } + + pFormat = m_pCharFormat; + m_aLink.clear(); + if( !bCreate && !pFormat ) + { + if( aName == SwResId(STR_POOLCHR_STANDARD)) + nPoolId = 0; + else + nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::ChrFmt ); + } + + if (m_pCharFormat) + { + const SwTextFormatColl* pParaFormat = m_pCharFormat->GetLinkedParaFormat(); + if (pParaFormat) + { + m_aLink = pParaFormat->GetName(); + } + } + + bRet = nullptr != m_pCharFormat || USHRT_MAX != nPoolId; + + if( bDeleteInfo ) + m_pCharFormat = nullptr; + break; + + case SfxStyleFamily::Para: + { + m_pColl = lcl_FindParaFormat(m_rDoc, aName, this, bCreate); + m_bPhysical = nullptr != m_pColl; + if( bFillOnlyInfo && !m_bPhysical ) + { + ::sw::UndoGuard const ug(m_rDoc.GetIDocumentUndoRedo()); + bDeleteInfo = true; + ::lcl_SaveStyles( nFamily, aDelArr, m_rDoc ); + m_pColl = lcl_FindParaFormat(m_rDoc, aName, this ); + } + + pFormat = m_pColl; + m_aLink.clear(); + if( m_pColl ) + { + PresetFollow( m_pColl->GetNextTextFormatColl().GetName() ); + const SwCharFormat* pCharFormat = m_pColl->GetLinkedCharFormat(); + if (pCharFormat) + { + m_aLink = pCharFormat->GetName(); + } + } + else if( !bCreate ) + nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::TxtColl ); + + bRet = nullptr != m_pColl || USHRT_MAX != nPoolId; + + if( bDeleteInfo ) + m_pColl = nullptr; + } + break; + + case SfxStyleFamily::Frame: + m_pFrameFormat = lcl_FindFrameFormat(m_rDoc, aName, this, bCreate); + m_bPhysical = nullptr != m_pFrameFormat; + if (bFillOnlyInfo && !m_bPhysical) + { + ::sw::UndoGuard const ug(m_rDoc.GetIDocumentUndoRedo()); + bDeleteInfo = true; + ::lcl_SaveStyles( nFamily, aDelArr, m_rDoc ); + m_pFrameFormat = lcl_FindFrameFormat(m_rDoc, aName, this ); + } + pFormat = m_pFrameFormat; + if( !bCreate && !pFormat ) + nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::FrmFmt ); + + bRet = nullptr != m_pFrameFormat || USHRT_MAX != nPoolId; + + if( bDeleteInfo ) + m_pFrameFormat = nullptr; + break; + + case SfxStyleFamily::Page: + m_pDesc = lcl_FindPageDesc(m_rDoc, aName, this, bCreate); + m_bPhysical = nullptr != m_pDesc; + if( bFillOnlyInfo && !m_pDesc ) + { + ::sw::UndoGuard const ug(m_rDoc.GetIDocumentUndoRedo()); + bDeleteInfo = true; + ::lcl_SaveStyles( nFamily, aDelArr, m_rDoc ); + m_pDesc = lcl_FindPageDesc( m_rDoc, aName, this ); + } + + if( m_pDesc ) + { + nPoolId = m_pDesc->GetPoolFormatId(); + nHelpId = m_pDesc->GetPoolHelpId(); + if (const OUString* pattern = m_pDesc->GetPoolHlpFileId() != UCHAR_MAX + ? m_rDoc.GetDocPattern(m_pDesc->GetPoolHlpFileId()) + : nullptr) + aHelpFile = *pattern; + else + aHelpFile.clear(); + } + else if( !bCreate ) + nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::PageDesc ); + SetMask( (USER_FMT & nPoolId) ? SfxStyleSearchBits::UserDefined : SfxStyleSearchBits::Auto ); + + bRet = nullptr != m_pDesc || USHRT_MAX != nPoolId; + if( bDeleteInfo ) + m_pDesc = nullptr; + break; + + case SfxStyleFamily::Pseudo: + m_pNumRule = lcl_FindNumRule(m_rDoc, aName, this, bCreate); + m_bPhysical = nullptr != m_pNumRule; + if( bFillOnlyInfo && !m_pNumRule ) + { + ::sw::UndoGuard const ug(m_rDoc.GetIDocumentUndoRedo()); + bDeleteInfo = true; + ::lcl_SaveStyles( nFamily, aDelArr, m_rDoc ); + m_pNumRule = lcl_FindNumRule( m_rDoc, aName, this ); + } + + if( m_pNumRule ) + { + nPoolId = m_pNumRule->GetPoolFormatId(); + nHelpId = m_pNumRule->GetPoolHelpId(); + if (const OUString* pattern = m_pNumRule->GetPoolHlpFileId() != UCHAR_MAX + ? m_rDoc.GetDocPattern(m_pNumRule->GetPoolHlpFileId()) + : nullptr) + aHelpFile = *pattern; + else + aHelpFile.clear(); + } + else if( !bCreate ) + nPoolId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::NumRule ); + SetMask( (USER_FMT & nPoolId) ? SfxStyleSearchBits::UserDefined : SfxStyleSearchBits::Auto ); + + bRet = nullptr != m_pNumRule || USHRT_MAX != nPoolId; + + if( bDeleteInfo ) + m_pNumRule = nullptr; + break; + + case SfxStyleFamily::Table: + m_pTableFormat = lcl_FindTableStyle(m_rDoc, aName, this, bCreate); + SetMask((m_pTableFormat && m_pTableFormat->IsUserDefined()) ? SfxStyleSearchBits::UserDefined : SfxStyleSearchBits::Auto); + bRet = m_bPhysical = (nullptr != m_pTableFormat); + break; + + case SfxStyleFamily::Cell: + m_pBoxFormat = lcl_FindCellStyle(m_rDoc, aName, this); + bRet = m_bPhysical = (nullptr != m_pBoxFormat); + break; + default:; //prevent warning + } + + if( SfxStyleFamily::Char == nFamily || + SfxStyleFamily::Para == nFamily || + SfxStyleFamily::Frame == nFamily ) + { + if( pFormat ) + nPoolId = pFormat->GetPoolFormatId(); + + SfxStyleSearchBits _nMask = SfxStyleSearchBits::Auto; + if( pFormat == m_rDoc.GetDfltCharFormat() ) + _nMask |= SfxStyleSearchBits::ReadOnly; + else if( USER_FMT & nPoolId ) + _nMask |= SfxStyleSearchBits::UserDefined; + + switch ( COLL_GET_RANGE_BITS & nPoolId ) + { + case COLL_TEXT_BITS: _nMask |= SfxStyleSearchBits::SwText; break; + case COLL_DOC_BITS : _nMask |= SfxStyleSearchBits::SwChapter; break; + case COLL_LISTS_BITS: _nMask |= SfxStyleSearchBits::SwList; break; + case COLL_REGISTER_BITS: _nMask |= SfxStyleSearchBits::SwIndex; break; + case COLL_EXTRA_BITS: _nMask |= SfxStyleSearchBits::SwExtra; break; + case COLL_HTML_BITS: _nMask |= SfxStyleSearchBits::SwHtml; break; + } + + if( pFormat ) + { + OSL_ENSURE( m_bPhysical, "Format not found" ); + + nHelpId = pFormat->GetPoolHelpId(); + if (const OUString* pattern = pFormat->GetPoolHlpFileId() != UCHAR_MAX + ? m_rDoc.GetDocPattern(pFormat->GetPoolHlpFileId()) + : nullptr) + aHelpFile = *pattern; + else + aHelpFile.clear(); + + if( RES_CONDTXTFMTCOLL == pFormat->Which() ) + _nMask |= SfxStyleSearchBits::SwCondColl; + + if (FillPreview == eFType) + { + assert(o_ppFlatSet); + lcl_SwFormatToFlatItemSet(pFormat, *o_ppFlatSet); + } + } + + SetMask( _nMask ); + } + if( bDeleteInfo && bFillOnlyInfo ) + { + ::sw::UndoGuard const ug(m_rDoc.GetIDocumentUndoRedo()); + ::lcl_DeleteInfoStyles( nFamily, aDelArr, m_rDoc ); + if (!isModified) + { + m_rDoc.getIDocumentState().ResetModified(); + } + } + return bRet; +} + +// Create new format in Core +void SwDocStyleSheet::Create() +{ + switch(nFamily) + { + case SfxStyleFamily::Char : + m_pCharFormat = lcl_FindCharFormat( m_rDoc, aName ); + if( !m_pCharFormat ) + m_pCharFormat = m_rDoc.MakeCharFormat(aName, + m_rDoc.GetDfltCharFormat()); + m_pCharFormat->SetAuto(false); + break; + + case SfxStyleFamily::Para : + m_pColl = lcl_FindParaFormat( m_rDoc, aName ); + if( !m_pColl ) + { + SwTextFormatColl *pPar = (*m_rDoc.GetTextFormatColls())[0]; + if( nMask & SfxStyleSearchBits::SwCondColl ) + m_pColl = m_rDoc.MakeCondTextFormatColl( aName, pPar ); + else + m_pColl = m_rDoc.MakeTextFormatColl( aName, pPar ); + } + break; + + case SfxStyleFamily::Frame: + m_pFrameFormat = lcl_FindFrameFormat( m_rDoc, aName ); + if( !m_pFrameFormat ) + m_pFrameFormat = m_rDoc.MakeFrameFormat(aName, m_rDoc.GetDfltFrameFormat(), false, false); + + break; + + case SfxStyleFamily::Page : + m_pDesc = lcl_FindPageDesc( m_rDoc, aName ); + if( !m_pDesc ) + { + m_pDesc = m_rDoc.MakePageDesc(aName); + } + break; + + case SfxStyleFamily::Pseudo: + m_pNumRule = lcl_FindNumRule( m_rDoc, aName ); + if( !m_pNumRule ) + { + const OUString sTmpNm( aName.isEmpty() ? m_rDoc.GetUniqueNumRuleName() : aName ); + SwNumRule* pRule = m_rDoc.GetNumRuleTable()[ + m_rDoc.MakeNumRule( sTmpNm, nullptr, false, + // #i89178# + numfunc::GetDefaultPositionAndSpaceMode() ) ]; + pRule->SetAutoRule( false ); + if( aName.isEmpty() ) + { + // #i91400# + pRule->SetName( aName, m_rDoc.getIDocumentListsAccess() ); + } + m_pNumRule = pRule; + } + break; + + case SfxStyleFamily::Table: + if (aName.isEmpty()) + return; + m_pTableFormat = lcl_FindTableStyle(m_rDoc, aName); + if (!m_pTableFormat) + { + m_rDoc.MakeTableStyle(aName); + m_pTableFormat = m_rDoc.GetTableStyles().FindAutoFormat(aName); + SAL_WARN_IF(!m_pTableFormat, "sw.ui", "Recently added auto format not found"); + } + break; + default:; //prevent warning + } + m_bPhysical = true; + m_aCoreSet.ClearItem(); +} + +SwCharFormat* SwDocStyleSheet::GetCharFormat() +{ + if(!m_bPhysical) + FillStyleSheet( FillPhysical ); + return m_pCharFormat; +} + +SwTextFormatColl* SwDocStyleSheet::GetCollection() +{ + if(!m_bPhysical) + FillStyleSheet( FillPhysical ); + return m_pColl; +} + +const SwPageDesc* SwDocStyleSheet::GetPageDesc() +{ + if(!m_bPhysical) + FillStyleSheet( FillPhysical ); + return m_pDesc; +} + +const SwNumRule * SwDocStyleSheet::GetNumRule() +{ + if(!m_bPhysical) + FillStyleSheet( FillPhysical ); + return m_pNumRule; +} + + +void SwDocStyleSheet::SetNumRule(const SwNumRule& rRule) +{ + OSL_ENSURE(m_pNumRule, "Where is the NumRule"); + m_rDoc.ChgNumRuleFormats( rRule ); +} + +SwTableAutoFormat* SwDocStyleSheet::GetTableFormat() +{ + if(!m_bPhysical) + FillStyleSheet( FillPhysical ); + assert(m_pTableFormat && "SwDocStyleSheet table style, SwTableAutoFormat not found"); + return m_pTableFormat; +} + +// re-generate Name AND Family from String +// First() and Next() (see below) insert an identification letter at Pos.1 + +void SwDocStyleSheet::PresetNameAndFamily(SfxStyleFamily eFamily, const OUString& rName) +{ + this->nFamily = eFamily; + this->aName = rName; +} + +// Is the format physically present yet +void SwDocStyleSheet::SetPhysical(bool bPhys) +{ + m_bPhysical = bPhys; + + if(!bPhys) + { + m_pCharFormat = nullptr; + m_pColl = nullptr; + m_pFrameFormat = nullptr; + m_pDesc = nullptr; + } +} + +SwFrameFormat* SwDocStyleSheet::GetFrameFormat() +{ + if(!m_bPhysical) + FillStyleSheet( FillPhysical ); + return m_pFrameFormat; +} + +bool SwDocStyleSheet::IsUsed() const +{ + if( !m_bPhysical ) + { + SwDocStyleSheet* pThis = const_cast<SwDocStyleSheet*>(this); + pThis->FillStyleSheet( FillOnlyName ); + } + + if( !m_bPhysical ) + return false; + + const sw::BroadcastingModify* pMod; + switch( nFamily ) + { + case SfxStyleFamily::Char : pMod = m_pCharFormat; break; + case SfxStyleFamily::Para : pMod = m_pColl; break; + case SfxStyleFamily::Frame: pMod = m_pFrameFormat; break; + case SfxStyleFamily::Page : pMod = m_pDesc; break; + + case SfxStyleFamily::Pseudo: + return m_pNumRule && m_rDoc.IsUsed(*m_pNumRule); + + case SfxStyleFamily::Table: + return m_pTableFormat && m_rDoc.IsUsed( *m_pTableFormat ); + + default: + OSL_ENSURE(false, "unknown style family"); + return false; + } + + if (m_rDoc.IsUsed(*pMod)) + return true; + + SfxStyleSheetIterator aIter(static_cast<SwDocStyleSheetPool*>(m_pPool)->GetEEStyleSheetPool(), nFamily, + SfxStyleSearchBits::Used); + return aIter.Find(GetName()) != nullptr; +} + +OUString SwDocStyleSheet::GetUsedBy() +{ + return m_pNumRule ? m_pNumRule->MakeParagraphStyleListString() : OUString(); +} + +sal_uLong SwDocStyleSheet::GetHelpId( OUString& rFile ) +{ + sal_uInt16 nId = 0; + sal_uInt16 nPoolId = 0; + unsigned char nFileId = UCHAR_MAX; + + rFile = "swrhlppi.hlp"; + + const SwFormat* pTmpFormat = nullptr; + switch( nFamily ) + { + case SfxStyleFamily::Char : + if( !m_pCharFormat && + nullptr == (m_pCharFormat = lcl_FindCharFormat( m_rDoc, aName, nullptr, false )) ) + { + nId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::ChrFmt ); + return USHRT_MAX == nId ? 0 : nId; + } + pTmpFormat = m_pCharFormat; + break; + + case SfxStyleFamily::Para: + if( !m_pColl && + nullptr == ( m_pColl = lcl_FindParaFormat( m_rDoc, aName, nullptr, false )) ) + { + nId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::TxtColl ); + return USHRT_MAX == nId ? 0 : nId; + } + pTmpFormat = m_pColl; + break; + + case SfxStyleFamily::Frame: + if( !m_pFrameFormat && + nullptr == ( m_pFrameFormat = lcl_FindFrameFormat( m_rDoc, aName, nullptr, false ) ) ) + { + nId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::FrmFmt ); + return USHRT_MAX == nId ? 0 : nId; + } + pTmpFormat = m_pFrameFormat; + break; + + case SfxStyleFamily::Page: + if( !m_pDesc && + nullptr == ( m_pDesc = lcl_FindPageDesc( m_rDoc, aName, nullptr, false ) ) ) + { + nId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::PageDesc ); + return USHRT_MAX == nId ? 0 : nId; + } + + nId = m_pDesc->GetPoolHelpId(); + nFileId = m_pDesc->GetPoolHlpFileId(); + nPoolId = m_pDesc->GetPoolFormatId(); + break; + + case SfxStyleFamily::Pseudo: + if( !m_pNumRule && + nullptr == ( m_pNumRule = lcl_FindNumRule( m_rDoc, aName, nullptr, false ) ) ) + { + nId = SwStyleNameMapper::GetPoolIdFromUIName( aName, SwGetPoolIdFromName::NumRule ); + return USHRT_MAX == nId ? 0 : nId; + } + + nId = m_pNumRule->GetPoolHelpId(); + nFileId = m_pNumRule->GetPoolHlpFileId(); + nPoolId = m_pNumRule->GetPoolFormatId(); + break; + + default: + OSL_ENSURE(false, "unknown style family"); + return 0; + } + + if( pTmpFormat ) + { + nId = pTmpFormat->GetPoolHelpId(); + nFileId = pTmpFormat->GetPoolHlpFileId(); + nPoolId = pTmpFormat->GetPoolFormatId(); + } + + if( UCHAR_MAX != nFileId ) + { + const OUString *pTemplate = m_rDoc.GetDocPattern( nFileId ); + if( pTemplate ) + { + rFile = *pTemplate; + } + } + else if( !IsPoolUserFormat( nPoolId ) ) + { + nId = nPoolId; + } + + // because SFX acts like that, with HelpId: + if( USHRT_MAX == nId ) + nId = 0; // don't show Help accordingly + + return nId; +} + +void SwDocStyleSheet::SetHelpId( const OUString& r, sal_uLong nId ) +{ + sal_uInt8 nFileId = static_cast< sal_uInt8 >(m_rDoc.SetDocPattern( r )); + sal_uInt16 nHId = static_cast< sal_uInt16 >(nId); //!! SFX changed over to ULONG arbitrarily! + + SwFormat* pTmpFormat = nullptr; + switch( nFamily ) + { + case SfxStyleFamily::Char : pTmpFormat = m_pCharFormat; break; + case SfxStyleFamily::Para : pTmpFormat = m_pColl; break; + case SfxStyleFamily::Frame: pTmpFormat = m_pFrameFormat; break; + case SfxStyleFamily::Page : + const_cast<SwPageDesc*>(m_pDesc)->SetPoolHelpId( nHId ); + const_cast<SwPageDesc*>(m_pDesc)->SetPoolHlpFileId( nFileId ); + break; + + case SfxStyleFamily::Pseudo: + const_cast<SwNumRule*>(m_pNumRule)->SetPoolHelpId( nHId ); + const_cast<SwNumRule*>(m_pNumRule)->SetPoolHlpFileId( nFileId ); + break; + + default: + OSL_ENSURE(false, "unknown style family"); + return ; + } + if( pTmpFormat ) + { + pTmpFormat->SetPoolHelpId( nHId ); + pTmpFormat->SetPoolHlpFileId( nFileId ); + } +} + +// methods for DocStyleSheetPool +SwDocStyleSheetPool::SwDocStyleSheetPool( SwDoc& rDocument, bool bOrg ) + : SfxStyleSheetBasePool(rDocument.GetAttrPool()) + , mxStyleSheet(new SwDocStyleSheet(rDocument, *this)) + , mxEEStyleSheetPool(new EEStyleSheetPool(this)) + , m_rDoc(rDocument) +{ + m_bOrganizer = bOrg; +} + +SwDocStyleSheetPool::~SwDocStyleSheetPool() +{ +} + +SfxStyleSheetBase& SwDocStyleSheetPool::Make( const OUString& rName, + SfxStyleFamily eFam, + SfxStyleSearchBits _nMask) +{ + mxStyleSheet->PresetName(rName); + mxStyleSheet->PresetParent(OUString()); + mxStyleSheet->PresetFollow(OUString()); + mxStyleSheet->SetMask(_nMask) ; + mxStyleSheet->SetFamily(eFam); + mxStyleSheet->SetPhysical(true); + mxStyleSheet->Create(); + + return *mxStyleSheet; +} + +rtl::Reference<SfxStyleSheetBase> SwDocStyleSheetPool::Create( const SfxStyleSheetBase& /*rOrg*/) +{ + OSL_ENSURE(false , "Create in SW-Stylesheet-Pool not possible" ); + return nullptr; +} + +rtl::Reference<SfxStyleSheetBase> SwDocStyleSheetPool::Create( const OUString &, + SfxStyleFamily, SfxStyleSearchBits ) +{ + OSL_ENSURE( false, "Create in SW-Stylesheet-Pool not possible" ); + return nullptr; +} + +std::unique_ptr<SfxStyleSheetIterator> SwDocStyleSheetPool::CreateIterator( SfxStyleFamily eFam, SfxStyleSearchBits _nMask ) +{ + return std::make_unique<SwStyleSheetIterator>(*this, eFam, _nMask); +} + +void SwDocStyleSheetPool::dispose() +{ + mxStyleSheet.clear(); + mxEEStyleSheetPool.clear(); +} + +void SwDocStyleSheetPool::Remove( SfxStyleSheetBase* pStyle) +{ + if( !pStyle ) + return; + + bool bBroadcast = true; + SwImplShellAction aTmpSh( m_rDoc ); + const OUString sName = pStyle->GetName(); + switch( pStyle->GetFamily() ) + { + case SfxStyleFamily::Char: + { + SwCharFormat* pFormat = lcl_FindCharFormat(m_rDoc, sName, nullptr, false ); + if(pFormat) + m_rDoc.DelCharFormat(pFormat); + } + break; + case SfxStyleFamily::Para: + { + SwTextFormatColl* pColl = lcl_FindParaFormat(m_rDoc, sName, nullptr, false ); + if(pColl) + m_rDoc.DelTextFormatColl(pColl); + } + break; + case SfxStyleFamily::Frame: + { + SwFrameFormat* pFormat = lcl_FindFrameFormat(m_rDoc, sName, nullptr, false ); + if(pFormat) + m_rDoc.DelFrameFormat(pFormat); + } + break; + case SfxStyleFamily::Page : + { + m_rDoc.DelPageDesc(sName); + } + break; + + case SfxStyleFamily::Pseudo: + { + if( !m_rDoc.DelNumRule( sName ) ) + // Only send Broadcast, when something was deleted + bBroadcast = false; + } + break; + + case SfxStyleFamily::Table: + { + m_rDoc.DelTableStyle(sName); + } + break; + + default: + OSL_ENSURE(false, "unknown style family"); + bBroadcast = false; + } + + if( bBroadcast ) + Broadcast( SfxStyleSheetHint( SfxHintId::StyleSheetErased, *pStyle ) ); +} + +SfxStyleSheetBase* SwDocStyleSheetPool::Find(const OUString& rName, + SfxStyleFamily eFam, SfxStyleSearchBits n) +{ + SfxStyleSearchBits nSMask = n; + if( SfxStyleFamily::Para == eFam && m_rDoc.getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) ) + { + // then only HTML-Templates are of interest + if( SfxStyleSearchBits::All == nSMask ) + nSMask = SfxStyleSearchBits::SwHtml | SfxStyleSearchBits::UserDefined | SfxStyleSearchBits::Used; + else + nSMask &= SfxStyleSearchBits::Used | SfxStyleSearchBits::UserDefined | + SfxStyleSearchBits::SwCondColl | SfxStyleSearchBits::SwHtml; + if( nSMask == SfxStyleSearchBits::Auto ) + nSMask = SfxStyleSearchBits::SwHtml; + } + + const bool bSearchUsed = ( n != SfxStyleSearchBits::All && n & SfxStyleSearchBits::Used ); + const sw::BroadcastingModify* pMod = nullptr; + + mxStyleSheet->SetPhysical( false ); + mxStyleSheet->PresetName( rName ); + mxStyleSheet->SetFamily( eFam ); + bool bFnd = mxStyleSheet->FillStyleSheet( SwDocStyleSheet::FillOnlyName ); + + if( mxStyleSheet->IsPhysical() ) + { + switch( eFam ) + { + case SfxStyleFamily::Char: + pMod = mxStyleSheet->GetCharFormat(); + break; + + case SfxStyleFamily::Para: + pMod = mxStyleSheet->GetCollection(); + break; + + case SfxStyleFamily::Frame: + pMod = mxStyleSheet->GetFrameFormat(); + break; + + case SfxStyleFamily::Page: + pMod = mxStyleSheet->GetPageDesc(); + break; + + case SfxStyleFamily::Pseudo: + { + const SwNumRule* pRule = mxStyleSheet->GetNumRule(); + if( pRule && + !bSearchUsed && + (( nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::UserDefined + ? !(pRule->GetPoolFormatId() & USER_FMT) + // searched for used and found none + : bSearchUsed )) + bFnd = false; + } + break; + + case SfxStyleFamily::Table: + case SfxStyleFamily::Cell: + break; + default: + OSL_ENSURE(false, "unknown style family"); + } + } + + // then evaluate the mask: + if( pMod && !bSearchUsed ) + { + const sal_uInt16 nId = SfxStyleFamily::Page == eFam + ? static_cast<const SwPageDesc*>(pMod)->GetPoolFormatId() + : static_cast<const SwFormat*>(pMod)->GetPoolFormatId(); + + if( ( nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::UserDefined + && !(nId & USER_FMT) ) + // searched for used and found none + bFnd = false; + } + return bFnd ? mxStyleSheet.get() : nullptr; +} + +SwStyleSheetIterator::SwStyleSheetIterator(SwDocStyleSheetPool& rBase, + SfxStyleFamily eFam, SfxStyleSearchBits n ) + : SfxStyleSheetIterator(&rBase, eFam, n) + , mxIterSheet(new SwDocStyleSheet(rBase.GetDoc(), rBase)) + , mxStyleSheet(new SwDocStyleSheet(rBase.GetDoc(), rBase)) +{ + m_bFirstCalled = false; + m_nLastPos = 0; + StartListening(rBase); +} + +SwStyleSheetIterator::~SwStyleSheetIterator() +{ + EndListening( *mxIterSheet->GetPool() ); +} + +sal_Int32 SwStyleSheetIterator::Count() +{ + // let the list fill correctly!! + if( !m_bFirstCalled ) + First(); + return m_aLst.size(); +} + +SfxStyleSheetBase* SwStyleSheetIterator::operator[]( sal_Int32 nIdx ) +{ + // found + if( !m_bFirstCalled ) + First(); + auto const & rEntry = m_aLst[ nIdx ]; + mxStyleSheet->PresetNameAndFamily( rEntry.first, rEntry.second ); + mxStyleSheet->SetPhysical( false ); + mxStyleSheet->FillStyleSheet( SwDocStyleSheet::FillOnlyName ); + + return mxStyleSheet.get(); +} + +SfxStyleSheetBase* SwStyleSheetIterator::First() +{ + // Delete old list + m_bFirstCalled = true; + m_nLastPos = 0; + m_aLst.clear(); + + // Delete current + mxIterSheet->Reset(); + + const SwDoc& rDoc = static_cast<const SwDocStyleSheetPool*>(pBasePool)->GetDoc(); + const SfxStyleSearchBits nSrchMask = nMask; + const bool bIsSearchUsed = SearchUsed(); + + bool bSearchHidden( nMask & SfxStyleSearchBits::Hidden ); + bool bOnlyHidden = nMask == SfxStyleSearchBits::Hidden; + + const bool bOrganizer = static_cast<const SwDocStyleSheetPool*>(pBasePool)->IsOrganizerMode(); + bool bAll = ( nSrchMask & SfxStyleSearchBits::AllVisible ) == SfxStyleSearchBits::AllVisible; + + if( nSearchFamily == SfxStyleFamily::Char + || nSearchFamily == SfxStyleFamily::All ) + { + const size_t nArrLen = rDoc.GetCharFormats()->size(); + for( size_t i = 0; i < nArrLen; i++ ) + { + SwCharFormat* pFormat = (*rDoc.GetCharFormats())[ i ]; + + const bool bUsed = bIsSearchUsed && (bOrganizer || rDoc.IsUsed(*pFormat)); + if( ( !bSearchHidden && pFormat->IsHidden() && !bUsed ) || ( pFormat->IsDefault() && pFormat != rDoc.GetDfltCharFormat() ) ) + continue; + + if ( nSrchMask == SfxStyleSearchBits::Hidden && !pFormat->IsHidden( ) ) + continue; + + if( !bUsed ) + { + // Standard is no User template + const sal_uInt16 nId = rDoc.GetDfltCharFormat() == pFormat ? + sal_uInt16( RES_POOLCHR_INET_NORMAL ): + pFormat->GetPoolFormatId(); + if( (nSrchMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::UserDefined + ? !(nId & USER_FMT) + // searched for used and found none + : bIsSearchUsed ) + { + continue; + } + + if( rDoc.getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) && !(nId & USER_FMT) && + ( RES_POOLCHR_HTML_BEGIN > nId || nId >= RES_POOLCHR_HTML_END ) && + RES_POOLCHR_INET_NORMAL != nId && + RES_POOLCHR_INET_VISIT != nId && + RES_POOLCHR_FOOTNOTE != nId && + RES_POOLCHR_ENDNOTE != nId ) + continue; + } + + m_aLst.Append( SfxStyleFamily::Char, pFormat == rDoc.GetDfltCharFormat() + ? SwResId(STR_POOLCHR_STANDARD) + : pFormat->GetName() ); + } + + // PoolFormat + if( bAll ) + { + if( ! rDoc.getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) ) + AppendStyleList(SwStyleNameMapper::GetChrFormatUINameArray(), + bIsSearchUsed, bSearchHidden, bOnlyHidden, + SwGetPoolIdFromName::ChrFmt, SfxStyleFamily::Char); + else + { + m_aLst.Append( SfxStyleFamily::Char, SwStyleNameMapper::GetChrFormatUINameArray()[ + RES_POOLCHR_INET_NORMAL - RES_POOLCHR_BEGIN ] ); + m_aLst.Append( SfxStyleFamily::Char, SwStyleNameMapper::GetChrFormatUINameArray()[ + RES_POOLCHR_INET_VISIT - RES_POOLCHR_BEGIN ] ); + m_aLst.Append( SfxStyleFamily::Char, SwStyleNameMapper::GetChrFormatUINameArray()[ + RES_POOLCHR_ENDNOTE - RES_POOLCHR_BEGIN ] ); + m_aLst.Append( SfxStyleFamily::Char, SwStyleNameMapper::GetChrFormatUINameArray()[ + RES_POOLCHR_FOOTNOTE - RES_POOLCHR_BEGIN ] ); + } + AppendStyleList(SwStyleNameMapper::GetHTMLChrFormatUINameArray(), + bIsSearchUsed, bSearchHidden, bOnlyHidden, + SwGetPoolIdFromName::ChrFmt, SfxStyleFamily::Char); + } + } + + if( nSearchFamily == SfxStyleFamily::Para || + nSearchFamily == SfxStyleFamily::All ) + { + SfxStyleSearchBits nSMask = nSrchMask; + if( rDoc.getIDocumentSettingAccess().get(DocumentSettingId::HTML_MODE) ) + { + // then only HTML-Template are of interest + if( SfxStyleSearchBits::AllVisible == ( nSMask & SfxStyleSearchBits::AllVisible ) ) + nSMask = SfxStyleSearchBits::SwHtml | SfxStyleSearchBits::UserDefined | + SfxStyleSearchBits::Used; + else + nSMask &= SfxStyleSearchBits::Used | SfxStyleSearchBits::UserDefined | + SfxStyleSearchBits::SwCondColl | SfxStyleSearchBits::SwHtml; + if( nSMask == SfxStyleSearchBits::Auto ) + nSMask = SfxStyleSearchBits::SwHtml; + } + + const size_t nArrLen = rDoc.GetTextFormatColls()->size(); + for( size_t i = 0; i < nArrLen; i++ ) + { + SwTextFormatColl* pColl = (*rDoc.GetTextFormatColls())[ i ]; + + const bool bUsed = bOrganizer || rDoc.IsUsed(*pColl) || IsUsedInComments(pColl->GetName()); + if ( ( !bSearchHidden && pColl->IsHidden( ) && !bUsed ) || pColl->IsDefault() ) + continue; + + if ( nSMask == SfxStyleSearchBits::Hidden && !pColl->IsHidden( ) ) + continue; + + if( !(bIsSearchUsed && bUsed )) + { + const sal_uInt16 nId = pColl->GetPoolFormatId(); + auto tmpMask = nSMask & ~SfxStyleSearchBits::Used; + if (tmpMask == SfxStyleSearchBits::UserDefined) + { + if(!IsPoolUserFormat(nId)) continue; + } + else if (tmpMask == SfxStyleSearchBits::SwText) + { + if((nId & COLL_GET_RANGE_BITS) != COLL_TEXT_BITS) continue; + } + else if (tmpMask == SfxStyleSearchBits::SwChapter) + { + if((nId & COLL_GET_RANGE_BITS) != COLL_DOC_BITS) continue; + } + else if (tmpMask == SfxStyleSearchBits::SwList) + { + if((nId & COLL_GET_RANGE_BITS) != COLL_LISTS_BITS) continue; + } + else if (tmpMask == SfxStyleSearchBits::SwIndex) + { + if((nId & COLL_GET_RANGE_BITS) != COLL_REGISTER_BITS) continue; + } + else if (tmpMask == SfxStyleSearchBits::SwExtra) + { + if((nId & COLL_GET_RANGE_BITS) != COLL_EXTRA_BITS) continue; + } + else if (tmpMask == (SfxStyleSearchBits::SwHtml | SfxStyleSearchBits::UserDefined) + || tmpMask == SfxStyleSearchBits::SwHtml) + { + if((tmpMask & SfxStyleSearchBits::UserDefined) && IsPoolUserFormat(nId)) + ; // do nothing + else if( (nId & COLL_GET_RANGE_BITS) != COLL_HTML_BITS) + { + // but some we also want to see in this section + bool bContinue = true; + switch( nId ) + { + case RES_POOLCOLL_SEND_ADDRESS: // --> ADDRESS + case RES_POOLCOLL_TABLE_HDLN: // --> TH + case RES_POOLCOLL_TABLE: // --> TD + case RES_POOLCOLL_TEXT: // --> P + case RES_POOLCOLL_HEADLINE_BASE:// --> H + case RES_POOLCOLL_HEADLINE1: // --> H1 + case RES_POOLCOLL_HEADLINE2: // --> H2 + case RES_POOLCOLL_HEADLINE3: // --> H3 + case RES_POOLCOLL_HEADLINE4: // --> H4 + case RES_POOLCOLL_HEADLINE5: // --> H5 + case RES_POOLCOLL_HEADLINE6: // --> H6 + case RES_POOLCOLL_STANDARD: // --> P + case RES_POOLCOLL_FOOTNOTE: + case RES_POOLCOLL_ENDNOTE: + bContinue = false; + break; + } + if( bContinue ) + continue; + } + } + else if (tmpMask == SfxStyleSearchBits::SwCondColl) + { + if( RES_CONDTXTFMTCOLL != pColl->Which() ) continue; + } + else + { + // searched for used and found none + if( bIsSearchUsed ) + continue; + } + } + m_aLst.Append( SfxStyleFamily::Para, pColl->GetName() ); + } + + bAll = ( nSMask & SfxStyleSearchBits::AllVisible ) == SfxStyleSearchBits::AllVisible; + if ( bAll || (nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::SwText ) + AppendStyleList(SwStyleNameMapper::GetTextUINameArray(), + bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::TxtColl, SfxStyleFamily::Para ); + if ( bAll || (nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::SwChapter ) + AppendStyleList(SwStyleNameMapper::GetDocUINameArray(), + bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::TxtColl, SfxStyleFamily::Para ) ; + if ( bAll || (nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::SwList ) + AppendStyleList(SwStyleNameMapper::GetListsUINameArray(), + bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::TxtColl, SfxStyleFamily::Para ) ; + if ( bAll || (nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::SwIndex ) + AppendStyleList(SwStyleNameMapper::GetRegisterUINameArray(), + bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::TxtColl, SfxStyleFamily::Para ) ; + if ( bAll || (nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::SwExtra ) + AppendStyleList(SwStyleNameMapper::GetExtraUINameArray(), + bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::TxtColl, SfxStyleFamily::Para ) ; + if ( bAll || (nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::SwCondColl ) + { + if( !bIsSearchUsed || + rDoc.getIDocumentStylePoolAccess().IsPoolTextCollUsed( RES_POOLCOLL_TEXT )) + m_aLst.Append( SfxStyleFamily::Para, SwStyleNameMapper::GetTextUINameArray()[ + RES_POOLCOLL_TEXT - RES_POOLCOLL_TEXT_BEGIN ] ); + } + if ( bAll || + (nSMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::SwHtml || + (nSMask & ~SfxStyleSearchBits::Used) == + (SfxStyleSearchBits::SwHtml | SfxStyleSearchBits::UserDefined) ) + { + AppendStyleList(SwStyleNameMapper::GetHTMLUINameArray(), + bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::TxtColl, SfxStyleFamily::Para ) ; + if( !bAll ) + { + // then also the ones, that we are mapping: + static sal_uInt16 aPoolIds[] = { + RES_POOLCOLL_SEND_ADDRESS, // --> ADDRESS + RES_POOLCOLL_TABLE_HDLN, // --> TH + RES_POOLCOLL_TABLE, // --> TD + RES_POOLCOLL_STANDARD, // --> P + RES_POOLCOLL_TEXT, // --> P + RES_POOLCOLL_HEADLINE_BASE, // --> H + RES_POOLCOLL_HEADLINE1, // --> H1 + RES_POOLCOLL_HEADLINE2, // --> H2 + RES_POOLCOLL_HEADLINE3, // --> H3 + RES_POOLCOLL_HEADLINE4, // --> H4 + RES_POOLCOLL_HEADLINE5, // --> H5 + RES_POOLCOLL_HEADLINE6, // --> H6 + RES_POOLCOLL_FOOTNOTE, + RES_POOLCOLL_ENDNOTE, + 0 + }; + + sal_uInt16* pPoolIds = aPoolIds; + OUString s; + while( *pPoolIds ) + { + if( !bIsSearchUsed || rDoc.getIDocumentStylePoolAccess().IsPoolTextCollUsed( *pPoolIds ) ) + { + s = SwStyleNameMapper::GetUIName( *pPoolIds, s ); + m_aLst.Append( SfxStyleFamily::Para, s); + } + ++pPoolIds; + } + } + } + } + + if( nSearchFamily == SfxStyleFamily::Frame || + nSearchFamily == SfxStyleFamily::All ) + { + const size_t nArrLen = rDoc.GetFrameFormats()->size(); + for( size_t i = 0; i < nArrLen; i++ ) + { + const SwFrameFormat* pFormat = (*rDoc.GetFrameFormats())[ i ]; + + bool bUsed = bIsSearchUsed && ( bOrganizer || rDoc.IsUsed(*pFormat)); + if( ( !bSearchHidden && pFormat->IsHidden( ) && !bUsed ) || pFormat->IsDefault() || pFormat->IsAuto() ) + continue; + + if ( nSrchMask == SfxStyleSearchBits::Hidden && !pFormat->IsHidden( ) ) + continue; + + const sal_uInt16 nId = pFormat->GetPoolFormatId(); + if( !bUsed ) + { + if( (nSrchMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::UserDefined + ? !(nId & USER_FMT) + // searched for used and found none + : bIsSearchUsed ) + { + continue; + } + } + + m_aLst.Append( SfxStyleFamily::Frame, pFormat->GetName() ); + } + + // PoolFormat + if ( bAll ) + AppendStyleList(SwStyleNameMapper::GetFrameFormatUINameArray(), + bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::FrmFmt, SfxStyleFamily::Frame); + } + + if( nSearchFamily == SfxStyleFamily::Page || + nSearchFamily == SfxStyleFamily::All ) + { + const size_t nCount = rDoc.GetPageDescCnt(); + for(size_t i = 0; i < nCount; ++i) + { + const SwPageDesc& rDesc = rDoc.GetPageDesc(i); + const sal_uInt16 nId = rDesc.GetPoolFormatId(); + bool bUsed = bIsSearchUsed && ( bOrganizer || rDoc.IsUsed(rDesc)); + if( !bUsed ) + { + if ( ( !bSearchHidden && rDesc.IsHidden() ) || + ( (nSrchMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::UserDefined + ? !(nId & USER_FMT) + // searched for used and found none + : bIsSearchUsed ) ) + continue; + } + + if ( nSrchMask == SfxStyleSearchBits::Hidden && !rDesc.IsHidden( ) ) + continue; + + m_aLst.Append( SfxStyleFamily::Page, rDesc.GetName() ); + } + if ( bAll ) + AppendStyleList(SwStyleNameMapper::GetPageDescUINameArray(), + bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::PageDesc, SfxStyleFamily::Page); + } + + if( nSearchFamily == SfxStyleFamily::Pseudo || + nSearchFamily == SfxStyleFamily::All ) + { + const SwNumRuleTable& rNumTable = rDoc.GetNumRuleTable(); + for(auto const& rNum: rNumTable) + { + const SwNumRule& rRule = *rNum; + if( !rRule.IsAutoRule() ) + { + if ( nSrchMask == SfxStyleSearchBits::Hidden && !rRule.IsHidden( ) ) + continue; + + bool bUsed = bIsSearchUsed && (bOrganizer || rDoc.IsUsed(rRule)); + if( !bUsed ) + { + if( ( !bSearchHidden && rRule.IsHidden() ) || + ( (nSrchMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::UserDefined + ? !(rRule.GetPoolFormatId() & USER_FMT) + // searched for used and found none + : bIsSearchUsed ) ) + continue; + } + + m_aLst.Append( SfxStyleFamily::Pseudo, rRule.GetName() ); + } + } + if ( bAll ) + AppendStyleList(SwStyleNameMapper::GetNumRuleUINameArray(), + bIsSearchUsed, bSearchHidden, bOnlyHidden, SwGetPoolIdFromName::NumRule, SfxStyleFamily::Pseudo); + } + + if( nSearchFamily == SfxStyleFamily::Table || + nSearchFamily == SfxStyleFamily::All ) + { + const SwTableAutoFormatTable& rTableStyles = rDoc.GetTableStyles(); + for(size_t i = 0; i < rTableStyles.size(); ++i) + { + const SwTableAutoFormat& rTableStyle = rTableStyles[i]; + + bool bUsed = bIsSearchUsed && (bOrganizer || rDoc.IsUsed(rTableStyle)); + if(!bUsed) + { + if(nSrchMask == SfxStyleSearchBits::Hidden && !rTableStyle.IsHidden()) + continue; + + if( (!bSearchHidden && rTableStyle.IsHidden() ) || + ( (nSrchMask & ~SfxStyleSearchBits::Used) == SfxStyleSearchBits::UserDefined + ? !rTableStyle.IsUserDefined() + // searched for used and found none + : bIsSearchUsed ) ) + continue; + } + + m_aLst.Append( SfxStyleFamily::Table, rTableStyle.GetName() ); + } + } + + if( nSearchFamily == SfxStyleFamily::Cell || + nSearchFamily == SfxStyleFamily::All ) + { + const auto& aTableTemplateMap = SwTableAutoFormat::GetTableTemplateMap(); + if (rDoc.HasTableStyles()) + { + const SwTableAutoFormatTable& rTableStyles = rDoc.GetTableStyles(); + for(size_t i = 0; i < rTableStyles.size(); ++i) + { + const SwTableAutoFormat& rTableStyle = rTableStyles[i]; + for(size_t nBoxFormat = 0; nBoxFormat < aTableTemplateMap.size(); ++nBoxFormat) + { + const sal_uInt32 nBoxIndex = aTableTemplateMap[nBoxFormat]; + const SwBoxAutoFormat& rBoxFormat = rTableStyle.GetBoxFormat(nBoxIndex); + OUString sBoxFormatName; + SwStyleNameMapper::FillProgName(rTableStyle.GetName(), sBoxFormatName, SwGetPoolIdFromName::TabStyle); + sBoxFormatName += rTableStyle.GetTableTemplateCellSubName(rBoxFormat); + m_aLst.Append( SfxStyleFamily::Cell, sBoxFormatName ); + } + } + } + const SwCellStyleTable& rCellStyles = rDoc.GetCellStyles(); + for(size_t i = 0; i < rCellStyles.size(); ++i) + m_aLst.Append( SfxStyleFamily::Cell, rCellStyles[i].GetName() ); + } + + if(!m_aLst.empty()) + { + m_nLastPos = SAL_MAX_UINT32; + return Next(); + } + return nullptr; +} + +SfxStyleSheetBase* SwStyleSheetIterator::Next() +{ + assert(m_bFirstCalled); + ++m_nLastPos; + if(m_nLastPos < m_aLst.size()) + { + auto const & rEntry = m_aLst[m_nLastPos]; + mxIterSheet->PresetNameAndFamily(rEntry.first, rEntry.second); + mxIterSheet->SetPhysical( false ); + mxIterSheet->SetMask( nMask ); + if(mxIterSheet->pSet) + { + mxIterSheet->pSet->ClearItem(); + mxIterSheet->pSet= nullptr; + } + return mxIterSheet.get(); + } + return nullptr; +} + +SfxStyleSheetBase* SwStyleSheetIterator::Find(const OUString& rName) +{ + // searching + if( !m_bFirstCalled ) + First(); + + m_nLastPos = m_aLst.FindName( nSearchFamily, rName ); + if( SAL_MAX_UINT32 != m_nLastPos ) + { + // found + auto const & rEntry = m_aLst[m_nLastPos]; + mxStyleSheet->PresetNameAndFamily(rEntry.first, rEntry.second); + // new name is set, so determine its Data + mxStyleSheet->FillStyleSheet( SwDocStyleSheet::FillOnlyName ); + if( !mxStyleSheet->IsPhysical() ) + mxStyleSheet->SetPhysical( false ); + + return mxStyleSheet.get(); + } + return nullptr; +} + +void SwStyleSheetIterator::AppendStyleList(const std::vector<OUString>& rList, + bool bTestUsed, bool bTestHidden, bool bOnlyHidden, + SwGetPoolIdFromName nSection, SfxStyleFamily eFamily ) +{ + const SwDoc& rDoc = static_cast<const SwDocStyleSheetPool*>(pBasePool)->GetDoc(); + bool bUsed = false; + for (const auto & i : rList) + { + bool bHidden = false; + sal_uInt16 nId = SwStyleNameMapper::GetPoolIdFromUIName(i, nSection); + switch ( nSection ) + { + case SwGetPoolIdFromName::TxtColl: + { + bUsed = rDoc.getIDocumentStylePoolAccess().IsPoolTextCollUsed( nId ); + SwFormat* pFormat = rDoc.FindTextFormatCollByName( i ); + bHidden = pFormat && pFormat->IsHidden( ); + } + break; + case SwGetPoolIdFromName::ChrFmt: + { + bUsed = rDoc.getIDocumentStylePoolAccess().IsPoolFormatUsed( nId ); + SwFormat* pFormat = rDoc.FindCharFormatByName( i ); + bHidden = pFormat && pFormat->IsHidden( ); + } + break; + case SwGetPoolIdFromName::FrmFmt: + { + bUsed = rDoc.getIDocumentStylePoolAccess().IsPoolFormatUsed( nId ); + SwFormat* pFormat = rDoc.FindFrameFormatByName( i ); + bHidden = pFormat && pFormat->IsHidden( ); + } + break; + case SwGetPoolIdFromName::PageDesc: + { + bUsed = rDoc.getIDocumentStylePoolAccess().IsPoolPageDescUsed( nId ); + SwPageDesc* pPgDesc = rDoc.FindPageDesc(i); + bHidden = pPgDesc && pPgDesc->IsHidden( ); + } + break; + case SwGetPoolIdFromName::NumRule: + { + SwNumRule* pRule = rDoc.FindNumRulePtr( i ); + bUsed = pRule && rDoc.IsUsed(*pRule); + bHidden = pRule && pRule->IsHidden( ); + } + break; + default: + OSL_ENSURE( false, "unknown PoolFormat-Id" ); + } + + bool bMatchHidden = ( bTestHidden && ( bHidden || !bOnlyHidden ) ) || ( !bTestHidden && ( !bHidden || bUsed ) ); + if ( ( !bTestUsed && bMatchHidden ) || ( bTestUsed && bUsed ) ) + m_aLst.Append( eFamily, i ); + } +} + +bool SwStyleSheetIterator::IsUsedInComments(const OUString& rName) const +{ + auto pPool = static_cast<const SwDocStyleSheetPool*>(pBasePool)->GetEEStyleSheetPool(); + SfxStyleSheetIterator aIter(pPool, GetSearchFamily(), SfxStyleSearchBits::Used); + return aIter.Find(rName) != nullptr; +} + +void SwDocStyleSheetPool::InvalidateIterator() +{ + if (SfxStyleSheetIterator* pIter = GetCachedIterator()) + dynamic_cast<SwStyleSheetIterator&>(*pIter).InvalidateIterator(); +} + +void SwStyleSheetIterator::InvalidateIterator() +{ + // potentially we could send an SfxHint to Notify but currently it's + // iterating over the vector anyway so would still be slow - why does + // this iterator not use a map? + m_bFirstCalled = false; + m_nLastPos = 0; + m_aLst.clear(); +} + +void SwStyleSheetIterator::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + // search and remove from View-List!! + const SfxStyleSheetHint* pStyleSheetHint = dynamic_cast<const SfxStyleSheetHint*>(&rHint); + if( pStyleSheetHint && + SfxHintId::StyleSheetErased == pStyleSheetHint->GetId() ) + { + SfxStyleSheetBase* pStyle = pStyleSheetHint->GetStyleSheet(); + + if (pStyle) + m_aLst.RemoveName(pStyle->GetFamily(), pStyle->GetName()); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/app/mainwn.cxx b/sw/source/uibase/app/mainwn.cxx new file mode 100644 index 0000000000..7c21797f8e --- /dev/null +++ b/sw/source/uibase/app/mainwn.cxx @@ -0,0 +1,133 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <mdiexp.hxx> +#include <sfx2/progress.hxx> +#include <docsh.hxx> +#include <swmodule.hxx> +#include <swtypes.hxx> + +class SwDocShell; + +namespace { + +struct SwProgress +{ + tools::Long nStartValue, + nStartCount; + SwDocShell *pDocShell; + std::unique_ptr<SfxProgress> pProgress; +}; + +} + +static std::vector<std::unique_ptr<SwProgress>> *pProgressContainer = nullptr; + +static SwProgress *lcl_SwFindProgress( SwDocShell const *pDocShell ) +{ + for (const auto& pTmp : *pProgressContainer) + { + if ( pTmp->pDocShell == pDocShell ) + return pTmp.get(); + } + return nullptr; +} + +void StartProgress( TranslateId pMessResId, tools::Long nStartValue, tools::Long nEndValue, + SwDocShell *pDocShell ) +{ + if( SW_MOD()->IsEmbeddedLoadSave() ) + return; + + SwProgress *pProgress = nullptr; + + if ( !pProgressContainer ) + pProgressContainer = new std::vector<std::unique_ptr<SwProgress>>; + else + { + pProgress = lcl_SwFindProgress( pDocShell ); + if ( pProgress ) + ++pProgress->nStartCount; + } + + if ( !pProgress ) + { + pProgress = new SwProgress; + pProgress->pProgress.reset( new SfxProgress( pDocShell, + SwResId(pMessResId), + nEndValue - nStartValue ) ); + pProgress->nStartCount = 1; + pProgress->pDocShell = pDocShell; + pProgressContainer->insert( pProgressContainer->begin(), std::unique_ptr<SwProgress>(pProgress) ); + } + pProgress->nStartValue = nStartValue; +} + +void SetProgressState( tools::Long nPosition, SwDocShell const *pDocShell ) +{ + if( pProgressContainer && !SW_MOD()->IsEmbeddedLoadSave() ) + { + SwProgress *pProgress = lcl_SwFindProgress( pDocShell ); + if ( pProgress ) + pProgress->pProgress->SetState(nPosition - pProgress->nStartValue); + } +} + +void EndProgress( SwDocShell const *pDocShell ) +{ + if( !pProgressContainer || SW_MOD()->IsEmbeddedLoadSave() ) + return; + + SwProgress *pProgress = nullptr; + std::vector<SwProgress *>::size_type i; + for ( i = 0; i < pProgressContainer->size(); ++i ) + { + SwProgress *pTmp = (*pProgressContainer)[i].get(); + if ( pTmp->pDocShell == pDocShell ) + { + pProgress = pTmp; + break; + } + } + + if ( pProgress && 0 == --pProgress->nStartCount ) + { + pProgress->pProgress->Stop(); + pProgressContainer->erase( pProgressContainer->begin() + i ); + //#112337# it may happen that the container has been removed + //while rescheduling + if ( pProgressContainer && pProgressContainer->empty() ) + { + delete pProgressContainer; + pProgressContainer = nullptr; + } + } +} + +void RescheduleProgress( SwDocShell const *pDocShell ) +{ + if( pProgressContainer && !SW_MOD()->IsEmbeddedLoadSave() ) + { + SwProgress *pProgress = lcl_SwFindProgress( pDocShell ); + if ( pProgress ) + SfxProgress::Reschedule(); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/app/swdll.cxx b/sw/source/uibase/app/swdll.cxx new file mode 100644 index 0000000000..c4564a4741 --- /dev/null +++ b/sw/source/uibase/app/swdll.cxx @@ -0,0 +1,184 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <memory> + +#include <svx/svdobj.hxx> + +#include <swdll.hxx> +#include <wdocsh.hxx> +#include <globdoc.hxx> +#include <initui.hxx> +#include <swmodule.hxx> +#include <init.hxx> +#include <dobjfac.hxx> + +#include <com/sun/star/frame/Desktop.hpp> +#include <unotools/configmgr.hxx> +#include <unotools/moduleoptions.hxx> +#include <comphelper/unique_disposing_ptr.hxx> +#include <comphelper/processfactory.hxx> + +#include <sal/log.hxx> +#include <svx/fmobjfac.hxx> +#include <svx/objfac3d.hxx> +#include <editeng/acorrcfg.hxx> + +#include <swacorr.hxx> +#include <swabstdlg.hxx> + +#include "swdllimpl.hxx" + +using namespace com::sun::star; + +namespace +{ + //Holds a SwDLL and release it on exit, or dispose of the + //default XComponent, whichever comes first + class SwDLLInstance : public comphelper::unique_disposing_solar_mutex_reset_ptr<SwDLL> + { + public: + SwDLLInstance() : comphelper::unique_disposing_solar_mutex_reset_ptr<SwDLL>(uno::Reference<lang::XComponent>( frame::Desktop::create(comphelper::getProcessComponentContext()), uno::UNO_QUERY_THROW), new SwDLL, true) + { + } + }; + + SwDLLInstance& theSwDLLInstance() + { + static SwDLLInstance aInstance; + return aInstance; + } +} + +namespace SwGlobals +{ + void ensure() + { + // coverity[side_effect_free : FALSE] - not actually side-effect-free + theSwDLLInstance(); + } + + sw::Filters & getFilters() + { + return theSwDLLInstance()->getFilters(); + } +} + +SwDLL::SwDLL() + : m_pAutoCorrCfg(nullptr) +{ + if ( SfxApplication::GetModule(SfxToolsModule::Writer) ) // Module already active + return; + + std::unique_ptr<SvtModuleOptions> xOpt; + if (!utl::ConfigManager::IsFuzzing()) + xOpt.reset(new SvtModuleOptions); + SfxObjectFactory* pDocFact = nullptr; + SfxObjectFactory* pGlobDocFact = nullptr; + if (!xOpt || xOpt->IsWriter()) + { + pDocFact = &SwDocShell::Factory(); + pGlobDocFact = &SwGlobalDocShell::Factory(); + } + + SfxObjectFactory* pWDocFact = &SwWebDocShell::Factory(); + + auto pUniqueModule = std::make_unique<SwModule>(pWDocFact, pDocFact, pGlobDocFact); + SwModule* pModule = pUniqueModule.get(); + SfxApplication::SetModule(SfxToolsModule::Writer, std::move(pUniqueModule)); + + pWDocFact->SetDocumentServiceName("com.sun.star.text.WebDocument"); + + if (!xOpt || xOpt->IsWriter()) + { + pGlobDocFact->SetDocumentServiceName("com.sun.star.text.GlobalDocument"); + pDocFact->SetDocumentServiceName("com.sun.star.text.TextDocument"); + } + + // register 3D-object-Factory + E3dObjFactory(); + + // register form::component::Form-object-Factory + FmFormObjFactory(); + + SdrObjFactory::InsertMakeObjectHdl( LINK( &aSwObjectFactory, SwObjectFactory, MakeObject ) ); + + SAL_INFO( "sw.ui", "Init Core/UI/Filter" ); + // Initialisation of Statics + ::InitCore(); + m_pFilters.reset(new sw::Filters); + ::InitUI(); + + pModule->InitAttrPool(); + // now SWModule can create its Pool + + // register your view-factories here + RegisterFactories(); + + // register your shell-interfaces here + RegisterInterfaces(); + + // register your controllers here + RegisterControls(); + + if (!utl::ConfigManager::IsFuzzing()) + { + // replace SvxAutocorrect with SwAutocorrect + SvxAutoCorrCfg& rACfg = SvxAutoCorrCfg::Get(); + const SvxAutoCorrect* pOld = rACfg.GetAutoCorrect(); + rACfg.SetAutoCorrect(new SwAutoCorrect( *pOld )); + m_pAutoCorrCfg = &rACfg; + } +} + +SwDLL::~SwDLL() COVERITY_NOEXCEPT_FALSE +{ + if (m_pAutoCorrCfg) + { + // fdo#86494 SwAutoCorrect must be deleted before FinitCore + m_pAutoCorrCfg->SetAutoCorrect(nullptr); // delete SwAutoCorrect before exit handlers + } + + // Pool has to be deleted before statics are + SW_MOD()->RemoveAttrPool(); + + ::FinitUI(); + m_pFilters.reset(); + ::FinitCore(); + // sign out object-Factory + SdrObjFactory::RemoveMakeObjectHdl(LINK(&aSwObjectFactory, SwObjectFactory, MakeObject )); +} + +sw::Filters & SwDLL::getFilters() +{ + assert(m_pFilters); + return *m_pFilters; +} + +#ifndef DISABLE_DYNLOADING + +extern "C" SAL_DLLPUBLIC_EXPORT +void lok_preload_hook() +{ + SwAbstractDialogFactory::Create(); +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/app/swdllimpl.hxx b/sw/source/uibase/app/swdllimpl.hxx new file mode 100644 index 0000000000..7dab66d6ce --- /dev/null +++ b/sw/source/uibase/app/swdllimpl.hxx @@ -0,0 +1,45 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#pragma once + +#include <sal/config.h> + +#include <sal/types.h> + +#include <memory> + +namespace sw +{ +class Filters; +} + +class SvxAutoCorrCfg; + +class SwDLL +{ +public: + static void RegisterFactories(); + static void RegisterInterfaces(); + static void RegisterControls(); + + SwDLL(); + ~SwDLL() COVERITY_NOEXCEPT_FALSE; + + sw::Filters& getFilters(); + +private: + SwDLL(SwDLL const&) = delete; + SwDLL& operator=(SwDLL const&) = delete; + + std::unique_ptr<sw::Filters> m_pFilters; + SvxAutoCorrCfg* m_pAutoCorrCfg; +}; + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/app/swmodul1.cxx b/sw/source/uibase/app/swmodul1.cxx new file mode 100644 index 0000000000..64bd38f444 --- /dev/null +++ b/sw/source/uibase/app/swmodul1.cxx @@ -0,0 +1,693 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <memory> + +#include <hintids.hxx> +#include <sfx2/request.hxx> +#include <unotools/useroptions.hxx> +#include <com/sun/star/frame/FrameSearchFlag.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/view/XSelectionSupplier.hpp> +#include <svx/colorwindow.hxx> +#include <svx/dataaccessdescriptor.hxx> +#include <editeng/editids.hrc> +#include <editeng/wghtitem.hxx> +#include <editeng/postitem.hxx> +#include <editeng/udlnitem.hxx> +#include <editeng/crossedoutitem.hxx> +#include <editeng/cmapitem.hxx> +#include <editeng/colritem.hxx> +#include <editeng/brushitem.hxx> +#include <svl/cjkoptions.hxx> +#include <osl/diagnose.h> +#include <swmodule.hxx> +#include <swtypes.hxx> +#include <usrpref.hxx> +#include <modcfg.hxx> +#include <view.hxx> +#include <pview.hxx> +#include <wview.hxx> +#include <wrtsh.hxx> +#include <docsh.hxx> +#include <uinums.hxx> +#include <prtopt.hxx> +#include <navicfg.hxx> +#include <doc.hxx> +#include <strings.hrc> +#include <IDocumentLayoutAccess.hxx> + +#include <tools/color.hxx> +#include <tools/json_writer.hxx> +#include <PostItMgr.hxx> + +using namespace ::svx; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::view; +using namespace ::com::sun::star::lang; + +static void lcl_SetUIPrefs(const SwViewOption &rPref, SwView* pView, SwViewShell* pSh ) +{ + // in FrameSets the actual visibility can differ from the ViewOption's setting + bool bVScrollChanged = rPref.IsViewVScrollBar() != pSh->GetViewOptions()->IsViewVScrollBar(); + bool bHScrollChanged = rPref.IsViewHScrollBar() != pSh->GetViewOptions()->IsViewHScrollBar(); + bool bVAlignChanged = rPref.IsVRulerRight() != pSh->GetViewOptions()->IsVRulerRight(); + + pSh->SetUIOptions(rPref); + const SwViewOption* pNewPref = pSh->GetViewOptions(); + + // Scrollbars on / off + if(bVScrollChanged) + { + pView->EnableVScrollbar(pNewPref->IsViewVScrollBar()); + } + if(bHScrollChanged) + { + pView->EnableHScrollbar( pNewPref->IsViewHScrollBar() || pNewPref->getBrowseMode() ); + } + //if only the position of the vertical ruler has been changed initiate an update + if(bVAlignChanged && !bHScrollChanged && !bVScrollChanged) + pView->InvalidateBorder(); + + // Rulers on / off + if(pNewPref->IsViewVRuler()) + pView->CreateVRuler(); + else + pView->KillVRuler(); + + // TabWindow on / off + if(pNewPref->IsViewHRuler()) + pView->CreateTab(); + else + pView->KillTab(); + + pView->GetPostItMgr()->PrepareView(true); +} + +SwWrtShell* GetActiveWrtShell() +{ + if (SwView *pActive = GetActiveView()) + return &pActive->GetWrtShell(); + return nullptr; +} + +SwView* GetActiveView() +{ + SfxViewShell* pView = SfxViewShell::Current(); + return dynamic_cast<SwView*>( pView ); +} + +SwView* SwModule::GetFirstView() +{ + // returns only visible SwView + SwView* pView = static_cast<SwView*>(SfxViewShell::GetFirst(true, checkSfxViewShell<SwView>)); + return pView; +} + +SwView* SwModule::GetNextView(SwView const * pView) +{ + OSL_ENSURE( pView,"return no SwView" ); + SwView* pNView = static_cast<SwView*>(SfxViewShell::GetNext(*pView, true, checkSfxViewShell<SwView>)); + return pNView; +} + +// New Master for the settings is set; this affects the current view and all following. +void SwModule::ApplyUsrPref(const SwViewOption &rUsrPref, SwView* pActView, + SvViewOpt nDest ) +{ + SwView* pCurrView = pActView; + SwViewShell* pSh = pCurrView ? &pCurrView->GetWrtShell() : nullptr; + + SwMasterUsrPref* pPref = const_cast<SwMasterUsrPref*>(GetUsrPref( + nDest == SvViewOpt::DestWeb + || (nDest != SvViewOpt::DestText + && dynamic_cast< const SwWebView *>( pCurrView )) )); + + // with Uno, only sdbcx::View, but not the Module should be changed + bool bViewOnly = SvViewOpt::DestViewOnly == nDest; + // fob Preview off + SwPagePreview* pPPView; + if( !pCurrView && nullptr != (pPPView = dynamic_cast<SwPagePreview*>( SfxViewShell::Current())) ) + { + if(!bViewOnly) + pPref->SetUIOptions( rUsrPref ); + pPPView->EnableVScrollbar(pPref->IsViewVScrollBar()); + pPPView->EnableHScrollbar(pPref->IsViewHScrollBar()); + if(!bViewOnly) + { + pPref->SetPagePrevRow(rUsrPref.GetPagePrevRow()); + pPref->SetPagePrevCol(rUsrPref.GetPagePrevCol()); + } + return; + } + + if(!bViewOnly) + { + pPref->SetUsrPref( rUsrPref ); + pPref->SetModified(); + } + + if( !pCurrView ) + return; + + // Passing on to CORE + bool bReadonly; + const SwDocShell* pDocSh = pCurrView->GetDocShell(); + if (pDocSh) + bReadonly = pDocSh->IsReadOnly(); + else //Use existing option if DocShell missing + bReadonly = pSh->GetViewOptions()->IsReadonly(); + std::unique_ptr<SwViewOption> xViewOpt; + if (!bViewOnly) + xViewOpt.reset(new SwViewOption(*pPref)); + else + xViewOpt.reset(new SwViewOption(rUsrPref)); + xViewOpt->SetReadonly( bReadonly ); + if( !(*pSh->GetViewOptions() == *xViewOpt) ) + { + //is maybe only a SwViewShell + pSh->StartAction(); + pSh->ApplyViewOptions( *xViewOpt ); + static_cast<SwWrtShell*>(pSh)->SetReadOnlyAvailable(xViewOpt->IsCursorInProtectedArea()); + pSh->EndAction(); + } + if ( pSh->GetViewOptions()->IsReadonly() != bReadonly ) + pSh->SetReadonlyOption(bReadonly); + + lcl_SetUIPrefs(*xViewOpt, pCurrView, pSh); + + // in the end the Idle-Flag is set again + pPref->SetIdle(true); +} + +void SwModule::ApplyUserMetric( FieldUnit eMetric, bool bWeb ) +{ + SwMasterUsrPref* pPref; + if(bWeb) + { + if(!m_pWebUsrPref) + GetUsrPref(true); + pPref = m_pWebUsrPref.get(); + } + else + { + if(!m_pUsrPref) + GetUsrPref(false); + pPref = m_pUsrPref.get(); + } + assert(pPref && "pPref is set by here"); + FieldUnit eOldMetric = pPref->GetMetric(); + if(eOldMetric != eMetric) + pPref->SetMetric(eMetric); + + FieldUnit eHScrollMetric = pPref->IsHScrollMetric() ? pPref->GetHScrollMetric() : eMetric; + FieldUnit eVScrollMetric = pPref->IsVScrollMetric() ? pPref->GetVScrollMetric() : eMetric; + + SwView* pTmpView = SwModule::GetFirstView(); + // switch the ruler for all MDI-Windows + while(pTmpView) + { + if(bWeb == (dynamic_cast<SwWebView*>( pTmpView) != nullptr) ) + { + pTmpView->ChangeVRulerMetric(eVScrollMetric); + pTmpView->ChangeTabMetric(eHScrollMetric); + } + + pTmpView = SwModule::GetNextView(pTmpView); + } +} + +void SwModule::ApplyRulerMetric( FieldUnit eMetric, bool bHorizontal, bool bWeb ) +{ + SwMasterUsrPref* pPref; + if(bWeb) + { + if(!m_pWebUsrPref) + GetUsrPref(true); + pPref = m_pWebUsrPref.get(); + } + else + { + if(!m_pUsrPref) + GetUsrPref(false); + pPref = m_pUsrPref.get(); + } + assert(pPref && "pPref will be set by now"); + if( bHorizontal ) + pPref->SetHScrollMetric(eMetric); + else + pPref->SetVScrollMetric(eMetric); + + SwView* pTmpView = SwModule::GetFirstView(); + // switch metric at the appropriate rulers + while(pTmpView) + { + if(bWeb == (dynamic_cast<SwWebView *>( pTmpView ) != nullptr)) + { + if( bHorizontal ) + pTmpView->ChangeTabMetric(eMetric); + else + pTmpView->ChangeVRulerMetric(eMetric); + } + pTmpView = SwModule::GetNextView(pTmpView); + } +} + +//set the usrpref 's char unit attribute and set rulers unit as char if the "apply char unit" is checked +void SwModule::ApplyUserCharUnit(bool bApplyChar, bool bWeb) +{ + SwMasterUsrPref* pPref; + if(bWeb) + { + if(!m_pWebUsrPref) + GetUsrPref(true); + pPref = m_pWebUsrPref.get(); + } + else + { + if(!m_pUsrPref) + GetUsrPref(false); + pPref = m_pUsrPref.get(); + } + assert(pPref && "pPref is set by here"); + bool bOldApplyCharUnit = pPref->IsApplyCharUnit(); + bool bHasChanged = false; + if(bOldApplyCharUnit != bApplyChar) + { + pPref->SetApplyCharUnit(bApplyChar); + bHasChanged = true; + } + + if( !bHasChanged ) + return; + + FieldUnit eHScrollMetric = pPref->IsHScrollMetric() ? pPref->GetHScrollMetric() : pPref->GetMetric(); + FieldUnit eVScrollMetric = pPref->IsVScrollMetric() ? pPref->GetVScrollMetric() : pPref->GetMetric(); + if(bApplyChar) + { + eHScrollMetric = FieldUnit::CHAR; + eVScrollMetric = FieldUnit::LINE; + } + else + { + if ( !SvtCJKOptions::IsAsianTypographyEnabled() && ( eHScrollMetric == FieldUnit::CHAR )) + eHScrollMetric = FieldUnit::INCH; + else if ( eHScrollMetric == FieldUnit::CHAR ) + eHScrollMetric = FieldUnit::CM; + if ( !SvtCJKOptions::IsAsianTypographyEnabled() && ( eVScrollMetric == FieldUnit::LINE )) + eVScrollMetric = FieldUnit::INCH; + else if ( eVScrollMetric == FieldUnit::LINE ) + eVScrollMetric = FieldUnit::CM; + } + SwView* pTmpView = SwModule::GetFirstView(); + // switch rulers for all MDI-Windows + while(pTmpView) + { + if(bWeb == (dynamic_cast<SwWebView*>( pTmpView) != nullptr) ) + { + pTmpView->ChangeVRulerMetric(eVScrollMetric); + pTmpView->ChangeTabMetric(eHScrollMetric); + } + + pTmpView = SwModule::GetNextView(pTmpView); + } +} + +SwNavigationConfig* SwModule::GetNavigationConfig() +{ + if(!m_pNavigationConfig) + { + m_pNavigationConfig.reset( new SwNavigationConfig ); + } + return m_pNavigationConfig.get(); +} + +SwPrintOptions* SwModule::GetPrtOptions(bool bWeb) +{ + if(bWeb && !m_pWebPrintOptions) + { + m_pWebPrintOptions.reset(new SwPrintOptions(true)); + } + else if(!bWeb && !m_pPrintOptions) + { + m_pPrintOptions.reset(new SwPrintOptions(false)); + } + + return bWeb ? m_pWebPrintOptions.get() : m_pPrintOptions.get(); +} + +SwChapterNumRules* SwModule::GetChapterNumRules() +{ + if(!m_pChapterNumRules) + m_pChapterNumRules.reset(new SwChapterNumRules); + return m_pChapterNumRules.get(); +} + +void SwModule::ShowDBObj(SwView const & rView, const SwDBData& rData) +{ + Reference<XFrame> xFrame = rView.GetViewFrame().GetFrame().GetFrameInterface(); + + uno::Reference<XFrame> xBeamerFrame = xFrame->findFrame("_beamer", FrameSearchFlag::CHILDREN); + if (!xBeamerFrame.is()) + return; + +// the beamer has been opened by the SfxViewFrame + Reference<XController> xController = xBeamerFrame->getController(); + Reference<XSelectionSupplier> xControllerSelection(xController, UNO_QUERY); + if (xControllerSelection.is()) + { + + ODataAccessDescriptor aSelection; + aSelection.setDataSource(rData.sDataSource); + aSelection[DataAccessDescriptorProperty::Command] <<= rData.sCommand; + aSelection[DataAccessDescriptorProperty::CommandType] <<= rData.nCommandType; + xControllerSelection->select(Any(aSelection.createPropertyValueSequence())); + } + else { + OSL_FAIL("no selection supplier in the beamer!"); + } +} + +std::size_t SwModule::GetRedlineAuthor() +{ + if (!m_bAuthorInitialised) + { + const SvtUserOptions& rOpt = GetUserOptions(); + m_sActAuthor = rOpt.GetFullName(); + if (m_sActAuthor.isEmpty()) + { + m_sActAuthor = rOpt.GetID(); + if (m_sActAuthor.isEmpty()) + m_sActAuthor = SwResId( STR_REDLINE_UNKNOWN_AUTHOR ); + } + m_bAuthorInitialised = true; + } + return InsertRedlineAuthor( m_sActAuthor ); +} + +void SwModule::SetRedlineAuthor(const OUString &rAuthor) +{ + m_bAuthorInitialised = true; + m_sActAuthor = rAuthor; + InsertRedlineAuthor( m_sActAuthor ); +} + +OUString const & SwModule::GetRedlineAuthor(std::size_t nPos) +{ + OSL_ENSURE(nPos < m_pAuthorNames.size(), "author not found!"); //#i45342# RTF doc with no author table caused reader to crash + while(nPos >= m_pAuthorNames.size()) + { + InsertRedlineAuthor("nn"); + } + return m_pAuthorNames[nPos]; +} + +void SwModule::ClearRedlineAuthors() +{ + m_pAuthorNames.clear(); +} + +static Color lcl_GetAuthorColor(std::size_t nPos) +{ + static const Color aColArr[] = + { + COL_AUTHOR1_DARK, COL_AUTHOR2_DARK, COL_AUTHOR3_DARK, + COL_AUTHOR4_DARK, COL_AUTHOR5_DARK, COL_AUTHOR6_DARK, + COL_AUTHOR7_DARK, COL_AUTHOR8_DARK, COL_AUTHOR9_DARK + }; + + return aColArr[nPos % SAL_N_ELEMENTS(aColArr)]; +} + +/// Returns a JSON representation of a redline author. +void SwModule::GetRedlineAuthorInfo(tools::JsonWriter& rJsonWriter) +{ + auto authorsNode = rJsonWriter.startArray("authors"); + for (std::size_t nAuthor = 0; nAuthor < m_pAuthorNames.size(); ++nAuthor) + { + auto authorNode = rJsonWriter.startStruct(); + rJsonWriter.put("index", static_cast<sal_Int64>(nAuthor)); + rJsonWriter.put("name", m_pAuthorNames[nAuthor]); + rJsonWriter.put("color", sal_uInt32(lcl_GetAuthorColor(nAuthor))); + } +} + +std::size_t SwModule::InsertRedlineAuthor(const OUString& rAuthor) +{ + std::size_t nPos = 0; + + while(nPos < m_pAuthorNames.size() && m_pAuthorNames[nPos] != rAuthor) + ++nPos; + + if (nPos == m_pAuthorNames.size()) + m_pAuthorNames.push_back(rAuthor); + + return nPos; +} + +static void lcl_FillAuthorAttr( std::size_t nAuthor, SfxItemSet &rSet, + const AuthorCharAttr &rAttr ) +{ + Color aCol( rAttr.m_nColor ); + + if( rAttr.m_nColor == COL_TRANSPARENT ) + aCol = lcl_GetAuthorColor(nAuthor); + + bool bBackGr = rAttr.m_nColor == COL_NONE_COLOR; + + switch (rAttr.m_nItemId) + { + case SID_ATTR_CHAR_WEIGHT: + { + SvxWeightItem aW( static_cast<FontWeight>(rAttr.m_nAttr), RES_CHRATR_WEIGHT ); + rSet.Put( aW ); + aW.SetWhich( RES_CHRATR_CJK_WEIGHT ); + rSet.Put( aW ); + aW.SetWhich( RES_CHRATR_CTL_WEIGHT ); + rSet.Put( aW ); + } + break; + + case SID_ATTR_CHAR_POSTURE: + { + SvxPostureItem aP( static_cast<FontItalic>(rAttr.m_nAttr), RES_CHRATR_POSTURE ); + rSet.Put( aP ); + aP.SetWhich( RES_CHRATR_CJK_POSTURE ); + rSet.Put( aP ); + aP.SetWhich( RES_CHRATR_CTL_POSTURE ); + rSet.Put( aP ); + } + break; + + case SID_ATTR_CHAR_UNDERLINE: + rSet.Put( SvxUnderlineItem( static_cast<FontLineStyle>(rAttr.m_nAttr), + RES_CHRATR_UNDERLINE)); + break; + + case SID_ATTR_CHAR_STRIKEOUT: + rSet.Put(SvxCrossedOutItem( static_cast<FontStrikeout>(rAttr.m_nAttr), + RES_CHRATR_CROSSEDOUT)); + break; + + case SID_ATTR_CHAR_CASEMAP: + rSet.Put( SvxCaseMapItem( static_cast<SvxCaseMap>(rAttr.m_nAttr), + RES_CHRATR_CASEMAP)); + break; + + case SID_ATTR_BRUSH: + rSet.Put( SvxBrushItem( aCol, RES_CHRATR_BACKGROUND )); + bBackGr = true; + break; + } + + if( !bBackGr ) + rSet.Put( SvxColorItem( aCol, RES_CHRATR_COLOR ) ); +} + +void SwModule::GetInsertAuthorAttr(std::size_t nAuthor, SfxItemSet &rSet) +{ + lcl_FillAuthorAttr(nAuthor, rSet, m_pModuleConfig->GetInsertAuthorAttr()); +} + +void SwModule::GetDeletedAuthorAttr(std::size_t nAuthor, SfxItemSet &rSet) +{ + lcl_FillAuthorAttr(nAuthor, rSet, m_pModuleConfig->GetDeletedAuthorAttr()); +} + +// For future extension: +void SwModule::GetFormatAuthorAttr( std::size_t nAuthor, SfxItemSet &rSet ) +{ + lcl_FillAuthorAttr( nAuthor, rSet, m_pModuleConfig->GetFormatAuthorAttr() ); +} + +sal_uInt16 SwModule::GetRedlineMarkPos() const +{ + return m_pModuleConfig->GetMarkAlignMode(); +} + +bool SwModule::IsInsTableFormatNum(bool bHTML) const +{ + return m_pModuleConfig->IsInsTableFormatNum(bHTML); +} + +bool SwModule::IsInsTableChangeNumFormat(bool bHTML) const +{ + return m_pModuleConfig->IsInsTableChangeNumFormat(bHTML); +} + +bool SwModule::IsInsTableAlignNum(bool bHTML) const +{ + return m_pModuleConfig->IsInsTableAlignNum(bHTML); +} + +bool SwModule::IsSplitVerticalByDefault(bool bHTML) const +{ + return m_pModuleConfig->IsSplitVerticalByDefault(bHTML); +} + +void SwModule::SetSplitVerticalByDefault(bool bHTML, bool value) +{ + m_pModuleConfig->SetSplitVerticalByDefault(bHTML, value); +} + +const Color &SwModule::GetRedlineMarkColor() const +{ + return m_pModuleConfig->GetMarkAlignColor(); +} + +const SwViewOption* SwModule::GetViewOption(bool bWeb) +{ + return GetUsrPref( bWeb ); +} + +OUString const & SwModule::GetDocStatWordDelim() const +{ + return m_pModuleConfig->GetWordDelimiter(); +} + +// Passing-through of the ModuleConfig's Metric (for HTML-Export) +FieldUnit SwModule::GetMetric( bool bWeb ) const +{ + SwMasterUsrPref* pPref; + if(bWeb) + { + if(!m_pWebUsrPref) + GetUsrPref(true); + pPref = m_pWebUsrPref.get(); + } + else + { + if(!m_pUsrPref) + GetUsrPref(false); + pPref = m_pUsrPref.get(); + } + assert(pPref && "pPref is set by here"); + return pPref->GetMetric(); +} + +// Pass-through Update-Status +sal_uInt16 SwModule::GetLinkUpdMode() const +{ + if (!m_pUsrPref) + GetUsrPref(false); + assert(m_pUsrPref && "m_pUsrPref is set by here"); + return o3tl::narrowing<sal_uInt16>(m_pUsrPref->GetUpdateLinkMode()); +} + +SwFieldUpdateFlags SwModule::GetFieldUpdateFlags() const +{ + if (!m_pUsrPref) + GetUsrPref(false); + assert(m_pUsrPref && "m_pUsrPref is set by here"); + return m_pUsrPref->GetFieldUpdateFlags(); +} + +void SwModule::ApplyFieldUpdateFlags(SwFieldUpdateFlags eFieldFlags) +{ + if (!m_pUsrPref) + GetUsrPref(false); + assert(m_pUsrPref && "m_pUsrPref is set by here"); + m_pUsrPref->SetFieldUpdateFlags(eFieldFlags); +} + +void SwModule::ApplyLinkMode(sal_Int32 nNewLinkMode) +{ + if (!m_pUsrPref) + GetUsrPref(false); + assert(m_pUsrPref && "m_pUsrPref is set by here"); + m_pUsrPref->SetUpdateLinkMode(nNewLinkMode); +} + +void SwModule::CheckSpellChanges( bool bOnlineSpelling, + bool bIsSpellWrongAgain, bool bIsSpellAllAgain, bool bSmartTags ) +{ + bool bOnlyWrong = bIsSpellWrongAgain && !bIsSpellAllAgain; + bool bInvalid = bOnlyWrong || bIsSpellAllAgain; + if( !(bOnlineSpelling || bInvalid) ) + return; + + for( SwDocShell *pDocSh = static_cast<SwDocShell*>(SfxObjectShell::GetFirst(checkSfxObjectShell<SwDocShell>)); + pDocSh; + pDocSh = static_cast<SwDocShell*>(SfxObjectShell::GetNext( *pDocSh, checkSfxObjectShell<SwDocShell> ) ) ) + { + SwDoc* pTmp = pDocSh->GetDoc(); + if ( pTmp->getIDocumentLayoutAccess().GetCurrentViewShell() ) + { + pTmp->SpellItAgainSam( bInvalid, bOnlyWrong, bSmartTags ); + SwViewShell* pViewShell = pTmp->getIDocumentLayoutAccess().GetCurrentViewShell(); + if ( bSmartTags && pViewShell && pViewShell->GetWin() ) + pViewShell->GetWin()->Invalidate(); + } + } +} + +void SwModule::ApplyDefaultPageMode(bool bIsSquaredPageMode) +{ + if (!m_pUsrPref) + GetUsrPref(false); + assert(m_pUsrPref && "pPref is set by here"); + m_pUsrPref->SetDefaultPageMode(bIsSquaredPageMode); +} + +SwCompareMode SwModule::GetCompareMode() const +{ + return m_pModuleConfig->GetCompareMode(); +} + +bool SwModule::IsUseRsid() const +{ + return m_pModuleConfig->IsUseRsid(); +} + +bool SwModule::IsIgnorePieces() const +{ + return m_pModuleConfig->IsIgnorePieces(); +} + +sal_uInt16 SwModule::GetPieceLen() const +{ + return m_pModuleConfig->GetPieceLen(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/app/swmodule.cxx b/sw/source/uibase/app/swmodule.cxx new file mode 100644 index 0000000000..e7a97f4b8c --- /dev/null +++ b/sw/source/uibase/app/swmodule.cxx @@ -0,0 +1,401 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <config_features.h> + +#include <svtools/ehdl.hxx> +#include <svtools/accessibilityoptions.hxx> +#include <unotools/resmgr.hxx> +#include <unotools/useroptions.hxx> +#include <svl/ctloptions.hxx> +#include <svx/ParaSpacingControl.hxx> +#include <svx/pszctrl.hxx> +#include <svx/insctrl.hxx> +#include <svx/selctrl.hxx> +#include <svx/linectrl.hxx> +#include <svx/tbxctl.hxx> +#include <svx/fillctrl.hxx> +#include <svx/formatpaintbrushctrl.hxx> +#include <svx/contdlg.hxx> +#include <svx/fontwork.hxx> +#include <SwSpellDialogChildWindow.hxx> +#include <svx/grafctrl.hxx> +#include <svx/clipboardctl.hxx> +#include <svx/imapdlg.hxx> +#include <svx/srchdlg.hxx> +#include <svx/hyperdlg.hxx> +#include <svx/modctrl.hxx> +#include <com/sun/star/scanner/ScannerManager.hpp> +#include <com/sun/star/linguistic2/LanguageGuessing.hpp> +#include <ooo/vba/XSinkCaller.hpp> +#include <comphelper/lok.hxx> +#include <comphelper/processfactory.hxx> +#include <docsh.hxx> +#include <swmodule.hxx> +#include <cmdid.h> +#include <pview.hxx> +#include <wview.hxx> +#include <wdocsh.hxx> +#include <srcview.hxx> +#include <glshell.hxx> +#include <tabsh.hxx> +#include <listsh.hxx> +#include <grfsh.hxx> +#include <mediash.hxx> +#include <olesh.hxx> +#include <drawsh.hxx> +#include <wformsh.hxx> +#include <drwtxtsh.hxx> +#include <beziersh.hxx> +#include <wtextsh.hxx> +#include <wfrmsh.hxx> +#include <drformsh.hxx> +#include <wgrfsh.hxx> +#include <wolesh.hxx> +#include <wlistsh.hxx> +#include <wtabsh.hxx> +#include <navipi.hxx> +#include <inputwin.hxx> +#include <usrpref.hxx> +#include <uinums.hxx> +#include <prtopt.hxx> +#include <bookctrl.hxx> +#include <tmplctrl.hxx> +#include <viewlayoutctrl.hxx> +#include <svx/zoomsliderctrl.hxx> +#include <zoomctrl.hxx> +#include <wordcountctrl.hxx> +#include <AccessibilityStatusBarControl.hxx> +#include <workctrl.hxx> +#include <fldwrap.hxx> +#include <redlndlg.hxx> +#include <syncbtn.hxx> +#include <modcfg.hxx> +#include <fontcfg.hxx> +#include <sfx2/sidebar/SidebarChildWindow.hxx> +#include <sfx2/devtools/DevelopmentToolChildWindow.hxx> +#include <swatrset.hxx> +#include <idxmrk.hxx> +#include <wordcountdialog.hxx> +#include <dlelstnr.hxx> +#include <barcfg.hxx> +#include <svx/rubydialog.hxx> +#include <svtools/colorcfg.hxx> + +#include <unotools/configmgr.hxx> +#include <unotools/moduleoptions.hxx> + +#include <avmedia/mediaplayer.hxx> +#include <avmedia/mediatoolbox.hxx> + +#include <annotsh.hxx> +#include <navsh.hxx> + +#include <app.hrc> +#include <error.hrc> +#include <strings.hrc> +#include <bitmaps.hlst> +#include <svx/xmlsecctrl.hxx> +bool g_bNoInterrupt = false; + +#include <sfx2/app.hxx> + +#include <svx/svxerr.hxx> + +#include "swdllimpl.hxx" +#include <dbconfig.hxx> +#include <navicfg.hxx> + +using namespace com::sun::star; +using namespace ::com::sun::star::uno; + +SwModule::SwModule( SfxObjectFactory* pWebFact, + SfxObjectFactory* pFact, + SfxObjectFactory* pGlobalFact ) + : SfxModule("sw"_ostr, {pWebFact, pFact, pGlobalFact}), + m_pView(nullptr), + m_bAuthorInitialised(false), + m_bEmbeddedLoadSave( false ), + m_pDragDrop( nullptr ), + m_pXSelection( nullptr ) +{ + SetName( "StarWriter" ); + SvxErrorHandler::ensure(); + m_pErrorHandler.reset( new SfxErrorHandler( RID_SW_ERRHDL, + ErrCodeArea::Sw, + ErrCodeArea::Sw, + GetResLocale() ) ); + + m_pModuleConfig.reset(new SwModuleOptions); + + // We need them anyways + m_pToolbarConfig.reset(new SwToolbarConfigItem( false )); + m_pWebToolbarConfig.reset(new SwToolbarConfigItem( true )); + + m_pStdFontConfig.reset(new SwStdFontConfig); + + { + SolarMutexGuard g; + StartListening( *SfxGetpApp() ); + } + + if (!utl::ConfigManager::IsFuzzing()) + { + // init color configuration + // member <pColorConfig> is created and the color configuration is applied + // at the view options. + GetColorConfig(); + m_xLinguServiceEventListener = new SwLinguServiceEventListener; + } +} + +OUString SwResId(TranslateId aId) +{ + return Translate::get(aId, SW_MOD()->GetResLocale()); +} + +OUString SwResId(TranslateNId aContextSingularPlural, int nCardinality) +{ + return Translate::nget(aContextSingularPlural, nCardinality, SW_MOD()->GetResLocale()); +} + +uno::Reference< scanner::XScannerManager2 > const & +SwModule::GetScannerManager() +{ + static bool bTestScannerManager = true; + if (bTestScannerManager && !m_xScannerManager.is()) + { + try { + m_xScannerManager = scanner::ScannerManager::create( comphelper::getProcessComponentContext() ); + } + catch (...) {} + bTestScannerManager = false; + } + return m_xScannerManager; +} + +uno::Reference< linguistic2::XLanguageGuessing > const & SwModule::GetLanguageGuesser() +{ + if (!m_xLanguageGuesser.is()) + { + m_xLanguageGuesser = linguistic2::LanguageGuessing::create( comphelper::getProcessComponentContext() ); + } + return m_xLanguageGuesser; +} + +SwModule::~SwModule() +{ + css::uno::Sequence< css::uno::Any > aArgs; + CallAutomationApplicationEventSinks( "Quit", aArgs ); + m_pErrorHandler.reset(); + EndListening( *SfxGetpApp() ); +} + +void SwDLL::RegisterFactories() +{ + // These Id's must not be changed. Through these Id's the View (resume Documentview) + // is created by Sfx. + if (utl::ConfigManager::IsFuzzing() || SvtModuleOptions().IsWriter()) + SwView::RegisterFactory ( SFX_INTERFACE_SFXDOCSH ); + +#if HAVE_FEATURE_DESKTOP + SwWebView::RegisterFactory ( SFX_INTERFACE_SFXMODULE ); + + if (utl::ConfigManager::IsFuzzing() || SvtModuleOptions().IsWriter()) + { + SwSrcView::RegisterFactory ( SfxInterfaceId(6) ); + SwPagePreview::RegisterFactory ( SfxInterfaceId(7) ); + } +#endif +} + +void SwDLL::RegisterInterfaces() +{ + SwModule* pMod = SW_MOD(); + SwModule::RegisterInterface( pMod ); + SwDocShell::RegisterInterface( pMod ); + SwWebDocShell::RegisterInterface( pMod ); + SwGlosDocShell::RegisterInterface( pMod ); + SwWebGlosDocShell::RegisterInterface( pMod ); + SwView::RegisterInterface( pMod ); + SwWebView::RegisterInterface( pMod ); + SwPagePreview::RegisterInterface( pMod ); + SwSrcView::RegisterInterface( pMod ); + + SwBaseShell::RegisterInterface(pMod); + SwTextShell::RegisterInterface(pMod); + SwTableShell::RegisterInterface(pMod); + SwListShell::RegisterInterface(pMod); + SwFrameShell::RegisterInterface(pMod); + SwDrawBaseShell::RegisterInterface(pMod); + SwDrawShell::RegisterInterface(pMod); + SwDrawFormShell::RegisterInterface(pMod); + SwDrawTextShell::RegisterInterface(pMod); + SwBezierShell::RegisterInterface(pMod); + SwGrfShell::RegisterInterface(pMod); + SwOleShell::RegisterInterface(pMod); + SwNavigationShell::RegisterInterface(pMod); + SwWebTextShell::RegisterInterface(pMod); + SwWebFrameShell::RegisterInterface(pMod); + SwWebGrfShell::RegisterInterface(pMod); + SwWebListShell::RegisterInterface(pMod); + SwWebTableShell::RegisterInterface(pMod); + SwWebDrawFormShell::RegisterInterface(pMod); + SwWebOleShell::RegisterInterface(pMod); + SwMediaShell::RegisterInterface(pMod); + SwAnnotationShell::RegisterInterface(pMod); +} + +void SwDLL::RegisterControls() +{ + SwModule* pMod = SW_MOD(); + + SvxTbxCtlDraw::RegisterControl(SID_INSERT_DRAW, pMod ); + SvxTbxCtlDraw::RegisterControl(SID_TRACK_CHANGES_BAR, pMod ); + SwTbxAutoTextCtrl::RegisterControl(FN_GLOSSARY_DLG, pMod ); + svx::ParaAboveSpacingControl::RegisterControl(SID_ATTR_PARA_ABOVESPACE, pMod); + svx::ParaBelowSpacingControl::RegisterControl(SID_ATTR_PARA_BELOWSPACE, pMod); + svx::ParaLeftSpacingControl::RegisterControl(SID_ATTR_PARA_LEFTSPACE, pMod); + svx::ParaRightSpacingControl::RegisterControl(SID_ATTR_PARA_RIGHTSPACE, pMod); + svx::ParaFirstLineSpacingControl::RegisterControl(SID_ATTR_PARA_FIRSTLINESPACE, pMod); + + SvxClipBoardControl::RegisterControl(SID_PASTE, pMod ); + svx::FormatPaintBrushToolBoxControl::RegisterControl(SID_FORMATPAINTBRUSH, pMod ); + + SvxFillToolBoxControl::RegisterControl(SID_ATTR_FILL_STYLE, pMod ); + SvxLineWidthToolBoxControl::RegisterControl(SID_ATTR_LINE_WIDTH, pMod ); + + SwZoomControl::RegisterControl(SID_ATTR_ZOOM, pMod ); + SwPreviewZoomControl::RegisterControl(FN_PREVIEW_ZOOM, pMod); + SvxPosSizeStatusBarControl::RegisterControl(0, pMod ); + SvxInsertStatusBarControl::RegisterControl(SID_ATTR_INSERT, pMod ); + SvxSelectionModeControl::RegisterControl(FN_STAT_SELMODE, pMod ); + XmlSecStatusBarControl::RegisterControl( SID_SIGNATURE, pMod ); + SwWordCountStatusBarControl::RegisterControl(FN_STAT_WORDCOUNT, pMod); + sw::AccessibilityStatusBarControl::RegisterControl(FN_STAT_ACCESSIBILITY_CHECK, pMod); + + SwBookmarkControl::RegisterControl(FN_STAT_PAGE, pMod ); + SwTemplateControl::RegisterControl(FN_STAT_TEMPLATE, pMod ); + SwViewLayoutControl::RegisterControl( SID_ATTR_VIEWLAYOUT, pMod ); + SvxModifyControl::RegisterControl( SID_DOC_MODIFIED, pMod ); + SvxZoomSliderControl::RegisterControl( SID_ATTR_ZOOMSLIDER, pMod ); + + SvxIMapDlgChildWindow::RegisterChildWindow( false, pMod ); + SvxSearchDialogWrapper::RegisterChildWindow( false, pMod ); + SvxHlinkDlgWrapper::RegisterChildWindow( false, pMod ); + SvxFontWorkChildWindow::RegisterChildWindow( false, pMod ); + SwFieldDlgWrapper::RegisterChildWindow( false, pMod ); + SwFieldDataOnlyDlgWrapper::RegisterChildWindow( false, pMod ); + SvxContourDlgChildWindow::RegisterChildWindow( false, pMod ); + SwInputChild::RegisterChildWindow( false, pMod, SfxChildWindowFlags::FORCEDOCK ); + SwRedlineAcceptChild::RegisterChildWindow( false, pMod ); + SwSyncChildWin::RegisterChildWindow( true, pMod ); + SwInsertIdxMarkWrapper::RegisterChildWindow( false, pMod ); + SwInsertAuthMarkWrapper::RegisterChildWindow( false, pMod ); + SwWordCountWrapper::RegisterChildWindow( false, pMod ); + SvxRubyChildWindow::RegisterChildWindow( false, pMod); + SwSpellDialogChildWindow::RegisterChildWindow( + false, pMod, comphelper::LibreOfficeKit::isActive() ? SfxChildWindowFlags::NEVERCLONE + : SfxChildWindowFlags::NONE); + DevelopmentToolChildWindow::RegisterChildWindow(false, pMod); + + SvxGrafRedToolBoxControl::RegisterControl( SID_ATTR_GRAF_RED, pMod ); + SvxGrafGreenToolBoxControl::RegisterControl( SID_ATTR_GRAF_GREEN, pMod ); + SvxGrafBlueToolBoxControl::RegisterControl( SID_ATTR_GRAF_BLUE, pMod ); + SvxGrafLuminanceToolBoxControl::RegisterControl( SID_ATTR_GRAF_LUMINANCE, pMod ); + SvxGrafContrastToolBoxControl::RegisterControl( SID_ATTR_GRAF_CONTRAST, pMod ); + SvxGrafGammaToolBoxControl::RegisterControl( SID_ATTR_GRAF_GAMMA, pMod ); + SvxGrafTransparenceToolBoxControl::RegisterControl( SID_ATTR_GRAF_TRANSPARENCE, pMod ); + SvxGrafModeToolBoxControl::RegisterControl( SID_ATTR_GRAF_MODE, pMod ); + +#if HAVE_FEATURE_AVMEDIA + ::avmedia::MediaToolBoxControl::RegisterControl(SID_AVMEDIA_TOOLBOX, pMod); + ::avmedia::MediaPlayer::RegisterChildWindow(false, pMod); +#endif + + ::sfx2::sidebar::SidebarChildWindow::RegisterChildWindow(false, pMod); + + SwNavigatorWrapper::RegisterChildWindow(false, pMod, SfxChildWindowFlags::NEVERHIDE); + + SwJumpToSpecificPageControl::RegisterControl(SID_JUMP_TO_SPECIFIC_PAGE, pMod); +} + +// Load Module (only dummy for linking of the DLL) +void SwModule::InitAttrPool() +{ + OSL_ENSURE(!m_pAttrPool, "Pool already exists!"); + m_pAttrPool = new SwAttrPool(nullptr); + SetPool(m_pAttrPool.get()); +} + +void SwModule::RemoveAttrPool() +{ + SetPool(nullptr); + m_pAttrPool.clear(); +} + +std::optional<SfxStyleFamilies> SwModule::CreateStyleFamilies() +{ + SfxStyleFamilies aStyleFamilies; + + aStyleFamilies.emplace_back(SfxStyleFamily::Para, + SwResId(STR_PARAGRAPHSTYLEFAMILY), + BMP_STYLES_FAMILY_PARA, + RID_PARAGRAPHSTYLEFAMILY, GetResLocale()); + + aStyleFamilies.emplace_back(SfxStyleFamily::Char, + SwResId(STR_CHARACTERSTYLEFAMILY), + BMP_STYLES_FAMILY_CHAR, + RID_CHARACTERSTYLEFAMILY, GetResLocale()); + + aStyleFamilies.emplace_back(SfxStyleFamily::Frame, + SwResId(STR_FRAMESTYLEFAMILY), + BMP_STYLES_FAMILY_FRAME, + RID_FRAMESTYLEFAMILY, GetResLocale()); + + aStyleFamilies.emplace_back(SfxStyleFamily::Page, + SwResId(STR_PAGESTYLEFAMILY), + BMP_STYLES_FAMILY_PAGE, + RID_PAGESTYLEFAMILY, GetResLocale()); + + aStyleFamilies.emplace_back(SfxStyleFamily::Pseudo, + SwResId(STR_LISTSTYLEFAMILY), + BMP_STYLES_FAMILY_LIST, + RID_LISTSTYLEFAMILY, GetResLocale()); + + aStyleFamilies.emplace_back(SfxStyleFamily::Table, + SwResId(STR_TABLESTYLEFAMILY), + BMP_STYLES_FAMILY_TABLE, + RID_TABLESTYLEFAMILY, GetResLocale()); + + return aStyleFamilies; +} + +void SwModule::RegisterAutomationApplicationEventsCaller(css::uno::Reference< ooo::vba::XSinkCaller > const& xCaller) +{ + mxAutomationApplicationEventsCaller = xCaller; +} + +void SwModule::CallAutomationApplicationEventSinks(const OUString& Method, css::uno::Sequence< css::uno::Any >& Arguments) +{ + if (mxAutomationApplicationEventsCaller.is()) + mxAutomationApplicationEventsCaller->CallSinks(Method, Arguments); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/app/swwait.cxx b/sw/source/uibase/app/swwait.cxx new file mode 100644 index 0000000000..62d8b277d6 --- /dev/null +++ b/sw/source/uibase/app/swwait.cxx @@ -0,0 +1,83 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <swwait.hxx> +#include <docsh.hxx> + +#include <sfx2/viewfrm.hxx> +#include <sfx2/dispatch.hxx> + +#include <vcl/window.hxx> + +SwWait::SwWait( + SwDocShell &rDocShell, + const bool bLockUnlockDispatcher ) + : mrDoc ( rDocShell ) + , mbLockUnlockDispatcher( bLockUnlockDispatcher ) +{ + EnterWaitAndLockDispatcher(); +} + +SwWait::~SwWait() +{ + LeaveWaitAndUnlockDispatcher(); +} + +void SwWait::EnterWaitAndLockDispatcher() +{ + SfxViewFrame *pFrame = SfxViewFrame::GetFirst( &mrDoc, false ); + while ( pFrame ) + { + pFrame->GetWindow().EnterWait(); + if ( mbLockUnlockDispatcher ) + { + // do not look already locked dispatchers + SfxDispatcher* pDispatcher = pFrame->GetDispatcher(); + if ( !pDispatcher->IsLocked() ) + { + pDispatcher->Lock( true ); + mpLockedDispatchers.insert( pDispatcher ); + } + } + + pFrame = SfxViewFrame::GetNext( *pFrame, &mrDoc, false ); + } +} + +void SwWait::LeaveWaitAndUnlockDispatcher() +{ + SfxViewFrame *pFrame = SfxViewFrame::GetFirst( &mrDoc, false ); + while ( pFrame ) + { + pFrame->GetWindow().LeaveWait(); + if ( mbLockUnlockDispatcher ) + { + // only unlock dispatchers which had been locked + SfxDispatcher* pDispatcher = pFrame->GetDispatcher(); + if ( mpLockedDispatchers.erase( pDispatcher ) ) + { + pDispatcher->Lock( false ); + } + } + + pFrame = SfxViewFrame::GetNext( *pFrame, &mrDoc, false ); + } +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |