/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace com::sun::star; static void lcl_DefaultPageFormat( sal_uInt16 nPoolFormatId, SwFrameFormat &rFormat1, SwFrameFormat &rFormat2, SwFrameFormat &rFormat3, SwFrameFormat &rFormat4) { // --> #i41075# Printer on demand // This function does not require a printer anymore. // The default page size is obtained from the application //locale SwFormatFrameSize aFrameSize( ATT_FIX_SIZE ); const Size aPhysSize = SvxPaperInfo::GetDefaultPaperSize(); aFrameSize.SetSize( aPhysSize ); // Prepare for default margins. // Margins have a default minimum size. // If the printer forces a larger margins, that's ok too. // The HTML page desc had A4 as page size always. // This has been changed to take the page size from the printer. // Unfortunately, the margins of the HTML page desc are smaller than // the margins used here in general, so one extra case is required. // In the long term, this needs to be changed to always keep the // margins from the page desc. sal_Int32 nMinTop, nMinBottom, nMinLeft, nMinRight; if( RES_POOLPAGE_HTML == nPoolFormatId ) { nMinRight = nMinTop = nMinBottom = GetMetricVal( CM_1 ); nMinLeft = nMinRight * 2; } else if (!utl::ConfigManager::IsAvoidConfig() && MEASURE_METRIC == SvtSysLocale().GetLocaleData().getMeasurementSystemEnum() ) { nMinTop = nMinBottom = nMinLeft = nMinRight = 1134; // 2 centimetres } else { nMinTop = nMinBottom = 1440; // as in MS Word: 1 Inch nMinLeft = nMinRight = 1800; // 1,25 Inch } // set margins SvxLRSpaceItem aLR( RES_LR_SPACE ); SvxULSpaceItem aUL( RES_UL_SPACE ); aUL.SetUpper( (sal_uInt16)nMinTop ); aUL.SetLower( (sal_uInt16)nMinBottom ); aLR.SetRight( nMinRight ); aLR.SetLeft( nMinLeft ); rFormat1.SetFormatAttr( aFrameSize ); rFormat1.SetFormatAttr( aLR ); rFormat1.SetFormatAttr( aUL ); rFormat2.SetFormatAttr( aFrameSize ); rFormat2.SetFormatAttr( aLR ); rFormat2.SetFormatAttr( aUL ); rFormat3.SetFormatAttr( aFrameSize ); rFormat3.SetFormatAttr( aLR ); rFormat3.SetFormatAttr( aUL ); rFormat4.SetFormatAttr( aFrameSize ); rFormat4.SetFormatAttr( aLR ); rFormat4.SetFormatAttr( aUL ); } static void lcl_DescSetAttr( const SwFrameFormat &rSource, SwFrameFormat &rDest, const bool bPage = true ) { // We should actually use ItemSet's Intersect here, but that doesn't work // correctly if we have different WhichRanges. // Take over the attributes which are of interest. sal_uInt16 const aIdArr[] = { RES_FRM_SIZE, RES_UL_SPACE, // [83..86 RES_BACKGROUND, RES_SHADOW, // [99..101 RES_COL, RES_COL, // [103 RES_TEXTGRID, RES_TEXTGRID, // [109 RES_FRAMEDIR, RES_FRAMEDIR, // [114 RES_HEADER_FOOTER_EAT_SPACING, RES_HEADER_FOOTER_EAT_SPACING, // [115 RES_UNKNOWNATR_CONTAINER, RES_UNKNOWNATR_CONTAINER, // [143 //UUUU take over DrawingLayer FillStyles XATTR_FILL_FIRST, XATTR_FILL_LAST, // [1014 0}; const SfxPoolItem* pItem; for( sal_uInt16 n = 0; aIdArr[ n ]; n += 2 ) { for( sal_uInt16 nId = aIdArr[ n ]; nId <= aIdArr[ n+1]; ++nId ) { // #i45539# // bPage == true: // All in aIdArr except from RES_HEADER_FOOTER_EAT_SPACING // bPage == false: // All in aIdArr except from RES_COL and RES_PAPER_BIN: bool bExecuteId(true); if(bPage) { // When Page switch(nId) { // All in aIdArr except from RES_HEADER_FOOTER_EAT_SPACING case RES_HEADER_FOOTER_EAT_SPACING: //UUUU take out SvxBrushItem; it's the result of the fallback // at SwFormat::GetItemState and not really in state SfxItemState::SET case RES_BACKGROUND: bExecuteId = false; break; default: break; } } else { // When not Page switch(nId) { // When not Page: All in aIdArr except from RES_COL and RES_PAPER_BIN: case RES_COL: case RES_PAPER_BIN: bExecuteId = false; break; default: break; } } if(bExecuteId) { if (SfxItemState::SET == rSource.GetItemState(nId, false, &pItem)) { rDest.SetFormatAttr(*pItem); } else { rDest.ResetFormatAttr(nId); } } } } // Transmit pool and help IDs too rDest.SetPoolFormatId( rSource.GetPoolFormatId() ); rDest.SetPoolHelpId( rSource.GetPoolHelpId() ); rDest.SetPoolHlpFileId( rSource.GetPoolHlpFileId() ); } namespace { SwFrameFormat& getFrameFormat(SwPageDesc &rDesc, bool bLeft, bool bFirst) { if (bFirst) { if (bLeft) return rDesc.GetFirstLeft(); return rDesc.GetFirstMaster(); } return rDesc.GetLeft(); } const SwFrameFormat& getConstFrameFormat(const SwPageDesc &rDesc, bool bLeft, bool bFirst) { return getFrameFormat(const_cast(rDesc), bLeft, bFirst); } } void SwDoc::CopyMasterHeader(const SwPageDesc &rChged, const SwFormatHeader &rHead, SwPageDesc &rDesc, bool bLeft, bool bFirst) { assert(bLeft || bFirst); SwFrameFormat& rDescFrameFormat = getFrameFormat(rDesc, bLeft, bFirst); if (bFirst && bLeft) { // special case: always shared with something rDescFrameFormat.SetFormatAttr( rChged.IsFirstShared() ? rDesc.GetLeft().GetHeader() : rDesc.GetFirstMaster().GetHeader()); } else if ((bFirst ? rChged.IsFirstShared() : rChged.IsHeaderShared()) || !rHead.IsActive()) { // Left or first shares the header with the Master. rDescFrameFormat.SetFormatAttr( rDesc.GetMaster().GetHeader() ); } else if ( rHead.IsActive() ) { // Left or first gets its own header if the Format doesn't already have one. // If it already has one and it points to the same Section as the // Right one, it needs to get an own Header. // The content is evidently copied. const SwFormatHeader &rFormatHead = rDescFrameFormat.GetHeader(); if ( !rFormatHead.IsActive() ) { SwFormatHeader aHead( getIDocumentLayoutAccess().MakeLayoutFormat( RND_STD_HEADERL, nullptr ) ); rDescFrameFormat.SetFormatAttr( aHead ); // take over additional attributes (margins, borders ...) ::lcl_DescSetAttr( *rHead.GetHeaderFormat(), *aHead.GetHeaderFormat(), false); } else { const SwFrameFormat *pRight = rHead.GetHeaderFormat(); const SwFormatContent &aRCnt = pRight->GetContent(); const SwFormatContent &aCnt = rFormatHead.GetHeaderFormat()->GetContent(); if (!aCnt.GetContentIdx()) { const SwFrameFormat& rChgedFrameFormat = getConstFrameFormat(rChged, bLeft, bFirst); rDescFrameFormat.SetFormatAttr( rChgedFrameFormat.GetHeader() ); } else if ((*aRCnt.GetContentIdx() == *aCnt.GetContentIdx()) || // The ContentIdx is _always_ different when called from // SwDocStyleSheet::SetItemSet, because it deep-copies the // PageDesc. So check if it was previously shared. ((bFirst) ? rDesc.IsFirstShared() : rDesc.IsHeaderShared())) { SwFrameFormat *pFormat = new SwFrameFormat( GetAttrPool(), (bFirst) ? "First header" : "Left header", GetDfltFrameFormat() ); ::lcl_DescSetAttr( *pRight, *pFormat, false ); // The section which the right header attribute is pointing // is copied, and the Index to the StartNode is set to // the left or first header attribute. SwNodeIndex aTmp( GetNodes().GetEndOfAutotext() ); SwStartNode* pSttNd = SwNodes::MakeEmptySection( aTmp, SwHeaderStartNode ); SwNodeRange aRange( aRCnt.GetContentIdx()->GetNode(), 0, *aRCnt.GetContentIdx()->GetNode().EndOfSectionNode() ); aTmp = *pSttNd->EndOfSectionNode(); GetNodes().Copy_( aRange, aTmp, false ); aTmp = *pSttNd; GetDocumentContentOperationsManager().CopyFlyInFlyImpl(aRange, 0, aTmp); pFormat->SetFormatAttr( SwFormatContent( pSttNd ) ); rDescFrameFormat.SetFormatAttr( SwFormatHeader( pFormat ) ); } else ::lcl_DescSetAttr( *pRight, *const_cast(rFormatHead.GetHeaderFormat()), false ); } } } void SwDoc::CopyMasterFooter(const SwPageDesc &rChged, const SwFormatFooter &rFoot, SwPageDesc &rDesc, bool bLeft, bool bFirst) { assert(bLeft || bFirst); SwFrameFormat& rDescFrameFormat = getFrameFormat(rDesc, bLeft, bFirst); if (bFirst && bLeft) { // special case: always shared with something rDescFrameFormat.SetFormatAttr( rChged.IsFirstShared() ? rDesc.GetLeft().GetFooter() : rDesc.GetFirstMaster().GetFooter()); } else if ((bFirst ? rChged.IsFirstShared() : rChged.IsFooterShared()) || !rFoot.IsActive()) { // Left or first shares the Header with the Master. rDescFrameFormat.SetFormatAttr( rDesc.GetMaster().GetFooter() ); } else if ( rFoot.IsActive() ) { // Left or first gets its own Footer if the Format does not already have one. // If the Format already has a Footer and it points to the same section as the Right one, // it needs to get an own one. // The content is evidently copied. const SwFormatFooter &rFormatFoot = rDescFrameFormat.GetFooter(); if ( !rFormatFoot.IsActive() ) { SwFormatFooter aFoot( getIDocumentLayoutAccess().MakeLayoutFormat( RND_STD_FOOTER, nullptr ) ); rDescFrameFormat.SetFormatAttr( aFoot ); // Take over additional attributes (margins, borders ...). ::lcl_DescSetAttr( *rFoot.GetFooterFormat(), *aFoot.GetFooterFormat(), false); } else { const SwFrameFormat *pRight = rFoot.GetFooterFormat(); const SwFormatContent &aRCnt = pRight->GetContent(); const SwFormatContent &aLCnt = rFormatFoot.GetFooterFormat()->GetContent(); if( !aLCnt.GetContentIdx() ) { const SwFrameFormat& rChgedFrameFormat = getConstFrameFormat(rChged, bLeft, bFirst); rDescFrameFormat.SetFormatAttr( rChgedFrameFormat.GetFooter() ); } else if ((*aRCnt.GetContentIdx() == *aLCnt.GetContentIdx()) || // The ContentIdx is _always_ different when called from // SwDocStyleSheet::SetItemSet, because it deep-copies the // PageDesc. So check if it was previously shared. ((bFirst) ? rDesc.IsFirstShared() : rDesc.IsFooterShared())) { SwFrameFormat *pFormat = new SwFrameFormat( GetAttrPool(), (bFirst) ? "First footer" : "Left footer", GetDfltFrameFormat() ); ::lcl_DescSetAttr( *pRight, *pFormat, false ); // The section to which the right footer attribute is pointing // is copied, and the Index to the StartNode is set to // the left footer attribute. SwNodeIndex aTmp( GetNodes().GetEndOfAutotext() ); SwStartNode* pSttNd = SwNodes::MakeEmptySection( aTmp, SwFooterStartNode ); SwNodeRange aRange( aRCnt.GetContentIdx()->GetNode(), 0, *aRCnt.GetContentIdx()->GetNode().EndOfSectionNode() ); aTmp = *pSttNd->EndOfSectionNode(); GetNodes().Copy_( aRange, aTmp, false ); aTmp = *pSttNd; GetDocumentContentOperationsManager().CopyFlyInFlyImpl(aRange, 0, aTmp); pFormat->SetFormatAttr( SwFormatContent( pSttNd ) ); rDescFrameFormat.SetFormatAttr( SwFormatFooter( pFormat ) ); } else ::lcl_DescSetAttr( *pRight, *const_cast(rFormatFoot.GetFooterFormat()), false ); } } } void SwDoc::ChgPageDesc( size_t i, const SwPageDesc &rChged ) { OSL_ENSURE(i < m_PageDescs.size(), "PageDescs is out of range."); SwPageDesc& rDesc = *m_PageDescs[i]; SwRootFrame* pTmpRoot = getIDocumentLayoutAccess().GetCurrentLayout(); if (GetIDocumentUndoRedo().DoesUndo()) { SwUndo *const pUndo(new SwUndoPageDesc(rDesc, rChged, this)); GetIDocumentUndoRedo().AppendUndo(pUndo); } ::sw::UndoGuard const undoGuard(GetIDocumentUndoRedo()); // Mirror at first if needed. if ( rChged.GetUseOn() == nsUseOnPage::PD_MIRROR ) const_cast(rChged).Mirror(); else { // Or else transfer values from Master to Left ::lcl_DescSetAttr(rChged.GetMaster(), const_cast(rChged).GetLeft()); } ::lcl_DescSetAttr(rChged.GetMaster(), const_cast(rChged).GetFirstMaster()); ::lcl_DescSetAttr(rChged.GetLeft(), const_cast(rChged).GetFirstLeft()); // Take over NumType. if( rChged.GetNumType().GetNumberingType() != rDesc.GetNumType().GetNumberingType() ) { rDesc.SetNumType( rChged.GetNumType() ); // Notify page number fields that NumFormat has changed getIDocumentFieldsAccess().GetSysFieldType( RES_PAGENUMBERFLD )->UpdateFields(); getIDocumentFieldsAccess().GetSysFieldType( RES_REFPAGEGETFLD )->UpdateFields(); // If the numbering scheme has changed we could have QuoVadis/ErgoSum texts // that refer to a changed page, so we invalidate foot notes. SwFootnoteIdxs& rFootnoteIdxs = GetFootnoteIdxs(); for( SwFootnoteIdxs::size_type nPos = 0; nPos < rFootnoteIdxs.size(); ++nPos ) { SwTextFootnote *pTextFootnote = rFootnoteIdxs[ nPos ]; const SwFormatFootnote &rFootnote = pTextFootnote->GetFootnote(); pTextFootnote->SetNumber(rFootnote.GetNumber(), rFootnote.GetNumStr()); } } // Take over orientation rDesc.SetLandscape( rChged.GetLandscape() ); // #i46909# no undo if header or footer changed bool bHeaderFooterChanged = false; // Synch header. const SwFormatHeader &rHead = rChged.GetMaster().GetHeader(); if (undoGuard.UndoWasEnabled()) { // #i46909# no undo if header or footer changed // Did something change in the nodes? const SwFormatHeader &rOldHead = rDesc.GetMaster().GetHeader(); bHeaderFooterChanged |= ( rHead.IsActive() != rOldHead.IsActive() || rChged.IsHeaderShared() != rDesc.IsHeaderShared() || rChged.IsFirstShared() != rDesc.IsFirstShared() ); } rDesc.GetMaster().SetFormatAttr( rHead ); CopyMasterHeader(rChged, rHead, rDesc, true, false); // Copy left header CopyMasterHeader(rChged, rHead, rDesc, false, true); // Copy first master CopyMasterHeader(rChged, rHead, rDesc, true, true); // Copy first left rDesc.ChgHeaderShare( rChged.IsHeaderShared() ); // Synch Footer. const SwFormatFooter &rFoot = rChged.GetMaster().GetFooter(); if (undoGuard.UndoWasEnabled()) { // #i46909# no undo if header or footer changed // Did something change in the Nodes? const SwFormatFooter &rOldFoot = rDesc.GetMaster().GetFooter(); bHeaderFooterChanged |= ( rFoot.IsActive() != rOldFoot.IsActive() || rChged.IsFooterShared() != rDesc.IsFooterShared() ); } rDesc.GetMaster().SetFormatAttr( rFoot ); CopyMasterFooter(rChged, rFoot, rDesc, true, false); // Copy left footer CopyMasterFooter(rChged, rFoot, rDesc, false, true); // Copy first master CopyMasterFooter(rChged, rFoot, rDesc, true, true); // Copy first left rDesc.ChgFooterShare( rChged.IsFooterShared() ); // there is just one first shared flag for both header and footer? rDesc.ChgFirstShare( rChged.IsFirstShared() ); if ( rDesc.GetName() != rChged.GetName() ) rDesc.SetName( rChged.GetName() ); // A RegisterChange is triggered, if necessary rDesc.SetRegisterFormatColl( rChged.GetRegisterFormatColl() ); // If UseOn or the Follow change, the paragraphs need to know about it. bool bUseOn = false; bool bFollow = false; if (rDesc.GetUseOn() != rChged.GetUseOn()) { rDesc.SetUseOn( rChged.GetUseOn() ); bUseOn = true; } if (rDesc.GetFollow() != rChged.GetFollow()) { if (rChged.GetFollow() == &rChged) { if (rDesc.GetFollow() != &rDesc) { rDesc.SetFollow( &rDesc ); bFollow = true; } } else { rDesc.SetFollow( rChged.m_pFollow ); bFollow = true; } } if ( (bUseOn || bFollow) && pTmpRoot) // Inform layout! { for( auto aLayout : GetAllLayouts() ) aLayout->AllCheckPageDescs(); } // Take over the page attributes. ::lcl_DescSetAttr( rChged.GetMaster(), rDesc.GetMaster() ); ::lcl_DescSetAttr( rChged.GetLeft(), rDesc.GetLeft() ); ::lcl_DescSetAttr( rChged.GetFirstMaster(), rDesc.GetFirstMaster() ); ::lcl_DescSetAttr( rChged.GetFirstLeft(), rDesc.GetFirstLeft() ); // If the FootnoteInfo changes, the pages are triggered. if( !(rDesc.GetFootnoteInfo() == rChged.GetFootnoteInfo()) ) { rDesc.SetFootnoteInfo( rChged.GetFootnoteInfo() ); sw::PageFootnoteHint aHint; rDesc.GetMaster().CallSwClientNotify(aHint); rDesc.GetLeft().CallSwClientNotify(aHint); rDesc.GetFirstMaster().CallSwClientNotify(aHint); rDesc.GetFirstLeft().CallSwClientNotify(aHint); } getIDocumentState().SetModified(); // #i46909# no undo if header or footer changed if( bHeaderFooterChanged ) { GetIDocumentUndoRedo().DelAllUndoObj(); } SfxBindings* pBindings = ( GetDocShell() && GetDocShell()->GetDispatcher() ) ? GetDocShell()->GetDispatcher()->GetBindings() : nullptr; if ( pBindings ) { pBindings->Invalidate( SID_ATTR_PAGE_COLUMN ); pBindings->Invalidate( SID_ATTR_PAGE ); pBindings->Invalidate( SID_ATTR_PAGE_SIZE ); pBindings->Invalidate( SID_ATTR_PAGE_ULSPACE ); pBindings->Invalidate( SID_ATTR_PAGE_LRSPACE ); } //h/f of first-left page must not be unique but same as first master or left assert((rDesc.IsFirstShared()) ? rDesc.GetFirstLeft().GetHeader().GetHeaderFormat() == rDesc.GetLeft().GetHeader().GetHeaderFormat() : rDesc.GetFirstLeft().GetHeader().GetHeaderFormat() == rDesc.GetFirstMaster().GetHeader().GetHeaderFormat()); assert((rDesc.IsFirstShared()) ? rDesc.GetFirstLeft().GetFooter().GetFooterFormat() == rDesc.GetLeft().GetFooter().GetFooterFormat() : rDesc.GetFirstLeft().GetFooter().GetFooterFormat() == rDesc.GetFirstMaster().GetFooter().GetFooterFormat()); } /// All descriptors whose Follow point to the to-be-deleted have to be adapted. // #i7983# void SwDoc::PreDelPageDesc(SwPageDesc * pDel) { if (nullptr == pDel) return; // mba: test iteration as clients are removed while iteration SwPageDescHint aHint( m_PageDescs[0] ); pDel->CallSwClientNotify( aHint ); bool bHasLayout = getIDocumentLayoutAccess().HasLayout(); if ( mpFootnoteInfo->DependsOn( pDel ) ) { mpFootnoteInfo->ChgPageDesc( m_PageDescs[0] ); if ( bHasLayout ) { for( auto aLayout : GetAllLayouts() ) aLayout->CheckFootnotePageDescs(false); } } else if ( mpEndNoteInfo->DependsOn( pDel ) ) { mpEndNoteInfo->ChgPageDesc( m_PageDescs[0] ); if ( bHasLayout ) { for( auto aLayout : GetAllLayouts() ) aLayout->CheckFootnotePageDescs(true); } } for (SwPageDesc* pPageDesc : m_PageDescs) { if (pPageDesc->GetFollow() == pDel) { pPageDesc->SetFollow(nullptr); if( bHasLayout ) { for( auto aLayout : GetAllLayouts() ) aLayout->AllCheckPageDescs(); } } } } void SwDoc::BroadcastStyleOperation(const OUString& rName, SfxStyleFamily eFamily, sal_uInt16 nOp) { if (mpDocShell) { SfxStyleSheetBasePool * pPool = mpDocShell->GetStyleSheetPool(); if (pPool) { pPool->SetSearchMask(eFamily); SfxStyleSheetBase * pBase = pPool->Find(rName); if (pBase != nullptr) pPool->Broadcast(SfxStyleSheetHint( nOp, *pBase )); } } } void SwDoc::DelPageDesc( size_t i, bool bBroadcast ) { OSL_ENSURE(i < m_PageDescs.size(), "PageDescs is out of range."); OSL_ENSURE( i != 0, "You cannot delete the default Pagedesc."); if ( i == 0 ) return; SwPageDesc &rDel = *m_PageDescs[i]; if (bBroadcast) BroadcastStyleOperation(rDel.GetName(), SfxStyleFamily::Page, SfxStyleSheetHintId::ERASED); if (GetIDocumentUndoRedo().DoesUndo()) { SwUndo *const pUndo(new SwUndoPageDescDelete(rDel, this)); GetIDocumentUndoRedo().AppendUndo(pUndo); } PreDelPageDesc(&rDel); // #i7983# m_PageDescs.erase(m_PageDescs.begin() + i); getIDocumentState().SetModified(); } SwPageDesc* SwDoc::MakePageDesc(const OUString &rName, const SwPageDesc *pCpy, bool bRegardLanguage, bool bBroadcast) { SwPageDesc *pNew; if( pCpy ) { pNew = new SwPageDesc( *pCpy ); pNew->SetName( rName ); if( rName != pCpy->GetName() ) { pNew->SetPoolFormatId( USHRT_MAX ); pNew->SetPoolHelpId( USHRT_MAX ); pNew->SetPoolHlpFileId( UCHAR_MAX ); } } else { pNew = new SwPageDesc( rName, GetDfltFrameFormat(), this ); // Set the default page format. lcl_DefaultPageFormat( USHRT_MAX, pNew->GetMaster(), pNew->GetLeft(), pNew->GetFirstMaster(), pNew->GetFirstLeft() ); SvxFrameDirection aFrameDirection = bRegardLanguage ? GetDefaultFrameDirection(GetAppLanguage()) : FRMDIR_HORI_LEFT_TOP; pNew->GetMaster().SetFormatAttr( SvxFrameDirectionItem(aFrameDirection, RES_FRAMEDIR) ); pNew->GetLeft().SetFormatAttr( SvxFrameDirectionItem(aFrameDirection, RES_FRAMEDIR) ); pNew->GetFirstMaster().SetFormatAttr( SvxFrameDirectionItem(aFrameDirection, RES_FRAMEDIR) ); pNew->GetFirstLeft().SetFormatAttr( SvxFrameDirectionItem(aFrameDirection, RES_FRAMEDIR) ); } std::pair res = m_PageDescs.push_back( pNew ); SAL_WARN_IF(!res.second, "sw", "MakePageDesc called with existing name" ); if (bBroadcast) BroadcastStyleOperation(rName, SfxStyleFamily::Page, SfxStyleSheetHintId::CREATED); if (GetIDocumentUndoRedo().DoesUndo()) { GetIDocumentUndoRedo().AppendUndo(new SwUndoPageDescCreate(pNew, this)); } getIDocumentState().SetModified(); return pNew; } // We collect the GlobalNames of the servers at runtime, who don't want to be notified // about printer changes. Thereby saving loading a lot of objects (luckily all foreign // objects are mapped to one ID). // Initialisation and deinitialisation can be found in init.cxx extern std::vector *pGlobalOLEExcludeList; void SwDoc::PrtOLENotify( bool bAll ) { SwFEShell *pShell = nullptr; { SwViewShell *pSh = getIDocumentLayoutAccess().GetCurrentViewShell(); if ( pSh ) { for(SwViewShell& rShell : pSh->GetRingContainer()) { if(dynamic_cast( &rShell) != nullptr) { pShell = static_cast(&rShell); break; } } } } if ( !pShell ) { // This doesn't make sense without a Shell and thus without a client, because // the communication about size changes is implemented by these components. // Because we don't have a Shell we remember this unfortunate situation // in the document, // which is made up for later on when creating the first Shell. mbOLEPrtNotifyPending = true; if ( bAll ) mbAllOLENotify = true; } else { if ( mbAllOLENotify ) bAll = true; mbOLEPrtNotifyPending = mbAllOLENotify = false; SwOLENodes *pNodes = SwContentNode::CreateOLENodesArray( *GetDfltGrfFormatColl(), !bAll ); if ( pNodes ) { ::StartProgress( STR_STATSTR_SWGPRTOLENOTIFY, 0, pNodes->size(), GetDocShell()); getIDocumentLayoutAccess().GetCurrentLayout()->StartAllAction(); for( SwOLENodes::size_type i = 0; i < pNodes->size(); ++i ) { ::SetProgressState( i, GetDocShell() ); SwOLENode* pOLENd = (*pNodes)[i]; pOLENd->SetOLESizeInvalid( false ); // At first load the Infos and see if it's not already in the exclude list. SvGlobalName aName; svt::EmbeddedObjectRef& xObj = pOLENd->GetOLEObj().GetObject(); if ( xObj.is() ) aName = SvGlobalName( xObj->getClassID() ); else // Not yet loaded { // TODO/LATER: retrieve ClassID of an unloaded object // aName = ???? } bool bFound = false; for ( std::vector::size_type j = 0; j < pGlobalOLEExcludeList->size() && !bFound; ++j ) { bFound = *(*pGlobalOLEExcludeList)[j] == aName; } if ( bFound ) continue; // We don't know it, so the object has to be loaded. // If it doesn't want to be informed if ( xObj.is() ) { pGlobalOLEExcludeList->push_back( new SvGlobalName( aName ) ); } } delete pNodes; getIDocumentLayoutAccess().GetCurrentLayout()->EndAllAction(); ::EndProgress( GetDocShell() ); } } } IMPL_LINK_NOARG( SwDoc, DoUpdateModifiedOLE, Idle *, void ) { SwFEShell* pSh = static_cast(GetEditShell()); if( pSh ) { mbOLEPrtNotifyPending = mbAllOLENotify = false; SwOLENodes *pNodes = SwContentNode::CreateOLENodesArray( *GetDfltGrfFormatColl(), true ); if( pNodes ) { ::StartProgress( STR_STATSTR_SWGPRTOLENOTIFY, 0, pNodes->size(), GetDocShell()); getIDocumentLayoutAccess().GetCurrentLayout()->StartAllAction(); SwMsgPoolItem aMsgHint( RES_UPDATE_ATTR ); for( SwOLENodes::size_type i = 0; i < pNodes->size(); ++i ) { ::SetProgressState( i, GetDocShell() ); SwOLENode* pOLENd = (*pNodes)[i]; pOLENd->SetOLESizeInvalid( false ); // We don't know it, so the object has to be loaded. // If it doesn't want to be informed if( pOLENd->GetOLEObj().GetOleRef().is() ) // Broken? { pOLENd->ModifyNotification( &aMsgHint, &aMsgHint ); } } getIDocumentLayoutAccess().GetCurrentLayout()->EndAllAction(); ::EndProgress( GetDocShell() ); delete pNodes; } } } static SwPageDesc* lcl_FindPageDesc( const SwPageDescs *pPageDescs, size_t *pPos, const OUString &rName ) { SwPageDesc* res = nullptr; SwPageDescs::const_iterator it = pPageDescs->find( rName ); if( it != pPageDescs->end() ) { res = *it; if( pPos ) *pPos = std::distance( pPageDescs->begin(), it ); } else if( pPos ) *pPos = SIZE_MAX; return res; } SwPageDesc* SwDoc::FindPageDesc( const OUString & rName, size_t* pPos ) const { return lcl_FindPageDesc( &m_PageDescs, pPos, rName ); } bool SwDoc::ContainsPageDesc( const SwPageDesc *pDesc, size_t* pPos ) const { if( pDesc == nullptr ) return false; if( !m_PageDescs.contains( const_cast ( pDesc ) ) ) { if( pPos ) *pPos = SIZE_MAX; return false; } if( ! pPos ) return true; SwPageDesc* desc = lcl_FindPageDesc( &m_PageDescs, pPos, pDesc->GetName() ); SAL_WARN_IF( desc != pDesc, "sw", "SwPageDescs container is broken!" ); return true; } void SwDoc::DelPageDesc( const OUString & rName, bool bBroadcast ) { size_t nI; if (FindPageDesc(rName, &nI)) DelPageDesc(nI, bBroadcast); } void SwDoc::ChgPageDesc( const OUString & rName, const SwPageDesc & rDesc) { size_t nI; if (FindPageDesc(rName, &nI)) ChgPageDesc(nI, rDesc); } /* * The HTML import cannot resist changing the page descriptions, I don't * know why. This function is meant to check the page descriptors for invalid * values. */ void SwDoc::CheckDefaultPageFormat() { for ( size_t i = 0; i < GetPageDescCnt(); ++i ) { SwPageDesc& rDesc = GetPageDesc( i ); SwFrameFormat& rMaster = rDesc.GetMaster(); SwFrameFormat& rLeft = rDesc.GetLeft(); const SwFormatFrameSize& rMasterSize = rMaster.GetFrameSize(); const SwFormatFrameSize& rLeftSize = rLeft.GetFrameSize(); const bool bSetSize = LONG_MAX == rMasterSize.GetWidth() || LONG_MAX == rMasterSize.GetHeight() || LONG_MAX == rLeftSize.GetWidth() || LONG_MAX == rLeftSize.GetHeight(); if ( bSetSize ) lcl_DefaultPageFormat( rDesc.GetPoolFormatId(), rDesc.GetMaster(), rDesc.GetLeft(), rDesc.GetFirstMaster(), rDesc.GetFirstLeft() ); } } void SwDoc::SetDefaultPageMode(bool bSquaredPageMode) { if( !bSquaredPageMode == !IsSquaredPageMode() ) return; const SwTextGridItem& rGrid = static_cast(GetDefault( RES_TEXTGRID )); SwTextGridItem aNewGrid = rGrid; aNewGrid.SetSquaredMode(bSquaredPageMode); aNewGrid.Init(); SetDefault(aNewGrid); for ( size_t i = 0; i < GetPageDescCnt(); ++i ) { SwPageDesc& rDesc = GetPageDesc( i ); SwFrameFormat& rMaster = rDesc.GetMaster(); SwFrameFormat& rLeft = rDesc.GetLeft(); SwTextGridItem aGrid(static_cast(rMaster.GetFormatAttr(RES_TEXTGRID))); aGrid.SwitchPaperMode( bSquaredPageMode ); rMaster.SetFormatAttr(aGrid); rLeft.SetFormatAttr(aGrid); } } bool SwDoc::IsSquaredPageMode() const { const SwTextGridItem& rGrid = static_cast(GetDefault( RES_TEXTGRID )); return rGrid.IsSquaredMode(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */