office-gobmx/editeng/source/uno/unofored.cxx
Armin Le Grand (allotropia) d053413402 ITEM: Remove InvalidateAllItems()
I checked if this is used, but it can be replaced
using Clear() -> all. This prevents that the whole
array of Items in an ItemSet gets set to
INVALID_POOL_ITEM.

I also checked if INVALID_POOL_ITEM/IsInvalidItem
is needed at all representing SfxItemState::DONTCARE
but it is and still will need to be set for individual
Items.

At last checked if SfxItemState::UNKNOWN and
::DISABLED really need to be separate states, but
indeed there are some rare cases that need that.

To make things more consistent I also renamed
SfxItemState::DONTCARE to SfxItemState::INVALID
to better match Set/IsInvalid calls at ItemSet.

The build showed a missing UT and led to a problem
due to the hand-made ItemSet-like SearchAttrItemList.
The state 'invalid' seems to be used as 'unused'
marker. It should be changed to use SfxPoolItemHolder
and not need that. For now, set by using an own loop
to set to that state.

Change-Id: Ifc51aad60570569a1e37d3084a5e307eed47d06c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165035
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
2024-03-21 21:39:57 +01:00

520 lines
16 KiB
C++

/* -*- 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 <osl/diagnose.h>
#include <tools/debug.hxx>
#include <editeng/eeitem.hxx>
#include <com/sun/star/i18n/WordType.hpp>
#include <svl/itemset.hxx>
#include <editeng/editeng.hxx>
#include <editeng/unoedhlp.hxx>
#include <editeng/editdata.hxx>
#include <editeng/outliner.hxx>
#include <editeng/editobj.hxx>
#include <editeng/unofored.hxx>
#include "unofored_internal.hxx"
using namespace ::com::sun::star;
SvxEditEngineForwarder::SvxEditEngineForwarder( EditEngine& rEngine ) :
rEditEngine( rEngine )
{
}
SvxEditEngineForwarder::~SvxEditEngineForwarder()
{
// the EditEngine may need to be deleted from the outside
}
sal_Int32 SvxEditEngineForwarder::GetParagraphCount() const
{
return rEditEngine.GetParagraphCount();
}
sal_Int32 SvxEditEngineForwarder::GetTextLen( sal_Int32 nParagraph ) const
{
return rEditEngine.GetTextLen( nParagraph );
}
OUString SvxEditEngineForwarder::GetText( const ESelection& rSel ) const
{
return convertLineEnd(rEditEngine.GetText(rSel), GetSystemLineEnd());
}
SfxItemSet SvxEditEngineForwarder::GetAttribs( const ESelection& rSel, EditEngineAttribs nOnlyHardAttrib ) const
{
if( rSel.nStartPara == rSel.nEndPara )
{
GetAttribsFlags nFlags = GetAttribsFlags::NONE;
switch( nOnlyHardAttrib )
{
case EditEngineAttribs::All:
nFlags = GetAttribsFlags::ALL;
break;
case EditEngineAttribs::OnlyHard:
nFlags = GetAttribsFlags::CHARATTRIBS;
break;
default:
OSL_FAIL("unknown flags for SvxOutlinerForwarder::GetAttribs");
}
return rEditEngine.GetAttribs( rSel.nStartPara, rSel.nStartPos, rSel.nEndPos, nFlags );
}
else
{
return rEditEngine.GetAttribs( rSel, nOnlyHardAttrib );
}
}
SfxItemSet SvxEditEngineForwarder::GetParaAttribs( sal_Int32 nPara ) const
{
SfxItemSet aSet( rEditEngine.GetParaAttribs( nPara ) );
sal_uInt16 nWhich = EE_PARA_START;
while( nWhich <= EE_PARA_END )
{
if( aSet.GetItemState( nWhich ) != SfxItemState::SET )
{
if( rEditEngine.HasParaAttrib( nPara, nWhich ) )
aSet.Put( rEditEngine.GetParaAttrib( nPara, nWhich ) );
}
nWhich++;
}
return aSet;
}
void SvxEditEngineForwarder::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet )
{
rEditEngine.SetParaAttribs( nPara, rSet );
}
void SvxEditEngineForwarder::RemoveAttribs( const ESelection& rSelection )
{
rEditEngine.RemoveAttribs( rSelection, false/*bRemoveParaAttribs*/, 0 );
}
SfxItemPool* SvxEditEngineForwarder::GetPool() const
{
return rEditEngine.GetEmptyItemSet().GetPool();
}
void SvxEditEngineForwarder::GetPortions( sal_Int32 nPara, std::vector<sal_Int32>& rList ) const
{
rEditEngine.GetPortions( nPara, rList );
}
OUString SvxEditEngineForwarder::GetStyleSheet(sal_Int32 nPara) const
{
if (auto pStyle = rEditEngine.GetStyleSheet(nPara))
return pStyle->GetName();
return OUString();
}
void SvxEditEngineForwarder::SetStyleSheet(sal_Int32 nPara, const OUString& rStyleName)
{
auto pStyleSheetPool = rEditEngine.GetStyleSheetPool();
if (auto pStyle = pStyleSheetPool ? pStyleSheetPool->Find(rStyleName, SfxStyleFamily::Para) : nullptr)
rEditEngine.SetStyleSheet(nPara, static_cast<SfxStyleSheet*>(pStyle));
}
void SvxEditEngineForwarder::QuickInsertText( const OUString& rText, const ESelection& rSel )
{
rEditEngine.QuickInsertText( rText, rSel );
}
void SvxEditEngineForwarder::QuickInsertLineBreak( const ESelection& rSel )
{
rEditEngine.QuickInsertLineBreak( rSel );
}
void SvxEditEngineForwarder::QuickInsertField( const SvxFieldItem& rFld, const ESelection& rSel )
{
rEditEngine.QuickInsertField( rFld, rSel );
}
void SvxEditEngineForwarder::QuickSetAttribs( const SfxItemSet& rSet, const ESelection& rSel )
{
rEditEngine.QuickSetAttribs( rSet, rSel );
}
bool SvxEditEngineForwarder::IsValid() const
{
// cannot reliably query EditEngine state
// while in the middle of an update
return rEditEngine.IsUpdateLayout();
}
OUString SvxEditEngineForwarder::CalcFieldValue( const SvxFieldItem& rField, sal_Int32 nPara, sal_Int32 nPos, std::optional<Color>& rpTxtColor, std::optional<Color>& rpFldColor, std::optional<FontLineStyle>& rpFldLineStyle )
{
return rEditEngine.CalcFieldValue( rField, nPara, nPos, rpTxtColor, rpFldColor, rpFldLineStyle );
}
void SvxEditEngineForwarder::FieldClicked( const SvxFieldItem& rField )
{
rEditEngine.FieldClicked( rField );
}
SfxItemState GetSvxEditEngineItemState( EditEngine const & rEditEngine, const ESelection& rSel, sal_uInt16 nWhich )
{
std::vector<EECharAttrib> aAttribs;
const SfxPoolItem* pLastItem = nullptr;
SfxItemState eState = SfxItemState::DEFAULT;
// check all paragraphs inside the selection
for( sal_Int32 nPara = rSel.nStartPara; nPara <= rSel.nEndPara; nPara++ )
{
SfxItemState eParaState = SfxItemState::DEFAULT;
// calculate start and endpos for this paragraph
sal_Int32 nPos = 0;
if( rSel.nStartPara == nPara )
nPos = rSel.nStartPos;
sal_Int32 nEndPos = rSel.nEndPos;
if( rSel.nEndPara != nPara )
nEndPos = rEditEngine.GetTextLen( nPara );
// get list of char attribs
rEditEngine.GetCharAttribs( nPara, aAttribs );
bool bEmpty = true; // we found no item inside the selection of this paragraph
bool bGaps = false; // we found items but there are gaps between them
sal_Int32 nLastEnd = nPos;
const SfxPoolItem* pParaItem = nullptr;
for (auto const& attrib : aAttribs)
{
DBG_ASSERT(attrib.pAttr, "GetCharAttribs gives corrupt data");
const bool bEmptyPortion = attrib.nStart == attrib.nEnd;
if((!bEmptyPortion && attrib.nStart >= nEndPos) ||
(bEmptyPortion && attrib.nStart > nEndPos))
break; // break if we are already behind our selection
if((!bEmptyPortion && attrib.nEnd <= nPos) ||
(bEmptyPortion && attrib.nEnd < nPos))
continue; // or if the attribute ends before our selection
if(attrib.pAttr->Which() != nWhich)
continue; // skip if is not the searched item
// if we already found an item
if( pParaItem )
{
// ... and its different to this one than the state is don't care
if(*pParaItem != *(attrib.pAttr))
return SfxItemState::INVALID;
}
else
pParaItem = attrib.pAttr;
if( bEmpty )
bEmpty = false;
if(!bGaps && attrib.nStart > nLastEnd)
bGaps = true;
nLastEnd = attrib.nEnd;
}
if( !bEmpty && !bGaps && nLastEnd < ( nEndPos - 1 ) )
bGaps = true;
if( bEmpty )
eParaState = SfxItemState::DEFAULT;
else if( bGaps )
eParaState = SfxItemState::INVALID;
else
eParaState = SfxItemState::SET;
// if we already found an item check if we found the same
if( pLastItem )
{
if( (pParaItem == nullptr) || (*pLastItem != *pParaItem) )
return SfxItemState::INVALID;
}
else
{
pLastItem = pParaItem;
eState = eParaState;
}
}
return eState;
}
SfxItemState SvxEditEngineForwarder::GetItemState( const ESelection& rSel, sal_uInt16 nWhich ) const
{
return GetSvxEditEngineItemState( rEditEngine, rSel, nWhich );
}
SfxItemState SvxEditEngineForwarder::GetItemState( sal_Int32 nPara, sal_uInt16 nWhich ) const
{
const SfxItemSet& rSet = rEditEngine.GetParaAttribs( nPara );
return rSet.GetItemState( nWhich );
}
LanguageType SvxEditEngineForwarder::GetLanguage( sal_Int32 nPara, sal_Int32 nIndex ) const
{
return rEditEngine.GetLanguage(nPara, nIndex).nLang;
}
sal_Int32 SvxEditEngineForwarder::GetFieldCount( sal_Int32 nPara ) const
{
return rEditEngine.GetFieldCount(nPara);
}
EFieldInfo SvxEditEngineForwarder::GetFieldInfo( sal_Int32 nPara, sal_uInt16 nField ) const
{
return rEditEngine.GetFieldInfo( nPara, nField );
}
EBulletInfo SvxEditEngineForwarder::GetBulletInfo( sal_Int32 ) const
{
return EBulletInfo();
}
tools::Rectangle SvxEditEngineForwarder::GetCharBounds( sal_Int32 nPara, sal_Int32 nIndex ) const
{
// EditEngine's 'internal' methods like GetCharacterBounds()
// don't rotate for vertical text.
Size aSize( rEditEngine.CalcTextWidth(), rEditEngine.GetTextHeight() );
// swap width and height
tools::Long tmp = aSize.Width();
aSize.setWidth(aSize.Height());
aSize.setHeight(tmp);
bool bIsVertical( rEditEngine.IsEffectivelyVertical() );
// #108900# Handle virtual position one-past-the end of the string
if( nIndex >= rEditEngine.GetTextLen(nPara) )
{
tools::Rectangle aLast;
if( nIndex )
{
// use last character, if possible
aLast = rEditEngine.GetCharacterBounds( EPosition(nPara, nIndex-1) );
// move at end of this last character, make one pixel wide
aLast.Move( aLast.Right() - aLast.Left(), 0 );
aLast.SetSize( Size(1, aLast.GetHeight()) );
// take care for CTL
aLast = SvxEditSourceHelper::EEToUserSpace( aLast, aSize, bIsVertical );
}
else
{
// #109864# Bounds must lie within the paragraph
aLast = GetParaBounds( nPara );
// #109151# Don't use paragraph height, but line height
// instead. aLast is already CTL-correct
if( bIsVertical)
aLast.SetSize( Size( rEditEngine.GetLineHeight(nPara), 1 ) );
else
aLast.SetSize( Size( 1, rEditEngine.GetLineHeight(nPara) ) );
}
return aLast;
}
else
{
return SvxEditSourceHelper::EEToUserSpace( rEditEngine.GetCharacterBounds( EPosition(nPara, nIndex) ),
aSize, bIsVertical );
}
}
tools::Rectangle SvxEditEngineForwarder::GetParaBounds( sal_Int32 nPara ) const
{
const Point aPnt = rEditEngine.GetDocPosTopLeft( nPara );
sal_uInt32 nWidth;
sal_uInt32 nHeight;
if( rEditEngine.IsEffectivelyVertical() )
{
// Hargl. EditEngine's 'external' methods return the rotated
// dimensions, 'internal' methods like GetTextHeight( n )
// don't rotate.
nWidth = rEditEngine.GetTextHeight( nPara );
nHeight = rEditEngine.GetTextHeight();
sal_uInt32 nTextWidth = rEditEngine.GetTextHeight();
return tools::Rectangle( nTextWidth - aPnt.Y() - nWidth, 0, nTextWidth - aPnt.Y(), nHeight );
}
else
{
nWidth = rEditEngine.CalcTextWidth();
nHeight = rEditEngine.GetTextHeight( nPara );
return tools::Rectangle( 0, aPnt.Y(), nWidth, aPnt.Y() + nHeight );
}
}
MapMode SvxEditEngineForwarder::GetMapMode() const
{
return rEditEngine.GetRefMapMode();
}
OutputDevice* SvxEditEngineForwarder::GetRefDevice() const
{
return rEditEngine.GetRefDevice();
}
bool SvxEditEngineForwarder::GetIndexAtPoint( const Point& rPos, sal_Int32& nPara, sal_Int32& nIndex ) const
{
Size aSize( rEditEngine.CalcTextWidth(), rEditEngine.GetTextHeight() );
// swap width and height
tools::Long tmp = aSize.Width();
aSize.setWidth(aSize.Height());
aSize.setHeight(tmp);
Point aEEPos( SvxEditSourceHelper::UserSpaceToEE( rPos,
aSize,
rEditEngine.IsEffectivelyVertical() ));
EPosition aDocPos = rEditEngine.FindDocPosition( aEEPos );
nPara = aDocPos.nPara;
nIndex = aDocPos.nIndex;
return true;
}
bool SvxEditEngineForwarder::GetWordIndices( sal_Int32 nPara, sal_Int32 nIndex, sal_Int32& nStart, sal_Int32& nEnd ) const
{
ESelection aRes = rEditEngine.GetWord( ESelection(nPara, nIndex, nPara, nIndex), css::i18n::WordType::DICTIONARY_WORD );
if( aRes.nStartPara == nPara &&
aRes.nStartPara == aRes.nEndPara )
{
nStart = aRes.nStartPos;
nEnd = aRes.nEndPos;
return true;
}
return false;
}
bool SvxEditEngineForwarder::GetAttributeRun( sal_Int32& nStartIndex, sal_Int32& nEndIndex, sal_Int32 nPara, sal_Int32 nIndex, bool bInCell ) const
{
SvxEditSourceHelper::GetAttributeRun( nStartIndex, nEndIndex, rEditEngine, nPara, nIndex, bInCell );
return true;
}
sal_Int32 SvxEditEngineForwarder::GetLineCount( sal_Int32 nPara ) const
{
return rEditEngine.GetLineCount(nPara);
}
sal_Int32 SvxEditEngineForwarder::GetLineLen( sal_Int32 nPara, sal_Int32 nLine ) const
{
return rEditEngine.GetLineLen(nPara, nLine);
}
void SvxEditEngineForwarder::GetLineBoundaries( /*out*/sal_Int32 &rStart, /*out*/sal_Int32 &rEnd, sal_Int32 nPara, sal_Int32 nLine ) const
{
rEditEngine.GetLineBoundaries(rStart, rEnd, nPara, nLine);
}
sal_Int32 SvxEditEngineForwarder::GetLineNumberAtIndex( sal_Int32 nPara, sal_Int32 nIndex ) const
{
return rEditEngine.GetLineNumberAtIndex(nPara, nIndex);
}
bool SvxEditEngineForwarder::QuickFormatDoc( bool )
{
rEditEngine.QuickFormatDoc();
return true;
}
bool SvxEditEngineForwarder::Delete( const ESelection& rSelection )
{
rEditEngine.QuickDelete( rSelection );
rEditEngine.QuickFormatDoc();
return true;
}
bool SvxEditEngineForwarder::InsertText( const OUString& rStr, const ESelection& rSelection )
{
rEditEngine.QuickInsertText( rStr, rSelection );
rEditEngine.QuickFormatDoc();
return true;
}
sal_Int16 SvxEditEngineForwarder::GetDepth( sal_Int32 ) const
{
// EditEngine does not support outline depth
return -1;
}
bool SvxEditEngineForwarder::SetDepth( sal_Int32, sal_Int16 nNewDepth )
{
// EditEngine does not support outline depth
return nNewDepth == -1;
}
const SfxItemSet * SvxEditEngineForwarder::GetEmptyItemSetPtr()
{
return &rEditEngine.GetEmptyItemSet();
}
void SvxEditEngineForwarder::AppendParagraph()
{
rEditEngine.InsertParagraph( rEditEngine.GetParagraphCount(), OUString() );
}
sal_Int32 SvxEditEngineForwarder::AppendTextPortion( sal_Int32 nPara, const OUString &rText, const SfxItemSet & /*rSet*/ )
{
sal_Int32 nLen = 0;
sal_Int32 nParaCount = rEditEngine.GetParagraphCount();
DBG_ASSERT( nPara < nParaCount, "paragraph index out of bounds" );
if (0 <= nPara && nPara < nParaCount)
{
nLen = rEditEngine.GetTextLen( nPara );
rEditEngine.QuickInsertText( rText, ESelection( nPara, nLen, nPara, nLen ) );
}
return nLen;
}
void SvxEditEngineForwarder::CopyText(const SvxTextForwarder& rSource)
{
const SvxEditEngineForwarder* pSourceForwarder = dynamic_cast< const SvxEditEngineForwarder* >( &rSource );
if( !pSourceForwarder )
return;
std::unique_ptr<EditTextObject> pNewTextObject = pSourceForwarder->rEditEngine.CreateTextObject();
rEditEngine.SetText( *pNewTextObject );
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */