/* -*- 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 .
*/
// do not clear items directly from item set and only clear to be kept // attributes, if no deletion item set is found. constbool bKeepAttributes =
!pPara || !pPara->pDelSet || pPara->pDelSet->Count() == 0; if ( bKeepAttributes )
{
pNode->ResetAttr( aClearWhichIds );
}
// Special case: if the Cursor is located within a URL attribute, we take over it's area
SwTextAttr const*const pURLAttr(
pTextNd->GetTextAttrAt(rSt.GetContentIndex(), RES_TXTATR_INETFMT)); if (pURLAttr && !pURLAttr->GetINetFormat().GetValue().isEmpty())
{
nMkPos = pURLAttr->GetStart();
nPtPos = *pURLAttr->End();
} else
{
assert(g_pBreakIt && g_pBreakIt->GetBreakIter().is());
Boundary aBndry = g_pBreakIt->GetBreakIter()->getWordBoundary(
pTextNd->GetText(), nPtPos,
g_pBreakIt->GetLocale( pTextNd->GetLang( nPtPos ) ),
WordType::ANY_WORD /*ANYWORD_IGNOREWHITESPACES*/, true);
/// Set the rsid of the next nLen symbols of rRg to the current session number void SwDoc::UpdateRsid( const SwPaM &rRg, const sal_Int32 nLen )
{ if (!SwModule::get()->GetModuleConfig()->IsStoreRsid()) return;
if (bRet && GetIDocumentUndoRedo().DoesUndo())
{
SwUndo *const pLastUndo = GetUndoManager().GetLastUndo();
SwUndoInsert *const pUndoInsert(dynamic_cast<SwUndoInsert*>(pLastUndo)); // this function is called after Insert so expects to find SwUndoInsert
assert(pUndoInsert); if (pUndoInsert)
{
pUndoInsert->SetWithRsid();
}
}
}
/// Set the attribute according to the stated format. /// If Undo is enabled, the old values is added to the Undo history. void SwDoc::SetAttr( const SfxPoolItem& rAttr, SwFormat& rFormat )
{
SfxItemSet aSet( GetAttrPool(), rAttr.Which(), rAttr.Which() );
aSet.Put( rAttr );
SetAttr( aSet, rFormat );
}
/// Set the attribute according to the stated format. /// If Undo is enabled, the old values is added to the Undo history. void SwDoc::SetAttr( const SfxItemSet& rSet, SwFormat& rFormat )
{ if (GetIDocumentUndoRedo().DoesUndo())
{
SwUndoFormatAttrHelper aTmp( rFormat );
rFormat.SetFormatAttr( rSet ); if ( aTmp.GetUndo() )
{
GetIDocumentUndoRedo().AppendUndo( aTmp.ReleaseUndo() );
} else
{
GetIDocumentUndoRedo().ClearRedo();
}
} else
{
rFormat.SetFormatAttr( rSet );
}
// If the format is a shape, and it has a textbox, sync. auto pShapeFormat = dynamic_cast<SwFrameFormat*>(&rFormat); if (pShapeFormat && SwTextBoxHelper::isTextBox(pShapeFormat, RES_DRAWFRMFMT))
{ if (auto pObj = pShapeFormat->FindRealSdrObject())
{
SwTextBoxHelper::syncFlyFrameAttr(*pShapeFormat, rSet, pObj);
SwTextBoxHelper::changeAnchor(pShapeFormat, pObj);
}
}
if ( bAttrReset )
{ if ( pUndo )
{
GetIDocumentUndoRedo().AppendUndo( std::move(pUndo) );
}
getIDocumentState().SetModified();
}
}
staticbool lcl_SetNewDefTabStops( SwTwips nOldWidth, SwTwips nNewWidth,
SvxTabStopItem& rChgTabStop )
{ // Set the default values of all TabStops to the new value. // Attention: we always work with the PoolAttribute here, so that // we don't calculate the same value on the same TabStop (pooled!) for all sets. // We send a FormatChg to modify.
// Find the default's beginning
sal_uInt16 n; for( n = nOldCnt; n ; --n ) if( SvxTabAdjust::Default != rChgTabStop[n - 1].GetAdjustment() ) break;
++n; if( n < nOldCnt ) // delete the DefTabStops
rChgTabStop.Remove( n, nOldCnt - n ); returntrue;
}
/// Set the attribute as new default attribute in this document. /// If Undo is enabled, the old value is added to the Undo history. void SwDoc::SetDefault( const SfxPoolItem& rAttr )
{
SfxItemSet aSet( GetAttrPool(), rAttr.Which(), rAttr.Which() );
aSet.Put( rAttr );
SetDefault( aSet );
}
const SvxTabStopItem* pTmpItem = aNew.GetItemIfSet( RES_PARATR_TABSTOP, false ); if( pTmpItem && pTmpItem->Count() )
{ // Set the default values of all TabStops to the new value. // Attention: we always work with the PoolAttribute here, so that // we don't calculate the same value on the same TabStop (pooled!) for all sets. // We send a FormatChg to modify.
SwTwips nNewWidth = (*pTmpItem)[ 0 ].GetTabPos(),
nOldWidth = aOld.Get(RES_PARATR_TABSTOP)[ 0 ].GetTabPos();
bool bChg = false;
ForEachParaAtrTabStopItem([&bChg, &nOldWidth, &nNewWidth](const SvxTabStopItem& rTabStopItem) -> bool { // pItem2 and thus pTabStopItem is a evtl. shared & RefCounted // Item and *should* not be changed that way. lcl_SetNewDefTabStops // seems to change pTabStopItem (!). This may need to be changed // to use iterateItemSurrogates and a defined write cycle.
bChg |= lcl_SetNewDefTabStops( nOldWidth, nNewWidth, const_cast<SvxTabStopItem&>(rTabStopItem) ); returntrue;
});
void SwDoc::DelFrameFormat( SwFrameFormat *pFormat, bool bBroadcast )
{
assert(pFormat && "ContainsFormat will always deref pFormat"); if( dynamic_cast<const SwTableBoxFormat*>( pFormat) != nullptr || dynamic_cast<const SwTableLineFormat*>( pFormat) != nullptr )
{
OSL_ENSURE( false, "Format is not in the DocArray any more, " "so it can be deleted with delete" ); delete pFormat;
} else
{ // The format has to be in the one or the other, we'll see in which one. if (mpFrameFormatTable->ContainsFormat(pFormat))
{ if (bBroadcast)
BroadcastStyleOperation(pFormat->GetName(),
SfxStyleFamily::Frame,
SfxHintId::StyleSheetErased);
if (GetIDocumentUndoRedo().DoesUndo())
{
GetIDocumentUndoRedo().AppendUndo(
std::make_unique<SwUndoFrameFormatDelete>(pFormat, *this));
}
// Who has the to-be-deleted as their Next?
SwTextFormatColl *pDel = (*mpTextFormatCollTable)[nFormatColl]; if( mpDfltTextFormatColl.get() == pDel ) return; // never delete default!
if (bBroadcast)
BroadcastStyleOperation(pDel->GetName(), SfxStyleFamily::Para,
SfxHintId::StyleSheetErased);
if (GetIDocumentUndoRedo().DoesUndo())
{
std::unique_ptr<SwUndoTextFormatCollDelete> pUndo; if (RES_CONDTXTFMTCOLL == pDel->Which())
{
pUndo.reset(new SwUndoCondTextFormatCollDelete(pDel, *this));
} else
{
pUndo.reset(new SwUndoTextFormatCollDelete(pDel, *this));
}
// #i62675# check, if paragraph style has changed if ( pPara->bResetListAttrs &&
(pPara->bResetAllCharAttrs || pFormat != pCNd->GetFormatColl())
&& pCNd->GetTextNode()->IsInList() )
{ // Check, if the list style of the paragraph will change. bool bChangeOfListStyleAtParagraph( true );
SwTextNode& rTNd(*pCNd->GetTextNode());
{
SwNumRule* pNumRuleAtParagraph(rTNd.GetNumRule()); if ( pNumRuleAtParagraph )
{ const SwNumRuleItem& rNumRuleItemAtParagraphStyle = pFormat->GetNumRule(); if ( rNumRuleItemAtParagraphStyle.GetValue() ==
pNumRuleAtParagraph->GetName() )
{
bChangeOfListStyleAtParagraph = false;
}
}
}
std::optional<SwRegHistory> oRegH; if (pPara->pHistory)
oRegH.emplace(&rTNd, rTNd, pPara->pHistory);
if ( bChangeOfListStyleAtParagraph )
{
pCNd->ResetAttr( RES_PARATR_NUMRULE );
// reset all list attributes
pCNd->ResetAttr( RES_PARATR_LIST_LEVEL );
pCNd->ResetAttr( RES_PARATR_LIST_ISRESTART );
pCNd->ResetAttr( RES_PARATR_LIST_RESTARTVALUE );
pCNd->ResetAttr( RES_PARATR_LIST_ISCOUNTED );
pCNd->ResetAttr( RES_PARATR_LIST_ID );
} else
{ // The List Level must be applied as direct formatting. The spec says: // 19.495 The style:list-level attribute specifies the list level value // of a list style that may be applied to any paragraph style. // It does not directly specify the paragraph's list level value, // but consumers can change the paragraph's list level value to the specified value // when the paragraph style is applied.
pCNd->SetAttr(pFormat->GetFormatAttr(RES_PARATR_LIST_LEVEL));
}
}
}
// add to History so that old data is saved, if necessary if( pPara->pHistory )
pPara->pHistory->AddColl(pCNd->GetFormatColl(), pCNd->GetIndex(),
SwNodeType::Text );
/// Copy the formats to itself
SwFormat* SwDoc::CopyFormat( const SwFormat& rFormat, const SwFormatsBase& rFormatArr,
FNCopyFormat fnCopyFormat, const SwFormat& rDfltFormat )
{ // It's no autoformat, default format or collection format, // then search for it. if( !rFormat.IsAuto() || !rFormat.GetRegisteredIn() ) for( size_t n = 0; n < rFormatArr.GetFormatCount(); ++n )
{ // Does the Doc already contain the template? if( rFormatArr.GetFormat(n)->GetName()==rFormat.GetName() ) return rFormatArr.GetFormat(n);
}
// Search for the "parent" first
SwFormat* pParent = const_cast<SwFormat*>(&rDfltFormat); if( rFormat.DerivedFrom() && pParent != rFormat.DerivedFrom() )
pParent = CopyFormat( *rFormat.DerivedFrom(), rFormatArr,
fnCopyFormat, rDfltFormat );
// Create the format and copy the attributes // #i40550#
SwFormat* pNewFormat = (this->*fnCopyFormat)( rFormat.GetName(), pParent, true );
pNewFormat->SetAuto( rFormat.IsAuto() );
pNewFormat->CopyAttrs( rFormat ); // copy the attributes
if( RES_CONDTXTFMTCOLL == pSrc->Which() )
{ if (pDstColl->Which() != RES_CONDTXTFMTCOLL)
{ // Target already had a style with a matching name, but it's not a conditional // style, then don't copy the conditions. continue;
}
// Copy the conditions, but delete the old ones first! static_cast<SwConditionTextFormatColl*>(pDstColl)->SetConditions( static_cast<SwConditionTextFormatColl*>(pSrc)->GetCondColls() );
}
}
}
}
void SwDoc::CopyPageDescHeaderFooterImpl( bool bCpyHeader, const SwFrameFormat& rSrcFormat, SwFrameFormat& rDestFormat )
{ // Treat the header and footer attributes in the right way: // Copy content nodes across documents!
sal_uInt16 nAttr = bCpyHeader ? sal_uInt16(RES_HEADER) : sal_uInt16(RES_FOOTER); const SfxPoolItem* pItem; if( SfxItemState::SET != rSrcFormat.GetAttrSet().GetItemState( nAttr, false, &pItem )) return ;
// The header only contains the reference to the format from the other document!
std::unique_ptr<SfxPoolItem> pNewItem(pItem->Clone());
// the header and footer attributes are copied separately // the content sections have to be copied in their entirety
{
SfxItemSet aAttrSet( rSrcDesc.GetMaster().GetAttrSet() );
aAttrSet.ClearItem( RES_HEADER );
aAttrSet.ClearItem( RES_FOOTER );
// If foot notes change the pages have to be triggered if( !(rDstDesc.GetFootnoteInfo() == rSrcDesc.GetFootnoteInfo()) )
{
sw::PageFootnoteHint aHint;
rDstDesc.SetFootnoteInfo( rSrcDesc.GetFootnoteInfo() );
rDstDesc.GetMaster().CallSwClientNotify(aHint);
rDstDesc.GetLeft().CallSwClientNotify(aHint);
rDstDesc.GetFirstMaster().CallSwClientNotify(aHint);
rDstDesc.GetFirstLeft().CallSwClientNotify(aHint);
}
// Copy the stashed formats as well between the page descriptors... for (bool bFirst : { true, false })
{ for (bool bLeft : { true, false })
{ for (bool bHeader : { true, false })
{ if (!bLeft && !bFirst) continue;
// Copy format only if it exists if (auto pStashedFormatSrc = rSrcDesc.GetStashedFrameFormat(bHeader, bLeft, bFirst))
{ if (&pStashedFormatSrc->GetDoc() != this)
{
SwFrameFormat newFormat(GetAttrPool(), UIName(u"CopyDesc"_ustr), GetDfltFrameFormat());
//To-Do: // a) in sd rtf import (View::InsertData) don't use // a super-fragile test for mere presence of \trowd to // indicate import of rtf into a table // b) then drop use of bIncludePageStyles if (bIncludePageStyles)
{ // and now the page templates
SwPageDescs::size_type nCnt = rSource.m_PageDescs.size(); if( nCnt )
{ // a different Doc -> Number formatter needs to be merged
SwTableNumFormatMerge aTNFM( rSource, *this );
// 2nd step: Copy all attributes, set the right parents for (SwPageDescs::size_type i = rSource.m_PageDescs.size(); i; )
{ const SwPageDesc &rSrc = *rSource.m_PageDescs[ --i ];
SwPageDesc* pDesc = FindPageDesc( rSrc.GetName() );
CopyPageDesc( rSrc, *pDesc);
}
}
}
// then there are the numbering templates const SwNumRuleTable::size_type nCnt = rSource.GetNumRuleTable().size(); if( nCnt )
{ const SwNumRuleTable& rArr = rSource.GetNumRuleTable(); for( SwNumRuleTable::size_type n = 0; n < nCnt; ++n )
{ const SwNumRule& rR = *rArr[ n ];
SwNumRule* pNew = FindNumRulePtr( rR.GetName()); if( pNew )
pNew->CopyNumRule(*this, rR); else
{ if( !rR.IsAutoRule() )
MakeNumRule( rR.GetName(), &rR ); else
{ // as we reset all styles, there shouldn't be any unknown // automatic SwNumRules, because all should have been // created by the style copying! // So just warn and ignore.
SAL_WARN( "sw.core", "Found unknown auto SwNumRule during reset!" );
}
}
}
}
if (undoGuard.UndoWasEnabled())
{ // nodes array was modified!
GetIDocumentUndoRedo().DelAllUndoObj();
}
if (mbIsAutoFormatRedline)
{ // create the redline object const SwTextFormatColl& rColl = *pTNd->GetTextColl();
SwRangeRedline* pRedl = new SwRangeRedline( RedlineType::FmtColl, aPam );
pRedl->SetMark();
// Only those items that are not set by the Set again in the Node // are of interest. Thus, we take the difference.
SwRedlineExtraData_FormatColl aExtraData( rColl.GetName(),
rColl.GetPoolFormatId() ); if( pSet && pTNd->HasSwAttrSet() )
{
SfxItemSet aTmp( *pTNd->GetpSwAttrSet() );
aTmp.Differentiate( *pSet ); // we handle the adjust item separately const SfxPoolItem* pItem; if( SfxItemState::SET == pTNd->GetpSwAttrSet()->GetItemState(
RES_PARATR_ADJUST, false, &pItem ))
aTmp.Put( *pItem );
IStyleAccess& rStyleAccess = pTNd->GetDoc().GetIStyleAccess();
std::shared_ptr<SfxItemSet> pAutoStyle = rStyleAccess.getAutomaticStyle(aTmp, IStyleAccess::AUTO_STYLE_CHAR);
aExtraData.SetItemSet( pAutoStyle );
}
pRedl->SetExtraData( &aExtraData );
//TODO: Undo is still missing!
getIDocumentRedlineAccess().AppendRedline( pRedl, true );
}
if (pSet && pSet->Count())
{
aPam.SetMark();
aPam.GetMark()->SetContent(pTNd->GetText().getLength()); // sw_redlinehide: don't need layout currently because the only caller // passes in the properties node
assert(static_cast<SwTextFrame const*>(pTNd->getLayoutFrame(nullptr))->GetTextNodeForParaProps() == pTNd);
getIDocumentContentOperations().InsertItemSet( aPam, *pSet );
}
}
if (mbIsAutoFormatRedline)
{ // create the redline object
SwRangeRedline* pRedl = new SwRangeRedline( RedlineType::Format, rPam ); if( !pRedl->HasMark() )
pRedl->SetMark();
// Only those items that are not set by the Set again in the Node // are of interest. Thus, we take the difference.
SwRedlineExtraData_Format aExtraData( rSet );
pRedl->SetExtraData( &aExtraData );
//TODO: Undo is still missing!
getIDocumentRedlineAccess().AppendRedline( pRedl, true );
::std::optional<SfxItemSet> oCurrentSet; if (!whichIds.empty())
{ // ITEM: Need to sort these due to ItemSet using unordered_set and // WhichRangesContainer expect these sorted ascending
std::sort(whichIds.begin(), whichIds.end(), [](WhichPair& a, WhichPair& b) {return a.first < b.first;});
oCurrentSet.emplace(GetAttrPool(), WhichRangesContainer(whichIds.data(), whichIds.size()));
pTNd->GetParaAttr(*oCurrentSet, nEnd, nEnd); for (const WhichPair& rPair : whichIds)
{ // yuk - want to explicitly set the pool defaults too :-/
oCurrentSet->Put(oCurrentSet->Get(rPair.first));
}
}
if (!whichIds.empty())
{ // fdo#62536: DONTEXPAND does not work when there is already an AUTOFMT // here, so insert the old attributes as an empty hint to stop expand
SwPaM endPam(*pTNd, nEnd);
endPam.SetMark();
getIDocumentContentOperations().InsertItemSet(endPam, *oCurrentSet);
}
void SwDoc::ChgFormat(SwFormat & rFormat, const SfxItemSet & rSet)
{ if (GetIDocumentUndoRedo().DoesUndo())
{ // copying <rSet> to <aSet>
SfxItemSet aSet(rSet); // remove from <aSet> all items, which are already set at the format
aSet.Differentiate(rFormat.GetAttrSet()); // <aSet> contains now all *new* items for the format
// copying current format item set to <aOldSet>
SfxItemSet aOldSet(rFormat.GetAttrSet()); // insert new items into <aOldSet>
aOldSet.Put(aSet); // invalidate all new items in <aOldSet> in order to clear these items, // if the undo action is triggered.
{
SfxItemIter aIter(aSet);
if (pUndo)
{
GetIDocumentUndoRedo().AppendUndo(std::move(pUndo));
}
}
// name change means the o3tl::sorted_array is not property sorted if (rFormat.Which() == RES_CHRFMT)
mpCharFormatTable->SetFormatNameAndReindex(static_cast<SwCharFormat*>(&rFormat), sNewName); else
rFormat.SetFormatName(sNewName);
if (bBroadcast)
BroadcastStyleOperation(sNewName, eFamily, SfxHintId::StyleSheetModified);
}
ForEachCharacterColorItem(
[&aDocColors] (const SvxColorItem& rColorItem) -> bool
{
Color aColor(rColorItem.GetValue()); if (COL_AUTO != aColor)
aDocColors.insert(aColor); returntrue;
});
ForEachCharacterHighlightBrushItem(
[&aDocColors] (const SvxBrushItem& rColorItem) -> bool
{
Color aColor(rColorItem.GetColor()); if (COL_AUTO != aColor)
aDocColors.insert(aColor); returntrue;
});
ForEachCharacterBackgroundBrushItem(
[&aDocColors] (const SvxBrushItem& rColorItem) -> bool
{
Color aColor(rColorItem.GetColor()); if (COL_AUTO != aColor)
aDocColors.insert(aColor); returntrue;
});
return aDocColors;
}
// #i69627# namespace docfunc
{ bool HasOutlineStyleToBeWrittenAsNormalListStyle( SwDoc& rDoc )
{ // If a parent paragraph style of one of the paragraph styles, which // are assigned to the list levels of the outline style, has a list style // set or inherits a list style from its parent style, the outline style // has to be written as a normal list style to the OpenDocument file // format or the OpenOffice.org file format. bool bRet( false );
const SwTextFormatColls* pTextFormatColls( rDoc.GetTextFormatColls() ); if ( pTextFormatColls )
{ for ( auto pTextFormatColl : *pTextFormatColls )
{ if ( pTextFormatColl->IsDefault() ||
! pTextFormatColl->IsAssignedToListLevelOfOutlineStyle() )
{ continue;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.