/* -*- 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 .
*/
/* Change and extend data structure: - data structure contains candidates of paragraph styles, which will be assigned to the outline style - data structure contains more than one candidate for each list level of the outline style (#i69629#)
*/
std::unique_ptr< std::vector< OUString > []>
m_xOutlineStylesCandidates;
if (xCNSupplier.is())
{ // note: m_xChapterNumbering is accessed to import some fields
m_xImpl->m_xChapterNumbering = xCNSupplier->getChapterNumberingRules(); // the AutoCorrect document doesn't have a proper outline numbering if (!IsBlockMode() && m_xImpl->m_xChapterNumbering.is())
{
Reference< XPropertySet > const xNumRuleProps(
m_xImpl->m_xChapterNumbering, UNO_QUERY); if ( xNumRuleProps.is() )
{
Reference< XPropertySetInfo > xNumRulePropSetInfo(
xNumRuleProps->getPropertySetInfo()); if (xNumRulePropSetInfo.is() &&
xNumRulePropSetInfo->hasPropertyByName(
s_PropNameDefaultListId))
{
OUString sListId;
xNumRuleProps->getPropertyValue(s_PropNameDefaultListId)
>>= sListId;
assert( !sListId.isEmpty() && "no default list id found at chapter numbering rules instance. Serious defect." ); if ( !sListId.isEmpty() )
{
Reference< XNamed > const xChapterNumNamed(
m_xImpl->m_xChapterNumbering, UNO_QUERY); if ( xChapterNumNamed.is() )
{
m_xImpl->m_xTextListsHelper->KeepListAsProcessed(
sListId,
xChapterNumNamed->getName(),
OUString() );
}
}
}
}
}
}
Reference< XStyleFamiliesSupplier > xFamiliesSupp( rModel, UNO_QUERY ); // SAL_WARN_IF( !xFamiliesSupp.is(), "xmloff", "no chapter numbering supplier" ); for clipboard there may be documents without styles
if (xPropSetInfo->hasPropertyByName(u"Height"_ustr))
{
sal_Int32 nOtherHeight = 0;
xOtherFrame->getPropertyValue(u"Height"_ustr) >>= nOtherHeight; if (nHeight != nOtherHeight) returnfalse;
}
if (xPropSetInfo->hasPropertyByName(u"HoriOrientPosition"_ustr))
{
sal_Int32 nOtherX = 0;
xOtherFrame->getPropertyValue(u"HoriOrientPosition"_ustr) >>= nOtherX; if (nX != nOtherX) returnfalse;
}
if (xPropSetInfo->hasPropertyByName(u"VertOrientPosition"_ustr))
{
sal_Int32 nOtherY = 0;
xOtherFrame->getPropertyValue(u"VertOrientPosition"_ustr) >>= nOtherY; if (nY != nOtherY) returnfalse;
}
// In some case, position is not defined for frames, so check whether the two frames follow each other (are anchored to the same position) return m_xImpl->msLastImportedFrameName == sName;
} returnfalse;
}
/* Helper method to determine, if a paragraph style has a list style (inclusive an empty one) inherits a list style (inclusive an empty one) from one of its parents (#i69629#)
*/ /* Apply special case, that found list style equals the chapter numbering, also to the found list styles of the parent styles. (#i73973#)
*/ staticbool lcl_HasListStyle( const OUString& sStyleName, const Reference < XNameContainer >& xParaStyles,
SvXMLImport const & rImport, const OUString& sNumberingStyleName,
std::u16string_view sOutlineStyleName )
{ bool bRet( false );
if ( !xParaStyles->hasByName( sStyleName ) )
{ // error case returntrue;
}
Reference< XPropertyState > xPropState( xParaStyles->getByName( sStyleName ),
UNO_QUERY ); if ( !xPropState.is() )
{ // error case returnfalse;
}
if ( xPropState->getPropertyState( sNumberingStyleName ) == PropertyState_DIRECT_VALUE )
{ // list style found
bRet = true; // special case: the set list style equals the chapter numbering
Reference< XPropertySet > xPropSet( xPropState, UNO_QUERY ); if ( xPropSet.is() )
{
OUString sListStyle;
xPropSet->getPropertyValue( sNumberingStyleName ) >>= sListStyle; if ( !sListStyle.isEmpty() &&
sListStyle == sOutlineStyleName )
{
bRet = false;
}
}
} else
{ // Tools.Outline settings lost on Save (#i77708#)
sal_Int32 nUPD( 0 );
sal_Int32 nBuild( 0 ); // Don't use UPD for versioning: xmloff/source/text/txtstyli.cxx and txtimp.cxx (#i86058#) constbool bBuildIdFound = rImport.getBuildIds( nUPD, nBuild ); // search list style at parent
Reference<XStyle> xStyle( xPropState, UNO_QUERY ); while ( xStyle.is() )
{
OUString aParentStyle( xStyle->getParentStyle() ); if ( !aParentStyle.isEmpty() )
{
aParentStyle =
rImport.GetStyleDisplayName( XmlStyleFamily::TEXT_PARAGRAPH,
aParentStyle );
} if ( aParentStyle.isEmpty() || !xParaStyles->hasByName( aParentStyle ) )
{ // no list style found break;
} else
{
xPropState.set( xParaStyles->getByName( aParentStyle ),
UNO_QUERY ); if ( !xPropState.is() )
{ // error case returntrue;
} if ( xPropState->getPropertyState( sNumberingStyleName ) == PropertyState_DIRECT_VALUE )
{ // list style found
bRet = true; // Special case: the found list style equals the chapter numbering (#i73973#)
Reference< XPropertySet > xPropSet( xPropState, UNO_QUERY ); if ( xPropSet.is() )
{
OUString sListStyle;
xPropSet->getPropertyValue( sNumberingStyleName ) >>= sListStyle; if ( !sListStyle.isEmpty() &&
sListStyle == sOutlineStyleName )
{
bRet = false;
} // Special handling for text documents from OOo version prior OOo 2.4 (#i77708#) /* Check explicitly on certain versions and on import of text documents in OpenOffice.org file format (#i86058#)
*/ elseif ( sListStyle.isEmpty() &&
( rImport.IsTextDocInOOoFileFormat() ||
( bBuildIdFound &&
( ( nUPD == 641 ) || ( nUPD == 645 ) || // prior OOo 2.0
( nUPD == 680 && nBuild <= 9238 ) ) ) ) ) // OOo 2.0 - OOo 2.3.1
{
bRet = false;
}
} break;
} else
{ // search list style at parent
Reference<XStyle> xParentStyle(xPropState, UNO_QUERY); if (xStyle == xParentStyle)
{ // error case returntrue;
}
xStyle = std::move(xParentStyle);
}
}
}
}
/* The outline level needs to be only applied as list level, if the heading is not inside a list and if it by default applies the outline style. (#i70748#)
*/ bool bApplyOutlineLevelAsListLevel( false ); // Numberings/Bullets in table not visible after save/reload (#i80724#) if (bSetListAttrs && bPara
&& xPropSetInfo->hasPropertyByName( s_NumberingRules))
{ // Set numbering rules
Reference< XIndexReplace > const xNumRules(
xPropSet->getPropertyValue(s_NumberingRules), UNO_QUERY);
if (pListBlock || pNumberedParagraph)
{ if (!bApplyNumRules)
{ bool bSameNumRules = xNewNumRules == xNumRules; if( !bSameNumRules && xNewNumRules.is() && xNumRules.is() )
{ // If the interface pointers are different, then this does // not mean that the num rules are different. Further tests // are required then. However, if only one num rule is // set, no tests are required of course.
Reference< XNamed > xNewNamed( xNewNumRules, UNO_QUERY );
Reference< XNamed > xNamed( xNumRules, UNO_QUERY ); if( xNewNamed.is() && xNamed.is() )
{
bSameNumRules = xNewNamed->getName() == xNamed->getName();
} else
{
Reference< XAnyCompare > xNumRuleCompare( xNumRules, UNO_QUERY ); if( xNumRuleCompare.is() )
{
bSameNumRules = (xNumRuleCompare->compare( Any(xNumRules), Any(xNewNumRules) ) == 0);
}
}
}
bApplyNumRules = !bSameNumRules;
}
if ( bApplyNumRules )
{ // #102607# This may except when xNewNumRules contains // a Writer-NumRule-Implementation bug gets applied to // a shape. Since this may occur inside a document // (e.g. when edited), this must be handled // gracefully. try
{
xPropSet->setPropertyValue(
s_NumberingRules, Any(xNewNumRules) );
} catch(const Exception&)
{
; // I would really like to use a warning here, // but I can't access the XMLErrorHandler from // here.
}
}
if (!bNumberingIsNumber &&
xPropSetInfo->hasPropertyByName(s_NumberingIsNumber))
{
xPropSet->setPropertyValue(s_NumberingIsNumber, Any(false));
}
if (xPropSetInfo->hasPropertyByName(s_PropNameListId))
{ if (!sListId.isEmpty()) {
xPropSet->setPropertyValue(s_PropNameListId,
Any(sListId) );
}
}
GetTextListHelper().SetListItem( nullptr );
} else
{ /* If the paragraph is not in a list but its style, remove it from the list. Do not remove it, if the list of the style is the chapter numbering rule.
*/ if( xNumRules.is() )
{ bool bRemove( true ); // Special handling for document from OOo 2.x (#i70748#)
sal_Int32 nUPD( 0 );
sal_Int32 nBuild( 0 ); constbool bBuildIdFound = rImport.getBuildIds( nUPD, nBuild ); if ( ( bBuildIdFound && nUPD == 680 ) ||
!pStyle || !pStyle->IsListStyleSet() )
{ if (m_xImpl->m_xChapterNumbering.is())
{
Reference< XNamed > xNumNamed( xNumRules, UNO_QUERY );
Reference< XNamed > const xChapterNumNamed (
m_xImpl->m_xChapterNumbering, UNO_QUERY); if ( xNumNamed.is() && xChapterNumNamed.is() &&
xNumNamed->getName() == xChapterNumNamed->getName() )
{
bRemove = false; // RFE: inserting headings into text documents (#i70748#)
bApplyOutlineLevelAsListLevel = true;
}
}
} else
{
SAL_INFO_IF(!pStyle->GetListStyle().isEmpty(), "xmloff.text", "automatic paragraph style with list style name, but paragraph not in list???");
} if ( bRemove )
{
xPropSet->setPropertyValue( s_NumberingRules, Any() );
}
}
}
}
// combined characters special treatment if (!bPara && pStyle->HasCombinedCharactersLetter())
{ // insert combined characters text field if (m_xImpl->m_xServiceFactory.is())
{
uno::Reference<beans::XPropertySet> const xTmp(
m_xImpl->m_xServiceFactory->createInstance(
u"com.sun.star.text.TextField.CombinedCharacters"_ustr), UNO_QUERY); if( xTmp.is() )
{ // fix cursor if larger than possible for // combined characters field if (rCursor->getString().getLength() >
MAX_COMBINED_CHARACTERS)
{
rCursor->gotoRange(rCursor->getStart(), false);
rCursor->goRight(MAX_COMBINED_CHARACTERS, true);
}
// set field value (the combined character string)
xTmp->setPropertyValue(u"Content"_ustr,
Any(rCursor->getString()));
// insert the field over it's original text
Reference<XTextContent> xTextContent(xTmp, UNO_QUERY); if (m_xImpl->m_xText.is() && rCursor.is())
{ // #i107225# the combined characters need to be inserted first // the selected text has to be removed afterwards
m_xImpl->m_xText->insertTextContent( rCursor->getStart(), xTextContent, true );
if( !rCursor->getString().isEmpty() )
{ try
{
uno::Reference< text::XTextCursor > xCrsr = rCursor->getText()->createTextCursorByRange( rCursor->getStart() );
xCrsr->goLeft( 1, true );
uno::Reference< beans::XPropertySet> xCrsrProperties( xCrsr, uno::UNO_QUERY_THROW ); //the hard properties of the removed text need to be applied to the combined characters field
pStyle->FillPropertySet( xCrsrProperties );
xCrsr->collapseToEnd();
xCrsr->gotoRange( rCursor->getEnd(), true );
xCrsr->setString( OUString() );
} catch(const uno::Exception&)
{
}
}
}
}
}
}
}
// outline level; set after list style has been set // Complete re-worked and corrected: (#i53198#) // - set outline level at paragraph // - set numbering level at paragraph, if none is already set // - assure that style is marked as an outline style for the corresponding // outline level. // - DO NOT set type of numbering rule to outline. // - DO NOT set numbering rule directly at the paragraph.
// Some minor rework and adjust access to paragraph styles (#i70748#) if ( bPara )
{ // Headings not numbered anymore in 3.1 (#i103817#)
sal_Int16 nCurrentOutlineLevelInheritedFromParagraphStyle = 0; constbool bHasOutlineLevelProp(
xPropSetInfo->hasPropertyByName(s_OutlineLevel)); if ( bHasOutlineLevelProp )
{
xPropSet->getPropertyValue(s_OutlineLevel)
>>= nCurrentOutlineLevelInheritedFromParagraphStyle;
} if ( nOutlineLevel > 0 )
{ if ( bHasOutlineLevelProp )
{ // In case that the value equals the value of its paragraph style // attribute outline level, the paragraph attribute value is left unset if ( nCurrentOutlineLevelInheritedFromParagraphStyle != nOutlineLevel )
{
xPropSet->setPropertyValue( s_OutlineLevel,
Any( static_cast<sal_Int16>(nOutlineLevel) ) );
}
} if (!bOutlineContentVisible)
{
uno::Sequence<beans::PropertyValue> aGrabBag;
xPropSet->getPropertyValue(u"ParaInteropGrabBag"_ustr) >>= aGrabBag;
sal_Int32 length = aGrabBag.getLength();
aGrabBag.realloc(length + 1); auto pGrabBag = aGrabBag.getArray();
pGrabBag[length].Name = "OutlineContentVisibleAttr";
pGrabBag[length].Value <<= bool(bOutlineContentVisible);
xPropSet->setPropertyValue(u"ParaInteropGrabBag"_ustr, uno::Any(aGrabBag));
} // RFE: inserting headings into text documents (#i70748#) if ( bApplyOutlineLevelAsListLevel )
{
sal_Int16 nNumLevel = -1;
xPropSet->getPropertyValue( s_NumberingLevel ) >>= nNumLevel; if ( nNumLevel == -1 ||
nNumLevel != (nOutlineLevel - 1) )
{
xPropSet->setPropertyValue( s_NumberingLevel,
Any( static_cast<sal_Int8>(nOutlineLevel - 1) ) );
}
} /* Correction: (#i69629#) - for text document from version OOo 2.0.4/SO 8 PU4 and earlier the paragraph style of a heading should be assigned to the corresponding list level of the outline style. - for other text documents the paragraph style of a heading is only a candidate for an assignment to the list level of the outline style, if it has no direct list style property and (if exists) the automatic paragraph style has also no direct list style set.
*/ if (m_xImpl->m_xParaStyles.is() && m_xImpl->m_xParaStyles->hasByName(sStyleName))
{ bool bOutlineStyleCandidate( false );
sal_Int32 nUPD( 0 );
sal_Int32 nBuild( 0 ); constbool bBuildIdFound = rImport.getBuildIds( nUPD, nBuild ); // Lost outline numbering in master document (#i73509#) // Check explicitly on certain versions (#i86058#) if ( rImport.IsTextDocInOOoFileFormat() ||
( bBuildIdFound &&
( nUPD == 645 || nUPD == 641 ) ) )
{
bOutlineStyleCandidate = true;
} elseif ( nUPD == 680 && nBuild <= 9073 ) /* BuildId of OOo 2.0.4/SO8 PU4 */
{
bOutlineStyleCandidate = bOutlineLevelAttrFound;
} if ( bOutlineStyleCandidate )
{
AddOutlineStyleCandidate( nOutlineLevel, sStyleName );
} // Assure that heading applies the outline style (#i103817#) if ( ( !pStyle || !pStyle->IsListStyleSet() ) &&
!bOutlineStyleCandidate &&
m_xImpl->m_xChapterNumbering.is())
{ if ( !lcl_HasListStyle( sStyleName,
m_xImpl->m_xParaStyles, GetXMLImport(),
u"NumberingStyleName"_ustr,
u"" ) )
{ // heading not in a list --> apply outline style
xPropSet->setPropertyValue( s_NumberingRules,
Any(m_xImpl->m_xChapterNumbering) );
xPropSet->setPropertyValue( s_NumberingLevel,
Any(static_cast<sal_Int8>(nOutlineLevel - 1)));
}
}
}
} //handle for text:p,if the paragraphstyle outlinelevel is set to[1~10] elseif( bHasOutlineLevelProp )
{ if ( nCurrentOutlineLevelInheritedFromParagraphStyle != 0 )
{
xPropSet->setPropertyValue(s_OutlineLevel,
Any( sal_Int16(0) ));
}
}
}
// Empty? Then we need o do stuff. Let's do error checking first. if (m_xImpl->m_xChapterNumbering.is() &&
( nOutlineLevel > 0 ) &&
(nOutlineLevel <= m_xImpl->m_xChapterNumbering->getCount()))
{
nOutlineLevel--; // for the remainder, the level's are 0-based
// empty style name: look-up previously used name
// if we don't have a previously used name, we'll use the default
m_xImpl->InitOutlineStylesCandidates(); if (m_xImpl->m_xOutlineStylesCandidates[nOutlineLevel].empty())
{ // no other name used previously? Then use default
// iterate over property value sequence to find the style name
Sequence<PropertyValue> aProperties;
m_xImpl->m_xChapterNumbering->getByIndex( nOutlineLevel )
>>= aProperties; auto pProp = std::find_if(std::cbegin(aProperties), std::cend(aProperties),
[](const PropertyValue& rProp) { return rProp.Name == "HeadingStyleName"; }); if (pProp != std::cend(aProperties))
{
OUString aOutlineStyle;
pProp->Value >>= aOutlineStyle;
m_xImpl->m_xOutlineStylesCandidates[nOutlineLevel]
.push_back( aOutlineStyle );
}
}
// finally, we'll use the previously used style name for this // format (or the default we've just put into that style) // take last added one (#i71249#)
rStyleName =
m_xImpl->m_xOutlineStylesCandidates[nOutlineLevel].back();
} // else: nothing we can do, so we'll leave it empty // else: we already had a style name, so we let it pass.
}
const sal_Int32 nCount = m_xImpl->m_xChapterNumbering->getCount(); /* First collect all paragraph styles chosen for assignment to each list level of the outline style, then perform the intrinsic assignment. Reason: The assignment of a certain paragraph style to a list level of the outline style causes side effects on the children paragraph styles in Writer. (#i106218#)
*/
::std::vector<OUString> sChosenStyles(nCount); for( sal_Int32 i=0; i < nCount; ++i )
{ if ( bSetEmptyLevels ||
(m_xImpl->m_xOutlineStylesCandidates &&
!m_xImpl->m_xOutlineStylesCandidates[i].empty()))
{ // determine, which candidate is one to be assigned to the list // level of the outline style if (m_xImpl->m_xOutlineStylesCandidates &&
!m_xImpl->m_xOutlineStylesCandidates[i].empty())
{ if ( bChooseLastOne )
{
sChosenStyles[i] =
m_xImpl->m_xOutlineStylesCandidates[i].back();
} else
{ for (size_t j = 0;
j < m_xImpl->m_xOutlineStylesCandidates[i].size();
++j)
{ if (!lcl_HasListStyle(
m_xImpl->m_xOutlineStylesCandidates[i][j],
m_xImpl->m_xParaStyles,
GetXMLImport(),
u"NumberingStyleName"_ustr,
sOutlineStyleName))
{
sChosenStyles[i] =
m_xImpl->m_xOutlineStylesCandidates[i][j]; break;
}
}
}
}
}
} // Trashed outline numbering in ODF 1.1 text document created by OOo 3.x (#i106218#)
Sequence < PropertyValue > aProps( 1 );
PropertyValue *pProps = aProps.getArray();
pProps->Name = "HeadingStyleName"; for ( sal_Int32 i = 0; i < nCount; ++i )
{ // Paragraph style assignments in Outline of template lost from second level on (#i107610#) if ( bSetEmptyLevels || !sChosenStyles[i].isEmpty() )
{
pProps->Value <<= sChosenStyles[i];
m_xImpl->m_xChapterNumbering->replaceByIndex(i,
Any( aProps ));
}
}
if (xPropSetInfo->hasPropertyByName(s_HyperLinkName))
{
xPropSet->setPropertyValue(s_HyperLinkName, Any(rName));
}
if (xPropSetInfo->hasPropertyByName(s_HyperLinkTarget))
{
xPropSet->setPropertyValue(s_HyperLinkTarget,
Any(rTargetFrameName));
}
if ( (pEvents != nullptr) &&
xPropSetInfo->hasPropertyByName(s_HyperLinkEvents))
{ // The API treats events at hyperlinks differently from most // other properties: You have to set a name replace with the // events in it. The easiest way to do this is to 1) get // events, 2) set new ones, and 3) then put events back.
uno::Reference<XNameReplace> const xReplace(
xPropSet->getPropertyValue(s_HyperLinkEvents), UNO_QUERY); if (xReplace.is())
{ // set events
pEvents->SetEvents(xReplace);
// put events
xPropSet->setPropertyValue(s_HyperLinkEvents, Any(xReplace));
}
}
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.