diff options
Diffstat (limited to 'editeng/source/editeng')
28 files changed, 6795 insertions, 6277 deletions
diff --git a/editeng/source/editeng/ContentNode.cxx b/editeng/source/editeng/ContentNode.cxx new file mode 100644 index 000000000000..08bf250b6c86 --- /dev/null +++ b/editeng/source/editeng/ContentNode.cxx @@ -0,0 +1,1029 @@ +/* -*- 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 <ContentNode.hxx> +#include <editeng/tstpitem.hxx> +#include "impedit.hxx" + +#include <rtl/ustrbuf.hxx> +#include <osl/diagnose.h> +#include <libxml/xmlwriter.h> + +#include <memory> +#include <set> + +ContentNode::ContentNode( SfxItemPool& rPool ) + : maContentAttribs( rPool ) +{ +} + +ContentNode::ContentNode( const OUString& rStr, const ContentAttribs& rContentAttribs ) + : maString(rStr) + , maContentAttribs(rContentAttribs) +{ +} + +void ContentNode::ExpandAttribs( sal_Int32 nIndex, sal_Int32 nNew ) +{ + if ( !nNew ) + return; + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(maCharAttribList); +#endif + + // Since features are treated differently than normal character attributes, + // but can also affect the order of the start list. // In every if ..., in the next (n) opportunities due to bFeature or + // an existing special case, must (n-1) opportunities be provided with + // bResort. The most likely possibility receives no bResort, so that is + // not sorted anew when all attributes are the same. + bool bResort = false; + bool bExpandedEmptyAtIndexNull = false; + + std::size_t nAttr = 0; + CharAttribList::AttribsType& rAttribs = maCharAttribList.GetAttribs(); + EditCharAttrib* pAttrib = GetAttrib(rAttribs, nAttr); + while ( pAttrib ) + { + if ( pAttrib->GetEnd() >= nIndex ) + { + // Move all attributes behind the insertion point... + if ( pAttrib->GetStart() > nIndex ) + { + pAttrib->MoveForward( nNew ); + } + // 0: Expand empty attribute, if at insertion point + else if ( pAttrib->IsEmpty() ) + { + // Do not check Index, an empty one could only be there + // When later checking it anyhow: + // Special case: Start == 0; AbsLen == 1, nNew = 1 + // => Expand, because of paragraph break! + // Start <= nIndex, End >= nIndex => Start=End=nIndex! +// if ( pAttrib->GetStart() == nIndex ) + pAttrib->Expand( nNew ); + bResort = true; + if ( pAttrib->GetStart() == 0 ) + bExpandedEmptyAtIndexNull = true; + } + // 1: Attribute starts before, goes to index ... + else if ( pAttrib->GetEnd() == nIndex ) // Start must be before + { + // Only expand when there is no feature + // and if not in exclude list! + // Otherwise, a UL will go on until a new ULDB, expanding both +// if ( !pAttrib->IsFeature() && !rExclList.FindAttrib( pAttrib->Which() ) ) + if ( !pAttrib->IsFeature() && !maCharAttribList.FindEmptyAttrib( pAttrib->Which(), nIndex ) ) + { + if ( !pAttrib->IsEdge() ) + pAttrib->Expand( nNew ); + } + else + bResort = true; + } + // 2: Attribute starts before, goes past the Index... + else if ( ( pAttrib->GetStart() < nIndex ) && ( pAttrib->GetEnd() > nIndex ) ) + { + DBG_ASSERT( !pAttrib->IsFeature(), "Large Feature?!" ); + pAttrib->Expand( nNew ); + } + // 3: Attribute starts on index... + else if ( pAttrib->GetStart() == nIndex ) + { + if ( pAttrib->IsFeature() ) + { + pAttrib->MoveForward( nNew ); + bResort = true; + } + else + { + bool bExpand = false; + if ( nIndex == 0 ) + { + bExpand = true; + if( bExpandedEmptyAtIndexNull ) + { + // Check if this kind of attribute was empty and expanded here... + sal_uInt16 nW = pAttrib->GetItem()->Which(); + for ( std::size_t nA = 0; nA < nAttr; nA++ ) + { + const EditCharAttrib& r = *maCharAttribList.GetAttribs()[nA]; + if ( ( r.GetStart() == 0 ) && ( r.GetItem()->Which() == nW ) ) + { + bExpand = false; + break; + } + } + + } + } + if ( bExpand ) + { + pAttrib->Expand( nNew ); + bResort = true; + } + else + { + pAttrib->MoveForward( nNew ); + } + } + } + } + + if ( pAttrib->IsEdge() ) + pAttrib->SetEdge(false); + + DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" ); + + DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Expand: Attribute distorted!" ); + DBG_ASSERT( ( pAttrib->GetEnd() <= Len() ), "Expand: Attribute larger than paragraph!" ); + if ( pAttrib->IsEmpty() ) + { + OSL_FAIL( "Empty Attribute after ExpandAttribs?" ); + bResort = true; + rAttribs.erase(rAttribs.begin()+nAttr); + } + else + { + ++nAttr; + } + pAttrib = GetAttrib(rAttribs, nAttr); + } + + if ( bResort ) + maCharAttribList.ResortAttribs(); + + if (mpWrongList) + { + bool bSep = ( maString[ nIndex ] == ' ' ) || IsFeature( nIndex ); + mpWrongList->TextInserted( nIndex, nNew, bSep ); + } + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(maCharAttribList); +#endif +} + +void ContentNode::CollapseAttribs( sal_Int32 nIndex, sal_Int32 nDeleted ) +{ + if ( !nDeleted ) + return; + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(maCharAttribList); +#endif + + // Since features are treated differently than normal character attributes, + // but can also affect the order of the start list + bool bResort = false; + sal_Int32 nEndChanges = nIndex+nDeleted; + + std::size_t nAttr = 0; + CharAttribList::AttribsType& rAttribs = maCharAttribList.GetAttribs(); + EditCharAttrib* pAttrib = GetAttrib(rAttribs, nAttr); + while ( pAttrib ) + { + bool bDelAttr = false; + if ( pAttrib->GetEnd() >= nIndex ) + { + // Move all Attribute behind the insert point... + if ( pAttrib->GetStart() >= nEndChanges ) + { + pAttrib->MoveBackward( nDeleted ); + } + // 1. Delete Internal attributes... + else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() <= nEndChanges ) ) + { + // Special case: Attribute covers the area exactly + // => keep as empty Attribute. + if ( !pAttrib->IsFeature() && ( pAttrib->GetStart() == nIndex ) && ( pAttrib->GetEnd() == nEndChanges ) ) + { + pAttrib->GetEnd() = nIndex; // empty + bResort = true; + } + else + bDelAttr = true; + } + // 2. Attribute starts earlier, ends inside or behind it ... + else if ( ( pAttrib->GetStart() <= nIndex ) && ( pAttrib->GetEnd() > nIndex ) ) + { + DBG_ASSERT( !pAttrib->IsFeature(), "Collapsing Feature!" ); + if ( pAttrib->GetEnd() <= nEndChanges ) // ends inside + pAttrib->GetEnd() = nIndex; + else + pAttrib->Collaps( nDeleted ); // ends behind + } + // 3. Attribute starts inside, ending behind ... + else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() > nEndChanges ) ) + { + // Features not allowed to expand! + if ( pAttrib->IsFeature() ) + { + pAttrib->MoveBackward( nDeleted ); + bResort = true; + } + else + { + pAttrib->GetStart() = nEndChanges; + pAttrib->MoveBackward( nDeleted ); + } + } + } + DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" ); + + DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Collapse: Attribute distorted!" ); + DBG_ASSERT( ( pAttrib->GetEnd() <= Len()) || bDelAttr, "Collapse: Attribute larger than paragraph!" ); + if ( bDelAttr ) + { + bResort = true; + rAttribs.erase(rAttribs.begin()+nAttr); + } + else + { + if ( pAttrib->IsEmpty() ) + maCharAttribList.SetHasEmptyAttribs(true); + nAttr++; + } + + pAttrib = GetAttrib(rAttribs, nAttr); + } + + if ( bResort ) + maCharAttribList.ResortAttribs(); + + if (mpWrongList) + mpWrongList->TextDeleted(nIndex, nDeleted); + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(maCharAttribList); +#endif +} + +void ContentNode::CopyAndCutAttribs( ContentNode* pPrevNode, SfxItemPool& rPool, bool bKeepEndingAttribs ) +{ + assert(pPrevNode); + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(maCharAttribList); + CharAttribList::DbgCheckAttribs(pPrevNode->maCharAttribList); +#endif + + sal_Int32 nCut = pPrevNode->Len(); + + std::size_t nAttr = 0; + CharAttribList::AttribsType& rPrevAttribs = pPrevNode->GetCharAttribs().GetAttribs(); + EditCharAttrib* pAttrib = GetAttrib(rPrevAttribs, nAttr); + while ( pAttrib ) + { + if ( pAttrib->GetEnd() < nCut ) + { + // remain unchanged... + nAttr++; + } + else if ( pAttrib->GetEnd() == nCut ) + { + // must be copied as an empty attributes. + if ( bKeepEndingAttribs && !pAttrib->IsFeature() && !maCharAttribList.FindAttrib( pAttrib->GetItem()->Which(), 0 ) ) + { + EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, 0 ); + assert(pNewAttrib); + maCharAttribList.InsertAttrib( pNewAttrib ); + } + nAttr++; + } + else if ( pAttrib->IsInside( nCut ) || ( !nCut && !pAttrib->GetStart() && !pAttrib->IsFeature() ) ) + { + // If cut is done right at the front then the attribute must be + // kept! Has to be copied and changed. + EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, pAttrib->GetEnd()-nCut ); + assert(pNewAttrib); + maCharAttribList.InsertAttrib( pNewAttrib ); + pAttrib->GetEnd() = nCut; + nAttr++; + } + else + { + // Move all attributes in the current node (this) + CharAttribList::AttribsType::iterator it = rPrevAttribs.begin() + nAttr; + maCharAttribList.InsertAttrib(it->release()); + rPrevAttribs.erase(it); + pAttrib->MoveBackward( nCut ); + } + pAttrib = GetAttrib(rPrevAttribs, nAttr); + } + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(maCharAttribList); + CharAttribList::DbgCheckAttribs(pPrevNode->maCharAttribList); +#endif +} + +void ContentNode::AppendAttribs( ContentNode* pNextNode ) +{ + assert(pNextNode); + + sal_Int32 nNewStart = maString.getLength(); + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(maCharAttribList); + CharAttribList::DbgCheckAttribs(pNextNode->maCharAttribList); +#endif + + std::size_t nAttr = 0; + CharAttribList::AttribsType& rNextAttribs = pNextNode->GetCharAttribs().GetAttribs(); + EditCharAttrib* pAttrib = GetAttrib(rNextAttribs, nAttr); + while ( pAttrib ) + { + // Move all attributes in the current node (this) + bool bMelted = false; + if ( ( pAttrib->GetStart() == 0 ) && ( !pAttrib->IsFeature() ) ) + { + // Attributes can possibly be summarized as: + std::size_t nTmpAttr = 0; + EditCharAttrib* pTmpAttrib = GetAttrib( maCharAttribList.GetAttribs(), nTmpAttr ); + while ( !bMelted && pTmpAttrib ) + { + ++nTmpAttr; + if ( pTmpAttrib->GetEnd() == nNewStart ) + { + if (pTmpAttrib->Which() == pAttrib->Which()) + { + // prevent adding 2 0-length attributes at same position + if ((*(pTmpAttrib->GetItem()) == *(pAttrib->GetItem())) + || (0 == pAttrib->GetLen())) + { + pTmpAttrib->GetEnd() = + pTmpAttrib->GetEnd() + pAttrib->GetLen(); + rNextAttribs.erase(rNextAttribs.begin()+nAttr); + // Unsubscribe from the pool?! + bMelted = true; + } + else if (0 == pTmpAttrib->GetLen()) + { + --nTmpAttr; // to cancel earlier increment... + maCharAttribList.Remove(nTmpAttr); + } + } + } + pTmpAttrib = GetAttrib( maCharAttribList.GetAttribs(), nTmpAttr ); + } + } + + if ( !bMelted ) + { + pAttrib->GetStart() = pAttrib->GetStart() + nNewStart; + pAttrib->GetEnd() = pAttrib->GetEnd() + nNewStart; + CharAttribList::AttribsType::iterator it = rNextAttribs.begin() + nAttr; + maCharAttribList.InsertAttrib(it->release()); + rNextAttribs.erase(it); + } + pAttrib = GetAttrib(rNextAttribs, nAttr); + } + // For the Attributes that just moved over: + rNextAttribs.clear(); + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(maCharAttribList); + CharAttribList::DbgCheckAttribs(pNextNode->maCharAttribList); +#endif +} + +void ContentNode::CreateDefFont() +{ + // First use the information from the style ... + SfxStyleSheet* pS = maContentAttribs.GetStyleSheet(); + if ( pS ) + CreateFont( GetCharAttribs().GetDefFont(), pS->GetItemSet() ); + + // ... then iron out the hard paragraph formatting... + CreateFont( GetCharAttribs().GetDefFont(), + GetContentAttribs().GetItems(), pS == nullptr ); +} + +void ContentNode::SetStyleSheet( SfxStyleSheet* pS, const SvxFont& rFontFromStyle ) +{ + maContentAttribs.SetStyleSheet( pS ); + + + // First use the information from the style ... + GetCharAttribs().GetDefFont() = rFontFromStyle; + // ... then iron out the hard paragraph formatting... + CreateFont( GetCharAttribs().GetDefFont(), + GetContentAttribs().GetItems(), pS == nullptr ); +} + +void ContentNode::SetStyleSheet( SfxStyleSheet* pS, bool bRecalcFont ) +{ + maContentAttribs.SetStyleSheet( pS ); + if ( bRecalcFont ) + CreateDefFont(); +} + +bool ContentNode::IsFeature( sal_Int32 nPos ) const +{ + return maString[nPos] == CH_FEATURE; +} + +sal_Int32 ContentNode::Len() const +{ + return maString.getLength(); +} + +sal_Int32 ContentNode::GetExpandedLen() const +{ + sal_Int32 nLen = maString.getLength(); + + // Fields can be longer than the placeholder in the Node + const CharAttribList::AttribsType& rAttrs = GetCharAttribs().GetAttribs(); + for (sal_Int32 nAttr = rAttrs.size(); nAttr; ) + { + const EditCharAttrib& rAttr = *rAttrs[--nAttr]; + if (rAttr.Which() == EE_FEATURE_FIELD) + { + nLen += static_cast<const EditCharAttribField&>(rAttr).GetFieldValue().getLength(); + --nLen; // Standalone, to avoid corner cases when previous getLength() returns 0 + } + } + + return nLen; +} + +OUString ContentNode::GetExpandedText(sal_Int32 nStartPos, sal_Int32 nEndPos) const +{ + if ( nEndPos < 0 || nEndPos > Len() ) + nEndPos = Len(); + + DBG_ASSERT( nStartPos <= nEndPos, "Start and End reversed?" ); + + sal_Int32 nIndex = nStartPos; + OUStringBuffer aStr(256); + const EditCharAttrib* pNextFeature = GetCharAttribs().FindFeature( nIndex ); + while ( nIndex < nEndPos ) + { + sal_Int32 nEnd = nEndPos; + if ( pNextFeature && ( pNextFeature->GetStart() < nEnd ) ) + nEnd = pNextFeature->GetStart(); + else + pNextFeature = nullptr; // Feature does not interest the below + + DBG_ASSERT( nEnd >= nIndex, "End in front of the index?" ); + //!! beware of sub string length of -1 + if (nEnd > nIndex) + aStr.append( GetString().subView(nIndex, nEnd - nIndex) ); + + if ( pNextFeature ) + { + switch ( pNextFeature->GetItem()->Which() ) + { + case EE_FEATURE_TAB: aStr.append( "\t" ); + break; + case EE_FEATURE_LINEBR: aStr.append( "\x0A" ); + break; + case EE_FEATURE_FIELD: + aStr.append( static_cast<const EditCharAttribField*>(pNextFeature)->GetFieldValue() ); + break; + default: OSL_FAIL( "What feature?" ); + } + pNextFeature = GetCharAttribs().FindFeature( ++nEnd ); + } + nIndex = nEnd; + } + return aStr.makeStringAndClear(); +} + +void ContentNode::UnExpandPosition( sal_Int32 &rPos, bool bBiasStart ) +{ + sal_Int32 nOffset = 0; + + const CharAttribList::AttribsType& rAttrs = GetCharAttribs().GetAttribs(); + for (size_t nAttr = 0; nAttr < rAttrs.size(); ++nAttr ) + { + const EditCharAttrib& rAttr = *rAttrs[nAttr]; + assert (!(nAttr < rAttrs.size() - 1) || + rAttrs[nAttr]->GetStart() <= rAttrs[nAttr + 1]->GetStart()); + + nOffset = rAttr.GetStart(); + + if (nOffset >= rPos) // happens after the position + return; + + if (rAttr.Which() == EE_FEATURE_FIELD) + { + sal_Int32 nChunk = static_cast<const EditCharAttribField&>(rAttr).GetFieldValue().getLength(); + nChunk--; // Character representing the field in the string + + if (nOffset + nChunk >= rPos) // we're inside the field + { + if (bBiasStart) + rPos = rAttr.GetStart(); + else + rPos = rAttr.GetEnd(); + return; + } + // Adjust for the position + rPos -= nChunk; + } + } + assert (rPos <= Len()); +} + +/* + * Fields are represented by a single character in the underlying string + * and/or selection, however, they can be expanded to the full value of + * the field. When we're dealing with selection / offsets however we need + * to deal in character positions inside the real (unexpanded) string. + * This method maps us back to character offsets. + */ +void ContentNode::UnExpandPositions( sal_Int32 &rStartPos, sal_Int32 &rEndPos ) +{ + UnExpandPosition( rStartPos, true ); + UnExpandPosition( rEndPos, false ); +} + +void ContentNode::SetChar(sal_Int32 nPos, sal_Unicode c) +{ + maString = maString.replaceAt(nPos, 1, rtl::OUStringChar(c)); +} + +void ContentNode::Insert(std::u16string_view rStr, sal_Int32 nPos) +{ + maString = maString.replaceAt(nPos, 0, rStr); +} + +void ContentNode::Append(std::u16string_view rStr) +{ + maString += rStr; +} + +void ContentNode::Erase(sal_Int32 nPos) +{ + maString = maString.copy(0, nPos); +} + +void ContentNode::Erase(sal_Int32 nPos, sal_Int32 nCount) +{ + maString = maString.replaceAt(nPos, nCount, u""); +} + +OUString ContentNode::Copy(sal_Int32 nPos) const +{ + return maString.copy(nPos); +} + +OUString ContentNode::Copy(sal_Int32 nPos, sal_Int32 nCount) const +{ + return maString.copy(nPos, nCount); +} + +sal_Unicode ContentNode::GetChar(sal_Int32 nPos) const +{ + return maString[nPos]; +} + +void ContentNode::EnsureWrongList() +{ + if (!mpWrongList) + CreateWrongList(); +} + +WrongList* ContentNode::GetWrongList() +{ + return mpWrongList.get(); +} + +const WrongList* ContentNode::GetWrongList() const +{ + return mpWrongList.get(); +} + +void ContentNode::SetWrongList( WrongList* p ) +{ + mpWrongList.reset(p); +} + +void ContentNode::CreateWrongList() +{ + SAL_WARN_IF( mpWrongList && !mpWrongList->empty(), "editeng", "WrongList already exist!"); + if (!mpWrongList || !mpWrongList->empty()) + mpWrongList.reset(new WrongList); +} + +void ContentNode::DestroyWrongList() +{ + mpWrongList.reset(); +} + +void ContentNode::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + (void)xmlTextWriterStartElement(pWriter, BAD_CAST("ContentNode")); + (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("maString"), BAD_CAST(maString.toUtf8().getStr())); + maContentAttribs.dumpAsXml(pWriter); + maCharAttribList.dumpAsXml(pWriter); + (void)xmlTextWriterEndElement(pWriter); +} + +void ContentNode::checkAndDeleteEmptyAttribs() const +{ + // Delete empty attributes, but only if paragraph is not empty! + if (GetCharAttribs().HasEmptyAttribs() && Len()) + { + const_cast<ContentNode*>(this)->GetCharAttribs().DeleteEmptyAttribs(); + } +} + +ContentAttribs::ContentAttribs( SfxItemPool& rPool ) + : maAttribSet(rPool) +{ +} + +SvxTabStop ContentAttribs::FindTabStop( sal_Int32 nCurPos, sal_uInt16 nDefTab ) +{ + const SvxTabStopItem& rTabs = GetItem( EE_PARA_TABS ); + for ( sal_uInt16 i = 0; i < rTabs.Count(); i++ ) + { + const SvxTabStop& rTab = rTabs[i]; + if ( rTab.GetTabPos() > nCurPos ) + return rTab; + } + + // if there's a default tab size defined for this item use that instead + if (rTabs.GetDefaultDistance()) + nDefTab = rTabs.GetDefaultDistance(); + + // Determine DefTab ... + SvxTabStop aTabStop; + const sal_Int32 x = nCurPos / nDefTab + 1; + aTabStop.GetTabPos() = nDefTab * x; + return aTabStop; +} + +void ContentAttribs::SetStyleSheet( SfxStyleSheet* pS ) +{ + bool bStyleChanged = ( mpStyle != pS ); + mpStyle = pS; + // Only when other style sheet, not when current style sheet modified + if ( !(mpStyle && bStyleChanged) ) + return; + + // Selectively remove the attributes from the paragraph formatting + // which are specified in the style, so that the attributes of the + // style can have an affect. + const SfxItemSet& rStyleAttribs = mpStyle->GetItemSet(); + for ( sal_uInt16 nWhich = EE_PARA_START; nWhich <= EE_CHAR_END; nWhich++ ) + { + // Don't change bullet on/off + if ( ( nWhich != EE_PARA_BULLETSTATE ) && ( rStyleAttribs.GetItemState( nWhich ) == SfxItemState::SET ) ) + maAttribSet.ClearItem( nWhich ); + } +} + +const SfxPoolItem& ContentAttribs::GetItem( sal_uInt16 nWhich ) const +{ + // Hard paragraph attributes take precedence! + const SfxItemSet* pTakeFrom = &maAttribSet; + if ( mpStyle && ( maAttribSet.GetItemState( nWhich, false ) != SfxItemState::SET ) ) + pTakeFrom = &mpStyle->GetItemSet(); + + return pTakeFrom->Get( nWhich ); +} + +bool ContentAttribs::HasItem( sal_uInt16 nWhich ) const +{ + bool bHasItem = false; + if ( maAttribSet.GetItemState( nWhich, false ) == SfxItemState::SET ) + bHasItem = true; + else if ( mpStyle && mpStyle->GetItemSet().GetItemState( nWhich ) == SfxItemState::SET ) + bHasItem = true; + + return bHasItem; +} + +void ContentAttribs::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + (void)xmlTextWriterStartElement(pWriter, BAD_CAST("ContentAttribs")); + (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("style"), "%s", mpStyle->GetName().toUtf8().getStr()); + maAttribSet.dumpAsXml(pWriter); + (void)xmlTextWriterEndElement(pWriter); +} + +namespace { + +struct LessByStart +{ + bool operator() (const std::unique_ptr<EditCharAttrib>& left, const std::unique_ptr<EditCharAttrib>& right) const + { + return left->GetStart() < right->GetStart(); + } +}; + +} + +void CharAttribList::InsertAttrib( EditCharAttrib* pAttrib ) +{ +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// optimize: binary search? ! +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + // Maybe just simply iterate backwards: + // The most common and critical case: Attributes are already sorted + // (InsertTextObject!) binary search would not be optimal here. + // => Would bring something! + + const sal_Int32 nStart = pAttrib->GetStart(); // may be better for Comp.Opt. + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(*this); +#endif + + if ( pAttrib->IsEmpty() ) + mbHasEmptyAttribs = true; + + bool bInsert(true); + for (sal_Int32 i = 0, n = maAttribs.size(); i < n; ++i) + { + const EditCharAttrib& rCurAttrib = *maAttribs[i]; + if (rCurAttrib.GetStart() > nStart) + { + maAttribs.insert(maAttribs.begin()+i, std::unique_ptr<EditCharAttrib>(pAttrib)); + bInsert = false; + break; + } + } + + if (bInsert) maAttribs.push_back(std::unique_ptr<EditCharAttrib>(pAttrib)); + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(*this); +#endif +} + +void CharAttribList::ResortAttribs() +{ + std::sort(maAttribs.begin(), maAttribs.end(), LessByStart()); + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(*this); +#endif +} + +void CharAttribList::OptimizeRanges() +{ +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(*this); +#endif + for (sal_Int32 i = 0; i < static_cast<sal_Int32>(maAttribs.size()); ++i) + { + EditCharAttrib& rAttr = *maAttribs[i]; + for (sal_Int32 nNext = i+1; nNext < static_cast<sal_Int32>(maAttribs.size()); ++nNext) + { + EditCharAttrib& rNext = *maAttribs[nNext]; + if (!rAttr.IsFeature() && rNext.GetStart() == rAttr.GetEnd() && rNext.Which() == rAttr.Which()) + { + if (*rNext.GetItem() == *rAttr.GetItem()) + { + rAttr.GetEnd() = rNext.GetEnd(); + maAttribs.erase(maAttribs.begin()+nNext); + } + break; // only 1 attr with same which can start here. + } + else if (rNext.GetStart() > rAttr.GetEnd()) + { + break; + } + } + } +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG + CharAttribList::DbgCheckAttribs(*this); +#endif +} + +sal_Int32 CharAttribList::Count() const +{ + return maAttribs.size(); +} + +const EditCharAttrib* CharAttribList::FindAttrib( sal_uInt16 nWhich, sal_Int32 nPos ) const +{ + // Backwards, if one ends where the next starts. + // => The starting one is the valid one ... + AttribsType::const_reverse_iterator it = std::find_if(maAttribs.rbegin(), maAttribs.rend(), + [&nWhich, &nPos](const AttribsType::value_type& rxAttr) { + return rxAttr->Which() == nWhich && rxAttr->IsIn(nPos); }); + if (it != maAttribs.rend()) + { + const EditCharAttrib& rAttr = **it; + return &rAttr; + } + return nullptr; +} + +EditCharAttrib* CharAttribList::FindAttrib( sal_uInt16 nWhich, sal_Int32 nPos ) +{ + // Backwards, if one ends where the next starts. + // => The starting one is the valid one ... + AttribsType::reverse_iterator it = std::find_if(maAttribs.rbegin(), maAttribs.rend(), + [&nWhich, &nPos](AttribsType::value_type& rxAttr) { + return rxAttr->Which() == nWhich && rxAttr->IsIn(nPos); }); + if (it != maAttribs.rend()) + { + EditCharAttrib& rAttr = **it; + return &rAttr; + } + return nullptr; +} + +EditCharAttrib* CharAttribList::FindAttribRightOpen( sal_uInt16 nWhich, sal_Int32 nPos ) +{ + AttribsType::reverse_iterator it = std::find_if(maAttribs.rbegin(), maAttribs.rend(), + [&nWhich, &nPos](AttribsType::value_type& rxAttr) { + return rxAttr->Which() == nWhich && rxAttr->IsInLeftClosedRightOpen(nPos); }); + if (it != maAttribs.rend()) + { + EditCharAttrib& rAttr = **it; + return &rAttr; + } + return nullptr; +} + +const EditCharAttrib* CharAttribList::FindNextAttrib( sal_uInt16 nWhich, sal_Int32 nFromPos ) const +{ + assert(nWhich); + for (auto const& attrib : maAttribs) + { + const EditCharAttrib& rAttr = *attrib; + if (rAttr.GetStart() >= nFromPos && rAttr.Which() == nWhich) + return &rAttr; + } + return nullptr; +} + +bool CharAttribList::HasAttrib( sal_Int32 nStartPos, sal_Int32 nEndPos ) const +{ + return std::any_of(maAttribs.rbegin(), maAttribs.rend(), + [&nStartPos, &nEndPos](const AttribsType::value_type& rxAttr) { + return rxAttr->GetStart() < nEndPos && rxAttr->GetEnd() > nStartPos; }); +} + + +namespace { + +class FindByAddress +{ + const EditCharAttrib* mpAttr; +public: + explicit FindByAddress(const EditCharAttrib* p) : mpAttr(p) {} + bool operator() (const std::unique_ptr<EditCharAttrib>& r) const + { + return r.get() == mpAttr; + } +}; + +} + +void CharAttribList::Remove(const EditCharAttrib* p) +{ + AttribsType::iterator it = std::find_if(maAttribs.begin(), maAttribs.end(), FindByAddress(p)); + if (it != maAttribs.end()) + maAttribs.erase(it); +} + +void CharAttribList::Remove(sal_Int32 nPos) +{ + if (nPos >= static_cast<sal_Int32>(maAttribs.size())) + return; + + maAttribs.erase(maAttribs.begin()+nPos); +} + +void CharAttribList::SetHasEmptyAttribs(bool b) +{ + mbHasEmptyAttribs = b; +} + +bool CharAttribList::HasBoundingAttrib( sal_Int32 nBound ) const +{ + // Backwards, if one ends where the next starts. + // => The starting one is the valid one ... + AttribsType::const_reverse_iterator it = maAttribs.rbegin(), itEnd = maAttribs.rend(); + for (; it != itEnd; ++it) + { + const EditCharAttrib& rAttr = **it; + if (rAttr.GetEnd() < nBound) + return false; + + if (rAttr.GetStart() == nBound || rAttr.GetEnd() == nBound) + return true; + } + return false; +} + +EditCharAttrib* CharAttribList::FindEmptyAttrib( sal_uInt16 nWhich, sal_Int32 nPos ) +{ + if ( !mbHasEmptyAttribs ) + return nullptr; + + for (const std::unique_ptr<EditCharAttrib>& rAttr : maAttribs) + { + if (rAttr->GetStart() == nPos && rAttr->GetEnd() == nPos && rAttr->Which() == nWhich) + return rAttr.get(); + } + return nullptr; +} + +namespace +{ + +class FindByStartPos +{ + sal_Int32 mnPos; +public: + explicit FindByStartPos(sal_Int32 nPos) + : mnPos(nPos) + {} + + bool operator() (std::unique_ptr<EditCharAttrib> const& pCharAttrib) const + { + return pCharAttrib->GetStart() >= mnPos; + } +}; + +} + +const EditCharAttrib* CharAttribList::FindFeature( sal_Int32 nPos ) const +{ + // First, find the first attribute that starts at or after specified position. + AttribsType::const_iterator iterator = + std::find_if(maAttribs.begin(), maAttribs.end(), FindByStartPos(nPos)); + + if (iterator == maAttribs.end()) + { + // All attributes are before the specified position. + return nullptr; + } + + // And find the first attribute with feature. + iterator = std::find_if(iterator, maAttribs.end(), [](const std::unique_ptr<EditCharAttrib>& aAttrib) { + return aAttrib->IsFeature(); + }); + + if (iterator == maAttribs.end()) + { + // Couldn't find the feature + return nullptr; + } + + // Found + return iterator->get(); +} + +void CharAttribList::DeleteEmptyAttribs() +{ + std::erase_if(maAttribs, [](const std::unique_ptr<EditCharAttrib>& aAttrib) { return aAttrib->IsEmpty(); } ); + mbHasEmptyAttribs = false; +} + +#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG +void CharAttribList::DbgCheckAttribs(CharAttribList const& rAttribs) +{ + std::set<std::pair<sal_Int32, sal_uInt16>> zero_set; + for (const std::unique_ptr<EditCharAttrib>& rAttr : rAttribs.maAttribs) + { + assert(rAttr->GetStart() <= rAttr->GetEnd()); + assert(!rAttr->IsFeature() || rAttr->GetLen() == 1); + if (0 == rAttr->GetLen()) + { + // not sure if 0-length attributes allowed at all in non-empty para? + assert(zero_set.insert(std::make_pair(rAttr->GetStart(), rAttr->Which())).second && "duplicate 0-length attribute detected"); + } + } + CheckOrderedList(rAttribs.GetAttribs()); +} +#endif + +void CharAttribList::dumpAsXml(xmlTextWriterPtr pWriter) const +{ + (void)xmlTextWriterStartElement(pWriter, BAD_CAST("CharAttribList")); + for (auto const & i : maAttribs) { + i->dumpAsXml(pWriter); + } + (void)xmlTextWriterEndElement(pWriter); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/EditLine.cxx b/editeng/source/editeng/EditLine.cxx new file mode 100644 index 000000000000..b43cf0a84f11 --- /dev/null +++ b/editeng/source/editeng/EditLine.cxx @@ -0,0 +1,96 @@ +/* -*- 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 <EditLine.hxx> +#include <editdoc.hxx> +#include <algorithm> + +EditLine* EditLine::Clone() const +{ + EditLine* pLine = new EditLine; + pLine->maPositions = maPositions; + pLine->mnStartPosX = mnStartPosX; + pLine->mnNextLinePosXDiff = mnNextLinePosXDiff; + pLine->mnStart = mnStart; + pLine->mnEnd = mnEnd; + pLine->mnStartPortion = mnStartPortion; + pLine->mnEndPortion = mnEndPortion; + pLine->mnHeight = mnHeight; + pLine->mnTextWidth = mnTextWidth; + pLine->mnTextHeight = mnTextHeight; + pLine->mnMaxAscent = mnMaxAscent; + + return pLine; +} + +Size EditLine::CalcTextSize(ParaPortion& rParaPortion) +{ + Size aSize; + + DBG_ASSERT(rParaPortion.GetTextPortions().Count(), "GetTextSize before CreatePortions !"); + + for (sal_Int32 nPosition = mnStartPortion; nPosition <= mnEndPortion; nPosition++) + { + TextPortion& rPortion = rParaPortion.GetTextPortions()[nPosition]; + switch (rPortion.GetKind()) + { + case PortionKind::TEXT: + case PortionKind::FIELD: + case PortionKind::HYPHENATOR: + { + Size aTmpSize = rPortion.GetSize(); + aSize.AdjustWidth(aTmpSize.Width()); + if (aSize.Height() < aTmpSize.Height() ) + aSize.setHeight( aTmpSize.Height() ); + } + break; + case PortionKind::TAB: + { + aSize.AdjustWidth(rPortion.GetSize().Width()); + } + break; + case PortionKind::LINEBREAK: + break; + } + } + + SetHeight(sal_uInt16(aSize.Height())); + return aSize; +} + +void EditLine::SetHeight(sal_uInt16 nHeight, sal_uInt16 nTextHeight) +{ + mnHeight = nHeight; + + if (nTextHeight != 0) + mnTextHeight = nTextHeight; + else + mnTextHeight = nHeight; +} + +void EditLine::SetStartPosX(sal_Int32 nStart) +{ + if (nStart > 0) + mnStartPosX = nStart; + else + mnStartPosX = 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/TextPortionList.cxx b/editeng/source/editeng/TextPortionList.cxx new file mode 100644 index 000000000000..ca9d68159a5a --- /dev/null +++ b/editeng/source/editeng/TextPortionList.cxx @@ -0,0 +1,95 @@ +/* -*- 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 <TextPortionList.hxx> + +#include <EditLine.hxx> +#include <osl/diagnose.h> + + +void TextPortionList::DeleteFromPortion(sal_Int32 nDelFrom) +{ + assert((nDelFrom < static_cast<sal_Int32>(maPortions.size())) || ((nDelFrom == 0) && maPortions.empty())); + PortionsType::iterator it = maPortions.begin(); + std::advance(it, nDelFrom); + maPortions.erase(it, maPortions.end()); +} + +namespace { + +class FindTextPortionByAddress +{ + const TextPortion* mp; +public: + explicit FindTextPortionByAddress(const TextPortion* p) : mp(p) {} + bool operator() (const std::unique_ptr<TextPortion>& v) const + { + return v.get() == mp; + } +}; + +} + +sal_Int32 TextPortionList::GetPos(const TextPortion* p) const +{ + PortionsType::const_iterator it = + std::find_if(maPortions.begin(), maPortions.end(), FindTextPortionByAddress(p)); + + if (it == maPortions.end()) + return std::numeric_limits<sal_Int32>::max(); // not found. + + return std::distance(maPortions.begin(), it); +} + +sal_Int32 TextPortionList::FindPortion( + sal_Int32 nCharPos, sal_Int32& nPortionStart, bool bPreferStartingPortion) const +{ + // When nCharPos at portion limit, the left portion is found + sal_Int32 nTmpPos = 0; + sal_Int32 n = maPortions.size(); + for (sal_Int32 i = 0; i < n; ++i) + { + const TextPortion& rPortion = *maPortions[i]; + nTmpPos = nTmpPos + rPortion.GetLen(); + if ( nTmpPos >= nCharPos ) + { + // take this one if we don't prefer the starting portion, or if it's the last one + if ( ( nTmpPos != nCharPos ) || !bPreferStartingPortion || ( i == n-1 ) ) + { + nPortionStart = nTmpPos - rPortion.GetLen(); + return i; + } + } + } + OSL_FAIL( "FindPortion: Not found!" ); + return n - 1; +} + +sal_Int32 TextPortionList::GetStartPos(sal_Int32 nPortion) +{ + sal_Int32 nPos = 0; + for (sal_Int32 i = 0; i < nPortion; ++i) + { + const TextPortion& rPortion = *maPortions[i]; + nPos = nPos + rPortion.GetLen(); + } + return nPos; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/editattr.cxx b/editeng/source/editeng/editattr.cxx index 5d7da53de477..75bbcabc5a66 100644 --- a/editeng/source/editeng/editattr.cxx +++ b/editeng/source/editeng/editattr.cxx @@ -20,6 +20,7 @@ #include <vcl/outdev.hxx> #include <svl/grabbagitem.hxx> +#include <svl/voiditem.hxx> #include <libxml/xmlwriter.h> #include <editeng/svxfont.hxx> #include <editeng/flditem.hxx> @@ -45,14 +46,15 @@ #include <editattr.hxx> - -EditCharAttrib::EditCharAttrib( const SfxPoolItem& rAttr, sal_Int32 nS, sal_Int32 nE ) : - nStart(nS), nEnd(nE), bFeature(false), bEdge(false) +EditCharAttrib::EditCharAttrib(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 nS, sal_Int32 nE ) +: maItemHolder(rPool, &rItem) +, nStart(nS) +, nEnd(nE) +, bFeature(false) +, bEdge(false) { - pItem = &rAttr; - - assert((rAttr.Which() >= EE_ITEMS_START) && (rAttr.Which() <= EE_ITEMS_END)); - assert((rAttr.Which() < EE_FEATURE_START) || (rAttr.Which() > EE_FEATURE_END) || (nE == (nS+1))); + assert((rItem.Which() >= EE_ITEMS_START) && (rItem.Which() <= EE_ITEMS_END)); + assert((rItem.Which() < EE_FEATURE_START) || (rItem.Which() > EE_FEATURE_END) || (nE == (nS+1))); } EditCharAttrib::~EditCharAttrib() @@ -70,16 +72,16 @@ void EditCharAttrib::dumpAsXml(xmlTextWriterPtr pWriter) const pWriter, BAD_CAST("nStart"), "%" SAL_PRIdINT32, nStart); (void)xmlTextWriterWriteFormatAttribute( pWriter, BAD_CAST("nEnd"), "%" SAL_PRIdINT32, nEnd); - pItem->dumpAsXml(pWriter); + GetItem()->dumpAsXml(pWriter); (void)xmlTextWriterEndElement(pWriter); } -EditCharAttribFont::EditCharAttribFont( const SvxFontItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribFont::EditCharAttribFont(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_FONTINFO || rAttr.Which() == EE_CHAR_FONTINFO_CJK || rAttr.Which() == EE_CHAR_FONTINFO_CTL); + assert(rItem.Which() == EE_CHAR_FONTINFO || rItem.Which() == EE_CHAR_FONTINFO_CJK || rItem.Which() == EE_CHAR_FONTINFO_CTL); } void EditCharAttribFont::SetFont( SvxFont& rFont, OutputDevice* ) @@ -94,10 +96,10 @@ void EditCharAttribFont::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribItalic::EditCharAttribItalic( const SvxPostureItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribItalic::EditCharAttribItalic(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_ITALIC || rAttr.Which() == EE_CHAR_ITALIC_CJK || rAttr.Which() == EE_CHAR_ITALIC_CTL); + assert(rItem.Which() == EE_CHAR_ITALIC || rItem.Which() == EE_CHAR_ITALIC_CJK || rItem.Which() == EE_CHAR_ITALIC_CTL); } void EditCharAttribItalic::SetFont( SvxFont& rFont, OutputDevice* ) @@ -107,10 +109,10 @@ void EditCharAttribItalic::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribWeight::EditCharAttribWeight( const SvxWeightItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribWeight::EditCharAttribWeight(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_WEIGHT || rAttr.Which() == EE_CHAR_WEIGHT_CJK || rAttr.Which() == EE_CHAR_WEIGHT_CTL); + assert(rItem.Which() == EE_CHAR_WEIGHT || rItem.Which() == EE_CHAR_WEIGHT_CJK || rItem.Which() == EE_CHAR_WEIGHT_CTL); } void EditCharAttribWeight::SetFont( SvxFont& rFont, OutputDevice* ) @@ -120,10 +122,10 @@ void EditCharAttribWeight::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribUnderline::EditCharAttribUnderline( const SvxUnderlineItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribUnderline::EditCharAttribUnderline(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_UNDERLINE); + assert(rItem.Which() == EE_CHAR_UNDERLINE); } void EditCharAttribUnderline::SetFont( SvxFont& rFont, OutputDevice* pOutDev ) @@ -137,10 +139,10 @@ void EditCharAttribUnderline::SetFont( SvxFont& rFont, OutputDevice* pOutDev ) -EditCharAttribOverline::EditCharAttribOverline( const SvxOverlineItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribOverline::EditCharAttribOverline(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_OVERLINE); + assert(rItem.Which() == EE_CHAR_OVERLINE); } void EditCharAttribOverline::SetFont( SvxFont& rFont, OutputDevice* pOutDev ) @@ -152,10 +154,10 @@ void EditCharAttribOverline::SetFont( SvxFont& rFont, OutputDevice* pOutDev ) -EditCharAttribFontHeight::EditCharAttribFontHeight( const SvxFontHeightItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribFontHeight::EditCharAttribFontHeight(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_FONTHEIGHT || rAttr.Which() == EE_CHAR_FONTHEIGHT_CJK || rAttr.Which() == EE_CHAR_FONTHEIGHT_CTL); + assert(rItem.Which() == EE_CHAR_FONTHEIGHT || rItem.Which() == EE_CHAR_FONTHEIGHT_CJK || rItem.Which() == EE_CHAR_FONTHEIGHT_CTL); } void EditCharAttribFontHeight::SetFont( SvxFont& rFont, OutputDevice* ) @@ -166,10 +168,10 @@ void EditCharAttribFontHeight::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribFontWidth::EditCharAttribFontWidth( const SvxCharScaleWidthItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribFontWidth::EditCharAttribFontWidth(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_FONTWIDTH); + assert(rItem.Which() == EE_CHAR_FONTWIDTH); } void EditCharAttribFontWidth::SetFont( SvxFont& /*rFont*/, OutputDevice* ) @@ -179,10 +181,10 @@ void EditCharAttribFontWidth::SetFont( SvxFont& /*rFont*/, OutputDevice* ) -EditCharAttribStrikeout::EditCharAttribStrikeout( const SvxCrossedOutItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribStrikeout::EditCharAttribStrikeout(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_STRIKEOUT); + assert(rItem.Which() == EE_CHAR_STRIKEOUT); } void EditCharAttribStrikeout::SetFont( SvxFont& rFont, OutputDevice* ) @@ -192,10 +194,10 @@ void EditCharAttribStrikeout::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribCaseMap::EditCharAttribCaseMap( const SvxCaseMapItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribCaseMap::EditCharAttribCaseMap(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_CASEMAP); + assert(rItem.Which() == EE_CHAR_CASEMAP); } void EditCharAttribCaseMap::SetFont( SvxFont& rFont, OutputDevice* ) @@ -205,10 +207,10 @@ void EditCharAttribCaseMap::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribColor::EditCharAttribColor( const SvxColorItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribColor::EditCharAttribColor(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_COLOR); + assert(rItem.Which() == EE_CHAR_COLOR); } void EditCharAttribColor::SetFont( SvxFont& rFont, OutputDevice* ) @@ -218,26 +220,23 @@ void EditCharAttribColor::SetFont( SvxFont& rFont, OutputDevice* ) } -EditCharAttribBackgroundColor::EditCharAttribBackgroundColor( - const SvxColorItem& rAttr, - sal_Int32 _nStart, - sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribBackgroundColor::EditCharAttribBackgroundColor(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_BKGCOLOR); + assert(rItem.Which() == EE_CHAR_BKGCOLOR); } void EditCharAttribBackgroundColor::SetFont( SvxFont& rFont, OutputDevice* ) { Color aColor = static_cast<const SvxColorItem*>(GetItem())->GetValue(); - rFont.SetTransparent(false); + rFont.SetTransparent(aColor.IsTransparent()); rFont.SetFillColor(aColor); } -EditCharAttribLanguage::EditCharAttribLanguage( const SvxLanguageItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribLanguage::EditCharAttribLanguage(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert((rAttr.Which() == EE_CHAR_LANGUAGE) || (rAttr.Which() == EE_CHAR_LANGUAGE_CJK) || (rAttr.Which() == EE_CHAR_LANGUAGE_CTL)); + assert((rItem.Which() == EE_CHAR_LANGUAGE) || (rItem.Which() == EE_CHAR_LANGUAGE_CJK) || (rItem.Which() == EE_CHAR_LANGUAGE_CTL)); } void EditCharAttribLanguage::SetFont( SvxFont& rFont, OutputDevice* ) @@ -247,10 +246,10 @@ void EditCharAttribLanguage::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribShadow::EditCharAttribShadow( const SvxShadowedItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribShadow::EditCharAttribShadow(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_SHADOW); + assert(rItem.Which() == EE_CHAR_SHADOW); } void EditCharAttribShadow::SetFont( SvxFont& rFont, OutputDevice* ) @@ -260,10 +259,10 @@ void EditCharAttribShadow::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribEscapement::EditCharAttribEscapement( const SvxEscapementItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribEscapement::EditCharAttribEscapement(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_ESCAPEMENT); + assert(rItem.Which() == EE_CHAR_ESCAPEMENT); } void EditCharAttribEscapement::SetFont( SvxFont& rFont, OutputDevice* pOutDev ) @@ -277,10 +276,10 @@ void EditCharAttribEscapement::SetFont( SvxFont& rFont, OutputDevice* pOutDev ) -EditCharAttribOutline::EditCharAttribOutline( const SvxContourItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribOutline::EditCharAttribOutline(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_OUTLINE); + assert(rItem.Which() == EE_CHAR_OUTLINE); } void EditCharAttribOutline::SetFont( SvxFont& rFont, OutputDevice* ) @@ -290,8 +289,8 @@ void EditCharAttribOutline::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribTab::EditCharAttribTab( const SfxVoidItem& rAttr, sal_Int32 nPos ) - : EditCharAttrib( rAttr, nPos, nPos+1 ) +EditCharAttribTab::EditCharAttribTab(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 nPos) +: EditCharAttrib(rPool, rItem, nPos, nPos+1) { SetFeature( true ); } @@ -302,8 +301,8 @@ void EditCharAttribTab::SetFont( SvxFont&, OutputDevice* ) -EditCharAttribLineBreak::EditCharAttribLineBreak( const SfxVoidItem& rAttr, sal_Int32 nPos ) - : EditCharAttrib( rAttr, nPos, nPos+1 ) +EditCharAttribLineBreak::EditCharAttribLineBreak(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 nPos) +: EditCharAttrib(rPool, rItem, nPos, nPos+1) { SetFeature( true ); } @@ -314,8 +313,8 @@ void EditCharAttribLineBreak::SetFont( SvxFont&, OutputDevice* ) -EditCharAttribField::EditCharAttribField( const SvxFieldItem& rAttr, sal_Int32 nPos ) - : EditCharAttrib( rAttr, nPos, nPos+1 ) +EditCharAttribField::EditCharAttribField(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 nPos) +: EditCharAttrib(rPool, rItem, nPos, nPos+1) { SetFeature( true ); // !!! } @@ -329,6 +328,8 @@ void EditCharAttribField::SetFont( SvxFont& rFont, OutputDevice* ) } if ( mxTxtColor ) rFont.SetColor( *mxTxtColor ); + if ( mxFldLineStyle ) + rFont.SetUnderline( *mxFldLineStyle ); } @@ -342,15 +343,17 @@ void EditCharAttribField::Reset() aFieldValue.clear(); mxTxtColor.reset(); mxFldColor.reset(); + mxFldLineStyle.reset(); } -EditCharAttribField::EditCharAttribField( const EditCharAttribField& rAttr ) - : EditCharAttrib( *rAttr.GetItem(), rAttr.GetStart(), rAttr.GetEnd() ), - aFieldValue( rAttr.aFieldValue ) +EditCharAttribField::EditCharAttribField(const EditCharAttribField& rAttr) +: EditCharAttrib(rAttr.GetHolder().getPool(), *rAttr.GetHolder().getItem(), rAttr.GetStart(), rAttr.GetEnd()) +, aFieldValue( rAttr.aFieldValue ) { // Use this constructor only for temporary Objects, Item is not pooled. mxTxtColor = rAttr.mxTxtColor; mxFldColor = rAttr.mxFldColor; + mxFldLineStyle = rAttr.mxFldLineStyle; } EditCharAttribField::~EditCharAttribField() @@ -373,15 +376,20 @@ bool EditCharAttribField::operator == ( const EditCharAttribField& rAttr ) const if ( ( mxFldColor && rAttr.mxFldColor ) && ( *mxFldColor != *rAttr.mxFldColor ) ) return false; + if ( ( mxFldLineStyle && !rAttr.mxFldLineStyle ) || ( !mxFldLineStyle && rAttr.mxFldLineStyle ) ) + return false; + if ( ( mxFldLineStyle && rAttr.mxFldLineStyle ) && ( *mxFldLineStyle != *rAttr.mxFldLineStyle ) ) + return false; + return true; } -EditCharAttribPairKerning::EditCharAttribPairKerning( const SvxAutoKernItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) -: EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribPairKerning::EditCharAttribPairKerning(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_PAIRKERNING); + assert(rItem.Which() == EE_CHAR_PAIRKERNING); } void EditCharAttribPairKerning::SetFont( SvxFont& rFont, OutputDevice* ) @@ -391,10 +399,10 @@ void EditCharAttribPairKerning::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribKerning::EditCharAttribKerning( const SvxKerningItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) -: EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribKerning::EditCharAttribKerning(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_KERNING); + assert(rItem.Which() == EE_CHAR_KERNING); } void EditCharAttribKerning::SetFont( SvxFont& rFont, OutputDevice* ) @@ -404,10 +412,10 @@ void EditCharAttribKerning::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribWordLineMode::EditCharAttribWordLineMode( const SvxWordLineModeItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) -: EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribWordLineMode::EditCharAttribWordLineMode(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_WLM); + assert(rItem.Which() == EE_CHAR_WLM); } void EditCharAttribWordLineMode::SetFont( SvxFont& rFont, OutputDevice* ) @@ -417,10 +425,10 @@ void EditCharAttribWordLineMode::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribEmphasisMark::EditCharAttribEmphasisMark( const SvxEmphasisMarkItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribEmphasisMark::EditCharAttribEmphasisMark(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_EMPHASISMARK); + assert(rItem.Which() == EE_CHAR_EMPHASISMARK); } void EditCharAttribEmphasisMark::SetFont( SvxFont& rFont, OutputDevice* ) @@ -430,10 +438,10 @@ void EditCharAttribEmphasisMark::SetFont( SvxFont& rFont, OutputDevice* ) -EditCharAttribRelief::EditCharAttribRelief( const SvxCharReliefItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribRelief::EditCharAttribRelief(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_RELIEF); + assert(rItem.Which() == EE_CHAR_RELIEF); } void EditCharAttribRelief::SetFont( SvxFont& rFont, OutputDevice* ) @@ -442,10 +450,10 @@ void EditCharAttribRelief::SetFont( SvxFont& rFont, OutputDevice* ) } -EditCharAttribGrabBag::EditCharAttribGrabBag( const SfxGrabBagItem& rAttr, sal_Int32 _nStart, sal_Int32 _nEnd ) - : EditCharAttrib( rAttr, _nStart, _nEnd ) +EditCharAttribGrabBag::EditCharAttribGrabBag(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 _nStart, sal_Int32 _nEnd) +: EditCharAttrib(rPool, rItem, _nStart, _nEnd) { - assert(rAttr.Which() == EE_CHAR_GRABBAG); + assert(rItem.Which() == EE_CHAR_GRABBAG); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/editdbg.cxx b/editeng/source/editeng/editdbg.cxx index 89bff9f34fc6..f94bc2c7ea14 100644 --- a/editeng/source/editeng/editdbg.cxx +++ b/editeng/source/editeng/editdbg.cxx @@ -58,241 +58,253 @@ #if defined( DBG_UTIL ) || ( OSL_DEBUG_LEVEL > 1 ) +namespace +{ +struct DebOutBuffer +{ + OStringBuffer str; + void append(std::string_view descr, const SfxEnumItemInterface& rItem) + { + str.append(descr + OString::number(rItem.GetEnumValue())); + } + void append(std::string_view descr, const SvxLRSpaceItem& rItem) + { + str.append(OString::Concat(descr) + "FI=" + OString::number(rItem.GetTextFirstLineOffset()) + + ", LI=" + OString::number(rItem.GetTextLeft()) + + ", RI=" + OString::number(rItem.GetRight())); + } + void append(std::string_view descr, const SvxNumBulletItem& rItem) + { + str.append(descr); + for (sal_uInt16 nLevel = 0; nLevel < 3; nLevel++) + { + str.append("Level" + OString::number(nLevel) + "="); + const SvxNumberFormat* pFmt = rItem.GetNumRule().Get(nLevel); + if (pFmt) + { + str.append("(" + OString::number(pFmt->GetFirstLineOffset()) + "," + + OString::number(pFmt->GetAbsLSpace()) + ","); + if (pFmt->GetNumberingType() == SVX_NUM_BITMAP) + str.append("Bitmap"); + else if (pFmt->GetNumberingType() != SVX_NUM_CHAR_SPECIAL) + str.append("Number"); + else + { + str.append("Char=[" + OString::number(pFmt->GetBulletChar()) + "]"); + } + str.append(") "); + } + } + } + void append(std::string_view descr, const SfxBoolItem& rItem) + { + str.append(descr + OString::number(static_cast<int>(rItem.GetValue()))); + } + void append(std::string_view descr, const SfxInt16Item& rItem) + { + str.append(descr + OString::number(rItem.GetValue())); + } + void append(std::string_view descr, const SfxUInt16Item& rItem) + { + str.append(descr + OString::number(rItem.GetValue())); + } + void append(const SvxULSpaceItem& rItem) + { + str.append("SB=" + OString::number(rItem.GetUpper()) + + ", SA=" + OString::number(rItem.GetLower())); + } + void append(std::string_view descr, const SvxLineSpacingItem& rItem) + { + str.append(descr); + if (rItem.GetLineSpaceRule() == SvxLineSpaceRule::Min) + { + str.append("Min: " + OString::number(rItem.GetInterLineSpace())); + } + else if (rItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop) + { + str.append("Prop: " + OString::number(rItem.GetPropLineSpace())); + } + else + str.append("Unsupported Type!"); + } + void append(const SvxTabStopItem& rTabs) + { + str.append("Tabs: " + OString::number(rTabs.Count())); + if (rTabs.Count()) + { + str.append("( "); + for (sal_uInt16 i = 0; i < rTabs.Count(); ++i) + { + const SvxTabStop& rTab = rTabs[i]; + str.append(OString::number(rTab.GetTabPos()) + " "); + } + str.append(')'); + } + } + void append(std::string_view descr, const SvxColorItem& rItem) + { + Color aColor(rItem.GetValue()); + str.append(descr + OString::number(aColor.GetRed()) + ", " + + OString::number(aColor.GetGreen()) + ", " + OString::number(aColor.GetBlue())); + } + void append(std::string_view descr, const SvxFontItem& rItem) + { + str.append(descr + OUStringToOString(rItem.GetFamilyName(), RTL_TEXTENCODING_ASCII_US) + + " (CharSet: " + OString::number(rItem.GetCharSet()) + ")"); + } + void append(std::string_view descr, const SvxEscapementItem& rItem) + { + str.append(descr + OString::number(rItem.GetEsc()) + ", " + + OString::number(rItem.GetProportionalHeight())); + } + void appendHeightAndPts(std::string_view descr, tools::Long h, MapUnit eUnit) + { + MapMode aItemMapMode(eUnit); + MapMode aPntMap(MapUnit::MapPoint); + Size aSz = OutputDevice::LogicToLogic(Size(0, h), aItemMapMode, aPntMap); + str.append(descr + OString::number(h) + " Points=" + OString::number(aSz.Height())); + } + void append(std::string_view descr, const SvxFontHeightItem& rItem, const SfxItemPool& rPool) + { + appendHeightAndPts(descr, rItem.GetHeight(), rPool.GetMetric(rItem.Which())); + } + void append(std::string_view descr, const SvxKerningItem& rItem, const SfxItemPool& rPool) + { + appendHeightAndPts(descr, rItem.GetValue(), rPool.GetMetric(rItem.Which())); + } +}; +} + static OString DbgOutItem(const SfxItemPool& rPool, const SfxPoolItem& rItem) { - OStringBuffer aDebStr; + DebOutBuffer buffer; switch ( rItem.Which() ) { case EE_PARA_WRITINGDIR: - aDebStr.append("WritingDir="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxFrameDirectionItem&>(rItem).GetValue())); + buffer.append("WritingDir=", rItem.StaticWhichCast(EE_PARA_WRITINGDIR)); break; case EE_PARA_OUTLLRSPACE: + buffer.append("Outline ", rItem.StaticWhichCast(EE_PARA_OUTLLRSPACE)); + break; case EE_PARA_LRSPACE: - aDebStr.append("FI="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxLRSpaceItem&>(rItem).GetTextFirstLineOffset())); - aDebStr.append(", LI="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxLRSpaceItem&>(rItem).GetTextLeft())); - aDebStr.append(", RI="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxLRSpaceItem&>(rItem).GetRight())); + buffer.append("", rItem.StaticWhichCast(EE_PARA_LRSPACE)); break; case EE_PARA_NUMBULLET: - aDebStr.append("NumItem "); - for ( sal_uInt16 nLevel = 0; nLevel < 3; nLevel++ ) - { - aDebStr.append("Level"); - aDebStr.append(static_cast<sal_Int32>(nLevel)); - aDebStr.append('='); - const SvxNumberFormat* pFmt = static_cast<const SvxNumBulletItem&>(rItem).GetNumRule().Get( nLevel ); - if ( pFmt ) - { - aDebStr.append('('); - aDebStr.append(pFmt->GetFirstLineOffset()); - aDebStr.append(','); - aDebStr.append(pFmt->GetAbsLSpace()); - aDebStr.append(','); - if ( pFmt->GetNumberingType() == SVX_NUM_BITMAP ) - aDebStr.append("Bitmap"); - else if( pFmt->GetNumberingType() != SVX_NUM_CHAR_SPECIAL ) - aDebStr.append("Number"); - else - { - aDebStr.append("Char=["); - aDebStr.append(static_cast<sal_Int32>(pFmt->GetBulletChar())); - aDebStr.append(']'); - } - aDebStr.append(") "); - } - } + buffer.append("NumItem ", rItem.StaticWhichCast(EE_PARA_NUMBULLET)); break; case EE_PARA_BULLETSTATE: - aDebStr.append("ShowBullet="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SfxBoolItem&>(rItem).GetValue())); + buffer.append("ShowBullet=", rItem.StaticWhichCast(EE_PARA_BULLETSTATE)); break; case EE_PARA_HYPHENATE: - aDebStr.append("Hyphenate="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SfxBoolItem&>(rItem).GetValue())); + buffer.append("Hyphenate=", rItem.StaticWhichCast(EE_PARA_HYPHENATE)); break; case EE_PARA_OUTLLEVEL: - aDebStr.append("Level="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SfxInt16Item&>(rItem).GetValue())); + buffer.append("Level=", rItem.StaticWhichCast(EE_PARA_OUTLLEVEL)); break; case EE_PARA_ULSPACE: - aDebStr.append("SB="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxULSpaceItem&>(rItem).GetUpper())); - aDebStr.append(", SA="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxULSpaceItem&>(rItem).GetLower())); + buffer.append(rItem.StaticWhichCast(EE_PARA_ULSPACE)); break; case EE_PARA_SBL: - aDebStr.append("SBL="); - if ( static_cast<const SvxLineSpacingItem&>(rItem).GetLineSpaceRule() == SvxLineSpaceRule::Min ) - { - aDebStr.append("Min: "); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxLineSpacingItem&>(rItem).GetInterLineSpace())); - } - else if ( static_cast<const SvxLineSpacingItem&>(rItem).GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop ) - { - aDebStr.append("Prop: "); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxLineSpacingItem&>(rItem).GetPropLineSpace())); - } - else - aDebStr.append("Unsupported Type!"); + buffer.append("SBL=", rItem.StaticWhichCast(EE_PARA_SBL)); break; case EE_PARA_JUST: - aDebStr.append("SvxAdust="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxAdjustItem&>(rItem).GetAdjust())); + buffer.append("SvxAdust=", rItem.StaticWhichCast(EE_PARA_JUST)); break; case EE_PARA_TABS: - { - aDebStr.append("Tabs: "); - const SvxTabStopItem& rTabs = static_cast<const SvxTabStopItem&>(rItem); - aDebStr.append(static_cast<sal_Int32>(rTabs.Count())); - if ( rTabs.Count() ) - { - aDebStr.append("( "); - for (sal_uInt16 i = 0; i < rTabs.Count(); ++i) - { - const SvxTabStop& rTab = rTabs[i]; - aDebStr.append(rTab.GetTabPos()); - aDebStr.append(' '); - } - aDebStr.append(')'); - } - } + buffer.append(rItem.StaticWhichCast(EE_PARA_TABS)); break; case EE_CHAR_LANGUAGE: + buffer.append("Language=", rItem.StaticWhichCast(EE_CHAR_LANGUAGE)); + break; case EE_CHAR_LANGUAGE_CJK: + buffer.append("LanguageCJK=", rItem.StaticWhichCast(EE_CHAR_LANGUAGE_CJK)); + break; case EE_CHAR_LANGUAGE_CTL: - aDebStr.append("Language="); - aDebStr.append(static_cast<sal_Int32>(static_cast<sal_uInt16>(static_cast<const SvxLanguageItem&>(rItem).GetLanguage()))); + buffer.append("LanguageCTL=", rItem.StaticWhichCast(EE_CHAR_LANGUAGE_CTL)); break; case EE_CHAR_COLOR: - { - aDebStr.append("Color= "); - Color aColor( static_cast<const SvxColorItem&>(rItem).GetValue() ); - aDebStr.append(static_cast<sal_Int32>(aColor.GetRed())); - aDebStr.append(", "); - aDebStr.append(static_cast<sal_Int32>(aColor.GetGreen())); - aDebStr.append(", "); - aDebStr.append(static_cast<sal_Int32>(aColor.GetBlue())); - } + buffer.append("Color= ", rItem.StaticWhichCast(EE_CHAR_COLOR)); break; case EE_CHAR_BKGCOLOR: - { - aDebStr.append("FillColor= "); - Color aColor( static_cast<const SvxColorItem&>(rItem).GetValue() ); - aDebStr.append(static_cast<sal_Int32>(aColor.GetRed())); - aDebStr.append(", "); - aDebStr.append(static_cast<sal_Int32>(aColor.GetGreen())); - aDebStr.append(", "); - aDebStr.append(static_cast<sal_Int32>(aColor.GetBlue())); - } + buffer.append("FillColor= ", rItem.StaticWhichCast(EE_CHAR_BKGCOLOR)); break; case EE_CHAR_FONTINFO: + buffer.append("Font=", rItem.StaticWhichCast(EE_CHAR_FONTINFO)); + break; case EE_CHAR_FONTINFO_CJK: + buffer.append("FontCJK=", rItem.StaticWhichCast(EE_CHAR_FONTINFO_CJK)); + break; case EE_CHAR_FONTINFO_CTL: - { - aDebStr.append("Font="); - aDebStr.append(OUStringToOString(static_cast<const SvxFontItem&>(rItem).GetFamilyName(), RTL_TEXTENCODING_ASCII_US)); - aDebStr.append(" (CharSet: "); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxFontItem&>(rItem).GetCharSet())); - aDebStr.append(')'); - } + buffer.append("FontCTL=", rItem.StaticWhichCast(EE_CHAR_FONTINFO_CTL)); break; case EE_CHAR_FONTHEIGHT: + buffer.append("Size=", rItem.StaticWhichCast(EE_CHAR_FONTHEIGHT), rPool); + break; case EE_CHAR_FONTHEIGHT_CJK: + buffer.append("SizeCJK=", rItem.StaticWhichCast(EE_CHAR_FONTHEIGHT_CJK), rPool); + break; case EE_CHAR_FONTHEIGHT_CTL: - { - aDebStr.append("Groesse="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxFontHeightItem&>(rItem).GetHeight())); - Size aSz( 0, static_cast<const SvxFontHeightItem&>(rItem).GetHeight() ); - MapUnit eUnit = rPool.GetMetric( rItem.Which() ); - MapMode aItemMapMode(eUnit); - MapMode aPntMap( MapUnit::MapPoint ); - aSz = OutputDevice::LogicToLogic( aSz, aItemMapMode, aPntMap ); - aDebStr.append(" Points="); - aDebStr.append(static_cast<sal_Int32>(aSz.Height())); - } + buffer.append("SizeCTL=", rItem.StaticWhichCast(EE_CHAR_FONTHEIGHT_CTL), rPool); break; case EE_CHAR_FONTWIDTH: - { - aDebStr.append("Breite="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxCharScaleWidthItem&>(rItem).GetValue())); - aDebStr.append('%'); - } + buffer.append("Width=", rItem.StaticWhichCast(EE_CHAR_FONTWIDTH)); break; case EE_CHAR_WEIGHT: + buffer.append("FontWeight=", rItem.StaticWhichCast(EE_CHAR_WEIGHT)); + break; case EE_CHAR_WEIGHT_CJK: + buffer.append("FontWeightCJK=", rItem.StaticWhichCast(EE_CHAR_WEIGHT_CJK)); + break; case EE_CHAR_WEIGHT_CTL: - aDebStr.append("FontWeight="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxWeightItem&>(rItem).GetWeight())); + buffer.append("FontWeightCTL=", rItem.StaticWhichCast(EE_CHAR_WEIGHT_CTL)); break; case EE_CHAR_UNDERLINE: - aDebStr.append("FontUnderline="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxUnderlineItem&>(rItem).GetLineStyle())); + buffer.append("FontUnderline=", rItem.StaticWhichCast(EE_CHAR_UNDERLINE)); break; case EE_CHAR_OVERLINE: - aDebStr.append("FontOverline="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxOverlineItem&>(rItem).GetLineStyle())); + buffer.append("FontOverline=", rItem.StaticWhichCast(EE_CHAR_OVERLINE)); break; case EE_CHAR_EMPHASISMARK: - aDebStr.append("FontUnderline="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxEmphasisMarkItem&>(rItem).GetEmphasisMark())); + buffer.append("FontEmphasisMark=", rItem.StaticWhichCast(EE_CHAR_EMPHASISMARK)); break; case EE_CHAR_RELIEF: - aDebStr.append("FontRelief="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxCharReliefItem&>(rItem).GetValue())); + buffer.append("FontRelief=", rItem.StaticWhichCast(EE_CHAR_RELIEF)); break; case EE_CHAR_STRIKEOUT: - aDebStr.append("FontStrikeout="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxCrossedOutItem&>(rItem).GetStrikeout())); + buffer.append("FontStrikeout=", rItem.StaticWhichCast(EE_CHAR_STRIKEOUT)); break; case EE_CHAR_ITALIC: + buffer.append("FontPosture=", rItem.StaticWhichCast(EE_CHAR_ITALIC)); + break; case EE_CHAR_ITALIC_CJK: + buffer.append("FontPostureCJK=", rItem.StaticWhichCast(EE_CHAR_ITALIC_CJK)); + break; case EE_CHAR_ITALIC_CTL: - aDebStr.append("FontPosture="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxPostureItem&>(rItem).GetPosture())); + buffer.append("FontPostureCTL=", rItem.StaticWhichCast(EE_CHAR_ITALIC_CTL)); break; case EE_CHAR_OUTLINE: - aDebStr.append("FontOutline="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxContourItem&>(rItem).GetValue())); + buffer.append("FontOutline=", rItem.StaticWhichCast(EE_CHAR_OUTLINE)); break; case EE_CHAR_SHADOW: - aDebStr.append("FontShadowed="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxShadowedItem&>(rItem).GetValue())); + buffer.append("FontShadowed=", rItem.StaticWhichCast(EE_CHAR_SHADOW)); break; case EE_CHAR_ESCAPEMENT: - aDebStr.append("Escape="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxEscapementItem&>(rItem).GetEsc())); - aDebStr.append(", "); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxEscapementItem&>(rItem).GetProportionalHeight())); + buffer.append("Escape=", rItem.StaticWhichCast(EE_CHAR_ESCAPEMENT)); break; case EE_CHAR_PAIRKERNING: - aDebStr.append("PairKerning="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxAutoKernItem&>(rItem).GetValue())); + buffer.append("PairKerning=", rItem.StaticWhichCast(EE_CHAR_PAIRKERNING)); break; case EE_CHAR_KERNING: - { - aDebStr.append("Kerning="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxKerningItem&>(rItem).GetValue())); - Size aSz( 0, static_cast<short>(static_cast<const SvxKerningItem&>(rItem).GetValue()) ); - MapUnit eUnit = rPool.GetMetric( rItem.Which() ); - MapMode aItemMapMode(eUnit); - MapMode aPntMap( MapUnit::MapPoint ); - aSz = OutputDevice::LogicToLogic( aSz, aItemMapMode, aPntMap ); - aDebStr.append(" Points="); - aDebStr.append(static_cast<sal_Int32>(aSz.Height())); - } + buffer.append("Kerning=", rItem.StaticWhichCast(EE_CHAR_KERNING), rPool); break; case EE_CHAR_WLM: - aDebStr.append("WordLineMode="); - aDebStr.append(static_cast<sal_Int32>(static_cast<const SvxWordLineModeItem&>(rItem).GetValue())); + buffer.append("WordLineMode=", rItem.StaticWhichCast(EE_CHAR_WLM)); break; case EE_CHAR_XMLATTRIBS: - aDebStr.append("XMLAttribs=..."); + buffer.str.append("XMLAttribs=..."); break; } - return aDebStr.makeStringAndClear(); + return buffer.str.makeStringAndClear(); } static void DbgOutItemSet(FILE* fp, const SfxItemSet& rSet, bool bSearchInParent, bool bShowALL) @@ -302,7 +314,7 @@ static void DbgOutItemSet(FILE* fp, const SfxItemSet& rSet, bool bSearchInParent fprintf( fp, "\nWhich: %i\t", nWhich ); if ( rSet.GetItemState( nWhich, bSearchInParent ) == SfxItemState::DEFAULT ) fprintf( fp, "ITEM_OFF " ); - else if ( rSet.GetItemState( nWhich, bSearchInParent ) == SfxItemState::DONTCARE ) + else if ( rSet.GetItemState( nWhich, bSearchInParent ) == SfxItemState::INVALID ) fprintf( fp, "ITEM_DC " ); else if ( rSet.GetItemState( nWhich, bSearchInParent ) == SfxItemState::SET ) fprintf( fp, "ITEM_ON *" ); @@ -333,9 +345,9 @@ void EditEngine::DumpData(const EditEngine* pEE, bool bInfoBox) fprintf( fp, "================================================================================" ); fprintf( fp, "\n================== Document ================================================" ); fprintf( fp, "\n================================================================================" ); - for ( sal_Int32 nPortion = 0; nPortion < pEE->pImpEditEngine->GetParaPortions().Count(); nPortion++) + for ( sal_Int32 nPortion = 0; nPortion < pEE->getImpl().GetParaPortions().Count(); nPortion++) { - ParaPortion& rPPortion = pEE->pImpEditEngine->GetParaPortions()[nPortion]; + ParaPortion const& rPPortion = pEE->getImpl().GetParaPortions().getRef(nPortion); fprintf( fp, "\nParagraph %" SAL_PRIdINT32 ": Length = %" SAL_PRIdINT32 ", Invalid = %i\nText = '%s'", nPortion, rPPortion.GetNode()->Len(), rPPortion.IsInvalid(), OUStringToOString(rPPortion.GetNode()->GetString(), RTL_TEXTENCODING_UTF8).getStr() ); @@ -351,15 +363,15 @@ void EditEngine::DumpData(const EditEngine* pEE, bool bInfoBox) for ( sal_Int32 z = 0; z < rPPortion.GetNode()->GetCharAttribs().Count(); ++z ) { const std::unique_ptr<EditCharAttrib>& rAttr = rPPortion.GetNode()->GetCharAttribs().GetAttribs()[z]; - OStringBuffer aCharAttribs; - aCharAttribs.append("\nA"); - aCharAttribs.append(nPortion); - aCharAttribs.append(": "); - aCharAttribs.append(static_cast<sal_Int32>(rAttr->GetItem()->Which())); - aCharAttribs.append('\t'); - aCharAttribs.append(rAttr->GetStart()); - aCharAttribs.append('\t'); - aCharAttribs.append(rAttr->GetEnd()); + OString aCharAttribs = + "\nA" + + OString::number(nPortion) + + ": " + + OString::number(rAttr->GetItem()->Which()) + + "\t" + + OString::number(rAttr->GetStart()) + + "\t" + + OString::number(rAttr->GetEnd()); if ( rAttr->IsEmpty() ) bZeroAttr = true; fprintf(fp, "%s => ", aCharAttribs.getStr()); @@ -371,34 +383,33 @@ void EditEngine::DumpData(const EditEngine* pEE, bool bInfoBox) fprintf( fp, "\nNULL-Attribute!" ); const sal_Int32 nTextPortions = rPPortion.GetTextPortions().Count(); - OStringBuffer aPortionStr("\nText portions: #"); - aPortionStr.append(nTextPortions); - aPortionStr.append(" \nA"); - aPortionStr.append(nPortion); - aPortionStr.append(": Paragraph Length = "); - aPortionStr.append(rPPortion.GetNode()->Len()); - aPortionStr.append("\nA"); - aPortionStr.append(nPortion); - aPortionStr.append(": "); + OStringBuffer aPortionStr("\nText portions: #" + + OString::number(nTextPortions) + + " \nA" + + OString::number(nPortion) + + ": Paragraph Length = " + + OString::number(rPPortion.GetNode()->Len()) + + "\nA" + + OString::number(nPortion) + + ": "); sal_Int32 n = 0; for ( sal_Int32 z = 0; z < nTextPortions; ++z ) { - TextPortion& rPortion = rPPortion.GetTextPortions()[z]; - aPortionStr.append(' '); - aPortionStr.append(rPortion.GetLen()); - aPortionStr.append('('); - aPortionStr.append(static_cast<sal_Int32>(rPortion.GetSize().Width())); - aPortionStr.append(')'); - aPortionStr.append('['); - aPortionStr.append(static_cast<sal_Int32>(rPortion.GetKind())); - aPortionStr.append(']'); - aPortionStr.append(';'); + TextPortion const& rPortion = rPPortion.GetTextPortions()[z]; + aPortionStr.append(" " + + OString::number(rPortion.GetLen()) + + "(" + + OString::number(rPortion.GetSize().Width()) + + ")" + "[" + + OString::number(static_cast<sal_Int32>(rPortion.GetKind())) + + "];"); n += rPortion.GetLen(); } - aPortionStr.append("\nA"); - aPortionStr.append(nPortion); - aPortionStr.append(": Total length: "); - aPortionStr.append(n); + aPortionStr.append("\nA" + + OString::number(nPortion) + + ": Total length: " + + OString::number(n)); if ( rPPortion.GetNode()->Len() != n ) aPortionStr.append(" => Error !!!"); fprintf(fp, "%s", aPortionStr.getStr()); @@ -407,7 +418,7 @@ void EditEngine::DumpData(const EditEngine* pEE, bool bInfoBox) // First the content ... for ( sal_Int32 nLine = 0; nLine < rPPortion.GetLines().Count(); nLine++ ) { - EditLine& rLine = rPPortion.GetLines()[nLine]; + EditLine const& rLine = rPPortion.GetLines()[nLine]; OString aLine(OUStringToOString(rPPortion.GetNode()->Copy(rLine.GetStart(), rLine.GetEnd() - rLine.GetStart()), RTL_TEXTENCODING_ASCII_US)); fprintf( fp, "\nLine %" SAL_PRIdINT32 "\t>%s<", nLine, aLine.getStr() ); @@ -415,7 +426,7 @@ void EditEngine::DumpData(const EditEngine* pEE, bool bInfoBox) // then the internal data ... for ( sal_Int32 nLine = 0; nLine < rPPortion.GetLines().Count(); nLine++ ) { - EditLine& rLine = rPPortion.GetLines()[nLine]; + EditLine const& rLine = rPPortion.GetLines()[nLine]; fprintf( fp, "\nLine %" SAL_PRIdINT32 ":\tStart: %" SAL_PRIdINT32 ",\tEnd: %" SAL_PRIdINT32, nLine, rLine.GetStart(), rLine.GetEnd() ); fprintf( fp, "\t\tPortions: %" SAL_PRIdINT32 " - %" SAL_PRIdINT32 ".\tHight: %i, Ascent=%i", rLine.GetStartPortion(), rLine.GetEndPortion(), rLine.GetHeight(), rLine.GetMaxAscent() ); } @@ -423,9 +434,9 @@ void EditEngine::DumpData(const EditEngine* pEE, bool bInfoBox) fprintf( fp, "\n-----------------------------------------------------------------------------" ); } - if ( pEE->pImpEditEngine->GetStyleSheetPool() ) + if (pEE->getImpl().GetStyleSheetPool()) { - SfxStyleSheetIterator aIter( pEE->pImpEditEngine->GetStyleSheetPool(), SfxStyleFamily::All ); + SfxStyleSheetIterator aIter(pEE->getImpl().GetStyleSheetPool(), SfxStyleFamily::All); sal_uInt16 nStyles = aIter.Count(); fprintf( fp, "\n\n================================================================================" ); fprintf( fp, "\n================== Stylesheets =============================================" ); @@ -447,13 +458,13 @@ void EditEngine::DumpData(const EditEngine* pEE, bool bInfoBox) fprintf( fp, "\n\n================================================================================" ); fprintf( fp, "\n================== Defaults ================================================" ); fprintf( fp, "\n================================================================================" ); - DbgOutItemSet( fp, pEE->pImpEditEngine->GetEmptyItemSet(), true, true ); + DbgOutItemSet(fp, pEE->getImpl().GetEmptyItemSet(), true, true); fprintf( fp, "\n\n================================================================================" ); fprintf( fp, "\n================== EditEngine & Views ======================================" ); fprintf( fp, "\n================================================================================" ); fprintf( fp, "\nControl: %x", unsigned( pEE->GetControlWord() ) ); - fprintf( fp, "\nRefMapMode: %i", int( pEE->pImpEditEngine->pRefDev->GetMapMode().GetMapUnit() ) ); + fprintf( fp, "\nRefMapMode: %i", int( pEE->getImpl().mpRefDev->GetMapMode().GetMapUnit())); fprintf( fp, "\nPaperSize: %" SAL_PRIdINT64 " x %" SAL_PRIdINT64, sal_Int64(pEE->GetPaperSize().Width()), sal_Int64(pEE->GetPaperSize().Height()) ); fprintf( fp, "\nMaxAutoPaperSize: %" SAL_PRIdINT64 " x %" SAL_PRIdINT64, sal_Int64(pEE->GetMaxAutoPaperSize().Width()), sal_Int64(pEE->GetMaxAutoPaperSize().Height()) ); fprintf( fp, "\nMinAutoPaperSize: %" SAL_PRIdINT64 " x %" SAL_PRIdINT64 , sal_Int64(pEE->GetMinAutoPaperSize().Width()), sal_Int64(pEE->GetMinAutoPaperSize().Height()) ); @@ -496,11 +507,12 @@ bool ParaPortion::DbgCheckTextPortions(ParaPortion const& rPara) { // check, if Portion length ok: sal_uInt16 nXLen = 0; - for (sal_Int32 nPortion = 0; nPortion < rPara.aTextPortionList.Count(); nPortion++) + + for (sal_Int32 nPortion = 0; nPortion < rPara.maTextPortionList.Count(); nPortion++) { - nXLen = nXLen + rPara.aTextPortionList[nPortion].GetLen(); + nXLen = nXLen + rPara.maTextPortionList[nPortion].GetLen(); } - return nXLen == rPara.pNode->Len(); + return nXLen == rPara.mpNode->Len(); } #endif diff --git a/editeng/source/editeng/editdoc.cxx b/editeng/source/editeng/editdoc.cxx index 36a7d5727434..e482eea38652 100644 --- a/editeng/source/editeng/editdoc.cxx +++ b/editeng/source/editeng/editdoc.cxx @@ -50,19 +50,23 @@ #include <rtl/ustrbuf.hxx> #include <sal/log.hxx> +#include <o3tl/safeint.hxx> #include <osl/diagnose.h> #include <svl/grabbagitem.hxx> +#include <svl/voiditem.hxx> #include <tools/debug.hxx> #include <com/sun/star/i18n/ScriptType.hpp> #include <libxml/xmlwriter.h> #include <algorithm> #include <cassert> +#include <cstddef> #include <limits> #include <memory> #include <set> #include <string_view> +#include <utility> using namespace ::com::sun::star; @@ -153,454 +157,230 @@ bool IsScriptItemValid( sal_uInt16 nItemId, short nScriptType ) return bValid; } -const SfxItemInfo aItemInfos[EDITITEMCOUNT] = { - { SID_ATTR_FRAMEDIRECTION, true }, // EE_PARA_WRITINGDIR - { 0, true }, // EE_PARA_XMLATTRIBS - { SID_ATTR_PARA_HANGPUNCTUATION, true }, // EE_PARA_HANGINGPUNCTUATION - { SID_ATTR_PARA_FORBIDDEN_RULES, true }, // EE_PARA_FORBIDDENRULES - { SID_ATTR_PARA_SCRIPTSPACE, true }, // EE_PARA_ASIANCJKSPACING - { SID_ATTR_NUMBERING_RULE, true }, // EE_PARA_NUMBULL - { 0, true }, // EE_PARA_HYPHENATE - { 0, true }, // EE_PARA_HYPHENATE_NO_CAPS - { 0, true }, // EE_PARA_BULLETSTATE - { 0, true }, // EE_PARA_OUTLLRSPACE - { SID_ATTR_PARA_OUTLLEVEL, true }, // EE_PARA_OUTLLEVEL - { SID_ATTR_PARA_BULLET, true }, // EE_PARA_BULLET - { SID_ATTR_LRSPACE, true }, // EE_PARA_LRSPACE - { SID_ATTR_ULSPACE, true }, // EE_PARA_ULSPACE - { SID_ATTR_PARA_LINESPACE, true }, // EE_PARA_SBL - { SID_ATTR_PARA_ADJUST, true }, // EE_PARA_JUST - { SID_ATTR_TABSTOP, true }, // EE_PARA_TABS - { SID_ATTR_ALIGN_HOR_JUSTIFY_METHOD, true }, // EE_PARA_JUST_METHOD - { SID_ATTR_ALIGN_VER_JUSTIFY, true }, // EE_PARA_VER_JUST - { SID_ATTR_CHAR_COLOR, true }, // EE_CHAR_COLOR - { SID_ATTR_CHAR_FONT, true }, // EE_CHAR_FONTINFO - { SID_ATTR_CHAR_FONTHEIGHT, true }, // EE_CHAR_FONTHEIGHT - { SID_ATTR_CHAR_SCALEWIDTH, true }, // EE_CHAR_FONTWIDTH - { SID_ATTR_CHAR_WEIGHT, true }, // EE_CHAR_WEIGHT - { SID_ATTR_CHAR_UNDERLINE, true }, // EE_CHAR_UNDERLINE - { SID_ATTR_CHAR_STRIKEOUT, true }, // EE_CHAR_STRIKEOUT - { SID_ATTR_CHAR_POSTURE, true }, // EE_CHAR_ITALIC - { SID_ATTR_CHAR_CONTOUR, true }, // EE_CHAR_OUTLINE - { SID_ATTR_CHAR_SHADOWED, true }, // EE_CHAR_SHADOW - { SID_ATTR_CHAR_ESCAPEMENT, true }, // EE_CHAR_ESCAPEMENT - { SID_ATTR_CHAR_AUTOKERN, true }, // EE_CHAR_PAIRKERNING - { SID_ATTR_CHAR_KERNING, true }, // EE_CHAR_KERNING - { SID_ATTR_CHAR_WORDLINEMODE, true }, // EE_CHAR_WLM - { SID_ATTR_CHAR_LANGUAGE, true }, // EE_CHAR_LANGUAGE - { SID_ATTR_CHAR_CJK_LANGUAGE, true }, // EE_CHAR_LANGUAGE_CJK - { SID_ATTR_CHAR_CTL_LANGUAGE, true }, // EE_CHAR_LANGUAGE_CTL - { SID_ATTR_CHAR_CJK_FONT, true }, // EE_CHAR_FONTINFO_CJK - { SID_ATTR_CHAR_CTL_FONT, true }, // EE_CHAR_FONTINFO_CTL - { SID_ATTR_CHAR_CJK_FONTHEIGHT, true }, // EE_CHAR_FONTHEIGHT_CJK - { SID_ATTR_CHAR_CTL_FONTHEIGHT, true }, // EE_CHAR_FONTHEIGHT_CTL - { SID_ATTR_CHAR_CJK_WEIGHT, true }, // EE_CHAR_WEIGHT_CJK - { SID_ATTR_CHAR_CTL_WEIGHT, true }, // EE_CHAR_WEIGHT_CTL - { SID_ATTR_CHAR_CJK_POSTURE, true }, // EE_CHAR_ITALIC_CJK - { SID_ATTR_CHAR_CTL_POSTURE, true }, // EE_CHAR_ITALIC_CTL - { SID_ATTR_CHAR_EMPHASISMARK, true }, // EE_CHAR_EMPHASISMARK - { SID_ATTR_CHAR_RELIEF, true }, // EE_CHAR_RELIEF - { 0, true }, // EE_CHAR_RUBI_DUMMY - { 0, true }, // EE_CHAR_XMLATTRIBS - { SID_ATTR_CHAR_OVERLINE, true }, // EE_CHAR_OVERLINE - { SID_ATTR_CHAR_CASEMAP, true }, // EE_CHAR_CASEMAP - { SID_ATTR_CHAR_GRABBAG, true }, // EE_CHAR_GRABBAG - { SID_ATTR_CHAR_BACK_COLOR, true }, // EE_CHAR_BKGCOLOR - { 0, true }, // EE_FEATURE_TAB - { 0, true }, // EE_FEATURE_LINEBR - { SID_ATTR_CHAR_CHARSETCOLOR, true }, // EE_FEATURE_NOTCONV - { SID_FIELD, false }, // EE_FEATURE_FIELD -}; - EditCharAttrib* MakeCharAttrib( SfxItemPool& rPool, const SfxPoolItem& rAttr, sal_Int32 nS, sal_Int32 nE ) { // Create a new attribute in the pool - const SfxPoolItem& rNew = rPool.Put( rAttr ); - - EditCharAttrib* pNew = nullptr; - switch( rNew.Which() ) + switch( rAttr.Which() ) { case EE_CHAR_LANGUAGE: case EE_CHAR_LANGUAGE_CJK: case EE_CHAR_LANGUAGE_CTL: { - pNew = new EditCharAttribLanguage( static_cast<const SvxLanguageItem&>(rNew), nS, nE ); + return new EditCharAttribLanguage(rPool, rAttr, nS, nE); } break; case EE_CHAR_COLOR: { - pNew = new EditCharAttribColor( static_cast<const SvxColorItem&>(rNew), nS, nE ); + return new EditCharAttribColor(rPool, rAttr, nS, nE ); } break; case EE_CHAR_FONTINFO: case EE_CHAR_FONTINFO_CJK: case EE_CHAR_FONTINFO_CTL: { - pNew = new EditCharAttribFont( static_cast<const SvxFontItem&>(rNew), nS, nE ); + return new EditCharAttribFont(rPool, rAttr, nS, nE ); } break; case EE_CHAR_FONTHEIGHT: case EE_CHAR_FONTHEIGHT_CJK: case EE_CHAR_FONTHEIGHT_CTL: { - pNew = new EditCharAttribFontHeight( static_cast<const SvxFontHeightItem&>(rNew), nS, nE ); + return new EditCharAttribFontHeight(rPool, rAttr, nS, nE ); } break; case EE_CHAR_FONTWIDTH: { - pNew = new EditCharAttribFontWidth( static_cast<const SvxCharScaleWidthItem&>(rNew), nS, nE ); + return new EditCharAttribFontWidth(rPool, rAttr, nS, nE ); } break; case EE_CHAR_WEIGHT: case EE_CHAR_WEIGHT_CJK: case EE_CHAR_WEIGHT_CTL: { - pNew = new EditCharAttribWeight( static_cast<const SvxWeightItem&>(rNew), nS, nE ); + return new EditCharAttribWeight(rPool, rAttr, nS, nE ); } break; case EE_CHAR_UNDERLINE: { - pNew = new EditCharAttribUnderline( static_cast<const SvxUnderlineItem&>(rNew), nS, nE ); + return new EditCharAttribUnderline(rPool, rAttr, nS, nE ); } break; case EE_CHAR_OVERLINE: { - pNew = new EditCharAttribOverline( static_cast<const SvxOverlineItem&>(rNew), nS, nE ); + return new EditCharAttribOverline(rPool, rAttr, nS, nE ); } break; case EE_CHAR_EMPHASISMARK: { - pNew = new EditCharAttribEmphasisMark( static_cast<const SvxEmphasisMarkItem&>(rNew), nS, nE ); + return new EditCharAttribEmphasisMark(rPool, rAttr, nS, nE ); } break; case EE_CHAR_RELIEF: { - pNew = new EditCharAttribRelief( static_cast<const SvxCharReliefItem&>(rNew), nS, nE ); + return new EditCharAttribRelief(rPool, rAttr, nS, nE ); } break; case EE_CHAR_STRIKEOUT: { - pNew = new EditCharAttribStrikeout( static_cast<const SvxCrossedOutItem&>(rNew), nS, nE ); + return new EditCharAttribStrikeout(rPool, rAttr, nS, nE ); } break; case EE_CHAR_ITALIC: case EE_CHAR_ITALIC_CJK: case EE_CHAR_ITALIC_CTL: { - pNew = new EditCharAttribItalic( static_cast<const SvxPostureItem&>(rNew), nS, nE ); + return new EditCharAttribItalic(rPool, rAttr, nS, nE ); } break; case EE_CHAR_OUTLINE: { - pNew = new EditCharAttribOutline( static_cast<const SvxContourItem&>(rNew), nS, nE ); + return new EditCharAttribOutline(rPool, rAttr, nS, nE ); } break; case EE_CHAR_SHADOW: { - pNew = new EditCharAttribShadow( static_cast<const SvxShadowedItem&>(rNew), nS, nE ); + return new EditCharAttribShadow(rPool, rAttr, nS, nE ); } break; case EE_CHAR_ESCAPEMENT: { - pNew = new EditCharAttribEscapement( static_cast<const SvxEscapementItem&>(rNew), nS, nE ); + return new EditCharAttribEscapement(rPool, rAttr, nS, nE ); } break; case EE_CHAR_PAIRKERNING: { - pNew = new EditCharAttribPairKerning( static_cast<const SvxAutoKernItem&>(rNew), nS, nE ); + return new EditCharAttribPairKerning(rPool, rAttr, nS, nE ); } break; case EE_CHAR_KERNING: { - pNew = new EditCharAttribKerning( static_cast<const SvxKerningItem&>(rNew), nS, nE ); + return new EditCharAttribKerning(rPool, rAttr, nS, nE ); } break; case EE_CHAR_WLM: { - pNew = new EditCharAttribWordLineMode( static_cast<const SvxWordLineModeItem&>(rNew), nS, nE ); + return new EditCharAttribWordLineMode(rPool, rAttr, nS, nE ); } break; case EE_CHAR_XMLATTRIBS: { - pNew = new EditCharAttrib( rNew, nS, nE ); // Attribute is only for holding XML information... + return new EditCharAttrib(rPool, rAttr, nS, nE); // Attribute is only for holding XML information... } break; case EE_CHAR_CASEMAP: { - pNew = new EditCharAttribCaseMap( static_cast<const SvxCaseMapItem&>(rNew), nS, nE ); + return new EditCharAttribCaseMap(rPool, rAttr, nS, nE ); } break; case EE_CHAR_GRABBAG: { - pNew = new EditCharAttribGrabBag( static_cast<const SfxGrabBagItem&>(rNew), nS, nE ); + return new EditCharAttribGrabBag(rPool, rAttr, nS, nE ); } break; case EE_FEATURE_TAB: { - pNew = new EditCharAttribTab( static_cast<const SfxVoidItem&>(rNew), nS ); + return new EditCharAttribTab(rPool, rAttr, nS ); } break; case EE_FEATURE_LINEBR: { - pNew = new EditCharAttribLineBreak( static_cast<const SfxVoidItem&>(rNew), nS ); + return new EditCharAttribLineBreak(rPool, rAttr, nS ); } break; case EE_FEATURE_FIELD: { - pNew = new EditCharAttribField( static_cast<const SvxFieldItem&>(rNew), nS ); + return new EditCharAttribField(rPool, rAttr, nS ); } break; case EE_CHAR_BKGCOLOR: { - pNew = new EditCharAttribBackgroundColor( static_cast<const SvxColorItem&>(rNew), nS, nE ); + return new EditCharAttribBackgroundColor(rPool, rAttr, nS, nE ); } break; default: - { - OSL_FAIL( "Invalid Attribute!" ); - } - } - return pNew; -} - -TextPortionList::TextPortionList() -{ -} - -TextPortionList::~TextPortionList() -{ -} - -void TextPortionList::Reset() -{ - maPortions.clear(); -} - -void TextPortionList::DeleteFromPortion(sal_Int32 nDelFrom) -{ - assert((nDelFrom < static_cast<sal_Int32>(maPortions.size())) || ((nDelFrom == 0) && maPortions.empty())); - PortionsType::iterator it = maPortions.begin(); - std::advance(it, nDelFrom); - maPortions.erase(it, maPortions.end()); -} - -sal_Int32 TextPortionList::Count() const -{ - return static_cast<sal_Int32>(maPortions.size()); -} - -const TextPortion& TextPortionList::operator[](sal_Int32 nPos) const -{ - return *maPortions[nPos]; -} - -TextPortion& TextPortionList::operator[](sal_Int32 nPos) -{ - return *maPortions[nPos]; -} - -void TextPortionList::Append(TextPortion* p) -{ - maPortions.push_back(std::unique_ptr<TextPortion>(p)); -} - -void TextPortionList::Insert(sal_Int32 nPos, TextPortion* p) -{ - maPortions.insert(maPortions.begin()+nPos, std::unique_ptr<TextPortion>(p)); -} - -void TextPortionList::Remove(sal_Int32 nPos) -{ - maPortions.erase(maPortions.begin()+nPos); -} - -namespace { - -class FindTextPortionByAddress -{ - const TextPortion* mp; -public: - explicit FindTextPortionByAddress(const TextPortion* p) : mp(p) {} - bool operator() (const std::unique_ptr<TextPortion>& v) const - { - return v.get() == mp; - } -}; - -} - -sal_Int32 TextPortionList::GetPos(const TextPortion* p) const -{ - PortionsType::const_iterator it = - std::find_if(maPortions.begin(), maPortions.end(), FindTextPortionByAddress(p)); - - if (it == maPortions.end()) - return std::numeric_limits<sal_Int32>::max(); // not found. - - return std::distance(maPortions.begin(), it); -} - -sal_Int32 TextPortionList::FindPortion( - sal_Int32 nCharPos, sal_Int32& nPortionStart, bool bPreferStartingPortion) const -{ - // When nCharPos at portion limit, the left portion is found - sal_Int32 nTmpPos = 0; - sal_Int32 n = maPortions.size(); - for (sal_Int32 i = 0; i < n; ++i) - { - const TextPortion& rPortion = *maPortions[i]; - nTmpPos = nTmpPos + rPortion.GetLen(); - if ( nTmpPos >= nCharPos ) - { - // take this one if we don't prefer the starting portion, or if it's the last one - if ( ( nTmpPos != nCharPos ) || !bPreferStartingPortion || ( i == n-1 ) ) - { - nPortionStart = nTmpPos - rPortion.GetLen(); - return i; - } - } - } - OSL_FAIL( "FindPortion: Not found!" ); - return n - 1; -} - -sal_Int32 TextPortionList::GetStartPos(sal_Int32 nPortion) -{ - sal_Int32 nPos = 0; - for (sal_Int32 i = 0; i < nPortion; ++i) - { - const TextPortion& rPortion = *maPortions[i]; - nPos = nPos + rPortion.GetLen(); - } - return nPos; -} - -ExtraPortionInfo::ExtraPortionInfo() -: nOrgWidth(0) -, nWidthFullCompression(0) -, nPortionOffsetX(0) -, nMaxCompression100thPercent(0) -, nAsianCompressionTypes(AsianCompressionFlags::Normal) -, bFirstCharIsRightPunktuation(false) -, bCompressed(false) -{ -} - -ExtraPortionInfo::~ExtraPortionInfo() -{ -} - -void ExtraPortionInfo::SaveOrgDXArray( const sal_Int32* pDXArray, sal_Int32 nLen ) -{ - if (pDXArray) - { - pOrgDXArray.reset(new sal_Int32[nLen]); - memcpy( pOrgDXArray.get(), pDXArray, nLen * sizeof(sal_Int32) ); + break; } - else - pOrgDXArray.reset(); -} - -ParaPortion::ParaPortion( ContentNode* pN ) : - pNode(pN), - nHeight(0), - nInvalidPosStart(0), - nFirstLineOffset(0), - nBulletX(0), - nInvalidDiff(0), - bInvalid(true), - bSimple(false), - bVisible(true), - bForceRepaint(false) -{ -} -ParaPortion::~ParaPortion() -{ + OSL_FAIL( "Invalid Attribute!" ); + return nullptr; } -void ParaPortion::MarkInvalid( sal_Int32 nStart, sal_Int32 nDiff ) +void ParaPortion::MarkInvalid(sal_Int32 nStart, sal_Int32 nDiff) { - if ( !bInvalid ) + if (!mbInvalid) { -// nInvalidPosEnd = nStart; // ??? => CreateLines - nInvalidPosStart = ( nDiff >= 0 ) ? nStart : ( nStart + nDiff ); - nInvalidDiff = nDiff; +// mnInvalidPosEnd = nStart; // ??? => CreateLines + mnInvalidPosStart = nDiff >= 0 ? nStart : nStart + nDiff; + mnInvalidDiff = nDiff; } else { // Simple tap in succession - if ( ( nDiff > 0 ) && ( nInvalidDiff > 0 ) && - ( ( nInvalidPosStart+nInvalidDiff ) == nStart ) ) + if (nDiff > 0 && mnInvalidDiff > 0 && (mnInvalidPosStart + mnInvalidDiff) == nStart) { - nInvalidDiff = nInvalidDiff + nDiff; + mnInvalidDiff = mnInvalidDiff + nDiff; } // Simple delete in succession - else if ( ( nDiff < 0 ) && ( nInvalidDiff < 0 ) && ( nInvalidPosStart == nStart ) ) + else if (nDiff < 0 && mnInvalidDiff < 0 && mnInvalidPosStart == nStart) { - nInvalidPosStart = nInvalidPosStart + nDiff; - nInvalidDiff = nInvalidDiff + nDiff; + mnInvalidPosStart = mnInvalidPosStart + nDiff; + mnInvalidDiff = mnInvalidDiff + nDiff; } else { -// nInvalidPosEnd = pNode->Len(); - DBG_ASSERT( ( nDiff >= 0 ) || ( (nStart+nDiff) >= 0 ), "MarkInvalid: Diff out of Range" ); - nInvalidPosStart = std::min( nInvalidPosStart, ( nDiff < 0 ? nStart+nDiff : nDiff ) ); - nInvalidDiff = 0; - bSimple = false; +// mnInvalidPosEnd = pNode->Len(); + DBG_ASSERT(nDiff >= 0 || (nStart + nDiff) >= 0, "MarkInvalid: Diff out of Range"); + mnInvalidPosStart = std::min(mnInvalidPosStart, nDiff < 0 ? nStart + nDiff : nDiff); + mnInvalidDiff = 0; + mbSimple = false; } } - bInvalid = true; - aScriptInfos.clear(); - aWritingDirectionInfos.clear(); + mbInvalid = true; + maScriptInfos.clear(); + maWritingDirectionInfos.clear(); } -void ParaPortion::MarkSelectionInvalid( sal_Int32 nStart ) +void ParaPortion::MarkSelectionInvalid(sal_Int32 nStart) { - if ( !bInvalid ) + if ( !mbInvalid ) { - nInvalidPosStart = nStart; + mnInvalidPosStart = nStart; } else { - nInvalidPosStart = std::min( nInvalidPosStart, nStart ); + mnInvalidPosStart = std::min(mnInvalidPosStart, nStart); } - nInvalidDiff = 0; - bInvalid = true; - bSimple = false; - aScriptInfos.clear(); - aWritingDirectionInfos.clear(); + mnInvalidDiff = 0; + mbInvalid = true; + mbSimple = false; + maScriptInfos.clear(); + maWritingDirectionInfos.clear(); } sal_Int32 ParaPortion::GetLineNumber( sal_Int32 nIndex ) const { - SAL_WARN_IF( !aLineList.Count(), "editeng", "Empty ParaPortion in GetLine!" ); - DBG_ASSERT( bVisible, "Why GetLine() on an invisible paragraph?" ); + SAL_WARN_IF(!maLineList.Count(), "editeng", "Empty ParaPortion in GetLine!"); + DBG_ASSERT(mbVisible, "Why GetLine() on an invisible paragraph?"); - for ( sal_Int32 nLine = 0; nLine < aLineList.Count(); nLine++ ) + for ( sal_Int32 nLine = 0; nLine < maLineList.Count(); nLine++ ) { - if ( aLineList[nLine].IsIn( nIndex ) ) + if (maLineList[nLine].IsIn(nIndex)) return nLine; } // Then it should be at the end of the last line! - DBG_ASSERT( nIndex == aLineList[ aLineList.Count() - 1 ].GetEnd(), "Index dead wrong!" ); - return (aLineList.Count()-1); -} - -void ParaPortion::SetVisible( bool bMakeVisible ) -{ - bVisible = bMakeVisible; + DBG_ASSERT(nIndex == maLineList[maLineList.Count() - 1].GetEnd(), "Index dead wrong!"); + return (maLineList.Count() - 1); } void ParaPortion::CorrectValuesBehindLastFormattedLine( sal_Int32 nLastFormattedLine ) { - sal_Int32 nLines = aLineList.Count(); + sal_Int32 nLines = maLineList.Count(); DBG_ASSERT( nLines, "CorrectPortionNumbersFromLine: Empty Portion?" ); if ( nLastFormattedLine < ( nLines - 1 ) ) { - const EditLine& rLastFormatted = aLineList[ nLastFormattedLine ]; - const EditLine& rUnformatted = aLineList[ nLastFormattedLine+1 ]; + const EditLine& rLastFormatted = maLineList[ nLastFormattedLine ]; + const EditLine& rUnformatted = maLineList[ nLastFormattedLine+1 ]; sal_Int32 nPortionDiff = rUnformatted.GetStartPortion() - rLastFormatted.GetEndPortion(); sal_Int32 nTextDiff = rUnformatted.GetStart() - rLastFormatted.GetEnd(); nTextDiff++; // LastFormatted->GetEnd() was included => 1 deducted too much! @@ -615,7 +395,7 @@ void ParaPortion::CorrectValuesBehindLastFormattedLine( sal_Int32 nLastFormatted { for ( sal_Int32 nL = nLastFormattedLine+1; nL < nLines; nL++ ) { - EditLine& rLine = aLineList[ nL ]; + EditLine& rLine = maLineList[ nL ]; rLine.GetStartPortion() = rLine.GetStartPortion() + nPDiff; rLine.GetEndPortion() = rLine.GetEndPortion() + nPDiff; @@ -627,7 +407,7 @@ void ParaPortion::CorrectValuesBehindLastFormattedLine( sal_Int32 nLastFormatted } } } - DBG_ASSERT( aLineList[ aLineList.Count()-1 ].GetEnd() == pNode->Len(), "CorrectLines: The end is not right!" ); + DBG_ASSERT(maLineList[maLineList.Count() - 1].GetEnd() == mpNode->Len(), "CorrectLines: The end is not right!"); } // Shared reverse lookup acceleration pieces ... @@ -673,75 +453,44 @@ sal_Int32 FastGetPos(const Array& rArray, const Val* p, sal_Int32& rLastPos) } -ParaPortionList::ParaPortionList() : nLastCache( 0 ) -{ -} - -ParaPortionList::~ParaPortionList() +sal_Int32 ParaPortionList::GetPos(const ParaPortion* p) const { + return FastGetPos(maPortions, p, nLastCache); } -sal_Int32 ParaPortionList::GetPos(const ParaPortion* p) const +std::unique_ptr<ParaPortion> ParaPortionList::Release(sal_Int32 nPos) { - sal_Int32 nArrayLen = maPortions.size(); - - // Through certain filter code-paths we do a lot of appends, which in - // turn call GetPos - creating some N^2 nightmares. If we have a - // non-trivially large list, do a few checks from the end first. - if (nLastCache > 16 && nArrayLen > 16) + if (nPos < 0 || maPortions.size() <= o3tl::make_unsigned(nPos)) { - sal_Int32 nEnd; - if (nLastCache > nArrayLen - 2) - nEnd = nArrayLen; - else - nEnd = nLastCache + 2; - - for (sal_Int32 nIdx = nLastCache - 2; nIdx < nEnd; ++nIdx) - { - if (&maPortions.at(nIdx) == p) - { - nLastCache = nIdx; - return nIdx; - } - } + SAL_WARN( "editeng", "ParaPortionList::Release - out of bounds pos " << nPos); + return nullptr; } - // The world's lamest linear search from svarray... - for (sal_Int32 nIdx = 0; nIdx < nArrayLen; ++nIdx) - if (&maPortions.at(nIdx) == p) - { - nLastCache = nIdx; - return nLastCache; - } - - // XXX "not found" condition for sal_Int32 indexes - return EE_PARA_NOT_FOUND; -} - -ParaPortion& ParaPortionList::operator [](sal_Int32 nPos) -{ - return maPortions[nPos]; -} - -const ParaPortion& ParaPortionList::operator [](sal_Int32 nPos) const -{ - return maPortions[nPos]; + std::unique_ptr<ParaPortion> p = std::move(maPortions[nPos]); + maPortions.erase(maPortions.begin()+nPos); + return p; } -ParaPortion ParaPortionList::Remove(sal_Int32 nPos) +void ParaPortionList::Remove(sal_Int32 nPos) { - auto it = maPortions.begin()+nPos; - ParaPortion val = std::move(*it); - maPortions.erase(it); - return val; + if (nPos < 0 || maPortions.size() <= o3tl::make_unsigned(nPos)) + { + SAL_WARN( "editeng", "ParaPortionList::Remove - out of bounds pos " << nPos); + return; + } + maPortions.erase(maPortions.begin()+nPos); } -ParaPortion& ParaPortionList::Insert(sal_Int32 nPos, ParaPortion&& p) +void ParaPortionList::Insert(sal_Int32 nPos, std::unique_ptr<ParaPortion> p) { + if (nPos < 0 || maPortions.size() < o3tl::make_unsigned(nPos)) + { + SAL_WARN( "editeng", "ParaPortionList::Insert - out of bounds pos " << nPos); + return; + } maPortions.insert(maPortions.begin()+nPos, std::move(p)); - return maPortions[nPos]; } -void ParaPortionList::Append(ParaPortion&& p) +void ParaPortionList::Append(std::unique_ptr<ParaPortion> p) { maPortions.push_back(std::move(p)); } @@ -767,9 +516,10 @@ tools::Long ParaPortionList::GetYOffset(const ParaPortion* pPPortion) const tools::Long nHeight = 0; for (const auto & rPortion : maPortions) { - if ( pPPortion == &rPortion ) + const ParaPortion* pTmpPortion = rPortion.get(); + if ( pTmpPortion == pPPortion ) return nHeight; - nHeight += rPortion.GetHeight(); + nHeight += pTmpPortion->GetHeight(); } OSL_FAIL( "GetYOffset: Portion not found" ); return nHeight; @@ -780,23 +530,13 @@ sal_Int32 ParaPortionList::FindParagraph(tools::Long nYOffset) const tools::Long nY = 0; for (size_t i = 0, n = maPortions.size(); i < n; ++i) { - nY += maPortions[i].GetHeight(); // should also be correct even in bVisible! + nY += maPortions[i]->GetHeight(); // should also be correct even in bVisible! if ( nY > nYOffset ) return i <= SAL_MAX_INT32 ? static_cast<sal_Int32>(i) : SAL_MAX_INT32; } return EE_PARA_NOT_FOUND; } -const ParaPortion* ParaPortionList::SafeGetObject(sal_Int32 nPos) const -{ - return 0 <= nPos && nPos < static_cast<sal_Int32>(maPortions.size()) ? &maPortions[nPos] : nullptr; -} - -ParaPortion* ParaPortionList::SafeGetObject(sal_Int32 nPos) -{ - return 0 <= nPos && nPos < static_cast<sal_Int32>(maPortions.size()) ? &maPortions[nPos] : nullptr; -} - #if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG void ParaPortionList::DbgCheck(ParaPortionList const& rParas, EditDoc const& rDoc) @@ -811,15 +551,9 @@ ParaPortionList::DbgCheck(ParaPortionList const& rParas, EditDoc const& rDoc) } #endif -ContentAttribsInfo::ContentAttribsInfo( const SfxItemSet& rParaAttribs ) : - aPrevParaAttribs( rParaAttribs) -{ -} - -void ContentAttribsInfo::RemoveAllCharAttribsFromPool(SfxItemPool& rPool) const +ContentAttribsInfo::ContentAttribsInfo( SfxItemSet aParaAttribs ) : + aPrevParaAttribs(std::move( aParaAttribs)) { - for (const std::unique_ptr<EditCharAttrib>& rAttrib : aPrevCharAttribs) - rPool.Remove(*rAttrib->GetItem()); } void ContentAttribsInfo::AppendCharAttrib(EditCharAttrib* pNew) @@ -864,6 +598,13 @@ void ConvertItem( std::unique_ptr<SfxPoolItem>& rPoolItem, MapUnit eSourceUnit, assert(dynamic_cast<const SvxTabStopItem *>(rPoolItem.get()) != nullptr); SvxTabStopItem& rItem = static_cast<SvxTabStopItem&>(*rPoolItem); SvxTabStopItem* pNewItem(new SvxTabStopItem(EE_PARA_TABS)); + + if (sal_Int32 nDefTabDistance = rItem.GetDefaultDistance()) + { + pNewItem->SetDefaultDistance( + OutputDevice::LogicToLogic(nDefTabDistance, eSourceUnit, eDestUnit)); + } + for ( sal_uInt16 i = 0; i < rItem.Count(); i++ ) { const SvxTabStop& rTab = rItem[i]; @@ -898,7 +639,7 @@ void ConvertAndPutItems( SfxItemSet& rDest, const SfxItemSet& rSource, const Map sal_uInt16 nSlot = pDestPool->GetTrueSlotId( nWhich ); if ( nSlot ) { - sal_uInt16 nW = pSourcePool->GetTrueWhich( nSlot ); + sal_uInt16 nW = pSourcePool->GetTrueWhichIDFromSlotID( nSlot ); if ( nW ) nSourceWhich = nW; } @@ -922,179 +663,6 @@ void ConvertAndPutItems( SfxItemSet& rDest, const SfxItemSet& rSource, const Map } } -EditLine::EditLine() : - nTxtWidth(0), - nStartPosX(0), - nStart(0), - nEnd(0), - nStartPortion(0), // to be able to tell the difference between a line - // without Portions from one with the Portion number 0 - nEndPortion(0), - nHeight(0), - nTxtHeight(0), - nMaxAscent(0), - bHangingPunctuation(false), - bInvalid(true) -{ -} - -EditLine* EditLine::Clone() const -{ - EditLine* pL = new EditLine; - pL->aPositions = aPositions; - pL->nStartPosX = nStartPosX; - pL->nStart = nStart; - pL->nEnd = nEnd; - pL->nStartPortion = nStartPortion; - pL->nEndPortion = nEndPortion; - pL->nHeight = nHeight; - pL->nTxtWidth = nTxtWidth; - pL->nTxtHeight = nTxtHeight; - pL->nMaxAscent = nMaxAscent; - - return pL; -} - -bool operator == ( const EditLine& r1, const EditLine& r2 ) -{ - if ( r1.nStart != r2.nStart ) - return false; - - if ( r1.nEnd != r2.nEnd ) - return false; - - if ( r1.nStartPortion != r2.nStartPortion ) - return false; - - if ( r1.nEndPortion != r2.nEndPortion ) - return false; - - return true; -} - - -void EditLine::SetHeight( sal_uInt16 nH, sal_uInt16 nTxtH ) -{ - nHeight = nH; - nTxtHeight = ( nTxtH ? nTxtH : nH ); -} - -void EditLine::SetStartPosX( sal_Int32 start ) -{ - if (start > 0) - nStartPosX = start; - else - nStartPosX = 0; -} - -Size EditLine::CalcTextSize( ParaPortion& rParaPortion ) -{ - Size aSz; - Size aTmpSz; - - DBG_ASSERT( rParaPortion.GetTextPortions().Count(), "GetTextSize before CreatePortions !" ); - - for ( sal_Int32 n = nStartPortion; n <= nEndPortion; n++ ) - { - TextPortion& rPortion = rParaPortion.GetTextPortions()[n]; - switch ( rPortion.GetKind() ) - { - case PortionKind::TEXT: - case PortionKind::FIELD: - case PortionKind::HYPHENATOR: - { - aTmpSz = rPortion.GetSize(); - aSz.AdjustWidth(aTmpSz.Width() ); - if ( aSz.Height() < aTmpSz.Height() ) - aSz.setHeight( aTmpSz.Height() ); - } - break; - case PortionKind::TAB: - { - aSz.AdjustWidth(rPortion.GetSize().Width() ); - } - break; - case PortionKind::LINEBREAK: break; - } - } - - SetHeight( static_cast<sal_uInt16>(aSz.Height()) ); - return aSz; -} - -EditLineList::EditLineList() -{ -} - -EditLineList::~EditLineList() -{ - Reset(); -} - -void EditLineList::Reset() -{ - maLines.clear(); -} - -void EditLineList::DeleteFromLine(sal_Int32 nDelFrom) -{ - assert(nDelFrom <= (static_cast<sal_Int32>(maLines.size()) - 1)); - LinesType::iterator it = maLines.begin(); - std::advance(it, nDelFrom); - maLines.erase(it, maLines.end()); -} - -sal_Int32 EditLineList::FindLine(sal_Int32 nChar, bool bInclEnd) -{ - sal_Int32 n = maLines.size(); - for (sal_Int32 i = 0; i < n; ++i) - { - const EditLine& rLine = *maLines[i]; - if ( (bInclEnd && (rLine.GetEnd() >= nChar)) || - (rLine.GetEnd() > nChar) ) - { - return i; - } - } - - DBG_ASSERT( !bInclEnd, "Line not found: FindLine" ); - return n - 1; -} - -sal_Int32 EditLineList::Count() const -{ - return maLines.size(); -} - -const EditLine& EditLineList::operator[](sal_Int32 nPos) const -{ - return *maLines[nPos]; -} - -EditLine& EditLineList::operator[](sal_Int32 nPos) -{ - return *maLines[nPos]; -} - -void EditLineList::Append(EditLine* p) -{ - maLines.push_back(std::unique_ptr<EditLine>(p)); -} - -void EditLineList::Insert(sal_Int32 nPos, EditLine* p) -{ - maLines.insert(maLines.begin()+nPos, std::unique_ptr<EditLine>(p)); -} - -EditPaM::EditPaM() : pNode(nullptr), nIndex(0) {} -EditPaM::EditPaM(ContentNode* p, sal_Int32 n) : pNode(p), nIndex(n) {} - - -void EditPaM::SetNode(ContentNode* p) -{ - pNode = p; -} - bool EditPaM::DbgIsBuggy( EditDoc const & rDoc ) const { return !pNode || @@ -1107,29 +675,6 @@ bool EditSelection::DbgIsBuggy( EditDoc const & rDoc ) const return aStartPaM.DbgIsBuggy( rDoc ) || aEndPaM.DbgIsBuggy( rDoc ); } -EditSelection::EditSelection() -{ -} - -EditSelection::EditSelection( const EditPaM& rStartAndAnd ) : - aStartPaM(rStartAndAnd), - aEndPaM(rStartAndAnd) -{ -} - -EditSelection::EditSelection( const EditPaM& rStart, const EditPaM& rEnd ) : - aStartPaM(rStart), - aEndPaM(rEnd) -{ -} - -EditSelection& EditSelection::operator = ( const EditPaM& rPaM ) -{ - aStartPaM = rPaM; - aEndPaM = rPaM; - return *this; -} - void EditSelection::Adjust( const EditDoc& rNodes ) { DBG_ASSERT( aStartPaM.GetIndex() <= aStartPaM.GetNode()->Len(), "Index out of range in Adjust(1)" ); @@ -1156,790 +701,28 @@ void EditSelection::Adjust( const EditDoc& rNodes ) } } -bool operator == ( const EditPaM& r1, const EditPaM& r2 ) -{ - return ( r1.GetNode() == r2.GetNode() ) && - ( r1.GetIndex() == r2.GetIndex() ); -} - -bool operator != ( const EditPaM& r1, const EditPaM& r2 ) -{ - return !( r1 == r2 ); -} - -ContentNode::ContentNode( SfxItemPool& rPool ) : aContentAttribs( rPool ) -{ -} - -ContentNode::ContentNode( const OUString& rStr, const ContentAttribs& rContentAttribs ) : - maString(rStr), aContentAttribs(rContentAttribs) -{ -} - -ContentNode::~ContentNode() -{ -} - -void ContentNode::ExpandAttribs( sal_Int32 nIndex, sal_Int32 nNew, SfxItemPool& rItemPool ) -{ - if ( !nNew ) - return; - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); -#endif - - // Since features are treated differently than normal character attributes, - // but can also affect the order of the start list. // In every if ..., in the next (n) opportunities due to bFeature or - // an existing special case, must (n-1) opportunities be provided with - // bResort. The most likely possibility receives no bResort, so that is - // not sorted anew when all attributes are the same. - bool bResort = false; - bool bExpandedEmptyAtIndexNull = false; - - sal_Int32 nAttr = 0; - CharAttribList::AttribsType& rAttribs = aCharAttribList.GetAttribs(); - EditCharAttrib* pAttrib = GetAttrib(rAttribs, nAttr); - while ( pAttrib ) - { - if ( pAttrib->GetEnd() >= nIndex ) - { - // Move all attributes behind the insertion point... - if ( pAttrib->GetStart() > nIndex ) - { - pAttrib->MoveForward( nNew ); - } - // 0: Expand empty attribute, if at insertion point - else if ( pAttrib->IsEmpty() ) - { - // Do not check Index, an empty one could only be there - // When later checking it anyhow: - // Special case: Start == 0; AbsLen == 1, nNew = 1 - // => Expand, because of paragraph break! - // Start <= nIndex, End >= nIndex => Start=End=nIndex! -// if ( pAttrib->GetStart() == nIndex ) - pAttrib->Expand( nNew ); - bResort = true; - if ( pAttrib->GetStart() == 0 ) - bExpandedEmptyAtIndexNull = true; - } - // 1: Attribute starts before, goes to index ... - else if ( pAttrib->GetEnd() == nIndex ) // Start must be before - { - // Only expand when there is no feature - // and if not in exclude list! - // Otherwise, a UL will go on until a new ULDB, expanding both -// if ( !pAttrib->IsFeature() && !rExclList.FindAttrib( pAttrib->Which() ) ) - if ( !pAttrib->IsFeature() && !aCharAttribList.FindEmptyAttrib( pAttrib->Which(), nIndex ) ) - { - if ( !pAttrib->IsEdge() ) - pAttrib->Expand( nNew ); - } - else - bResort = true; - } - // 2: Attribute starts before, goes past the Index... - else if ( ( pAttrib->GetStart() < nIndex ) && ( pAttrib->GetEnd() > nIndex ) ) - { - DBG_ASSERT( !pAttrib->IsFeature(), "Large Feature?!" ); - pAttrib->Expand( nNew ); - } - // 3: Attribute starts on index... - else if ( pAttrib->GetStart() == nIndex ) - { - if ( pAttrib->IsFeature() ) - { - pAttrib->MoveForward( nNew ); - bResort = true; - } - else - { - bool bExpand = false; - if ( nIndex == 0 ) - { - bExpand = true; - if( bExpandedEmptyAtIndexNull ) - { - // Check if this kind of attribute was empty and expanded here... - sal_uInt16 nW = pAttrib->GetItem()->Which(); - for ( sal_Int32 nA = 0; nA < nAttr; nA++ ) - { - const EditCharAttrib& r = *aCharAttribList.GetAttribs()[nA]; - if ( ( r.GetStart() == 0 ) && ( r.GetItem()->Which() == nW ) ) - { - bExpand = false; - break; - } - } - - } - } - if ( bExpand ) - { - pAttrib->Expand( nNew ); - bResort = true; - } - else - { - pAttrib->MoveForward( nNew ); - } - } - } - } - - if ( pAttrib->IsEdge() ) - pAttrib->SetEdge(false); - - DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" ); - - DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Expand: Attribute distorted!" ); - DBG_ASSERT( ( pAttrib->GetEnd() <= Len() ), "Expand: Attribute larger than paragraph!" ); - if ( pAttrib->IsEmpty() ) - { - OSL_FAIL( "Empty Attribute after ExpandAttribs?" ); - bResort = true; - rItemPool.Remove( *pAttrib->GetItem() ); - rAttribs.erase(rAttribs.begin()+nAttr); - --nAttr; - } - ++nAttr; - pAttrib = GetAttrib(rAttribs, nAttr); - } - - if ( bResort ) - aCharAttribList.ResortAttribs(); - - if (mpWrongList) - { - bool bSep = ( maString[ nIndex ] == ' ' ) || IsFeature( nIndex ); - mpWrongList->TextInserted( nIndex, nNew, bSep ); - } - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); -#endif -} - -void ContentNode::CollapseAttribs( sal_Int32 nIndex, sal_Int32 nDeleted, SfxItemPool& rItemPool ) -{ - if ( !nDeleted ) - return; - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); -#endif - - // Since features are treated differently than normal character attributes, - // but can also affect the order of the start list - bool bResort = false; - sal_Int32 nEndChanges = nIndex+nDeleted; - - sal_Int32 nAttr = 0; - CharAttribList::AttribsType& rAttribs = aCharAttribList.GetAttribs(); - EditCharAttrib* pAttrib = GetAttrib(rAttribs, nAttr); - while ( pAttrib ) - { - bool bDelAttr = false; - if ( pAttrib->GetEnd() >= nIndex ) - { - // Move all Attribute behind the insert point... - if ( pAttrib->GetStart() >= nEndChanges ) - { - pAttrib->MoveBackward( nDeleted ); - } - // 1. Delete Internal attributes... - else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() <= nEndChanges ) ) - { - // Special case: Attribute covers the area exactly - // => keep as empty Attribute. - if ( !pAttrib->IsFeature() && ( pAttrib->GetStart() == nIndex ) && ( pAttrib->GetEnd() == nEndChanges ) ) - { - pAttrib->GetEnd() = nIndex; // empty - bResort = true; - } - else - bDelAttr = true; - } - // 2. Attribute starts earlier, ends inside or behind it ... - else if ( ( pAttrib->GetStart() <= nIndex ) && ( pAttrib->GetEnd() > nIndex ) ) - { - DBG_ASSERT( !pAttrib->IsFeature(), "Collapsing Feature!" ); - if ( pAttrib->GetEnd() <= nEndChanges ) // ends inside - pAttrib->GetEnd() = nIndex; - else - pAttrib->Collaps( nDeleted ); // ends behind - } - // 3. Attribute starts inside, ending behind ... - else if ( ( pAttrib->GetStart() >= nIndex ) && ( pAttrib->GetEnd() > nEndChanges ) ) - { - // Features not allowed to expand! - if ( pAttrib->IsFeature() ) - { - pAttrib->MoveBackward( nDeleted ); - bResort = true; - } - else - { - pAttrib->GetStart() = nEndChanges; - pAttrib->MoveBackward( nDeleted ); - } - } - } - DBG_ASSERT( !pAttrib->IsFeature() || ( pAttrib->GetLen() == 1 ), "Expand: FeaturesLen != 1" ); - - DBG_ASSERT( pAttrib->GetStart() <= pAttrib->GetEnd(), "Collapse: Attribute distorted!" ); - DBG_ASSERT( ( pAttrib->GetEnd() <= Len()) || bDelAttr, "Collapse: Attribute larger than paragraph!" ); - if ( bDelAttr ) - { - bResort = true; - rItemPool.Remove( *pAttrib->GetItem() ); - rAttribs.erase(rAttribs.begin()+nAttr); - nAttr--; - } - else if ( pAttrib->IsEmpty() ) - aCharAttribList.SetHasEmptyAttribs(true); - - nAttr++; - pAttrib = GetAttrib(rAttribs, nAttr); - } - - if ( bResort ) - aCharAttribList.ResortAttribs(); - - if (mpWrongList) - mpWrongList->TextDeleted(nIndex, nDeleted); - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); -#endif -} - -void ContentNode::CopyAndCutAttribs( ContentNode* pPrevNode, SfxItemPool& rPool, bool bKeepEndingAttribs ) -{ - assert(pPrevNode); - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); - CharAttribList::DbgCheckAttribs(pPrevNode->aCharAttribList); -#endif - - sal_Int32 nCut = pPrevNode->Len(); - - sal_Int32 nAttr = 0; - CharAttribList::AttribsType& rPrevAttribs = pPrevNode->GetCharAttribs().GetAttribs(); - EditCharAttrib* pAttrib = GetAttrib(rPrevAttribs, nAttr); - while ( pAttrib ) - { - if ( pAttrib->GetEnd() < nCut ) - { - // remain unchanged... - ; - } - else if ( pAttrib->GetEnd() == nCut ) - { - // must be copied as an empty attributes. - if ( bKeepEndingAttribs && !pAttrib->IsFeature() && !aCharAttribList.FindAttrib( pAttrib->GetItem()->Which(), 0 ) ) - { - EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, 0 ); - assert(pNewAttrib); - aCharAttribList.InsertAttrib( pNewAttrib ); - } - } - else if ( pAttrib->IsInside( nCut ) || ( !nCut && !pAttrib->GetStart() && !pAttrib->IsFeature() ) ) - { - // If cut is done right at the front then the attribute must be - // kept! Has to be copied and changed. - EditCharAttrib* pNewAttrib = MakeCharAttrib( rPool, *(pAttrib->GetItem()), 0, pAttrib->GetEnd()-nCut ); - assert(pNewAttrib); - aCharAttribList.InsertAttrib( pNewAttrib ); - pAttrib->GetEnd() = nCut; - } - else - { - // Move all attributes in the current node (this) - CharAttribList::AttribsType::iterator it = rPrevAttribs.begin() + nAttr; - aCharAttribList.InsertAttrib(it->release()); - rPrevAttribs.erase(it); - pAttrib->MoveBackward( nCut ); - nAttr--; - } - nAttr++; - pAttrib = GetAttrib(rPrevAttribs, nAttr); - } - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); - CharAttribList::DbgCheckAttribs(pPrevNode->aCharAttribList); -#endif -} - -void ContentNode::AppendAttribs( ContentNode* pNextNode ) -{ - assert(pNextNode); - - sal_Int32 nNewStart = maString.getLength(); - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); - CharAttribList::DbgCheckAttribs(pNextNode->aCharAttribList); -#endif - - sal_Int32 nAttr = 0; - CharAttribList::AttribsType& rNextAttribs = pNextNode->GetCharAttribs().GetAttribs(); - EditCharAttrib* pAttrib = GetAttrib(rNextAttribs, nAttr); - while ( pAttrib ) - { - // Move all attributes in the current node (this) - bool bMelted = false; - if ( ( pAttrib->GetStart() == 0 ) && ( !pAttrib->IsFeature() ) ) - { - // Attributes can possibly be summarized as: - sal_Int32 nTmpAttr = 0; - EditCharAttrib* pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr ); - while ( !bMelted && pTmpAttrib ) - { - if ( pTmpAttrib->GetEnd() == nNewStart ) - { - if (pTmpAttrib->Which() == pAttrib->Which()) - { - // prevent adding 2 0-length attributes at same position - if ((*(pTmpAttrib->GetItem()) == *(pAttrib->GetItem())) - || (0 == pAttrib->GetLen())) - { - pTmpAttrib->GetEnd() = - pTmpAttrib->GetEnd() + pAttrib->GetLen(); - rNextAttribs.erase(rNextAttribs.begin()+nAttr); - // Unsubscribe from the pool?! - bMelted = true; - } - else if (0 == pTmpAttrib->GetLen()) - { - aCharAttribList.Remove(nTmpAttr); - --nTmpAttr; // to cancel later increment... - } - } - } - ++nTmpAttr; - pTmpAttrib = GetAttrib( aCharAttribList.GetAttribs(), nTmpAttr ); - } - } - - if ( !bMelted ) - { - pAttrib->GetStart() = pAttrib->GetStart() + nNewStart; - pAttrib->GetEnd() = pAttrib->GetEnd() + nNewStart; - CharAttribList::AttribsType::iterator it = rNextAttribs.begin() + nAttr; - aCharAttribList.InsertAttrib(it->release()); - rNextAttribs.erase(it); - } - pAttrib = GetAttrib(rNextAttribs, nAttr); - } - // For the Attributes that just moved over: - rNextAttribs.clear(); - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(aCharAttribList); - CharAttribList::DbgCheckAttribs(pNextNode->aCharAttribList); -#endif -} - -void ContentNode::CreateDefFont() -{ - // First use the information from the style ... - SfxStyleSheet* pS = aContentAttribs.GetStyleSheet(); - if ( pS ) - CreateFont( GetCharAttribs().GetDefFont(), pS->GetItemSet() ); - - // ... then iron out the hard paragraph formatting... - CreateFont( GetCharAttribs().GetDefFont(), - GetContentAttribs().GetItems(), pS == nullptr ); -} - -void ContentNode::SetStyleSheet( SfxStyleSheet* pS, const SvxFont& rFontFromStyle ) -{ - aContentAttribs.SetStyleSheet( pS ); - - - // First use the information from the style ... - GetCharAttribs().GetDefFont() = rFontFromStyle; - // ... then iron out the hard paragraph formatting... - CreateFont( GetCharAttribs().GetDefFont(), - GetContentAttribs().GetItems(), pS == nullptr ); -} - -void ContentNode::SetStyleSheet( SfxStyleSheet* pS, bool bRecalcFont ) -{ - aContentAttribs.SetStyleSheet( pS ); - if ( bRecalcFont ) - CreateDefFont(); -} - -bool ContentNode::IsFeature( sal_Int32 nPos ) const -{ - return maString[nPos] == CH_FEATURE; -} - -sal_Int32 ContentNode::Len() const -{ - return maString.getLength(); -} - -sal_Int32 ContentNode::GetExpandedLen() const -{ - sal_Int32 nLen = maString.getLength(); - - // Fields can be longer than the placeholder in the Node - const CharAttribList::AttribsType& rAttrs = GetCharAttribs().GetAttribs(); - for (sal_Int32 nAttr = rAttrs.size(); nAttr; ) - { - const EditCharAttrib& rAttr = *rAttrs[--nAttr]; - if (rAttr.Which() == EE_FEATURE_FIELD) - { - nLen += static_cast<const EditCharAttribField&>(rAttr).GetFieldValue().getLength(); - --nLen; // Standalone, to avoid corner cases when previous getLength() returns 0 - } - } - - return nLen; -} - -OUString ContentNode::GetExpandedText(sal_Int32 nStartPos, sal_Int32 nEndPos) const -{ - if ( nEndPos < 0 || nEndPos > Len() ) - nEndPos = Len(); - - DBG_ASSERT( nStartPos <= nEndPos, "Start and End reversed?" ); - - sal_Int32 nIndex = nStartPos; - OUStringBuffer aStr(256); - const EditCharAttrib* pNextFeature = GetCharAttribs().FindFeature( nIndex ); - while ( nIndex < nEndPos ) - { - sal_Int32 nEnd = nEndPos; - if ( pNextFeature && ( pNextFeature->GetStart() < nEnd ) ) - nEnd = pNextFeature->GetStart(); - else - pNextFeature = nullptr; // Feature does not interest the below - - DBG_ASSERT( nEnd >= nIndex, "End in front of the index?" ); - //!! beware of sub string length of -1 - if (nEnd > nIndex) - aStr.append( GetString().subView(nIndex, nEnd - nIndex) ); - - if ( pNextFeature ) - { - switch ( pNextFeature->GetItem()->Which() ) - { - case EE_FEATURE_TAB: aStr.append( "\t" ); - break; - case EE_FEATURE_LINEBR: aStr.append( "\x0A" ); - break; - case EE_FEATURE_FIELD: - aStr.append( static_cast<const EditCharAttribField*>(pNextFeature)->GetFieldValue() ); - break; - default: OSL_FAIL( "What feature?" ); - } - pNextFeature = GetCharAttribs().FindFeature( ++nEnd ); - } - nIndex = nEnd; - } - return aStr.makeStringAndClear(); -} - -void ContentNode::UnExpandPosition( sal_Int32 &rPos, bool bBiasStart ) -{ - sal_Int32 nOffset = 0; - - const CharAttribList::AttribsType& rAttrs = GetCharAttribs().GetAttribs(); - for (size_t nAttr = 0; nAttr < rAttrs.size(); ++nAttr ) - { - const EditCharAttrib& rAttr = *rAttrs[nAttr]; - assert (!(nAttr < rAttrs.size() - 1) || - rAttrs[nAttr]->GetStart() <= rAttrs[nAttr + 1]->GetStart()); - - nOffset = rAttr.GetStart(); - - if (nOffset >= rPos) // happens after the position - return; - - if (rAttr.Which() == EE_FEATURE_FIELD) - { - sal_Int32 nChunk = static_cast<const EditCharAttribField&>(rAttr).GetFieldValue().getLength(); - nChunk--; // Character representing the field in the string - - if (nOffset + nChunk >= rPos) // we're inside the field - { - if (bBiasStart) - rPos = rAttr.GetStart(); - else - rPos = rAttr.GetEnd(); - return; - } - // Adjust for the position - rPos -= nChunk; - } - } - assert (rPos <= Len()); -} - -/* - * Fields are represented by a single character in the underlying string - * and/or selection, however, they can be expanded to the full value of - * the field. When we're dealing with selection / offsets however we need - * to deal in character positions inside the real (unexpanded) string. - * This method maps us back to character offsets. - */ -void ContentNode::UnExpandPositions( sal_Int32 &rStartPos, sal_Int32 &rEndPos ) -{ - UnExpandPosition( rStartPos, true ); - UnExpandPosition( rEndPos, false ); -} - -void ContentNode::SetChar(sal_Int32 nPos, sal_Unicode c) -{ - maString = maString.replaceAt(nPos, 1, rtl::OUStringChar(c)); -} - -void ContentNode::Insert(std::u16string_view rStr, sal_Int32 nPos) -{ - maString = maString.replaceAt(nPos, 0, rStr); -} - -void ContentNode::Append(std::u16string_view rStr) -{ - maString += rStr; -} - -void ContentNode::Erase(sal_Int32 nPos) -{ - maString = maString.copy(0, nPos); -} - -void ContentNode::Erase(sal_Int32 nPos, sal_Int32 nCount) -{ - maString = maString.replaceAt(nPos, nCount, u""); -} - -OUString ContentNode::Copy(sal_Int32 nPos) const -{ - return maString.copy(nPos); -} - -OUString ContentNode::Copy(sal_Int32 nPos, sal_Int32 nCount) const -{ - return maString.copy(nPos, nCount); -} - -sal_Unicode ContentNode::GetChar(sal_Int32 nPos) const -{ - return maString[nPos]; -} - -void ContentNode::EnsureWrongList() -{ - if (!mpWrongList) - CreateWrongList(); -} - -WrongList* ContentNode::GetWrongList() -{ - return mpWrongList.get(); -} - -const WrongList* ContentNode::GetWrongList() const -{ - return mpWrongList.get(); -} - -void ContentNode::SetWrongList( WrongList* p ) -{ - mpWrongList.reset(p); -} - -void ContentNode::CreateWrongList() -{ - SAL_WARN_IF( mpWrongList && !mpWrongList->empty(), "editeng", "WrongList already exist!"); - if (!mpWrongList || !mpWrongList->empty()) - mpWrongList.reset(new WrongList); -} - -void ContentNode::DestroyWrongList() -{ - mpWrongList.reset(); -} - -void ContentNode::dumpAsXml(xmlTextWriterPtr pWriter) const -{ - (void)xmlTextWriterStartElement(pWriter, BAD_CAST("ContentNode")); - (void)xmlTextWriterWriteAttribute(pWriter, BAD_CAST("maString"), BAD_CAST(maString.toUtf8().getStr())); - aContentAttribs.dumpAsXml(pWriter); - aCharAttribList.dumpAsXml(pWriter); - (void)xmlTextWriterEndElement(pWriter); -} - - -ContentAttribs::ContentAttribs( SfxItemPool& rPool ) -: pStyle(nullptr) -, aAttribSet( rPool ) -{ -} - - -SvxTabStop ContentAttribs::FindTabStop( sal_Int32 nCurPos, sal_uInt16 nDefTab ) -{ - const SvxTabStopItem& rTabs = GetItem( EE_PARA_TABS ); - for ( sal_uInt16 i = 0; i < rTabs.Count(); i++ ) - { - const SvxTabStop& rTab = rTabs[i]; - if ( rTab.GetTabPos() > nCurPos ) - return rTab; - } - - // Determine DefTab ... - SvxTabStop aTabStop; - const sal_Int32 x = nCurPos / nDefTab + 1; - aTabStop.GetTabPos() = nDefTab * x; - return aTabStop; -} - -void ContentAttribs::SetStyleSheet( SfxStyleSheet* pS ) -{ - bool bStyleChanged = ( pStyle != pS ); - pStyle = pS; - // Only when other style sheet, not when current style sheet modified - if ( !(pStyle && bStyleChanged) ) - return; - - // Selectively remove the attributes from the paragraph formatting - // which are specified in the style, so that the attributes of the - // style can have an affect. - const SfxItemSet& rStyleAttribs = pStyle->GetItemSet(); - for ( sal_uInt16 nWhich = EE_PARA_START; nWhich <= EE_CHAR_END; nWhich++ ) - { - // Don't change bullet on/off - if ( ( nWhich != EE_PARA_BULLETSTATE ) && ( rStyleAttribs.GetItemState( nWhich ) == SfxItemState::SET ) ) - aAttribSet.ClearItem( nWhich ); - } -} - -const SfxPoolItem& ContentAttribs::GetItem( sal_uInt16 nWhich ) const -{ - // Hard paragraph attributes take precedence! - const SfxItemSet* pTakeFrom = &aAttribSet; - if ( pStyle && ( aAttribSet.GetItemState( nWhich, false ) != SfxItemState::SET ) ) - pTakeFrom = &pStyle->GetItemSet(); - - return pTakeFrom->Get( nWhich ); -} - -bool ContentAttribs::HasItem( sal_uInt16 nWhich ) const -{ - bool bHasItem = false; - if ( aAttribSet.GetItemState( nWhich, false ) == SfxItemState::SET ) - bHasItem = true; - else if ( pStyle && pStyle->GetItemSet().GetItemState( nWhich ) == SfxItemState::SET ) - bHasItem = true; - - return bHasItem; -} - -void ContentAttribs::dumpAsXml(xmlTextWriterPtr pWriter) const -{ - (void)xmlTextWriterStartElement(pWriter, BAD_CAST("ContentAttribs")); - (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("style"), "%s", pStyle->GetName().toUtf8().getStr()); - aAttribSet.dumpAsXml(pWriter); - (void)xmlTextWriterEndElement(pWriter); -} - - -ItemList::ItemList() : CurrentItem( 0 ) -{ -} - -const SfxPoolItem* ItemList::First() -{ - CurrentItem = 0; - return aItemPool.empty() ? nullptr : aItemPool[ 0 ]; -} - -const SfxPoolItem* ItemList::Next() -{ - if ( CurrentItem + 1 < static_cast<sal_Int32>(aItemPool.size()) ) - { - ++CurrentItem; - return aItemPool[ CurrentItem ]; - } - return nullptr; -} - -void ItemList::Insert( const SfxPoolItem* pItem ) -{ - aItemPool.push_back( pItem ); - CurrentItem = aItemPool.size() - 1; -} - - EditDoc::EditDoc( SfxItemPool* pPool ) : - nLastCache(0), - pItemPool(pPool ? pPool : new EditEngineItemPool()), - nDefTab(DEFTAB), - bIsVertical(false), + mnLastCache(0), + mpItemPool(pPool ? pPool : new EditEngineItemPool()), + mnDefTab(DEFTAB), + mbIsVertical(false), mnRotation(TextRotation::NONE), - bIsFixedCellHeight(false), - bModified(false), - bDisableAttributeExpanding(false) + mbIsFixedCellHeight(false), + mbModified(false), + mbDisableAttributeExpanding(false) { // Don't create an empty node, Clear() will be called in EditEngine-CTOR }; EditDoc::~EditDoc() { - ImplDestroyContents(); -} - -namespace { - -class RemoveEachItemFromPool -{ - EditDoc& mrDoc; -public: - explicit RemoveEachItemFromPool(EditDoc& rDoc) : mrDoc(rDoc) {} - void operator() (const std::unique_ptr<ContentNode>& rNode) - { - mrDoc.RemoveItemsFromPool(*rNode); - } -}; - -struct ClearSpellErrorsHandler -{ - void operator() (std::unique_ptr<ContentNode> const & rNode) - { - rNode->DestroyWrongList(); - } -}; - -} - -void EditDoc::ImplDestroyContents() -{ - std::for_each(maContents.begin(), maContents.end(), RemoveEachItemFromPool(*this)); maContents.clear(); } -void EditDoc::RemoveItemsFromPool(const ContentNode& rNode) -{ - for (sal_Int32 nAttr = 0; nAttr < rNode.GetCharAttribs().Count(); ++nAttr) - { - const EditCharAttrib& rAttr = *rNode.GetCharAttribs().GetAttribs()[nAttr]; - GetItemPool().Remove(*rAttr.GetItem()); - } -} - void CreateFont( SvxFont& rFont, const SfxItemSet& rSet, bool bSearchInParent, SvtScriptType nScriptType ) { vcl::Font aPrevFont( rFont ); rFont.SetAlignment( ALIGN_BASELINE ); - rFont.SetTransparent( true ); sal_uInt16 nWhich_FontInfo = GetScriptItemId( EE_CHAR_FONTINFO, nScriptType ); sal_uInt16 nWhich_Language = GetScriptItemId( EE_CHAR_LANGUAGE, nScriptType ); @@ -1960,7 +743,11 @@ void CreateFont( SvxFont& rFont, const SfxItemSet& rSet, bool bSearchInParent, S if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_COLOR ) == SfxItemState::SET ) ) rFont.SetColor( rSet.Get( EE_CHAR_COLOR ).GetValue() ); if ( bSearchInParent || ( rSet.GetItemState( EE_CHAR_BKGCOLOR ) == SfxItemState::SET ) ) - rFont.SetFillColor( rSet.Get( EE_CHAR_BKGCOLOR ).GetValue() ); + { + auto& aColor = rSet.Get( EE_CHAR_BKGCOLOR ).GetValue(); + rFont.SetTransparent(aColor.IsTransparent()); + rFont.SetFillColor(aColor); + } if ( bSearchInParent || ( rSet.GetItemState( nWhich_FontHeight ) == SfxItemState::SET ) ) rFont.SetFontSize( Size( rFont.GetFontSize().Width(), static_cast<const SvxFontHeightItem&>(rSet.Get( nWhich_FontHeight ) ).GetHeight() ) ); if ( bSearchInParent || ( rSet.GetItemState( nWhich_Weight ) == SfxItemState::SET ) ) @@ -2013,74 +800,63 @@ void CreateFont( SvxFont& rFont, const SfxItemSet& rSet, bool bSearchInParent, S void EditDoc::CreateDefFont( bool bUseStyles ) { SfxItemSetFixed<EE_PARA_START, EE_CHAR_END> aTmpSet( GetItemPool() ); - CreateFont( aDefFont, aTmpSet ); - aDefFont.SetVertical( IsEffectivelyVertical() ); - aDefFont.SetOrientation( Degree10(IsEffectivelyVertical() ? (IsTopToBottom() ? 2700 : 900) : 0) ); + CreateFont(maDefFont, aTmpSet); + maDefFont.SetVertical( IsEffectivelyVertical() ); + maDefFont.SetOrientation( Degree10(IsEffectivelyVertical() ? (IsTopToBottom() ? 2700 : 900) : 0) ); - for ( sal_Int32 nNode = 0; nNode < Count(); nNode++ ) + for (std::unique_ptr<ContentNode>& pNode : maContents) { - ContentNode* pNode = GetObject( nNode ); - pNode->GetCharAttribs().GetDefFont() = aDefFont; - if ( bUseStyles ) + pNode->GetCharAttribs().GetDefFont() = maDefFont; + if (bUseStyles) pNode->CreateDefFont(); } } bool EditDoc::IsEffectivelyVertical() const { - return (bIsVertical && mnRotation == TextRotation::NONE) || - (!bIsVertical && mnRotation != TextRotation::NONE); + return (mbIsVertical && mnRotation == TextRotation::NONE) || + (!mbIsVertical && mnRotation != TextRotation::NONE); } bool EditDoc::IsTopToBottom() const { - return (bIsVertical && mnRotation == TextRotation::NONE) || - (!bIsVertical && mnRotation == TextRotation::TOPTOBOTTOM); + return (mbIsVertical && mnRotation == TextRotation::NONE) || + (!mbIsVertical && mnRotation == TextRotation::TOPTOBOTTOM); } bool EditDoc::GetVertical() const { - return bIsVertical; + return mbIsVertical; } -sal_Int32 EditDoc::GetPos(const ContentNode* p) const +sal_Int32 EditDoc::GetPos(const ContentNode* pContentNode) const { - return FastGetPos(maContents, p, nLastCache); + return FastGetPos(maContents, pContentNode, mnLastCache); } const ContentNode* EditDoc::GetObject(sal_Int32 nPos) const { - return 0 <= nPos && nPos < static_cast<sal_Int32>(maContents.size()) ? maContents[nPos].get() : nullptr; + return 0 <= nPos && o3tl::make_unsigned(nPos) < maContents.size() ? maContents[nPos].get() : nullptr; } ContentNode* EditDoc::GetObject(sal_Int32 nPos) { - return 0 <= nPos && nPos < static_cast<sal_Int32>(maContents.size()) ? maContents[nPos].get() : nullptr; + return 0 <= nPos && o3tl::make_unsigned(nPos) < maContents.size() ? maContents[nPos].get() : nullptr; } -const ContentNode* EditDoc::operator[](sal_Int32 nPos) const -{ - return GetObject(nPos); -} - -ContentNode* EditDoc::operator[](sal_Int32 nPos) -{ - return GetObject(nPos); -} - -void EditDoc::Insert(sal_Int32 nPos, ContentNode* p) +void EditDoc::Insert(sal_Int32 nPos, std::unique_ptr<ContentNode> pNode) { if (nPos < 0 || nPos == SAL_MAX_INT32) { SAL_WARN( "editeng", "EditDoc::Insert - overflow pos " << nPos); return; } - maContents.insert(maContents.begin()+nPos, std::unique_ptr<ContentNode>(p)); + maContents.insert(maContents.begin()+nPos, std::move(pNode)); } void EditDoc::Remove(sal_Int32 nPos) { - if (nPos < 0 || nPos >= static_cast<sal_Int32>(maContents.size())) + if (nPos < 0 || o3tl::make_unsigned(nPos) >= maContents.size()) { SAL_WARN( "editeng", "EditDoc::Remove - out of bounds pos " << nPos); return; @@ -2088,15 +864,17 @@ void EditDoc::Remove(sal_Int32 nPos) maContents.erase(maContents.begin() + nPos); } -void EditDoc::Release(sal_Int32 nPos) +std::unique_ptr<ContentNode> EditDoc::Release(sal_Int32 nPos) { - if (nPos < 0 || nPos >= static_cast<sal_Int32>(maContents.size())) + if (nPos < 0 || o3tl::make_unsigned(nPos) >= maContents.size()) { SAL_WARN( "editeng", "EditDoc::Release - out of bounds pos " << nPos); - return; + return nullptr; } - (void)maContents[nPos].release(); + + std::unique_ptr<ContentNode> pNode = std::move(maContents[nPos]); maContents.erase(maContents.begin() + nPos); + return pNode; } sal_Int32 EditDoc::Count() const @@ -2168,21 +946,20 @@ EditPaM EditDoc::GetEndPaM() const sal_Int32 EditDoc::GetTextLen() const { - sal_Int32 nLen = 0; - for ( sal_Int32 nNode = 0; nNode < Count(); nNode++ ) + sal_Int32 nLength = 0; + for (auto const& pContent : maContents) { - const ContentNode* pNode = GetObject( nNode ); - nLen += pNode->GetExpandedLen(); + nLength += pContent->GetExpandedLen(); } - return nLen; + return nLength; } EditPaM EditDoc::Clear() { - ImplDestroyContents(); + maContents.clear(); - ContentNode* pNode = new ContentNode( GetItemPool() ); - Insert(0, pNode); + ContentNode* pNode = new ContentNode(GetItemPool()); + Insert(0, std::unique_ptr<ContentNode>(pNode)); CreateDefFont(false); @@ -2191,6 +968,17 @@ EditPaM EditDoc::Clear() return EditPaM( pNode, 0 ); } +namespace +{ +struct ClearSpellErrorsHandler +{ + void operator() (std::unique_ptr<ContentNode> const & rNode) + { + rNode->DestroyWrongList(); + } +}; +} + void EditDoc::ClearSpellErrors() { std::for_each(maContents.begin(), maContents.end(), ClearSpellErrorsHandler()); @@ -2198,13 +986,9 @@ void EditDoc::ClearSpellErrors() void EditDoc::SetModified( bool b ) { - if (bModified == b) - return; - bModified = b; - if ( bModified ) - { - aModifyHdl.Call( nullptr ); - } + mbModified = b; + if (mbModified) + maModifyHdl.Call(nullptr); } EditPaM EditDoc::RemoveText() @@ -2215,10 +999,10 @@ EditPaM EditDoc::RemoveText() SfxItemSet aPrevSet( pPrevFirstNode->GetContentAttribs().GetItems() ); vcl::Font aPrevFont( pPrevFirstNode->GetCharAttribs().GetDefFont() ); - ImplDestroyContents(); + maContents.clear(); - ContentNode* pNode = new ContentNode( GetItemPool() ); - Insert(0, pNode); + ContentNode* pNode = new ContentNode(GetItemPool()); + Insert(0, std::unique_ptr<ContentNode>(pNode)); pNode->SetStyleSheet(pPrevStyle, false); pNode->GetContentAttribs().GetItems().Set( aPrevSet ); @@ -2226,19 +1010,19 @@ EditPaM EditDoc::RemoveText() SetModified(true); - return EditPaM( pNode, 0 ); + return EditPaM(pNode, 0); } -EditPaM EditDoc::InsertText( EditPaM aPaM, const OUString& rStr ) +EditPaM EditDoc::InsertText( EditPaM aPaM, std::u16string_view rStr ) { - DBG_ASSERT( rStr.indexOf( 0x0A ) == -1, "EditDoc::InsertText: Newlines prohibited in paragraph!" ); - DBG_ASSERT( rStr.indexOf( 0x0D ) == -1, "EditDoc::InsertText: Newlines prohibited in paragraph!" ); - DBG_ASSERT( rStr.indexOf( '\t' ) == -1, "EditDoc::InsertText: Newlines prohibited in paragraph!" ); + DBG_ASSERT( rStr.find( 0x0A ) == std::u16string_view::npos, "EditDoc::InsertText: Newlines prohibited in paragraph!" ); + DBG_ASSERT( rStr.find( 0x0D ) == std::u16string_view::npos, "EditDoc::InsertText: Newlines prohibited in paragraph!" ); + DBG_ASSERT( rStr.find( '\t' ) == std::u16string_view::npos, "EditDoc::InsertText: Newlines prohibited in paragraph!" ); assert(aPaM.GetNode()); aPaM.GetNode()->Insert( rStr, aPaM.GetIndex() ); - aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), rStr.getLength(), GetItemPool() ); - aPaM.SetIndex( aPaM.GetIndex() + rStr.getLength() ); + aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), rStr.size() ); + aPaM.SetIndex( aPaM.GetIndex() + rStr.size() ); SetModified( true ); @@ -2260,7 +1044,7 @@ EditPaM EditDoc::InsertParaBreak( EditPaM aPaM, bool bKeepEndingAttribs ) aContentAttribs.GetItems().Put( SfxBoolItem( EE_PARA_BULLETSTATE, true) ); // ContentNode constructor copies also the paragraph attributes - ContentNode* pNode = new ContentNode( aStr, aContentAttribs ); + ContentNode* pNode = new ContentNode(aStr, std::move(aContentAttribs)); // Copy the Default Font pNode->GetCharAttribs().GetDefFont() = aPaM.GetNode()->GetCharAttribs().GetDefFont(); @@ -2278,7 +1062,7 @@ EditPaM EditDoc::InsertParaBreak( EditPaM aPaM, bool bKeepEndingAttribs ) // Character attributes may need to be copied or trimmed: pNode->CopyAndCutAttribs( aPaM.GetNode(), GetItemPool(), bKeepEndingAttribs ); - Insert(nPos+1, pNode); + Insert(nPos+1, std::unique_ptr<ContentNode>(pNode)); SetModified(true); @@ -2292,7 +1076,7 @@ EditPaM EditDoc::InsertFeature( EditPaM aPaM, const SfxPoolItem& rItem ) assert(aPaM.GetNode()); aPaM.GetNode()->Insert( rtl::OUStringChar(CH_FEATURE), aPaM.GetIndex() ); - aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), 1, GetItemPool() ); + aPaM.GetNode()->ExpandAttribs( aPaM.GetIndex(), 1 ); // Create a feature-attribute for the feature... EditCharAttrib* pAttrib = MakeCharAttrib( GetItemPool(), rItem, aPaM.GetIndex(), aPaM.GetIndex()+1 ); @@ -2315,7 +1099,6 @@ EditPaM EditDoc::ConnectParagraphs( ContentNode* pLeft, ContentNode* pRight ) pLeft->Append(pRight->GetString()); // the one to the right disappears. - RemoveItemsFromPool(*pRight); sal_Int32 nRight = GetPos( pRight ); Remove( nRight ); @@ -2328,7 +1111,7 @@ void EditDoc::RemoveChars( EditPaM aPaM, sal_Int32 nChars ) { // Maybe remove Features! aPaM.GetNode()->Erase( aPaM.GetIndex(), nChars ); - aPaM.GetNode()->CollapseAttribs( aPaM.GetIndex(), nChars, GetItemPool() ); + aPaM.GetNode()->CollapseAttribs( aPaM.GetIndex(), nChars ); SetModified( true ); } @@ -2351,7 +1134,7 @@ void EditDoc::InsertAttribInSelection( ContentNode* pNode, sal_Int32 nStart, sal // tdf#132288 By default inserting an attribute beside another that is of // the same type expands the original instead of inserting another. But the // spell check dialog doesn't want that behaviour - if (bDisableAttributeExpanding) + if (mbDisableAttributeExpanding) { pStartingAttrib = nullptr; pEndingAttrib = nullptr; @@ -2363,7 +1146,6 @@ void EditDoc::InsertAttribInSelection( ContentNode* pNode, sal_Int32 nStart, sal { // Will become a large Attribute. pEndingAttrib->GetEnd() = pStartingAttrib->GetEnd(); - GetItemPool().Remove( *(pStartingAttrib->GetItem()) ); pNode->GetCharAttribs().Remove(pStartingAttrib); } else if ( pStartingAttrib && ( *(pStartingAttrib->GetItem()) == rPoolItem ) ) @@ -2407,7 +1189,7 @@ bool EditDoc::RemoveAttribs( ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEn #endif // iterate over the attributes ... - sal_Int32 nAttr = 0; + std::size_t nAttr = 0; CharAttribList::AttribsType& rAttribs = pNode->GetCharAttribs().GetAttribs(); EditCharAttrib* pAttr = GetAttrib(rAttribs, nAttr); while ( pAttr ) @@ -2485,11 +1267,12 @@ bool EditDoc::RemoveAttribs( ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEn { DBG_ASSERT( ( pAttr != rpStarting ) && ( pAttr != rpEnding ), "Delete and retain the same attribute?" ); DBG_ASSERT( !pAttr->IsFeature(), "RemoveAttribs: Remove a feature?!" ); - GetItemPool().Remove( *pAttr->GetItem() ); rAttribs.erase(rAttribs.begin()+nAttr); - nAttr--; } - nAttr++; + else + { + nAttr++; + } pAttr = GetAttrib(rAttribs, nAttr); } @@ -2567,7 +1350,7 @@ void EditDoc::FindAttribs( ContentNode* pNode, sal_Int32 nStartPos, sal_Int32 nE assert(pNode); DBG_ASSERT( nStartPos <= nEndPos, "Invalid region!" ); - sal_uInt16 nAttr = 0; + std::size_t nAttr = 0; EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr ); // No Selection... if ( nStartPos == nEndPos ) @@ -2694,319 +1477,14 @@ void EditDoc::dumpAsXml(xmlTextWriterPtr pWriter) const } } - -namespace { - -struct LessByStart -{ - bool operator() (const std::unique_ptr<EditCharAttrib>& left, const std::unique_ptr<EditCharAttrib>& right) const - { - return left->GetStart() < right->GetStart(); - } -}; - -} - -CharAttribList::CharAttribList() -: bHasEmptyAttribs(false) -{ -} - -CharAttribList::~CharAttribList() -{ -} - -void CharAttribList::InsertAttrib( EditCharAttrib* pAttrib ) -{ -// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! -// optimize: binary search? ! -// !!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - // Maybe just simply iterate backwards: - // The most common and critical case: Attributes are already sorted - // (InsertTextObject!) binary search would not be optimal here. - // => Would bring something! - - const sal_Int32 nStart = pAttrib->GetStart(); // may be better for Comp.Opt. - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(*this); -#endif - - if ( pAttrib->IsEmpty() ) - bHasEmptyAttribs = true; - - bool bInsert(true); - for (sal_Int32 i = 0, n = aAttribs.size(); i < n; ++i) - { - const EditCharAttrib& rCurAttrib = *aAttribs[i]; - if (rCurAttrib.GetStart() > nStart) - { - aAttribs.insert(aAttribs.begin()+i, std::unique_ptr<EditCharAttrib>(pAttrib)); - bInsert = false; - break; - } - } - - if (bInsert) aAttribs.push_back(std::unique_ptr<EditCharAttrib>(pAttrib)); - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(*this); -#endif -} - -void CharAttribList::ResortAttribs() -{ - std::sort(aAttribs.begin(), aAttribs.end(), LessByStart()); - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(*this); -#endif -} - -void CharAttribList::OptimizeRanges( SfxItemPool& rItemPool ) -{ -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(*this); -#endif - for (sal_Int32 i = 0; i < static_cast<sal_Int32>(aAttribs.size()); ++i) - { - EditCharAttrib& rAttr = *aAttribs[i]; - for (sal_Int32 nNext = i+1; nNext < static_cast<sal_Int32>(aAttribs.size()); ++nNext) - { - EditCharAttrib& rNext = *aAttribs[nNext]; - if (!rAttr.IsFeature() && rNext.GetStart() == rAttr.GetEnd() && rNext.Which() == rAttr.Which()) - { - if (*rNext.GetItem() == *rAttr.GetItem()) - { - rAttr.GetEnd() = rNext.GetEnd(); - rItemPool.Remove(*rNext.GetItem()); - aAttribs.erase(aAttribs.begin()+nNext); - } - break; // only 1 attr with same which can start here. - } - else if (rNext.GetStart() > rAttr.GetEnd()) - { - break; - } - } - } -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - CharAttribList::DbgCheckAttribs(*this); -#endif -} - -sal_Int32 CharAttribList::Count() const -{ - return aAttribs.size(); -} - -const EditCharAttrib* CharAttribList::FindAttrib( sal_uInt16 nWhich, sal_Int32 nPos ) const -{ - // Backwards, if one ends where the next starts. - // => The starting one is the valid one ... - AttribsType::const_reverse_iterator it = std::find_if(aAttribs.rbegin(), aAttribs.rend(), - [&nWhich, &nPos](const AttribsType::value_type& rxAttr) { - return rxAttr->Which() == nWhich && rxAttr->IsIn(nPos); }); - if (it != aAttribs.rend()) - { - const EditCharAttrib& rAttr = **it; - return &rAttr; - } - return nullptr; -} - -EditCharAttrib* CharAttribList::FindAttrib( sal_uInt16 nWhich, sal_Int32 nPos ) -{ - // Backwards, if one ends where the next starts. - // => The starting one is the valid one ... - AttribsType::reverse_iterator it = std::find_if(aAttribs.rbegin(), aAttribs.rend(), - [&nWhich, &nPos](AttribsType::value_type& rxAttr) { - return rxAttr->Which() == nWhich && rxAttr->IsIn(nPos); }); - if (it != aAttribs.rend()) - { - EditCharAttrib& rAttr = **it; - return &rAttr; - } - return nullptr; -} - -const EditCharAttrib* CharAttribList::FindNextAttrib( sal_uInt16 nWhich, sal_Int32 nFromPos ) const -{ - assert(nWhich); - for (auto const& attrib : aAttribs) - { - const EditCharAttrib& rAttr = *attrib; - if (rAttr.GetStart() >= nFromPos && rAttr.Which() == nWhich) - return &rAttr; - } - return nullptr; -} - -bool CharAttribList::HasAttrib( sal_Int32 nStartPos, sal_Int32 nEndPos ) const -{ - return std::any_of(aAttribs.rbegin(), aAttribs.rend(), - [&nStartPos, &nEndPos](const AttribsType::value_type& rxAttr) { - return rxAttr->GetStart() < nEndPos && rxAttr->GetEnd() > nStartPos; }); -} - - -namespace { - -class FindByAddress -{ - const EditCharAttrib* mpAttr; -public: - explicit FindByAddress(const EditCharAttrib* p) : mpAttr(p) {} - bool operator() (const std::unique_ptr<EditCharAttrib>& r) const - { - return r.get() == mpAttr; - } -}; - -} - -void CharAttribList::Remove(const EditCharAttrib* p) -{ - AttribsType::iterator it = std::find_if(aAttribs.begin(), aAttribs.end(), FindByAddress(p)); - if (it != aAttribs.end()) - aAttribs.erase(it); -} - -void CharAttribList::Remove(sal_Int32 nPos) -{ - if (nPos >= static_cast<sal_Int32>(aAttribs.size())) - return; - - aAttribs.erase(aAttribs.begin()+nPos); -} - -void CharAttribList::SetHasEmptyAttribs(bool b) -{ - bHasEmptyAttribs = b; -} - -bool CharAttribList::HasBoundingAttrib( sal_Int32 nBound ) const -{ - // Backwards, if one ends where the next starts. - // => The starting one is the valid one ... - AttribsType::const_reverse_iterator it = aAttribs.rbegin(), itEnd = aAttribs.rend(); - for (; it != itEnd; ++it) - { - const EditCharAttrib& rAttr = **it; - if (rAttr.GetEnd() < nBound) - return false; - - if (rAttr.GetStart() == nBound || rAttr.GetEnd() == nBound) - return true; - } - return false; -} - -EditCharAttrib* CharAttribList::FindEmptyAttrib( sal_uInt16 nWhich, sal_Int32 nPos ) -{ - if ( !bHasEmptyAttribs ) - return nullptr; - - for (const std::unique_ptr<EditCharAttrib>& rAttr : aAttribs) - { - if (rAttr->GetStart() == nPos && rAttr->GetEnd() == nPos && rAttr->Which() == nWhich) - return rAttr.get(); - } - return nullptr; -} - -namespace { - -class FindByStartPos -{ - sal_Int32 mnPos; -public: - explicit FindByStartPos(sal_Int32 nPos) : mnPos(nPos) {} - bool operator() (const std::unique_ptr<EditCharAttrib>& r) const - { - return r->GetStart() >= mnPos; - } -}; - -} - -const EditCharAttrib* CharAttribList::FindFeature( sal_Int32 nPos ) const -{ - // First, find the first attribute that starts at or after specified position. - AttribsType::const_iterator it = - std::find_if(aAttribs.begin(), aAttribs.end(), FindByStartPos(nPos)); - - if (it == aAttribs.end()) - // All attributes are before the specified position. - return nullptr; - - // And find the first attribute with feature. - it = std::find_if(it, aAttribs.end(), [](const std::unique_ptr<EditCharAttrib>& aAttrib) { return aAttrib->IsFeature(); } ); - return it == aAttribs.end() ? nullptr : it->get(); -} - -namespace { - -class RemoveEmptyAttrItem -{ - SfxItemPool& mrItemPool; -public: - explicit RemoveEmptyAttrItem(SfxItemPool& rPool) : mrItemPool(rPool) {} - void operator() (const std::unique_ptr<EditCharAttrib>& r) - { - if (r->IsEmpty()) - mrItemPool.Remove(*r->GetItem()); - } -}; - -} - -void CharAttribList::DeleteEmptyAttribs( SfxItemPool& rItemPool ) -{ - std::for_each(aAttribs.begin(), aAttribs.end(), RemoveEmptyAttrItem(rItemPool)); - aAttribs.erase( std::remove_if(aAttribs.begin(), aAttribs.end(), [](const std::unique_ptr<EditCharAttrib>& aAttrib) { return aAttrib->IsEmpty(); } ), aAttribs.end() ); - bHasEmptyAttribs = false; -} - -#if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG -void CharAttribList::DbgCheckAttribs(CharAttribList const& rAttribs) -{ - std::set<std::pair<sal_Int32, sal_uInt16>> zero_set; - for (const std::unique_ptr<EditCharAttrib>& rAttr : rAttribs.aAttribs) - { - assert(rAttr->GetStart() <= rAttr->GetEnd()); - assert(!rAttr->IsFeature() || rAttr->GetLen() == 1); - if (0 == rAttr->GetLen()) - { - // not sure if 0-length attributes allowed at all in non-empty para? - assert(zero_set.insert(std::make_pair(rAttr->GetStart(), rAttr->Which())).second && "duplicate 0-length attribute detected"); - } - } - CheckOrderedList(rAttribs.GetAttribs()); -} -#endif - -void CharAttribList::dumpAsXml(xmlTextWriterPtr pWriter) const -{ - (void)xmlTextWriterStartElement(pWriter, BAD_CAST("CharAttribList")); - for (auto const & i : aAttribs) { - i->dumpAsXml(pWriter); - } - (void)xmlTextWriterEndElement(pWriter); -} - EditEngineItemPool::EditEngineItemPool() - : SfxItemPool( "EditEngineItemPool", EE_ITEMS_START, EE_ITEMS_END, - aItemInfos, nullptr ) +: SfxItemPool("EditEngineItemPool") { - m_xDefItems = EditDLL::Get().GetGlobalData()->GetDefItems(); - SetDefaults(&m_xDefItems->getDefaults()); + registerItemInfoPackage(getItemInfoPackageEditEngine()); } EditEngineItemPool::~EditEngineItemPool() { - ClearDefaults(); SetSecondaryPool(nullptr); } diff --git a/editeng/source/editeng/editeng.cxx b/editeng/source/editeng/editeng.cxx index ae30e651b594..ce9b182c0f54 100644 --- a/editeng/source/editeng/editeng.cxx +++ b/editeng/source/editeng/editeng.cxx @@ -23,6 +23,7 @@ #include <comphelper/lok.hxx> #include <comphelper/processfactory.hxx> #include <config_global.h> +#include <o3tl/safeint.hxx> #include <vcl/svapp.hxx> #include <vcl/weld.hxx> #include <vcl/window.hxx> @@ -84,120 +85,122 @@ using namespace ::com::sun::star::linguistic2; static bool bDebugPaint = false; #endif - static rtl::Reference<SfxItemPool> pGlobalPool; -EditEngine::EditEngine( SfxItemPool* pItemPool ) +ImpEditEngine& EditEngine::getImpl() const { - pImpEditEngine.reset( new ImpEditEngine( this, pItemPool ) ); + return *mpImpEditEngine; } -EditEngine::~EditEngine() +EditEngine::EditEngine(SfxItemPool* pItemPool) + : mpImpEditEngine(new ImpEditEngine(this, pItemPool)) { } +EditEngine::~EditEngine() = default; + void EditEngine::EnableUndo( bool bEnable ) { - pImpEditEngine->EnableUndo( bEnable ); + getImpl().EnableUndo(bEnable); } bool EditEngine::IsUndoEnabled() const { - return pImpEditEngine->IsUndoEnabled(); + return getImpl().IsUndoEnabled(); } bool EditEngine::IsInUndo() const { - return pImpEditEngine->IsInUndo(); + return getImpl().IsInUndo(); } -SfxUndoManager& EditEngine::GetUndoManager() +EditUndoManager& EditEngine::GetUndoManager() { - return pImpEditEngine->GetUndoManager(); + return getImpl().GetUndoManager(); } -SfxUndoManager* EditEngine::SetUndoManager(SfxUndoManager* pNew) +EditUndoManager* EditEngine::SetUndoManager(EditUndoManager* pNew) { - return pImpEditEngine->SetUndoManager(pNew); + return getImpl().SetUndoManager(pNew); } void EditEngine::UndoActionStart( sal_uInt16 nId ) { - DBG_ASSERT( !pImpEditEngine->IsInUndo(), "Calling UndoActionStart in Undomode!" ); - if ( !pImpEditEngine->IsInUndo() ) - pImpEditEngine->UndoActionStart( nId ); + DBG_ASSERT(!getImpl().IsInUndo(), "Calling UndoActionStart in Undomode!"); + if (!getImpl().IsInUndo()) + getImpl().UndoActionStart(nId); } void EditEngine::UndoActionStart(sal_uInt16 nId, const ESelection& rSel) { - pImpEditEngine->UndoActionStart(nId, rSel); + getImpl().UndoActionStart(nId, rSel); } void EditEngine::UndoActionEnd() { - DBG_ASSERT( !pImpEditEngine->IsInUndo(), "Calling UndoActionEnd in Undomode!" ); - if ( !pImpEditEngine->IsInUndo() ) - pImpEditEngine->UndoActionEnd(); + DBG_ASSERT(!getImpl().IsInUndo(), "Calling UndoActionEnd in Undomode!"); + if (!getImpl().IsInUndo()) + getImpl().UndoActionEnd(); } bool EditEngine::HasTriedMergeOnLastAddUndo() const { - return pImpEditEngine->mbLastTryMerge; + return getImpl().mbLastTryMerge; } void EditEngine::SetRefDevice( OutputDevice* pRefDev ) { - pImpEditEngine->SetRefDevice( pRefDev ); + getImpl().SetRefDevice(pRefDev); } OutputDevice* EditEngine::GetRefDevice() const { - return pImpEditEngine->GetRefDevice(); + return getImpl().GetRefDevice(); } void EditEngine::SetRefMapMode( const MapMode& rMapMode ) { - pImpEditEngine->SetRefMapMode( rMapMode ); + getImpl().SetRefMapMode(rMapMode); } MapMode const & EditEngine::GetRefMapMode() const { - return pImpEditEngine->GetRefMapMode(); + return getImpl().GetRefMapMode(); } void EditEngine::SetBackgroundColor( const Color& rColor ) { - pImpEditEngine->SetBackgroundColor( rColor ); + getImpl().SetBackgroundColor(rColor); } Color const & EditEngine::GetBackgroundColor() const { - return pImpEditEngine->GetBackgroundColor(); + return getImpl().GetBackgroundColor(); } Color EditEngine::GetAutoColor() const { - return pImpEditEngine->GetAutoColor(); + return getImpl().GetAutoColor(); } void EditEngine::EnableAutoColor( bool b ) { - pImpEditEngine->EnableAutoColor( b ); + getImpl().EnableAutoColor( b ); } void EditEngine::ForceAutoColor( bool b ) { - pImpEditEngine->ForceAutoColor( b ); + getImpl().ForceAutoColor( b ); } bool EditEngine::IsForceAutoColor() const { - return pImpEditEngine->IsForceAutoColor(); + return getImpl().IsForceAutoColor(); } const SfxItemSet& EditEngine::GetEmptyItemSet() const { - return pImpEditEngine->GetEmptyItemSet(); + return getImpl().GetEmptyItemSet(); } void EditEngine::Draw( OutputDevice& rOutDev, const tools::Rectangle& rOutRect ) @@ -216,10 +219,10 @@ void EditEngine::Draw( OutputDevice& rOutDev, const Point& rStartPos, Degree10 n if ( IsEffectivelyVertical() ) { aStartPos.AdjustX(GetPaperSize().Width() ); - aStartPos = Rotate( aStartPos, nOrientation, rStartPos ); + rStartPos.RotateAround(aStartPos, nOrientation); } - pImpEditEngine->Paint(rOutDev, aBigRect, aStartPos, false, nOrientation); - if( rOutDev.GetConnectMetaFile() ) + getImpl().Paint(rOutDev, aBigRect, aStartPos, false, nOrientation); + if (rOutDev.GetConnectMetaFile()) rOutDev.Pop(); } @@ -283,7 +286,7 @@ void EditEngine::Draw( OutputDevice& rOutDev, const tools::Rectangle& rOutRect, } } - pImpEditEngine->Paint( rOutDev, aOutRect, aStartPos ); + getImpl().Paint(rOutDev, aOutRect, aStartPos); if ( bMetafile ) rOutDev.Pop(); @@ -295,27 +298,25 @@ void EditEngine::Draw( OutputDevice& rOutDev, const tools::Rectangle& rOutRect, void EditEngine::InsertView(EditView* pEditView, size_t nIndex) { + if (nIndex > getImpl().GetEditViews().size()) + nIndex = getImpl().GetEditViews().size(); - if ( nIndex > pImpEditEngine->GetEditViews().size() ) - nIndex = pImpEditEngine->GetEditViews().size(); - - ImpEditEngine::ViewsType& rViews = pImpEditEngine->GetEditViews(); + ImpEditEngine::ViewsType& rViews = getImpl().GetEditViews(); rViews.insert(rViews.begin()+nIndex, pEditView); - EditSelection aStartSel = pImpEditEngine->GetEditDoc().GetStartPaM(); - pEditView->pImpEditView->SetEditSelection( aStartSel ); - if ( !pImpEditEngine->GetActiveView() ) - pImpEditEngine->SetActiveView( pEditView ); + EditSelection aStartSel = getImpl().GetEditDoc().GetStartPaM(); + pEditView->getImpl().SetEditSelection( aStartSel ); + if (!getImpl().GetActiveView()) + getImpl().SetActiveView(pEditView); - pEditView->pImpEditView->AddDragAndDropListeners(); + pEditView->getImpl().AddDragAndDropListeners(); } EditView* EditEngine::RemoveView( EditView* pView ) { - pView->HideCursor(); EditView* pRemoved = nullptr; - ImpEditEngine::ViewsType& rViews = pImpEditEngine->GetEditViews(); + ImpEditEngine::ViewsType& rViews = getImpl().GetEditViews(); ImpEditEngine::ViewsType::iterator it = std::find(rViews.begin(), rViews.end(), pView); DBG_ASSERT( it != rViews.end(), "RemoveView with invalid index" ); @@ -323,12 +324,12 @@ EditView* EditEngine::RemoveView( EditView* pView ) { pRemoved = *it; rViews.erase(it); - if ( pImpEditEngine->GetActiveView() == pView ) + if (getImpl().GetActiveView() == pView) { - pImpEditEngine->SetActiveView( nullptr ); - pImpEditEngine->GetSelEngine().SetCurView( nullptr ); + getImpl().SetActiveView(nullptr); + getImpl().GetSelEngine().SetCurView(nullptr); } - pView->pImpEditView->RemoveDragAndDropListeners(); + pView->getImpl().RemoveDragAndDropListeners(); } return pRemoved; @@ -336,7 +337,7 @@ EditView* EditEngine::RemoveView( EditView* pView ) void EditEngine::RemoveView(size_t nIndex) { - ImpEditEngine::ViewsType& rViews = pImpEditEngine->GetEditViews(); + ImpEditEngine::ViewsType& rViews = getImpl().GetEditViews(); if (nIndex >= rViews.size()) return; @@ -347,173 +348,171 @@ void EditEngine::RemoveView(size_t nIndex) EditView* EditEngine::GetView(size_t nIndex) const { - return pImpEditEngine->GetEditViews()[nIndex]; + return getImpl().GetEditViews()[nIndex]; } size_t EditEngine::GetViewCount() const { - return pImpEditEngine->GetEditViews().size(); + return getImpl().GetEditViews().size(); } bool EditEngine::HasView( EditView* pView ) const { - ImpEditEngine::ViewsType& rViews = pImpEditEngine->GetEditViews(); + ImpEditEngine::ViewsType const& rViews = getImpl().GetEditViews(); return std::find(rViews.begin(), rViews.end(), pView) != rViews.end(); } EditView* EditEngine::GetActiveView() const { - return pImpEditEngine->GetActiveView(); + return getImpl().GetActiveView(); } void EditEngine::SetActiveView(EditView* pView) { - pImpEditEngine->SetActiveView(pView); + getImpl().SetActiveView(pView); } void EditEngine::SetDefTab( sal_uInt16 nDefTab ) { - pImpEditEngine->GetEditDoc().SetDefTab( nDefTab ); - if ( pImpEditEngine->IsFormatted() ) + getImpl().GetEditDoc().SetDefTab(nDefTab); + if (getImpl().IsFormatted()) { - pImpEditEngine->FormatFullDoc(); - pImpEditEngine->UpdateViews(); + getImpl().FormatFullDoc(); + getImpl().UpdateViews(); } } -void EditEngine::SetPaperSize( const Size& rNewSize ) +void EditEngine::SetPaperSize(const Size& rNewSize) { + Size aOldSize = getImpl().GetPaperSize(); + getImpl().SetValidPaperSize(rNewSize); + Size aNewSize = getImpl().GetPaperSize(); - Size aOldSize( pImpEditEngine->GetPaperSize() ); - pImpEditEngine->SetValidPaperSize( rNewSize ); - Size aNewSize( pImpEditEngine->GetPaperSize() ); - - bool bAutoPageSize = pImpEditEngine->GetStatus().AutoPageSize(); + bool bAutoPageSize = getImpl().GetStatus().AutoPageSize(); if ( !(bAutoPageSize || ( aNewSize.Width() != aOldSize.Width() )) ) return; - for (EditView* pView : pImpEditEngine->aEditViews) + for (EditView* pView : getImpl().maEditViews) { if ( bAutoPageSize ) - pView->pImpEditView->RecalcOutputArea(); - else if ( pView->pImpEditView->DoAutoSize() ) + pView->getImpl().RecalcOutputArea(); + else if (pView->getImpl().DoAutoSize()) { - pView->pImpEditView->ResetOutputArea( tools::Rectangle( - pView->pImpEditView->GetOutputArea().TopLeft(), aNewSize ) ); + pView->getImpl().ResetOutputArea(tools::Rectangle(pView->getImpl().GetOutputArea().TopLeft(), aNewSize)); } } - if ( bAutoPageSize || pImpEditEngine->IsFormatted() ) + if ( bAutoPageSize || getImpl().IsFormatted() ) { // Changing the width has no effect for AutoPageSize, as this is // determined by the text width. // Optimization first after Vobis delivery was enabled ... - pImpEditEngine->FormatFullDoc(); + getImpl().FormatFullDoc(); - pImpEditEngine->UpdateViews( pImpEditEngine->GetActiveView() ); + getImpl().UpdateViews(getImpl().GetActiveView()); - if ( pImpEditEngine->IsUpdateLayout() && pImpEditEngine->GetActiveView() ) - pImpEditEngine->pActiveView->ShowCursor( false, false ); + if (getImpl().IsUpdateLayout() && getImpl().GetActiveView()) + getImpl().mpActiveView->ShowCursor(false, false); } } const Size& EditEngine::GetPaperSize() const { - return pImpEditEngine->GetPaperSize(); + return getImpl().GetPaperSize(); } void EditEngine::SetVertical(bool bVertical) { - pImpEditEngine->SetVertical(bVertical); + getImpl().SetVertical(bVertical); } void EditEngine::SetRotation(TextRotation nRotation) { - pImpEditEngine->SetRotation(nRotation); + getImpl().SetRotation(nRotation); } TextRotation EditEngine::GetRotation() const { - return pImpEditEngine->GetRotation(); + return getImpl().GetRotation(); } bool EditEngine::IsEffectivelyVertical() const { - return pImpEditEngine->IsEffectivelyVertical(); + return getImpl().IsEffectivelyVertical(); } bool EditEngine::IsTopToBottom() const { - return pImpEditEngine->IsTopToBottom(); + return getImpl().IsTopToBottom(); } bool EditEngine::GetVertical() const { - return pImpEditEngine->GetVertical(); + return getImpl().GetVertical(); } void EditEngine::SetTextColumns(sal_Int16 nColumns, sal_Int32 nSpacing) { - pImpEditEngine->SetTextColumns(nColumns, nSpacing); + getImpl().SetTextColumns(nColumns, nSpacing); } void EditEngine::SetFixedCellHeight( bool bUseFixedCellHeight ) { - pImpEditEngine->SetFixedCellHeight( bUseFixedCellHeight ); + getImpl().SetFixedCellHeight(bUseFixedCellHeight); } void EditEngine::SetDefaultHorizontalTextDirection( EEHorizontalTextDirection eHTextDir ) { - pImpEditEngine->SetDefaultHorizontalTextDirection( eHTextDir ); + getImpl().SetDefaultHorizontalTextDirection(eHTextDir); } EEHorizontalTextDirection EditEngine::GetDefaultHorizontalTextDirection() const { - return pImpEditEngine->GetDefaultHorizontalTextDirection(); + return getImpl().GetDefaultHorizontalTextDirection(); } SvtScriptType EditEngine::GetScriptType( const ESelection& rSelection ) const { - EditSelection aSel( pImpEditEngine->CreateSel( rSelection ) ); - return pImpEditEngine->GetItemScriptType( aSel ); + EditSelection aSel(getImpl().CreateSel(rSelection)); + return getImpl().GetItemScriptType( aSel ); } -LanguageType EditEngine::GetLanguage(const EditPaM& rPaM) const +editeng::LanguageSpan EditEngine::GetLanguage(const EditPaM& rPaM) const { - return pImpEditEngine->GetLanguage(rPaM); + return getImpl().GetLanguage(rPaM); } -LanguageType EditEngine::GetLanguage( sal_Int32 nPara, sal_Int32 nPos ) const +editeng::LanguageSpan EditEngine::GetLanguage( sal_Int32 nPara, sal_Int32 nPos ) const { - ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( nPara ); + ContentNode* pNode = getImpl().GetEditDoc().GetObject( nPara ); DBG_ASSERT( pNode, "GetLanguage - nPara is invalid!" ); - return pNode ? pImpEditEngine->GetLanguage( EditPaM( pNode, nPos ) ) : LANGUAGE_DONTKNOW; + return pNode ? getImpl().GetLanguage( EditPaM( pNode, nPos ) ) : editeng::LanguageSpan{}; } void EditEngine::TransliterateText( const ESelection& rSelection, TransliterationFlags nTransliterationMode ) { - pImpEditEngine->TransliterateText( pImpEditEngine->CreateSel( rSelection ), nTransliterationMode ); + getImpl().TransliterateText(getImpl().CreateSel( rSelection ), nTransliterationMode); } EditSelection EditEngine::TransliterateText(const EditSelection& rSelection, TransliterationFlags nTransliterationMode) { - return pImpEditEngine->TransliterateText(rSelection, nTransliterationMode); + return getImpl().TransliterateText(rSelection, nTransliterationMode); } void EditEngine::SetAsianCompressionMode( CharCompressType n ) { - pImpEditEngine->SetAsianCompressionMode( n ); + getImpl().SetAsianCompressionMode( n ); } void EditEngine::SetKernAsianPunctuation( bool b ) { - pImpEditEngine->SetKernAsianPunctuation( b ); + getImpl().SetKernAsianPunctuation( b ); } void EditEngine::SetAddExtLeading( bool b ) { - pImpEditEngine->SetAddExtLeading( b ); + getImpl().SetAddExtLeading( b ); } void EditEngine::SetPolygon( const basegfx::B2DPolyPolygon& rPolyPolygon ) @@ -535,116 +534,115 @@ void EditEngine::SetPolygon(const basegfx::B2DPolyPolygon& rPolyPolygon, const b } TextRanger* pRanger = new TextRanger( rPolyPolygon, pLinePolyPolygon, 30, 2, 2, bSimple, true ); - pImpEditEngine->SetTextRanger( std::unique_ptr<TextRanger>(pRanger) ); - pImpEditEngine->SetPaperSize( pRanger->GetBoundRect().GetSize() ); + getImpl().SetTextRanger( std::unique_ptr<TextRanger>(pRanger) ); + getImpl().SetPaperSize( pRanger->GetBoundRect().GetSize() ); } void EditEngine::ClearPolygon() { - pImpEditEngine->SetTextRanger( nullptr ); + getImpl().SetTextRanger( nullptr ); } const Size& EditEngine::GetMinAutoPaperSize() const { - return pImpEditEngine->GetMinAutoPaperSize(); + return getImpl().GetMinAutoPaperSize(); } void EditEngine::SetMinAutoPaperSize( const Size& rSz ) { - pImpEditEngine->SetMinAutoPaperSize( rSz ); + getImpl().SetMinAutoPaperSize( rSz ); } const Size& EditEngine::GetMaxAutoPaperSize() const { - return pImpEditEngine->GetMaxAutoPaperSize(); + return getImpl().GetMaxAutoPaperSize(); } -void EditEngine::SetMaxAutoPaperSize( const Size& rSz ) +void EditEngine::SetMaxAutoPaperSize(const Size& rSize) { - pImpEditEngine->SetMaxAutoPaperSize( rSz ); + getImpl().SetMaxAutoPaperSize(rSize); } void EditEngine::SetMinColumnWrapHeight(tools::Long nVal) { - pImpEditEngine->SetMinColumnWrapHeight(nVal); + getImpl().SetMinColumnWrapHeight(nVal); } OUString EditEngine::GetText( LineEnd eEnd ) const { - return pImpEditEngine->GetEditDoc().GetText( eEnd ); + return getImpl().GetEditDoc().GetText(eEnd); } OUString EditEngine::GetText( const ESelection& rESelection ) const { - EditSelection aSel( pImpEditEngine->CreateSel( rESelection ) ); - return pImpEditEngine->GetSelected( aSel ); + EditSelection aSel = getImpl().CreateSel(rESelection); + return getImpl().GetSelected(aSel); } sal_Int32 EditEngine::GetTextLen() const { - return pImpEditEngine->GetEditDoc().GetTextLen(); + return getImpl().GetEditDoc().GetTextLen(); } sal_Int32 EditEngine::GetParagraphCount() const { - return pImpEditEngine->aEditDoc.Count(); + return getImpl().maEditDoc.Count(); +} + +void EditEngine::ensureDocumentFormatted() const +{ + if (!getImpl().IsFormatted()) + getImpl().FormatDoc(); } sal_Int32 EditEngine::GetLineCount( sal_Int32 nParagraph ) const { - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); - return pImpEditEngine->GetLineCount( nParagraph ); + ensureDocumentFormatted(); + return getImpl().GetLineCount(nParagraph); } sal_Int32 EditEngine::GetLineLen( sal_Int32 nParagraph, sal_Int32 nLine ) const { - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); - return pImpEditEngine->GetLineLen( nParagraph, nLine ); + ensureDocumentFormatted(); + return getImpl().GetLineLen(nParagraph, nLine); } void EditEngine::GetLineBoundaries( /*out*/sal_Int32& rStart, /*out*/sal_Int32& rEnd, sal_Int32 nParagraph, sal_Int32 nLine ) const { - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); - return pImpEditEngine->GetLineBoundaries( rStart, rEnd, nParagraph, nLine ); + ensureDocumentFormatted(); + return getImpl().GetLineBoundaries(rStart, rEnd, nParagraph, nLine); } sal_Int32 EditEngine::GetLineNumberAtIndex( sal_Int32 nPara, sal_Int32 nIndex ) const { - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); - return pImpEditEngine->GetLineNumberAtIndex( nPara, nIndex ); + ensureDocumentFormatted(); + return getImpl().GetLineNumberAtIndex(nPara, nIndex); } sal_uInt32 EditEngine::GetLineHeight( sal_Int32 nParagraph ) { // If someone calls GetLineHeight() with an empty Engine. - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); - return pImpEditEngine->GetLineHeight( nParagraph, 0 ); + ensureDocumentFormatted(); + return getImpl().GetLineHeight( nParagraph, 0 ); } tools::Rectangle EditEngine::GetParaBounds( sal_Int32 nPara ) { - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); - + ensureDocumentFormatted(); Point aPnt = GetDocPosTopLeft( nPara ); if( IsEffectivelyVertical() ) { - sal_Int32 nTextHeight = pImpEditEngine->GetTextHeight(); - sal_Int32 nParaWidth = pImpEditEngine->CalcParaWidth( nPara, true ); - sal_uLong nParaHeight = pImpEditEngine->GetParaHeight( nPara ); + sal_Int32 nTextHeight = getImpl().GetTextHeight(); + sal_Int32 nParaWidth = getImpl().CalcParaWidth(nPara, true); + sal_Int32 nParaHeight = getImpl().GetParaHeight(nPara); return tools::Rectangle( nTextHeight - aPnt.Y() - nParaHeight, 0, nTextHeight - aPnt.Y(), nParaWidth ); } else { - sal_Int32 nParaWidth = pImpEditEngine->CalcParaWidth( nPara, true ); - sal_uLong nParaHeight = pImpEditEngine->GetParaHeight( nPara ); + sal_Int32 nParaWidth = getImpl().CalcParaWidth( nPara, true ); + sal_Int32 nParaHeight = getImpl().GetParaHeight( nPara ); return tools::Rectangle( 0, aPnt.Y(), nParaWidth, aPnt.Y() + nParaHeight ); } @@ -652,119 +650,112 @@ tools::Rectangle EditEngine::GetParaBounds( sal_Int32 nPara ) sal_uInt32 EditEngine::GetTextHeight( sal_Int32 nParagraph ) const { - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); - - sal_uInt32 nHeight = pImpEditEngine->GetParaHeight( nParagraph ); + ensureDocumentFormatted(); + sal_uInt32 nHeight = getImpl().GetParaHeight(nParagraph); return nHeight; } OUString EditEngine::GetWord( sal_Int32 nPara, sal_Int32 nIndex ) { ESelection aESel( nPara, nIndex, nPara, nIndex ); - EditSelection aSel( pImpEditEngine->CreateSel( aESel ) ); - aSel = pImpEditEngine->SelectWord( aSel ); - return pImpEditEngine->GetSelected( aSel ); + EditSelection aSel(getImpl().CreateSel(aESel)); + aSel = getImpl().SelectWord(aSel); + return getImpl().GetSelected(aSel); } ESelection EditEngine::GetWord( const ESelection& rSelection, sal_uInt16 nWordType ) const { // ImpEditEngine-Iteration-Methods should be const! - EditEngine* pE = const_cast<EditEngine*>(this); + EditEngine* pNonConstEditEngine = const_cast<EditEngine*>(this); - EditSelection aSel( pE->pImpEditEngine->CreateSel( rSelection ) ); - aSel = pE->pImpEditEngine->SelectWord( aSel, nWordType ); - return pE->pImpEditEngine->CreateESel( aSel ); -} - -void EditEngine::CursorMoved(const ContentNode* pPrevNode) -{ - pImpEditEngine->CursorMoved(pPrevNode); + EditSelection aSel(pNonConstEditEngine->getImpl().CreateSel( rSelection ) ); + aSel = pNonConstEditEngine->getImpl().SelectWord( aSel, nWordType ); + return pNonConstEditEngine->getImpl().CreateESel( aSel ); } void EditEngine::CheckIdleFormatter() { - pImpEditEngine->CheckIdleFormatter(); + getImpl().CheckIdleFormatter(); } bool EditEngine::IsIdleFormatterActive() const { - return pImpEditEngine->aIdleFormatter.IsActive(); + return getImpl().maIdleFormatter.IsActive(); } ParaPortion* EditEngine::FindParaPortion(ContentNode const * pNode) { - return &pImpEditEngine->FindParaPortion(pNode); + return getImpl().FindParaPortion(pNode); } const ParaPortion* EditEngine::FindParaPortion(ContentNode const * pNode) const { - return &pImpEditEngine->FindParaPortion(pNode); + return getImpl().FindParaPortion(pNode); } const ParaPortion* EditEngine::GetPrevVisPortion(const ParaPortion* pCurPortion) const { - return pImpEditEngine->GetPrevVisPortion(pCurPortion); + return getImpl().GetPrevVisPortion(pCurPortion); } SvtScriptType EditEngine::GetScriptType(const EditSelection& rSel) const { - return pImpEditEngine->GetItemScriptType(rSel); + return getImpl().GetItemScriptType(rSel); } void EditEngine::RemoveParaPortion(sal_Int32 nNode) { - pImpEditEngine->GetParaPortions().Remove(nNode); + getImpl().GetParaPortions().Remove(nNode); } void EditEngine::SetCallParaInsertedOrDeleted(bool b) { - pImpEditEngine->SetCallParaInsertedOrDeleted(b); + getImpl().SetCallParaInsertedOrDeleted(b); } bool EditEngine::IsCallParaInsertedOrDeleted() const { - return pImpEditEngine->IsCallParaInsertedOrDeleted(); + return getImpl().IsCallParaInsertedOrDeleted(); } void EditEngine::AppendDeletedNodeInfo(DeletedNodeInfo* pInfo) { - pImpEditEngine->aDeletedNodes.push_back(std::unique_ptr<DeletedNodeInfo>(pInfo)); + getImpl().maDeletedNodes.push_back(std::unique_ptr<DeletedNodeInfo>(pInfo)); } void EditEngine::UpdateSelections() { - pImpEditEngine->UpdateSelections(); + getImpl().UpdateSelections(); } -void EditEngine::InsertContent(ContentNode* pNode, sal_Int32 nPos) +void EditEngine::InsertContent(std::unique_ptr<ContentNode> pNode, sal_Int32 nPos) { - pImpEditEngine->InsertContent(pNode, nPos); + getImpl().InsertContent(std::move(pNode), nPos); } EditPaM EditEngine::SplitContent(sal_Int32 nNode, sal_Int32 nSepPos) { - return pImpEditEngine->SplitContent(nNode, nSepPos); + return getImpl().SplitContent(nNode, nSepPos); } EditPaM EditEngine::ConnectContents(sal_Int32 nLeftNode, bool bBackward) { - return pImpEditEngine->ConnectContents(nLeftNode, bBackward); + return getImpl().ConnectContents(nLeftNode, bBackward); } void EditEngine::InsertFeature(const EditSelection& rEditSelection, const SfxPoolItem& rItem) { - pImpEditEngine->ImpInsertFeature(rEditSelection, rItem); + getImpl().ImpInsertFeature(rEditSelection, rItem); } EditSelection EditEngine::MoveParagraphs(const Range& rParagraphs, sal_Int32 nNewPos) { - return pImpEditEngine->MoveParagraphs(rParagraphs, nNewPos, nullptr); + return getImpl().MoveParagraphs(rParagraphs, nNewPos, nullptr); } void EditEngine::RemoveCharAttribs(sal_Int32 nPara, sal_uInt16 nWhich, bool bRemoveFeatures) { - pImpEditEngine->RemoveCharAttribs(nPara, nWhich, bRemoveFeatures); + getImpl().RemoveCharAttribs(nPara, nWhich, bRemoveFeatures); } void EditEngine::RemoveCharAttribs(const EditSelection& rSel, bool bRemoveParaAttribs, sal_uInt16 nWhich) @@ -772,228 +763,226 @@ void EditEngine::RemoveCharAttribs(const EditSelection& rSel, bool bRemoveParaAt const EERemoveParaAttribsMode eMode = bRemoveParaAttribs? EERemoveParaAttribsMode::RemoveAll : EERemoveParaAttribsMode::RemoveCharItems; - pImpEditEngine->RemoveCharAttribs(rSel, eMode, nWhich); + getImpl().RemoveCharAttribs(rSel, eMode, nWhich); } void EditEngine::RemoveCharAttribs(const EditSelection& rSel, EERemoveParaAttribsMode eMode, sal_uInt16 nWhich) { - pImpEditEngine->RemoveCharAttribs(rSel, eMode, nWhich); + getImpl().RemoveCharAttribs(rSel, eMode, nWhich); } EditEngine::ViewsType& EditEngine::GetEditViews() { - return pImpEditEngine->GetEditViews(); + return getImpl().GetEditViews(); } const EditEngine::ViewsType& EditEngine::GetEditViews() const { - return pImpEditEngine->GetEditViews(); + return getImpl().GetEditViews(); } void EditEngine::SetUndoMode(bool b) { - pImpEditEngine->SetUndoMode(b); + getImpl().SetUndoMode(b); } void EditEngine::FormatAndLayout(EditView* pCurView, bool bCalledFromUndo) { - pImpEditEngine->FormatAndLayout(pCurView, bCalledFromUndo); + getImpl().FormatAndLayout(pCurView, bCalledFromUndo); } void EditEngine::Undo(EditView* pView) { - pImpEditEngine->Undo(pView); + getImpl().Undo(pView); } void EditEngine::Redo(EditView* pView) { - pImpEditEngine->Redo(pView); + getImpl().Redo(pView); } uno::Reference<datatransfer::XTransferable> EditEngine::CreateTransferable(const EditSelection& rSelection) { - return pImpEditEngine->CreateTransferable(rSelection); + return getImpl().CreateTransferable(rSelection); } void EditEngine::ParaAttribsToCharAttribs(ContentNode* pNode) { - pImpEditEngine->ParaAttribsToCharAttribs(pNode); + getImpl().ParaAttribsToCharAttribs(pNode); } EditPaM EditEngine::CreateEditPaM(const EPaM& rEPaM) { - return pImpEditEngine->CreateEditPaM(rEPaM); + return getImpl().CreateEditPaM(rEPaM); } EditPaM EditEngine::ConnectParagraphs( ContentNode* pLeft, ContentNode* pRight, bool bBackward) { - return pImpEditEngine->ImpConnectParagraphs(pLeft, pRight, bBackward); + return getImpl().ImpConnectParagraphs(pLeft, pRight, bBackward); } EditPaM EditEngine::InsertField(const EditSelection& rEditSelection, const SvxFieldItem& rFld) { - return pImpEditEngine->InsertField(rEditSelection, rFld); + return getImpl().InsertField(rEditSelection, rFld); } EditPaM EditEngine::InsertText(const EditSelection& aCurEditSelection, const OUString& rStr) { - return pImpEditEngine->InsertText(aCurEditSelection, rStr); + return getImpl().InsertText(aCurEditSelection, rStr); } EditSelection EditEngine::InsertText(const EditTextObject& rTextObject, const EditSelection& rSel) { - return pImpEditEngine->InsertText(rTextObject, rSel); + return getImpl().InsertText(rTextObject, rSel); } EditSelection EditEngine::InsertText( uno::Reference<datatransfer::XTransferable > const & rxDataObj, - const OUString& rBaseURL, const EditPaM& rPaM, bool bUseSpecial) + const OUString& rBaseURL, const EditPaM& rPaM, bool bUseSpecial, SotClipboardFormatId format) { - return pImpEditEngine->PasteText(rxDataObj, rBaseURL, rPaM, bUseSpecial); + return getImpl().PasteText(rxDataObj, rBaseURL, rPaM, bUseSpecial, format); } EditPaM EditEngine::EndOfWord(const EditPaM& rPaM) { - return pImpEditEngine->EndOfWord(rPaM); + return getImpl().EndOfWord(rPaM); } EditPaM EditEngine::GetPaM(const Point& aDocPos, bool bSmart) { - return pImpEditEngine->GetPaM(aDocPos, bSmart); + return getImpl().GetPaM(aDocPos, bSmart); } EditSelection EditEngine::SelectWord( const EditSelection& rCurSelection, sal_Int16 nWordType) { - return pImpEditEngine->SelectWord(rCurSelection, nWordType); + return getImpl().SelectWord(rCurSelection, nWordType); } -tools::Long EditEngine::GetXPos( - const ParaPortion* pParaPortion, const EditLine* pLine, sal_Int32 nIndex, bool bPreferPortionStart) const +tools::Long EditEngine::GetXPos(ParaPortion const& rParaPortion, EditLine const& rLine, sal_Int32 nIndex, bool bPreferPortionStart) const { - return pImpEditEngine->GetXPos(pParaPortion, pLine, nIndex, bPreferPortionStart); + return getImpl().GetXPos(rParaPortion, rLine, nIndex, bPreferPortionStart); } -Range EditEngine::GetLineXPosStartEnd( - const ParaPortion* pParaPortion, const EditLine* pLine) const +Range EditEngine::GetLineXPosStartEnd(ParaPortion const& rParaPortion, EditLine const& rLine) const { - return pImpEditEngine->GetLineXPosStartEnd(pParaPortion, pLine); + return getImpl().GetLineXPosStartEnd(rParaPortion, rLine); } bool EditEngine::IsFormatted() const { - return pImpEditEngine->IsFormatted(); + return getImpl().IsFormatted(); } EditPaM EditEngine::CursorLeft(const EditPaM& rPaM, sal_uInt16 nCharacterIteratorMode) { - return pImpEditEngine->CursorLeft(rPaM, nCharacterIteratorMode); + return getImpl().CursorLeft(rPaM, nCharacterIteratorMode); } EditPaM EditEngine::CursorRight(const EditPaM& rPaM, sal_uInt16 nCharacterIteratorMode) { - return pImpEditEngine->CursorRight(rPaM, nCharacterIteratorMode); + return getImpl().CursorRight(rPaM, nCharacterIteratorMode); } InternalEditStatus& EditEngine::GetInternalEditStatus() { - return pImpEditEngine->GetStatus(); + return getImpl().GetStatus(); } EditDoc& EditEngine::GetEditDoc() { - return pImpEditEngine->GetEditDoc(); + return getImpl().GetEditDoc(); } const EditDoc& EditEngine::GetEditDoc() const { - return pImpEditEngine->GetEditDoc(); + return getImpl().GetEditDoc(); } void EditEngine::dumpAsXmlEditDoc(xmlTextWriterPtr pWriter) const { - pImpEditEngine->GetEditDoc().dumpAsXml(pWriter); + getImpl().GetEditDoc().dumpAsXml(pWriter); } ParaPortionList& EditEngine::GetParaPortions() { - return pImpEditEngine->GetParaPortions(); + return getImpl().GetParaPortions(); } const ParaPortionList& EditEngine::GetParaPortions() const { - return pImpEditEngine->GetParaPortions(); + return getImpl().GetParaPortions(); } void EditEngine::SeekCursor(ContentNode* pNode, sal_Int32 nPos, SvxFont& rFont) { - pImpEditEngine->SeekCursor(pNode, nPos, rFont); + getImpl().SeekCursor(pNode, nPos, rFont); } EditPaM EditEngine::DeleteSelection(const EditSelection& rSel) { - return pImpEditEngine->ImpDeleteSelection(rSel); + return getImpl().ImpDeleteSelection(rSel); } ESelection EditEngine::CreateESelection(const EditSelection& rSel) const { - return pImpEditEngine->CreateESel(rSel); + return getImpl().CreateESel(rSel); } EditSelection EditEngine::CreateSelection(const ESelection& rSel) { - return pImpEditEngine->CreateSel(rSel); + return getImpl().CreateSel(rSel); } const SfxItemSet& EditEngine::GetBaseParaAttribs(sal_Int32 nPara) const { - return pImpEditEngine->GetParaAttribs(nPara); + return getImpl().GetParaAttribs(nPara); } void EditEngine::SetParaAttribsOnly(sal_Int32 nPara, const SfxItemSet& rSet) { - pImpEditEngine->SetParaAttribs(nPara, rSet); + getImpl().SetParaAttribs(nPara, rSet); } void EditEngine::SetAttribs(const EditSelection& rSel, const SfxItemSet& rSet, SetAttribsMode nSpecial) { - pImpEditEngine->SetAttribs(rSel, rSet, nSpecial); + getImpl().SetAttribs(rSel, rSet, nSpecial); } OUString EditEngine::GetSelected(const EditSelection& rSel) const { - return pImpEditEngine->GetSelected(rSel); + return getImpl().GetSelected(rSel); } EditPaM EditEngine::DeleteSelected(const EditSelection& rSel) { - return pImpEditEngine->DeleteSelected(rSel); + return getImpl().DeleteSelected(rSel); } void EditEngine::HandleBeginPasteOrDrop(PasteOrDropInfos& rInfos) { - pImpEditEngine->aBeginPasteOrDropHdl.Call(rInfos); + getImpl().maBeginPasteOrDropHdl.Call(rInfos); } void EditEngine::HandleEndPasteOrDrop(PasteOrDropInfos& rInfos) { - pImpEditEngine->aEndPasteOrDropHdl.Call(rInfos); + getImpl().maEndPasteOrDropHdl.Call(rInfos); } bool EditEngine::HasText() const { - return pImpEditEngine->ImplHasText(); + return getImpl().ImplHasText(); } const EditSelectionEngine& EditEngine::GetSelectionEngine() const { - return pImpEditEngine->aSelEngine; + return getImpl().maSelEngine; } void EditEngine::SetInSelectionMode(bool b) { - pImpEditEngine->bInSelection = b; + getImpl().mbInSelection = b; } bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, vcl::Window const * pFrameWin ) @@ -1007,15 +996,15 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v bool bAllowIdle = true; bool bReadOnly = pEditView->IsReadOnly(); - GetCursorFlags nNewCursorFlags = GetCursorFlags::NONE; + CursorFlags aNewCursorFlags; bool bSetCursorFlags = true; - EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() ); + EditSelection aCurSel( pEditView->getImpl().GetEditSelection() ); DBG_ASSERT( !aCurSel.IsInvalid(), "Blinde Selection in EditEngine::PostKeyEvent" ); - OUString aAutoText( pImpEditEngine->GetAutoCompleteText() ); - if (!pImpEditEngine->GetAutoCompleteText().isEmpty()) - pImpEditEngine->SetAutoCompleteText(OUString(), true); + OUString aAutoText(getImpl().GetAutoCompleteText()); + if (!getImpl().GetAutoCompleteText().isEmpty()) + getImpl().SetAutoCompleteText(OUString(), true); sal_uInt16 nCode = rKeyEvent.GetKeyCode().GetCode(); KeyFuncType eFunc = rKeyEvent.GetKeyCode().GetFunction(); @@ -1053,7 +1042,7 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v sal_Int32 nParas = GetParagraphCount(); Point aPos; Point aViewStart( pEditView->GetOutputArea().TopLeft() ); - tools::Long n20 = 40 * pImpEditEngine->nOnePixelInRef; + tools::Long n20 = 40 * getImpl().mnOnePixelInRef; for ( sal_Int32 n = 0; n < nParas; n++ ) { tools::Long nH = GetTextHeight( n ); @@ -1079,7 +1068,7 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v aInfo.append(bDebugPaint ? "On" : "Off"); std::unique_ptr<weld::MessageDialog> xInfoBox(Application::CreateMessageDialog(pEditView->GetWindow()->GetFrameWeld(), VclMessageType::Info, VclButtonsType::Ok, - OStringToOUString(aInfo.makeStringAndClear(), RTL_TEXTENCODING_ASCII_US))); + OStringToOUString(aInfo, RTL_TEXTENCODING_ASCII_US))); xInfoBox->run(); } @@ -1121,25 +1110,25 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v { if ( !rKeyEvent.GetKeyCode().IsMod2() || ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) ) { - if ( pImpEditEngine->DoVisualCursorTraveling() && ( ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) /* || ( nCode == KEY_HOME ) || ( nCode == KEY_END ) */ ) ) + if ( ImpEditEngine::DoVisualCursorTraveling() && ( ( nCode == KEY_LEFT ) || ( nCode == KEY_RIGHT ) /* || ( nCode == KEY_HOME ) || ( nCode == KEY_END ) */ ) ) bSetCursorFlags = false; // Will be manipulated within visual cursor move - aCurSel = pImpEditEngine->MoveCursor( rKeyEvent, pEditView ); + aCurSel = getImpl().MoveCursor( rKeyEvent, pEditView ); if ( aCurSel.HasRange() ) { Reference<css::datatransfer::clipboard::XClipboard> aSelection(GetSystemPrimarySelection()); - pEditView->pImpEditView->CutCopy( aSelection, false ); + pEditView->getImpl().CutCopy( aSelection, false ); } bMoved = true; if ( nCode == KEY_HOME ) - nNewCursorFlags |= GetCursorFlags::StartOfLine; + aNewCursorFlags.bStartOfLine = true; else if ( nCode == KEY_END ) - nNewCursorFlags |= GetCursorFlags::EndOfLine; + aNewCursorFlags.bEndOfLine = true; } #if OSL_DEBUG_LEVEL > 1 - GetLanguage( pImpEditEngine->GetEditDoc().GetPos( aCurSel.Max().GetNode() ), aCurSel.Max().GetIndex() ); + GetLanguage(getImpl().GetEditDoc().GetPos( aCurSel.Max().GetNode() ), aCurSel.Max().GetIndex()); #endif } break; @@ -1154,7 +1143,7 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v { // check if we are behind a bullet and using the backspace key ContentNode *pNode = aCurSel.Min().GetNode(); - const SvxNumberFormat *pFmt = pImpEditEngine->GetNumberFormat( pNode ); + const SvxNumberFormat *pFmt = getImpl().GetNumberFormat( pNode ); if (pFmt && nCode == KEY_BACKSPACE && !aCurSel.HasRange() && aCurSel.Min().GetIndex() == 0) { @@ -1162,22 +1151,22 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v // Otherwise continue as usual. - sal_Int32 nPara = pImpEditEngine->GetEditDoc().GetPos( pNode ); - SfxBoolItem aBulletState( pImpEditEngine->GetParaAttrib( nPara, EE_PARA_BULLETSTATE ) ); + sal_Int32 nPara = getImpl().GetEditDoc().GetPos( pNode ); + SfxBoolItem aBulletState(getImpl().GetParaAttrib(nPara, EE_PARA_BULLETSTATE)); if ( aBulletState.GetValue() ) { aBulletState.SetValue( false ); - SfxItemSet aSet( pImpEditEngine->GetParaAttribs( nPara ) ); + SfxItemSet aSet( getImpl().GetParaAttribs( nPara ) ); aSet.Put( aBulletState ); - pImpEditEngine->SetParaAttribs( nPara, aSet ); + getImpl().SetParaAttribs( nPara, aSet ); // have this and the following paragraphs formatted and repainted. // (not painting a numbering in the list may cause the following // numberings to have different numbers than before and thus the // length may have changed as well ) - pImpEditEngine->FormatAndLayout( pImpEditEngine->GetActiveView() ); + getImpl().FormatAndLayout(getImpl().GetActiveView()); break; } @@ -1211,10 +1200,10 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v break; } - pEditView->pImpEditView->DrawSelectionXOR(); - pImpEditEngine->UndoActionStart( EDITUNDO_DELETE ); - aCurSel = pImpEditEngine->DeleteLeftOrRight( aCurSel, nDel, nMode ); - pImpEditEngine->UndoActionEnd(); + pEditView->getImpl().DrawSelectionXOR(); + getImpl().UndoActionStart( EDITUNDO_DELETE ); + aCurSel = getImpl().DeleteLeftOrRight( aCurSel, nDel, nMode ); + getImpl().UndoActionEnd(); bModified = true; bAllowIdle = false; } @@ -1229,12 +1218,12 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v { bool bSel = pEditView->HasSelection(); if ( bSel ) - pImpEditEngine->UndoActionStart( EDITUNDO_INSERT ); - if ( pImpEditEngine->GetStatus().DoAutoCorrect() ) - aCurSel = pImpEditEngine->AutoCorrect( aCurSel, 0, !pEditView->IsInsertMode(), pFrameWin ); - aCurSel = pImpEditEngine->InsertTab( aCurSel ); + getImpl().UndoActionStart( EDITUNDO_INSERT ); + if ( getImpl().GetStatus().DoAutoCorrect() ) + aCurSel = getImpl().AutoCorrect( aCurSel, 0, !pEditView->IsInsertMode(), pFrameWin ); + aCurSel = getImpl().InsertTab( aCurSel ); if ( bSel ) - pImpEditEngine->UndoActionEnd(); + getImpl().UndoActionEnd(); bModified = true; } } @@ -1246,33 +1235,33 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v { if ( !bReadOnly ) { - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); if ( !rKeyEvent.GetKeyCode().IsMod1() && !rKeyEvent.GetKeyCode().IsMod2() ) { - pImpEditEngine->UndoActionStart( EDITUNDO_INSERT ); + getImpl().UndoActionStart( EDITUNDO_INSERT ); if ( rKeyEvent.GetKeyCode().IsShift() ) { - aCurSel = pImpEditEngine->AutoCorrect( aCurSel, 0, !pEditView->IsInsertMode(), pFrameWin ); - aCurSel = pImpEditEngine->InsertLineBreak( aCurSel ); + aCurSel = getImpl().AutoCorrect( aCurSel, 0, !pEditView->IsInsertMode(), pFrameWin ); + aCurSel = getImpl().InsertLineBreak( aCurSel ); } else { if (aAutoText.isEmpty()) { - if ( pImpEditEngine->GetStatus().DoAutoCorrect() ) - aCurSel = pImpEditEngine->AutoCorrect( aCurSel, 0, !pEditView->IsInsertMode(), pFrameWin ); - aCurSel = pImpEditEngine->InsertParaBreak( aCurSel ); + if (getImpl().GetStatus().DoAutoCorrect()) + aCurSel = getImpl().AutoCorrect( aCurSel, 0, !pEditView->IsInsertMode(), pFrameWin ); + aCurSel = getImpl().InsertParaBreak( aCurSel ); } else { DBG_ASSERT( !aCurSel.HasRange(), "Selection on complete?!" ); - EditPaM aStart( pImpEditEngine->WordLeft( aCurSel.Max() ) ); - aCurSel = pImpEditEngine->InsertText( - EditSelection( aStart, aCurSel.Max() ), aAutoText ); - pImpEditEngine->SetAutoCompleteText( OUString(), true ); + EditPaM aStart = getImpl().WordLeft(aCurSel.Max()); + EditSelection aSelection(aStart, aCurSel.Max()); + aCurSel = getImpl().InsertText(aSelection, aAutoText); + getImpl().SetAutoCompleteText( OUString(), true ); } } - pImpEditEngine->UndoActionEnd(); + getImpl().UndoActionEnd(); bModified = true; } } @@ -1301,48 +1290,48 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v if ( !bReadOnly && IsSimpleCharInput( rKeyEvent ) ) { sal_Unicode nCharCode = rKeyEvent.GetCharCode(); - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); // Autocorrection? - if ( ( pImpEditEngine->GetStatus().DoAutoCorrect() ) && - ( SvxAutoCorrect::IsAutoCorrectChar( nCharCode ) || - pImpEditEngine->IsNbspRunNext() ) ) + if ((getImpl().GetStatus().DoAutoCorrect()) && + (SvxAutoCorrect::IsAutoCorrectChar(nCharCode) || + getImpl().IsNbspRunNext())) { - aCurSel = pImpEditEngine->AutoCorrect( + aCurSel = getImpl().AutoCorrect( aCurSel, nCharCode, !pEditView->IsInsertMode(), pFrameWin ); } else { - aCurSel = pImpEditEngine->InsertTextUserInput( aCurSel, nCharCode, !pEditView->IsInsertMode() ); + aCurSel = getImpl().InsertTextUserInput( aCurSel, nCharCode, !pEditView->IsInsertMode() ); } // AutoComplete ??? - if ( pImpEditEngine->GetStatus().DoAutoComplete() && ( nCharCode != ' ' ) ) + if ( getImpl().GetStatus().DoAutoComplete() && ( nCharCode != ' ' ) ) { // Only at end of word... sal_Int32 nIndex = aCurSel.Max().GetIndex(); - if ( ( nIndex >= aCurSel.Max().GetNode()->Len() ) || - ( pImpEditEngine->aWordDelimiters.indexOf( aCurSel.Max().GetNode()->GetChar( nIndex ) ) != -1 ) ) + if ((nIndex >= aCurSel.Max().GetNode()->Len()) || + (getImpl().maWordDelimiters.indexOf(aCurSel.Max().GetNode()->GetChar(nIndex)) != -1)) { - EditPaM aStart( pImpEditEngine->WordLeft( aCurSel.Max() ) ); - OUString aWord = pImpEditEngine->GetSelected( EditSelection( aStart, aCurSel.Max() ) ); + EditPaM aStart(getImpl().WordLeft(aCurSel.Max())); + OUString aWord = getImpl().GetSelected(EditSelection(aStart, aCurSel.Max())); if ( aWord.getLength() >= 3 ) { OUString aComplete; - LanguageType eLang = pImpEditEngine->GetLanguage( EditPaM( aStart.GetNode(), aStart.GetIndex()+1)); + LanguageType eLang = getImpl().GetLanguage(EditPaM( aStart.GetNode(), aStart.GetIndex()+1)).nLang; LanguageTag aLanguageTag( eLang); - if (!pImpEditEngine->xLocaleDataWrapper.isInitialized()) - pImpEditEngine->xLocaleDataWrapper.init( SvtSysLocale().GetLocaleData().getComponentContext(), aLanguageTag); + if (!getImpl().mxLocaleDataWrapper.isInitialized()) + getImpl().mxLocaleDataWrapper.init( SvtSysLocale().GetLocaleData().getComponentContext(), aLanguageTag); else - pImpEditEngine->xLocaleDataWrapper.changeLocale( aLanguageTag); + getImpl().mxLocaleDataWrapper.changeLocale( aLanguageTag); - if (!pImpEditEngine->xTransliterationWrapper.isInitialized()) - pImpEditEngine->xTransliterationWrapper.init( SvtSysLocale().GetLocaleData().getComponentContext(), eLang); + if (!getImpl().mxTransliterationWrapper.isInitialized()) + getImpl().mxTransliterationWrapper.init( SvtSysLocale().GetLocaleData().getComponentContext(), eLang); else - pImpEditEngine->xTransliterationWrapper.changeLocale( eLang); + getImpl().mxTransliterationWrapper.changeLocale( eLang); - const ::utl::TransliterationWrapper* pTransliteration = pImpEditEngine->xTransliterationWrapper.get(); - Sequence< i18n::CalendarItem2 > xItem = pImpEditEngine->xLocaleDataWrapper->getDefaultCalendarDays(); + const ::utl::TransliterationWrapper* pTransliteration = getImpl().mxTransliterationWrapper.get(); + Sequence< i18n::CalendarItem2 > xItem = getImpl().mxLocaleDataWrapper->getDefaultCalendarDays(); sal_Int32 nCount = xItem.getLength(); const i18n::CalendarItem2* pArr = xItem.getConstArray(); for( sal_Int32 n = 0; n <= nCount; ++n ) @@ -1357,7 +1346,7 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v if ( aComplete.isEmpty() ) { - xItem = pImpEditEngine->xLocaleDataWrapper->getDefaultCalendarMonths(); + xItem = getImpl().mxLocaleDataWrapper->getDefaultCalendarMonths(); sal_Int32 nMonthCount = xItem.getLength(); const i18n::CalendarItem2* pMonthArr = xItem.getConstArray(); for( sal_Int32 n = 0; n <= nMonthCount; ++n ) @@ -1373,10 +1362,10 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v if( !aComplete.isEmpty() && ( ( aWord.getLength() + 1 ) < aComplete.getLength() ) ) { - pImpEditEngine->SetAutoCompleteText( aComplete, false ); - Point aPos = pImpEditEngine->PaMtoEditCursor( aCurSel.Max() ).TopLeft(); - aPos = pEditView->pImpEditView->GetWindowPos( aPos ); - aPos = pEditView->pImpEditView->GetWindow()->LogicToPixel( aPos ); + getImpl().SetAutoCompleteText( aComplete, false ); + Point aPos = getImpl().PaMtoEditCursor( aCurSel.Max() ).TopLeft(); + aPos = pEditView->getImpl().GetWindowPos( aPos ); + aPos = pEditView->getImpl().GetWindow()->LogicToPixel( aPos ); aPos = pEditView->GetWindow()->OutputToScreenPixel( aPos ); aPos.AdjustY( -3 ); Help::ShowQuickHelp( pEditView->GetWindow(), tools::Rectangle( aPos, Size( 1, 1 ) ), aComplete, QuickHelpFlags::Bottom|QuickHelpFlags::Left ); @@ -1392,44 +1381,44 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v } } - pEditView->pImpEditView->SetEditSelection( aCurSel ); + pEditView->getImpl().SetEditSelection( aCurSel ); if (comphelper::LibreOfficeKit::isActive()) { - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); } - pImpEditEngine->UpdateSelections(); + getImpl().UpdateSelections(); if ( ( !IsEffectivelyVertical() && ( nCode != KEY_UP ) && ( nCode != KEY_DOWN ) ) || ( IsEffectivelyVertical() && ( nCode != KEY_LEFT ) && ( nCode != KEY_RIGHT ) )) { - pEditView->pImpEditView->nTravelXPos = TRAVEL_X_DONTKNOW; + pEditView->getImpl().mnTravelXPos = TRAVEL_X_DONTKNOW; } if ( /* ( nCode != KEY_HOME ) && ( nCode != KEY_END ) && */ ( !IsEffectivelyVertical() && ( nCode != KEY_LEFT ) && ( nCode != KEY_RIGHT ) ) || ( IsEffectivelyVertical() && ( nCode != KEY_UP ) && ( nCode != KEY_DOWN ) )) { - pEditView->pImpEditView->SetCursorBidiLevel( CURSOR_BIDILEVEL_DONTKNOW ); + pEditView->getImpl().SetCursorBidiLevel( CURSOR_BIDILEVEL_DONTKNOW ); } - if ( bSetCursorFlags ) - pEditView->pImpEditView->nExtraCursorFlags = nNewCursorFlags; + if (bSetCursorFlags) + pEditView->getImpl().maExtraCursorFlags = aNewCursorFlags; if ( bModified ) { DBG_ASSERT( !bReadOnly, "ReadOnly but modified???" ); // Idle-Formatter only when AnyInput. - if ( bAllowIdle && pImpEditEngine->GetStatus().UseIdleFormatter() + if ( bAllowIdle && getImpl().GetStatus().UseIdleFormatter() && Application::AnyInput( VclInputFlags::KEYBOARD) ) - pImpEditEngine->IdleFormatAndLayout( pEditView ); + getImpl().IdleFormatAndLayout( pEditView ); else - pImpEditEngine->FormatAndLayout( pEditView ); + getImpl().FormatAndLayout( pEditView ); } else if ( bMoved ) { - bool bGotoCursor = pEditView->pImpEditView->DoAutoScroll(); - pEditView->pImpEditView->ShowCursor( bGotoCursor, true ); - pImpEditEngine->CallStatusHdl(); + bool bGotoCursor = pEditView->getImpl().DoAutoScroll(); + pEditView->getImpl().ShowCursor( bGotoCursor, true ); + getImpl().CallStatusHdl(); } return bDone; @@ -1437,178 +1426,169 @@ bool EditEngine::PostKeyEvent( const KeyEvent& rKeyEvent, EditView* pEditView, v sal_uInt32 EditEngine::GetTextHeight() const { - - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); - - sal_uInt32 nHeight = !IsEffectivelyVertical() ? pImpEditEngine->GetTextHeight() : pImpEditEngine->CalcTextWidth( true ); + ensureDocumentFormatted(); + sal_uInt32 nHeight = !IsEffectivelyVertical() ? getImpl().GetTextHeight() : getImpl().CalcTextWidth( true ); return nHeight; } sal_uInt32 EditEngine::GetTextHeightNTP() const { + ensureDocumentFormatted(); - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); - - if ( IsEffectivelyVertical() ) - return pImpEditEngine->CalcTextWidth( true ); + if (IsEffectivelyVertical()) + return getImpl().CalcTextWidth(true); - return pImpEditEngine->GetTextHeightNTP(); + return getImpl().GetTextHeightNTP(); } sal_uInt32 EditEngine::CalcTextWidth() { - - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); - - sal_uInt32 nWidth = !IsEffectivelyVertical() ? pImpEditEngine->CalcTextWidth( true ) : pImpEditEngine->GetTextHeight(); + ensureDocumentFormatted(); + sal_uInt32 nWidth = !IsEffectivelyVertical() ? getImpl().CalcTextWidth(true) : getImpl().GetTextHeight(); return nWidth; } bool EditEngine::SetUpdateLayout(bool bUpdate, bool bRestoring) { - bool bPrevUpdateLayout = pImpEditEngine->SetUpdateLayout( bUpdate ); - if (pImpEditEngine->pActiveView) + bool bPrevUpdateLayout = getImpl().SetUpdateLayout(bUpdate); + if (getImpl().mpActiveView) { // Not an activation if we are restoring the previous update mode. - pImpEditEngine->pActiveView->ShowCursor(false, false, /*bActivate=*/!bRestoring); + getImpl().mpActiveView->ShowCursor(false, false, /*bActivate=*/!bRestoring); } return bPrevUpdateLayout; } bool EditEngine::IsUpdateLayout() const { - return pImpEditEngine->IsUpdateLayout(); + return getImpl().IsUpdateLayout(); } void EditEngine::Clear() { - pImpEditEngine->Clear(); + getImpl().Clear(); } void EditEngine::SetText( const OUString& rText ) { - pImpEditEngine->SetText( rText ); - if ( !rText.isEmpty() && pImpEditEngine->IsUpdateLayout() ) - pImpEditEngine->FormatAndLayout(); + getImpl().SetText(rText); + if (!rText.isEmpty() && getImpl().IsUpdateLayout()) + getImpl().FormatAndLayout(); } ErrCode EditEngine::Read( SvStream& rInput, const OUString& rBaseURL, EETextFormat eFormat, SvKeyValueIterator* pHTTPHeaderAttrs /* = NULL */ ) { - bool bUndoEnabled = pImpEditEngine->IsUndoEnabled(); - pImpEditEngine->EnableUndo( false ); - pImpEditEngine->SetText( OUString() ); - EditPaM aPaM( pImpEditEngine->GetEditDoc().GetStartPaM() ); - pImpEditEngine->Read( rInput, rBaseURL, eFormat, EditSelection( aPaM, aPaM ), pHTTPHeaderAttrs ); - pImpEditEngine->EnableUndo( bUndoEnabled ); + bool bUndoEnabled = getImpl().IsUndoEnabled(); + getImpl().EnableUndo(false); + getImpl().SetText(OUString()); + EditPaM aPaM(getImpl().GetEditDoc().GetStartPaM()); + getImpl().Read(rInput, rBaseURL, eFormat, EditSelection(aPaM, aPaM), pHTTPHeaderAttrs); + getImpl().EnableUndo(bUndoEnabled); return rInput.GetError(); } void EditEngine::Write( SvStream& rOutput, EETextFormat eFormat ) { - EditPaM aStartPaM( pImpEditEngine->GetEditDoc().GetStartPaM() ); - EditPaM aEndPaM( pImpEditEngine->GetEditDoc().GetEndPaM() ); - pImpEditEngine->Write( rOutput, eFormat, EditSelection( aStartPaM, aEndPaM ) ); + EditPaM aStartPaM(getImpl().GetEditDoc().GetStartPaM()); + EditPaM aEndPaM(getImpl().GetEditDoc().GetEndPaM()); + getImpl().Write(rOutput, eFormat, EditSelection(aStartPaM, aEndPaM)); } std::unique_ptr<EditTextObject> EditEngine::CreateTextObject() { - return pImpEditEngine->CreateTextObject(); + return getImpl().CreateTextObject(); } std::unique_ptr<EditTextObject> EditEngine::CreateTextObject( const ESelection& rESelection ) { - EditSelection aSel( pImpEditEngine->CreateSel( rESelection ) ); - return pImpEditEngine->CreateTextObject( aSel ); + EditSelection aSel(getImpl().CreateSel(rESelection)); + return getImpl().CreateTextObject(aSel); } -std::unique_ptr<EditTextObject> EditEngine::GetEmptyTextObject() const +std::unique_ptr<EditTextObject> EditEngine::GetEmptyTextObject() { - return pImpEditEngine->GetEmptyTextObject(); + return getImpl().GetEmptyTextObject(); } - void EditEngine::SetText( const EditTextObject& rTextObject ) { - pImpEditEngine->SetText( rTextObject ); - pImpEditEngine->FormatAndLayout(); + getImpl().SetText(rTextObject); + getImpl().FormatAndLayout(); } void EditEngine::ShowParagraph( sal_Int32 nParagraph, bool bShow ) { - pImpEditEngine->ShowParagraph( nParagraph, bShow ); + getImpl().ShowParagraph(nParagraph, bShow); } void EditEngine::SetNotifyHdl( const Link<EENotify&,void>& rLink ) { - pImpEditEngine->SetNotifyHdl( rLink ); + getImpl().SetNotifyHdl(rLink); } Link<EENotify&,void> const & EditEngine::GetNotifyHdl() const { - return pImpEditEngine->GetNotifyHdl(); + return getImpl().GetNotifyHdl(); } void EditEngine::SetStatusEventHdl( const Link<EditStatus&, void>& rLink ) { - pImpEditEngine->SetStatusEventHdl( rLink ); + getImpl().SetStatusEventHdl(rLink); } Link<EditStatus&, void> const & EditEngine::GetStatusEventHdl() const { - return pImpEditEngine->GetStatusEventHdl(); + return getImpl().GetStatusEventHdl(); } void EditEngine::SetHtmlImportHdl( const Link<HtmlImportInfo&,void>& rLink ) { - pImpEditEngine->aHtmlImportHdl = rLink; + getImpl().maHtmlImportHdl = rLink; } const Link<HtmlImportInfo&,void>& EditEngine::GetHtmlImportHdl() const { - return pImpEditEngine->aHtmlImportHdl; + return getImpl().maHtmlImportHdl; } void EditEngine::SetRtfImportHdl( const Link<RtfImportInfo&,void>& rLink ) { - pImpEditEngine->aRtfImportHdl = rLink; + getImpl().maRtfImportHdl = rLink; } const Link<RtfImportInfo&,void>& EditEngine::GetRtfImportHdl() const { - return pImpEditEngine->aRtfImportHdl; + return getImpl().maRtfImportHdl; } void EditEngine::SetBeginMovingParagraphsHdl( const Link<MoveParagraphsInfo&,void>& rLink ) { - pImpEditEngine->aBeginMovingParagraphsHdl = rLink; + getImpl().maBeginMovingParagraphsHdl = rLink; } void EditEngine::SetEndMovingParagraphsHdl( const Link<MoveParagraphsInfo&,void>& rLink ) { - pImpEditEngine->aEndMovingParagraphsHdl = rLink; + getImpl().maEndMovingParagraphsHdl = rLink; } void EditEngine::SetBeginPasteOrDropHdl( const Link<PasteOrDropInfos&,void>& rLink ) { - pImpEditEngine->aBeginPasteOrDropHdl = rLink; + getImpl().maBeginPasteOrDropHdl = rLink; } void EditEngine::SetEndPasteOrDropHdl( const Link<PasteOrDropInfos&,void>& rLink ) { - pImpEditEngine->aEndPasteOrDropHdl = rLink; + getImpl().maEndPasteOrDropHdl = rLink; } std::unique_ptr<EditTextObject> EditEngine::CreateTextObject( sal_Int32 nPara, sal_Int32 nParas ) { - DBG_ASSERT( 0 <= nPara && nPara < pImpEditEngine->GetEditDoc().Count(), "CreateTextObject: Startpara out of Range" ); - DBG_ASSERT( nParas <= pImpEditEngine->GetEditDoc().Count() - nPara, "CreateTextObject: Endpara out of Range" ); + DBG_ASSERT(0 <= nPara && nPara < getImpl().GetEditDoc().Count(), "CreateTextObject: Startpara out of Range"); + DBG_ASSERT(nParas <= getImpl().GetEditDoc().Count() - nPara, "CreateTextObject: Endpara out of Range"); - ContentNode* pStartNode = pImpEditEngine->GetEditDoc().GetObject( nPara ); - ContentNode* pEndNode = pImpEditEngine->GetEditDoc().GetObject( nPara+nParas-1 ); + ContentNode* pStartNode = getImpl().GetEditDoc().GetObject(nPara); + ContentNode* pEndNode = getImpl().GetEditDoc().GetObject(nPara + nParas - 1); DBG_ASSERT( pStartNode, "Start-Paragraph does not exist: CreateTextObject" ); DBG_ASSERT( pEndNode, "End-Paragraph does not exist: CreateTextObject" ); @@ -1617,34 +1597,34 @@ std::unique_ptr<EditTextObject> EditEngine::CreateTextObject( sal_Int32 nPara, s EditSelection aTmpSel; aTmpSel.Min() = EditPaM( pStartNode, 0 ); aTmpSel.Max() = EditPaM( pEndNode, pEndNode->Len() ); - return pImpEditEngine->CreateTextObject( aTmpSel ); + return getImpl().CreateTextObject(aTmpSel); } return nullptr; } void EditEngine::RemoveParagraph( sal_Int32 nPara ) { - DBG_ASSERT( pImpEditEngine->GetEditDoc().Count() > 1, "The first paragraph should not be deleted!" ); - if( pImpEditEngine->GetEditDoc().Count() <= 1 ) + DBG_ASSERT(getImpl().GetEditDoc().Count() > 1, "The first paragraph should not be deleted!"); + if (getImpl().GetEditDoc().Count() <= 1) return; - ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( nPara ); - const ParaPortion* pPortion = pImpEditEngine->GetParaPortions().SafeGetObject( nPara ); + ContentNode* pNode = getImpl().GetEditDoc().GetObject(nPara); + const ParaPortion* pPortion = getImpl().GetParaPortions().SafeGetObject(nPara); DBG_ASSERT( pPortion && pNode, "Paragraph not found: RemoveParagraph" ); if ( pNode && pPortion ) { // No Undo encapsulation needed. - pImpEditEngine->ImpRemoveParagraph( nPara ); - pImpEditEngine->InvalidateFromParagraph( nPara ); - pImpEditEngine->UpdateSelections(); - if (pImpEditEngine->IsUpdateLayout()) - pImpEditEngine->FormatAndLayout(); + getImpl().ImpRemoveParagraph(nPara); + getImpl().InvalidateFromParagraph(nPara); + getImpl().UpdateSelections(); + if (getImpl().IsUpdateLayout()) + getImpl().FormatAndLayout(); } } sal_Int32 EditEngine::GetTextLen( sal_Int32 nPara ) const { - ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( nPara ); + ContentNode* pNode = getImpl().GetEditDoc().GetObject(nPara); DBG_ASSERT( pNode, "Paragraph not found: GetTextLen" ); if ( pNode ) return pNode->Len(); @@ -1654,41 +1634,34 @@ sal_Int32 EditEngine::GetTextLen( sal_Int32 nPara ) const OUString EditEngine::GetText( sal_Int32 nPara ) const { OUString aStr; - if ( 0 <= nPara && nPara < pImpEditEngine->GetEditDoc().Count() ) - aStr = pImpEditEngine->GetEditDoc().GetParaAsString( nPara ); + if (0 <= nPara && nPara < getImpl().GetEditDoc().Count()) + aStr = getImpl().GetEditDoc().GetParaAsString(nPara); return aStr; } void EditEngine::SetModifyHdl( const Link<LinkParamNone*,void>& rLink ) { - pImpEditEngine->SetModifyHdl( rLink ); + getImpl().SetModifyHdl(rLink); } -Link<LinkParamNone*,void> const & EditEngine::GetModifyHdl() const -{ - return pImpEditEngine->GetModifyHdl(); -} - - void EditEngine::ClearModifyFlag() { - pImpEditEngine->SetModifyFlag( false ); + getImpl().SetModifyFlag(false); } void EditEngine::SetModified() { - pImpEditEngine->SetModifyFlag( true ); + getImpl().SetModifyFlag(true); } bool EditEngine::IsModified() const { - return pImpEditEngine->IsModified(); + return getImpl().IsModified(); } bool EditEngine::IsInSelectionMode() const { - return ( pImpEditEngine->IsInSelectionMode() || - pImpEditEngine->GetSelEngine().IsInSelection() ); + return getImpl().IsInSelectionMode() || getImpl().GetSelEngine().IsInSelection(); } void EditEngine::InsertParagraph( sal_Int32 nPara, const EditTextObject& rTxtObj, bool bAppend ) @@ -1699,22 +1672,22 @@ void EditEngine::InsertParagraph( sal_Int32 nPara, const EditTextObject& rTxtObj nPara = GetParagraphCount(); } - pImpEditEngine->UndoActionStart( EDITUNDO_INSERT ); + getImpl().UndoActionStart(EDITUNDO_INSERT); // No Undo compounding needed. - EditPaM aPaM( pImpEditEngine->InsertParagraph( nPara ) ); + EditPaM aPaM(getImpl().InsertParagraph(nPara)); // When InsertParagraph from the outside, no hard attributes // should be taken over! - pImpEditEngine->RemoveCharAttribs( nPara ); - pImpEditEngine->InsertText( rTxtObj, EditSelection( aPaM, aPaM ) ); + getImpl().RemoveCharAttribs(nPara); + getImpl().InsertText(rTxtObj, EditSelection(aPaM, aPaM)); if ( bAppend && nPara ) - pImpEditEngine->ConnectContents( nPara-1, /*bBackwards=*/false ); + getImpl().ConnectContents(nPara - 1, /*bBackwards=*/false); - pImpEditEngine->UndoActionEnd(); + getImpl().UndoActionEnd(); - if (pImpEditEngine->IsUpdateLayout()) - pImpEditEngine->FormatAndLayout(); + if (getImpl().IsUpdateLayout()) + getImpl().FormatAndLayout(); } void EditEngine::InsertParagraph(sal_Int32 nPara, const OUString& rTxt) @@ -1725,77 +1698,76 @@ void EditEngine::InsertParagraph(sal_Int32 nPara, const OUString& rTxt) nPara = GetParagraphCount(); } - pImpEditEngine->UndoActionStart( EDITUNDO_INSERT ); - EditPaM aPaM( pImpEditEngine->InsertParagraph( nPara ) ); + getImpl().UndoActionStart(EDITUNDO_INSERT); + EditPaM aPaM(getImpl().InsertParagraph(nPara)); // When InsertParagraph from the outside, no hard attributes // should be taken over! - pImpEditEngine->RemoveCharAttribs( nPara ); - pImpEditEngine->UndoActionEnd(); - pImpEditEngine->ImpInsertText( EditSelection( aPaM, aPaM ), rTxt ); - if (pImpEditEngine->IsUpdateLayout()) - pImpEditEngine->FormatAndLayout(); + getImpl().RemoveCharAttribs(nPara); + getImpl().UndoActionEnd(); + getImpl().ImpInsertText(EditSelection(aPaM, aPaM), rTxt); + if (getImpl().IsUpdateLayout()) + getImpl().FormatAndLayout(); } void EditEngine::SetText(sal_Int32 nPara, const OUString& rTxt) { - std::optional<EditSelection> pSel = pImpEditEngine->SelectParagraph( nPara ); + std::optional<EditSelection> pSel = getImpl().SelectParagraph(nPara); if ( pSel ) { - pImpEditEngine->UndoActionStart( EDITUNDO_INSERT ); - pImpEditEngine->ImpInsertText( *pSel, rTxt ); - pImpEditEngine->UndoActionEnd(); - if (pImpEditEngine->IsUpdateLayout()) - pImpEditEngine->FormatAndLayout(); + getImpl().UndoActionStart(EDITUNDO_INSERT); + getImpl().ImpInsertText(*pSel, rTxt); + getImpl().UndoActionEnd(); + if (getImpl().IsUpdateLayout()) + getImpl().FormatAndLayout(); } } void EditEngine::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet ) { - pImpEditEngine->SetParaAttribs( nPara, rSet ); - if ( pImpEditEngine->IsUpdateLayout() ) - pImpEditEngine->FormatAndLayout(); + getImpl().SetParaAttribs(nPara, rSet); + if (getImpl().IsUpdateLayout()) + getImpl().FormatAndLayout(); } const SfxItemSet& EditEngine::GetParaAttribs( sal_Int32 nPara ) const { - return pImpEditEngine->GetParaAttribs( nPara ); + return getImpl().GetParaAttribs(nPara); } bool EditEngine::HasParaAttrib( sal_Int32 nPara, sal_uInt16 nWhich ) const { - return pImpEditEngine->HasParaAttrib( nPara, nWhich ); + return getImpl().HasParaAttrib(nPara, nWhich); } const SfxPoolItem& EditEngine::GetParaAttrib( sal_Int32 nPara, sal_uInt16 nWhich ) const { - return pImpEditEngine->GetParaAttrib( nPara, nWhich ); + return getImpl().GetParaAttrib(nPara, nWhich); } void EditEngine::SetCharAttribs(sal_Int32 nPara, const SfxItemSet& rSet) { - EditSelection aSel(pImpEditEngine->ConvertSelection(nPara, 0, nPara, GetTextLen(nPara))); + EditSelection aSel(getImpl().ConvertSelection(nPara, 0, nPara, GetTextLen(nPara))); // This is called by sd::View::OnBeginPasteOrDrop(), updating the cursor position on undo is not // wanted. - pImpEditEngine->SetAttribs(aSel, rSet, /*nSpecial=*/SetAttribsMode::NONE, /*bSetSelection=*/false); - if (pImpEditEngine->IsUpdateLayout()) - pImpEditEngine->FormatAndLayout(); + getImpl().SetAttribs(aSel, rSet, /*nSpecial=*/SetAttribsMode::NONE, /*bSetSelection=*/false); + if (getImpl().IsUpdateLayout()) + getImpl().FormatAndLayout(); } -void EditEngine::GetCharAttribs( sal_Int32 nPara, std::vector<EECharAttrib>& rLst ) const +void EditEngine::GetCharAttribs( sal_Int32 nPara, std::vector<EECharAttrib>& rList ) const { - pImpEditEngine->GetCharAttribs( nPara, rLst ); + getImpl().GetCharAttribs(nPara, rList); } SfxItemSet EditEngine::GetAttribs( const ESelection& rSel, EditEngineAttribs nOnlyHardAttrib ) { - EditSelection aSel( pImpEditEngine-> - ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) ); - return pImpEditEngine->GetAttribs( aSel, nOnlyHardAttrib ); + EditSelection aSel(getImpl().ConvertSelection(rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos)); + return getImpl().GetAttribs(aSel, nOnlyHardAttrib); } SfxItemSet EditEngine::GetAttribs( sal_Int32 nPara, sal_Int32 nStart, sal_Int32 nEnd, GetAttribsFlags nFlags ) const { - return pImpEditEngine->GetAttribs( nPara, nStart, nEnd, nFlags ); + return getImpl().GetAttribs(nPara, nStart, nEnd, nFlags); } void EditEngine::RemoveAttribs( const ESelection& rSelection, bool bRemoveParaAttribs, sal_uInt16 nWhich ) @@ -1804,12 +1776,12 @@ void EditEngine::RemoveAttribs( const ESelection& rSelection, bool bRemoveParaAt EERemoveParaAttribsMode::RemoveAll : EERemoveParaAttribsMode::RemoveCharItems; - pImpEditEngine->UndoActionStart( EDITUNDO_RESETATTRIBS ); - EditSelection aSel( pImpEditEngine->ConvertSelection( rSelection.nStartPara, rSelection.nStartPos, rSelection.nEndPara, rSelection.nEndPos ) ); - pImpEditEngine->RemoveCharAttribs( aSel, eMode, nWhich ); - pImpEditEngine->UndoActionEnd(); - if (pImpEditEngine->IsUpdateLayout()) - pImpEditEngine->FormatAndLayout(); + getImpl().UndoActionStart(EDITUNDO_RESETATTRIBS); + EditSelection aSel(getImpl().ConvertSelection(rSelection.nStartPara, rSelection.nStartPos, rSelection.nEndPara, rSelection.nEndPos)); + getImpl().RemoveCharAttribs(aSel, eMode, nWhich); + getImpl().UndoActionEnd(); + if (getImpl().IsUpdateLayout()) + getImpl().FormatAndLayout(); } vcl::Font EditEngine::GetStandardFont( sal_Int32 nPara ) @@ -1819,7 +1791,7 @@ vcl::Font EditEngine::GetStandardFont( sal_Int32 nPara ) SvxFont EditEngine::GetStandardSvxFont( sal_Int32 nPara ) { - ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( nPara ); + ContentNode* pNode = getImpl().GetEditDoc().GetObject( nPara ); return pNode->GetCharAttribs().GetDefFont(); } @@ -1840,15 +1812,15 @@ void EditEngine::StripPortions() aBigRect.SetBottom( 0 ); } } - pImpEditEngine->Paint(*aTmpDev, aBigRect, Point(), true); + getImpl().Paint(*aTmpDev, aBigRect, Point(), true); } void EditEngine::GetPortions( sal_Int32 nPara, std::vector<sal_Int32>& rList ) { - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatFullDoc(); + if (!getImpl().IsFormatted()) + getImpl().FormatFullDoc(); - const ParaPortion* pParaPortion = pImpEditEngine->GetParaPortions().SafeGetObject( nPara ); + const ParaPortion* pParaPortion = getImpl().GetParaPortions().SafeGetObject(nPara); if ( pParaPortion ) { sal_Int32 nEnd = 0; @@ -1863,25 +1835,36 @@ void EditEngine::GetPortions( sal_Int32 nPara, std::vector<sal_Int32>& rList ) void EditEngine::SetFlatMode( bool bFlat) { - pImpEditEngine->SetFlatMode( bFlat ); + getImpl().SetFlatMode(bFlat); } bool EditEngine::IsFlatMode() const { - return !( pImpEditEngine->aStatus.UseCharAttribs() ); + return !getImpl().GetStatus().UseCharAttribs(); +} + +void EditEngine::SetSingleLine(bool bValue) +{ + if (bValue == getImpl().GetStatus().IsSingleLine()) + return; + + if (bValue) + getImpl().GetStatus().TurnOnFlags(EEControlBits::SINGLELINE); + else + getImpl().GetStatus().TurnOffFlags(EEControlBits::SINGLELINE); } void EditEngine::SetControlWord( EEControlBits nWord ) { - if ( nWord == pImpEditEngine->aStatus.GetControlWord() ) + if (nWord == getImpl().GetStatus().GetControlWord()) return; - EEControlBits nPrev = pImpEditEngine->aStatus.GetControlWord(); - pImpEditEngine->aStatus.GetControlWord() = nWord; + EEControlBits nPrev = getImpl().GetStatus().GetControlWord(); + getImpl().GetStatus().GetControlWord() = nWord; EEControlBits nChanges = nPrev ^ nWord; - if ( pImpEditEngine->IsFormatted() ) + if (getImpl().IsFormatted()) { // possibly reformat: if ( ( nChanges & EEControlBits::USECHARATTRIBS ) || @@ -1893,11 +1876,11 @@ void EditEngine::SetControlWord( EEControlBits nWord ) { if ( nChanges & EEControlBits::USECHARATTRIBS ) { - pImpEditEngine->GetEditDoc().CreateDefFont( true ); + getImpl().GetEditDoc().CreateDefFont(true); } - pImpEditEngine->FormatFullDoc(); - pImpEditEngine->UpdateViews( pImpEditEngine->GetActiveView() ); + getImpl().FormatFullDoc(); + getImpl().UpdateViews(getImpl().GetActiveView()); } } @@ -1906,38 +1889,38 @@ void EditEngine::SetControlWord( EEControlBits nWord ) if ( !bSpellingChanged ) return; - pImpEditEngine->StopOnlineSpellTimer(); + getImpl().StopOnlineSpellTimer(); if (nWord & EEControlBits::ONLINESPELLING) { // Create WrongList, start timer... - sal_Int32 nNodes = pImpEditEngine->GetEditDoc().Count(); - for ( sal_Int32 n = 0; n < nNodes; n++ ) + sal_Int32 nNodes = getImpl().GetEditDoc().Count(); + for (sal_Int32 nNode = 0; nNode < nNodes; nNode++) { - ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( n ); + ContentNode* pNode = getImpl().GetEditDoc().GetObject(nNode); pNode->CreateWrongList(); } - if (pImpEditEngine->IsFormatted()) - pImpEditEngine->StartOnlineSpellTimer(); + if (getImpl().IsFormatted()) + getImpl().StartOnlineSpellTimer(); } else { tools::Long nY = 0; - sal_Int32 nNodes = pImpEditEngine->GetEditDoc().Count(); - for ( sal_Int32 n = 0; n < nNodes; n++ ) + sal_Int32 nNodes = getImpl().GetEditDoc().Count(); + for ( sal_Int32 nNode = 0; nNode < nNodes; nNode++) { - ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( n ); - const ParaPortion& rPortion = pImpEditEngine->GetParaPortions()[n]; + ContentNode* pNode = getImpl().GetEditDoc().GetObject(nNode); + ParaPortion const& rPortion = getImpl().GetParaPortions().getRef(nNode); bool bWrongs = false; if (pNode->GetWrongList() != nullptr) bWrongs = !pNode->GetWrongList()->empty(); pNode->DestroyWrongList(); if ( bWrongs ) { - pImpEditEngine->aInvalidRect.SetLeft( 0 ); - pImpEditEngine->aInvalidRect.SetRight( pImpEditEngine->GetPaperSize().Width() ); - pImpEditEngine->aInvalidRect.SetTop( nY+1 ); - pImpEditEngine->aInvalidRect.SetBottom( nY + rPortion.GetHeight()-1 ); - pImpEditEngine->UpdateViews( pImpEditEngine->pActiveView ); + getImpl().maInvalidRect.SetLeft(0); + getImpl().maInvalidRect.SetRight(getImpl().GetPaperSize().Width()); + getImpl().maInvalidRect.SetTop(nY + 1); + getImpl().maInvalidRect.SetBottom(nY + rPortion.GetHeight() - 1); + getImpl().UpdateViews(getImpl().mpActiveView); } nY += rPortion.GetHeight(); } @@ -1946,19 +1929,18 @@ void EditEngine::SetControlWord( EEControlBits nWord ) EEControlBits EditEngine::GetControlWord() const { - return pImpEditEngine->aStatus.GetControlWord(); + return getImpl().GetStatus().GetControlWord(); } tools::Long EditEngine::GetFirstLineStartX( sal_Int32 nParagraph ) { tools::Long nX = 0; - const ParaPortion* pPPortion = pImpEditEngine->GetParaPortions().SafeGetObject( nParagraph ); + const ParaPortion* pPPortion = getImpl().GetParaPortions().SafeGetObject(nParagraph); if ( pPPortion ) { - DBG_ASSERT( pImpEditEngine->IsFormatted() || !pImpEditEngine->IsFormatting(), "GetFirstLineStartX: Doc not formatted - unable to format!" ); - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); + DBG_ASSERT(getImpl().IsFormatted() || !getImpl().IsFormatting(), "GetFirstLineStartX: Doc not formatted - unable to format!"); + ensureDocumentFormatted(); const EditLine& rFirstLine = pPPortion->GetLines()[0]; nX = rFirstLine.GetStartPosX(); } @@ -1986,17 +1968,16 @@ Point EditEngine::GetDocPos( const Point& rPaperPos ) const Point EditEngine::GetDocPosTopLeft( sal_Int32 nParagraph ) { - const ParaPortion* pPPortion = pImpEditEngine->GetParaPortions().SafeGetObject( nParagraph ); + const ParaPortion* pPPortion = getImpl().GetParaPortions().SafeGetObject(nParagraph); DBG_ASSERT( pPPortion, "Paragraph not found: GetWindowPosTopLeft" ); Point aPoint; if ( pPPortion ) { - // If someone calls GetLineHeight() with an empty Engine. - DBG_ASSERT( pImpEditEngine->IsFormatted() || !pImpEditEngine->IsFormatting(), "GetDocPosTopLeft: Doc not formatted - unable to format!" ); - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatAndLayout(); - if ( pPPortion->GetLines().Count() ) + DBG_ASSERT(getImpl().IsFormatted() || !getImpl().IsFormatting(), "GetDocPosTopLeft: Doc not formatted - unable to format!"); + if (!getImpl().IsFormatted()) + getImpl().FormatAndLayout(); + if (pPPortion->GetLines().Count()) { // Correct it if large Bullet. const EditLine& rFirstLine = pPPortion->GetLines()[0]; @@ -2004,17 +1985,16 @@ Point EditEngine::GetDocPosTopLeft( sal_Int32 nParagraph ) } else { - const SvxLRSpaceItem& rLRItem = pImpEditEngine->GetLRSpaceItem( pPPortion->GetNode() ); -// TL_NF_LR aPoint.X() = pImpEditEngine->GetXValue( (short)(rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset()) ); + const SvxLRSpaceItem& rLRItem = getImpl().GetLRSpaceItem(pPPortion->GetNode()); sal_Int32 nSpaceBefore = 0; - pImpEditEngine->GetSpaceBeforeAndMinLabelWidth( pPPortion->GetNode(), &nSpaceBefore ); + getImpl().GetSpaceBeforeAndMinLabelWidth(pPPortion->GetNode(), &nSpaceBefore); short nX = static_cast<short>(rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset() + nSpaceBefore); - aPoint.setX( pImpEditEngine->GetXValue( nX - ) ); + + aPoint.setX(getImpl().scaleXSpacingValue(nX)); } - aPoint.setY( pImpEditEngine->GetParaPortions().GetYOffset( pPPortion ) ); + aPoint.setY(getImpl().GetParaPortions().GetYOffset(pPPortion)); } return aPoint; } @@ -2028,49 +2008,44 @@ const SvxNumberFormat* EditEngine::GetNumberFormat( sal_Int32 ) const bool EditEngine::IsRightToLeft( sal_Int32 nPara ) const { - return pImpEditEngine->IsRightToLeft( nPara ); + return getImpl().IsRightToLeft(nPara); } bool EditEngine::IsTextPos( const Point& rPaperPos, sal_uInt16 nBorder ) { - - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); + ensureDocumentFormatted(); // take unrotated positions for calculation here Point aDocPos = GetDocPos( rPaperPos ); - if ( ( aDocPos.Y() > 0 ) && ( aDocPos.Y() < static_cast<tools::Long>(pImpEditEngine->GetTextHeight()) ) ) - return pImpEditEngine->IsTextPos(aDocPos, nBorder); + if ((aDocPos.Y() > 0) && (o3tl::make_unsigned(aDocPos.Y()) < getImpl().GetTextHeight())) + return getImpl().IsTextPos(aDocPos, nBorder); return false; } void EditEngine::SetEditTextObjectPool( SfxItemPool* pPool ) { - pImpEditEngine->SetEditTextObjectPool( pPool ); + getImpl().SetEditTextObjectPool(pPool); } SfxItemPool* EditEngine::GetEditTextObjectPool() const { - return pImpEditEngine->GetEditTextObjectPool(); + return getImpl().GetEditTextObjectPool(); } void EditEngine::QuickSetAttribs( const SfxItemSet& rSet, const ESelection& rSel ) { - - EditSelection aSel( pImpEditEngine-> - ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) ); - - pImpEditEngine->SetAttribs( aSel, rSet ); + EditSelection aSel(getImpl().ConvertSelection(rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos)); + getImpl().SetAttribs(aSel, rSet); } void EditEngine::QuickMarkInvalid( const ESelection& rSel ) { - DBG_ASSERT( rSel.nStartPara < pImpEditEngine->GetEditDoc().Count(), "MarkInvalid: Start out of Range!" ); - DBG_ASSERT( rSel.nEndPara < pImpEditEngine->GetEditDoc().Count(), "MarkInvalid: End out of Range!" ); - for ( sal_Int32 nPara = rSel.nStartPara; nPara <= rSel.nEndPara; nPara++ ) + DBG_ASSERT(rSel.nStartPara < getImpl().GetEditDoc().Count(), "MarkInvalid: Start out of Range!"); + DBG_ASSERT(rSel.nEndPara < getImpl().GetEditDoc().Count(), "MarkInvalid: End out of Range!"); + for (sal_Int32 nPara = rSel.nStartPara; nPara <= rSel.nEndPara; nPara++) { - ParaPortion* pPortion = pImpEditEngine->GetParaPortions().SafeGetObject( nPara ); + ParaPortion* pPortion = getImpl().GetParaPortions().SafeGetObject(nPara); if ( pPortion ) pPortion->MarkSelectionInvalid( 0 ); } @@ -2078,128 +2053,117 @@ void EditEngine::QuickMarkInvalid( const ESelection& rSel ) void EditEngine::QuickInsertText(const OUString& rText, const ESelection& rSel) { - - EditSelection aSel( pImpEditEngine-> - ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) ); - - pImpEditEngine->ImpInsertText( aSel, rText ); + EditSelection aSel(getImpl().ConvertSelection(rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos)); + getImpl().ImpInsertText(aSel, rText); } void EditEngine::QuickDelete( const ESelection& rSel ) { - - EditSelection aSel( pImpEditEngine-> - ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) ); - - pImpEditEngine->ImpDeleteSelection( aSel ); + EditSelection aSel(getImpl().ConvertSelection(rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos)); + getImpl().ImpDeleteSelection( aSel ); } void EditEngine::QuickMarkToBeRepainted( sal_Int32 nPara ) { - ParaPortion* pPortion = pImpEditEngine->GetParaPortions().SafeGetObject( nPara ); + ParaPortion* pPortion = getImpl().GetParaPortions().SafeGetObject(nPara); if ( pPortion ) pPortion->SetMustRepaint( true ); } void EditEngine::QuickInsertLineBreak( const ESelection& rSel ) { - - EditSelection aSel( pImpEditEngine-> - ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) ); - - pImpEditEngine->InsertLineBreak( aSel ); + EditSelection aSel(getImpl().ConvertSelection(rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos)); + getImpl().InsertLineBreak( aSel ); } void EditEngine::QuickInsertField( const SvxFieldItem& rFld, const ESelection& rSel ) { - EditSelection aSel( pImpEditEngine-> - ConvertSelection( rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos ) ); - - pImpEditEngine->ImpInsertFeature( aSel, rFld ); + EditSelection aSel(getImpl().ConvertSelection(rSel.nStartPara, rSel.nStartPos, rSel.nEndPara, rSel.nEndPos)); + getImpl().ImpInsertFeature(aSel, rFld); } void EditEngine::QuickFormatDoc( bool bFull ) { - if ( bFull ) - pImpEditEngine->FormatFullDoc(); + if (bFull) + getImpl().FormatFullDoc(); else - pImpEditEngine->FormatDoc(); + getImpl().FormatDoc(); // Don't pass active view, maybe selection is not updated yet... - pImpEditEngine->UpdateViews(); + getImpl().UpdateViews(); } void EditEngine::SetStyleSheet(const EditSelection& aSel, SfxStyleSheet* pStyle) { - pImpEditEngine->SetStyleSheet(aSel, pStyle); + getImpl().SetStyleSheet(aSel, pStyle); } void EditEngine::SetStyleSheet( sal_Int32 nPara, SfxStyleSheet* pStyle ) { - pImpEditEngine->SetStyleSheet( nPara, pStyle ); + getImpl().SetStyleSheet(nPara, pStyle); } const SfxStyleSheet* EditEngine::GetStyleSheet( sal_Int32 nPara ) const { - return pImpEditEngine->GetStyleSheet( nPara ); + return getImpl().GetStyleSheet(nPara); } SfxStyleSheet* EditEngine::GetStyleSheet( sal_Int32 nPara ) { - return pImpEditEngine->GetStyleSheet( nPara ); + return getImpl().GetStyleSheet(nPara); } void EditEngine::SetStyleSheetPool( SfxStyleSheetPool* pSPool ) { - pImpEditEngine->SetStyleSheetPool( pSPool ); + getImpl().SetStyleSheetPool(pSPool); } SfxStyleSheetPool* EditEngine::GetStyleSheetPool() { - return pImpEditEngine->GetStyleSheetPool(); + return getImpl().GetStyleSheetPool(); } void EditEngine::SetWordDelimiters( const OUString& rDelimiters ) { - pImpEditEngine->aWordDelimiters = rDelimiters; - if (pImpEditEngine->aWordDelimiters.indexOf(CH_FEATURE) == -1) - pImpEditEngine->aWordDelimiters += OUStringChar(CH_FEATURE); + getImpl().maWordDelimiters = rDelimiters; + if (getImpl().maWordDelimiters.indexOf(CH_FEATURE) == -1) + getImpl().maWordDelimiters += OUStringChar(CH_FEATURE); } const OUString& EditEngine::GetWordDelimiters() const { - return pImpEditEngine->aWordDelimiters; + return getImpl().maWordDelimiters; } void EditEngine::EraseVirtualDevice() { - pImpEditEngine->EraseVirtualDevice(); + getImpl().EraseVirtualDevice(); } void EditEngine::SetSpeller( Reference< XSpellChecker1 > const &xSpeller ) { - pImpEditEngine->SetSpeller( xSpeller ); + getImpl().SetSpeller(xSpeller); } Reference< XSpellChecker1 > const & EditEngine::GetSpeller() { - return pImpEditEngine->GetSpeller(); + return getImpl().GetSpeller(); } void EditEngine::SetHyphenator( Reference< XHyphenator > const & xHyph ) { - pImpEditEngine->SetHyphenator( xHyph ); + getImpl().SetHyphenator(xHyph); } void EditEngine::GetAllMisspellRanges( std::vector<editeng::MisspellRanges>& rRanges ) const { - pImpEditEngine->GetAllMisspellRanges(rRanges); + getImpl().GetAllMisspellRanges(rRanges); } void EditEngine::SetAllMisspellRanges( const std::vector<editeng::MisspellRanges>& rRanges ) { - pImpEditEngine->SetAllMisspellRanges(rRanges); + getImpl().SetAllMisspellRanges(rRanges); } void EditEngine::SetForbiddenCharsTable(const std::shared_ptr<SvxForbiddenCharactersTable>& xForbiddenChars) @@ -2209,12 +2173,12 @@ void EditEngine::SetForbiddenCharsTable(const std::shared_ptr<SvxForbiddenCharac void EditEngine::SetDefaultLanguage( LanguageType eLang ) { - pImpEditEngine->SetDefaultLanguage( eLang ); + getImpl().SetDefaultLanguage(eLang); } LanguageType EditEngine::GetDefaultLanguage() const { - return pImpEditEngine->GetDefaultLanguage(); + return getImpl().GetDefaultLanguage(); } bool EditEngine::SpellNextDocument() @@ -2224,35 +2188,35 @@ bool EditEngine::SpellNextDocument() EESpellState EditEngine::HasSpellErrors() { - if ( !pImpEditEngine->GetSpeller().is() ) + if (!getImpl().GetSpeller().is()) return EESpellState::NoSpeller; - return pImpEditEngine->HasSpellErrors(); + return getImpl().HasSpellErrors(); } void EditEngine::ClearSpellErrors() { - pImpEditEngine->ClearSpellErrors(); + getImpl().ClearSpellErrors(); } bool EditEngine::SpellSentence(EditView const & rView, svx::SpellPortions& rToFill ) { - return pImpEditEngine->SpellSentence( rView, rToFill ); + return getImpl().SpellSentence(rView, rToFill); } void EditEngine::PutSpellingToSentenceStart( EditView const & rEditView ) { - pImpEditEngine->PutSpellingToSentenceStart( rEditView ); + getImpl().PutSpellingToSentenceStart(rEditView); } void EditEngine::ApplyChangedSentence(EditView const & rEditView, const svx::SpellPortions& rNewPortions, bool bRecheck ) { - pImpEditEngine->ApplyChangedSentence( rEditView, rNewPortions, bRecheck ); + getImpl().ApplyChangedSentence(rEditView, rNewPortions, bRecheck); } bool EditEngine::HasConvertibleTextPortion( LanguageType nLang ) { - return pImpEditEngine->HasConvertibleTextPortion( nLang ); + return getImpl().HasConvertibleTextPortion(nLang); } bool EditEngine::ConvertNextDocument() @@ -2262,35 +2226,40 @@ bool EditEngine::ConvertNextDocument() bool EditEngine::HasText( const SvxSearchItem& rSearchItem ) { - return pImpEditEngine->HasText( rSearchItem ); + return getImpl().HasText(rSearchItem); +} + +ScalingParameters EditEngine::getScalingParameters() const +{ + return getImpl().getScalingParameters(); } -void EditEngine::SetGlobalCharStretching( sal_uInt16 nX, sal_uInt16 nY ) +void EditEngine::setScalingParameters(ScalingParameters const& rScalingParameters) { - pImpEditEngine->SetCharStretching( nX, nY ); + getImpl().setScalingParameters(rScalingParameters); } -void EditEngine::GetGlobalCharStretching( sal_uInt16& rX, sal_uInt16& rY ) const +void EditEngine::setRoundFontSizeToPt(bool bRound) { - pImpEditEngine->GetCharStretching( rX, rY ); + getImpl().setRoundToNearestPt(bRound); } bool EditEngine::ShouldCreateBigTextObject() const { sal_Int32 nTextPortions = 0; - sal_Int32 nParas = pImpEditEngine->GetEditDoc().Count(); - for ( sal_Int32 nPara = 0; nPara < nParas; nPara++ ) + sal_Int32 nParas = getImpl().GetEditDoc().Count(); + for (sal_Int32 nPara = 0; nPara < nParas; nPara++) { - ParaPortion& rParaPortion = pImpEditEngine->GetParaPortions()[nPara]; + ParaPortion& rParaPortion = getImpl().GetParaPortions().getRef(nPara); nTextPortions = nTextPortions + rParaPortion.GetTextPortions().Count(); } - return nTextPortions >= pImpEditEngine->GetBigTextObjectStart(); + return nTextPortions >= getImpl().GetBigTextObjectStart(); } sal_uInt16 EditEngine::GetFieldCount( sal_Int32 nPara ) const { sal_uInt16 nFields = 0; - ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( nPara ); + ContentNode* pNode = getImpl().GetEditDoc().GetObject(nPara); if ( pNode ) { for (auto const& attrib : pNode->GetCharAttribs().GetAttribs()) @@ -2305,7 +2274,7 @@ sal_uInt16 EditEngine::GetFieldCount( sal_Int32 nPara ) const EFieldInfo EditEngine::GetFieldInfo( sal_Int32 nPara, sal_uInt16 nField ) const { - ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( nPara ); + ContentNode* pNode = getImpl().GetEditDoc().GetObject(nPara); if ( pNode ) { sal_uInt16 nCurrentField = 0; @@ -2332,25 +2301,25 @@ EFieldInfo EditEngine::GetFieldInfo( sal_Int32 nPara, sal_uInt16 nField ) const bool EditEngine::UpdateFields() { - bool bChanges = pImpEditEngine->UpdateFields(); - if ( bChanges && pImpEditEngine->IsUpdateLayout()) - pImpEditEngine->FormatAndLayout(); + bool bChanges = getImpl().UpdateFields(); + if (bChanges && getImpl().IsUpdateLayout()) + getImpl().FormatAndLayout(); return bChanges; } bool EditEngine::UpdateFieldsOnly() { - return pImpEditEngine->UpdateFields(); + return getImpl().UpdateFields(); } void EditEngine::RemoveFields( const std::function<bool ( const SvxFieldData* )>& isFieldData ) { - pImpEditEngine->UpdateFields(); + getImpl().UpdateFields(); - sal_Int32 nParas = pImpEditEngine->GetEditDoc().Count(); + sal_Int32 nParas = getImpl().GetEditDoc().Count(); for ( sal_Int32 nPara = 0; nPara < nParas; nPara++ ) { - ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( nPara ); + ContentNode* pNode = getImpl().GetEditDoc().GetObject(nPara); const CharAttribList::AttribsType& rAttrs = pNode->GetCharAttribs().GetAttribs(); for (size_t nAttr = rAttrs.size(); nAttr; ) { @@ -2363,7 +2332,7 @@ void EditEngine::RemoveFields( const std::function<bool ( const SvxFieldData* )> DBG_ASSERT( dynamic_cast<const SvxFieldItem*>(rAttr.GetItem()), "no field item..." ); EditSelection aSel( EditPaM(pNode, rAttr.GetStart()), EditPaM(pNode, rAttr.GetEnd()) ); OUString aFieldText = static_cast<const EditCharAttribField&>(rAttr).GetFieldValue(); - pImpEditEngine->ImpInsertText( aSel, aFieldText ); + getImpl().ImpInsertText(aSel, aFieldText); } } } @@ -2372,10 +2341,10 @@ void EditEngine::RemoveFields( const std::function<bool ( const SvxFieldData* )> bool EditEngine::HasOnlineSpellErrors() const { - sal_Int32 nNodes = pImpEditEngine->GetEditDoc().Count(); + sal_Int32 nNodes = getImpl().GetEditDoc().Count(); for ( sal_Int32 n = 0; n < nNodes; n++ ) { - ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( n ); + ContentNode* pNode = getImpl().GetEditDoc().GetObject(n); if ( pNode->GetWrongList() && !pNode->GetWrongList()->empty() ) return true; } @@ -2384,29 +2353,29 @@ bool EditEngine::HasOnlineSpellErrors() const void EditEngine::CompleteOnlineSpelling() { - if ( pImpEditEngine->GetStatus().DoOnlineSpelling() ) + if (getImpl().GetStatus().DoOnlineSpelling()) { - if( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatAndLayout(); + if (!getImpl().IsFormatted()) + getImpl().FormatAndLayout(); - pImpEditEngine->StopOnlineSpellTimer(); - pImpEditEngine->DoOnlineSpelling( nullptr, true, false ); + getImpl().StopOnlineSpellTimer(); + getImpl().DoOnlineSpelling(nullptr, true, false); } } sal_Int32 EditEngine::FindParagraph( tools::Long nDocPosY ) { - return pImpEditEngine->GetParaPortions().FindParagraph( nDocPosY ); + return getImpl().GetParaPortions().FindParagraph(nDocPosY); } EPosition EditEngine::FindDocPosition( const Point& rDocPos ) const { EPosition aPos; // From the point of the API, this is const... - EditPaM aPaM = const_cast<EditEngine*>(this)->pImpEditEngine->GetPaM( rDocPos, false ); + EditPaM aPaM = getImpl().GetPaM(rDocPos, false); if ( aPaM.GetNode() ) { - aPos.nPara = pImpEditEngine->aEditDoc.GetPos( aPaM.GetNode() ); + aPos.nPara = getImpl().maEditDoc.GetPos(aPaM.GetNode()); aPos.nIndex = aPaM.GetIndex(); } return aPos; @@ -2415,13 +2384,14 @@ EPosition EditEngine::FindDocPosition( const Point& rDocPos ) const tools::Rectangle EditEngine::GetCharacterBounds( const EPosition& rPos ) const { tools::Rectangle aBounds; - ContentNode* pNode = pImpEditEngine->GetEditDoc().GetObject( rPos.nPara ); + ContentNode* pNode = getImpl().GetEditDoc().GetObject(rPos.nPara); // Check against index, not paragraph if ( pNode && ( rPos.nIndex < pNode->Len() ) ) { - aBounds = pImpEditEngine->PaMtoEditCursor( EditPaM( pNode, rPos.nIndex ), GetCursorFlags::TextOnly ); - tools::Rectangle aR2 = pImpEditEngine->PaMtoEditCursor( EditPaM( pNode, rPos.nIndex+1 ), GetCursorFlags::TextOnly|GetCursorFlags::EndOfLine ); + aBounds = getImpl().PaMtoEditCursor(EditPaM(pNode, rPos.nIndex), CursorFlags{.bTextOnly = true}); + CursorFlags aFlags { .bTextOnly = true, .bEndOfLine = true}; + tools::Rectangle aR2 = getImpl().PaMtoEditCursor(EditPaM(pNode, rPos.nIndex + 1), aFlags); if ( aR2.Right() > aBounds.Right() ) aBounds.SetRight( aR2.Right() ); } @@ -2430,20 +2400,17 @@ tools::Rectangle EditEngine::GetCharacterBounds( const EPosition& rPos ) const ParagraphInfos EditEngine::GetParagraphInfos( sal_Int32 nPara ) { - // This only works if not already in the format ... - if ( !pImpEditEngine->IsFormatted() ) - pImpEditEngine->FormatDoc(); + ensureDocumentFormatted(); ParagraphInfos aInfos; - aInfos.bValid = pImpEditEngine->IsFormatted(); - if ( pImpEditEngine->IsFormatted() ) + aInfos.bValid = getImpl().IsFormatted(); + if (getImpl().IsFormatted() && getImpl().GetParaPortions().exists(nPara)) { - const ParaPortion& rParaPortion = pImpEditEngine->GetParaPortions()[nPara]; - const EditLine* pLine = rParaPortion.GetLines().Count() ? - &rParaPortion.GetLines()[0] : nullptr; - DBG_ASSERT( pLine, "GetParagraphInfos - Paragraph out of range" ); - if ( pLine ) + ParaPortion const& rParaPortion = getImpl().GetParaPortions().getRef(nPara); + const EditLine* pLine = (rParaPortion.GetLines().Count()) ? &rParaPortion.GetLines()[0] : nullptr; + DBG_ASSERT(pLine, "GetParagraphInfos - Paragraph out of range"); + if (pLine) { aInfos.nFirstLineHeight = pLine->GetHeight(); aInfos.nFirstLineTextHeight = pLine->GetTxtHeight(); @@ -2453,18 +2420,19 @@ ParagraphInfos EditEngine::GetParagraphInfos( sal_Int32 nPara ) return aInfos; } -css::uno::Reference< css::datatransfer::XTransferable > - EditEngine::CreateTransferable( const ESelection& rSelection ) const +uno::Reference<datatransfer::XTransferable> +EditEngine::CreateTransferable(const ESelection& rSelection) { - EditSelection aSel( pImpEditEngine->CreateSel( rSelection ) ); - return pImpEditEngine->CreateTransferable( aSel ); + EditSelection aSel(getImpl().CreateSel(rSelection)); + return getImpl().CreateTransferable(aSel); } // ====================== Virtual Methods ======================== void EditEngine::DrawingText( const Point&, const OUString&, sal_Int32, sal_Int32, - o3tl::span<const sal_Int32>, const SvxFont&, sal_Int32 /*nPara*/, sal_uInt8 /*nRightToLeft*/, + std::span<const sal_Int32>, std::span<const sal_Bool>, + const SvxFont&, sal_Int32 /*nPara*/, sal_uInt8 /*nRightToLeft*/, const EEngineData::WrongSpellVector*, const SvxFieldData*, bool, bool, const css::lang::Locale*, const Color&, const Color&) @@ -2485,25 +2453,24 @@ void EditEngine::PaintingFirstLine(sal_Int32, const Point&, const Point&, Degree void EditEngine::ParagraphInserted( sal_Int32 nPara ) { - if ( GetNotifyHdl().IsSet() ) { EENotify aNotify( EE_NOTIFY_PARAGRAPHINSERTED ); aNotify.nParagraph = nPara; - pImpEditEngine->GetNotifyHdl().Call( aNotify ); + getImpl().GetNotifyHdl().Call(aNotify); } } void EditEngine::ParagraphDeleted( sal_Int32 nPara ) { - if ( GetNotifyHdl().IsSet() ) { EENotify aNotify( EE_NOTIFY_PARAGRAPHREMOVED ); aNotify.nParagraph = nPara; - pImpEditEngine->GetNotifyHdl().Call( aNotify ); + getImpl().GetNotifyHdl().Call(aNotify); } } + void EditEngine::ParagraphConnected( sal_Int32 /*nLeftParagraph*/, sal_Int32 /*nRightParagraph*/ ) { } @@ -2522,11 +2489,11 @@ void EditEngine::ParagraphHeightChanged( sal_Int32 nPara ) { EENotify aNotify( EE_NOTIFY_TextHeightChanged ); aNotify.nParagraph = nPara; - pImpEditEngine->GetNotifyHdl().Call( aNotify ); + getImpl().GetNotifyHdl().Call(aNotify); } - for (EditView* pView : pImpEditEngine->aEditViews) - pView->pImpEditView->ScrollStateChange(); + for (EditView* pView : getImpl().maEditViews) + pView->getImpl().ScrollStateChange(); } OUString EditEngine::GetUndoComment( sal_uInt16 nId ) const @@ -2583,13 +2550,14 @@ tools::Rectangle EditEngine::GetBulletArea( sal_Int32 ) return tools::Rectangle( Point(), Point() ); } -OUString EditEngine::CalcFieldValue( const SvxFieldItem&, sal_Int32, sal_Int32, std::optional<Color>&, std::optional<Color>& ) +OUString EditEngine::CalcFieldValue( const SvxFieldItem&, sal_Int32, sal_Int32, std::optional<Color>&, std::optional<Color>&, std::optional<FontLineStyle>& ) { return OUString(' '); } -void EditEngine::FieldClicked( const SvxFieldItem& ) +bool EditEngine::FieldClicked( const SvxFieldItem& ) { + return false; } @@ -2622,9 +2590,14 @@ SfxItemPool& EditEngine::GetGlobalItemPool() if ( !pGlobalPool ) { pGlobalPool = CreatePool(); +#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) + // TerminateListener option not available, force it to leak + pGlobalPool->acquire(); +#else uno::Reference< frame::XDesktop2 > xDesktop = frame::Desktop::create(comphelper::getProcessComponentContext()); uno::Reference< frame::XTerminateListener > xListener( new TerminateListener ); xDesktop->addTerminateListener( xListener ); +#endif } return *pGlobalPool; } @@ -2762,6 +2735,13 @@ bool EditEngine::HasValidData( const css::uno::Reference< css::datatransfer::XTr datatransfer::DataFlavor aFlavor; SotExchange::GetFormatDataFlavor( SotClipboardFormatId::STRING, aFlavor ); bValidData = rTransferable->isDataFlavorSupported( aFlavor ); + + if (!bValidData) + { + // Allow HTML-only clipboard, i.e. without plain text. + SotExchange::GetFormatDataFlavor(SotClipboardFormatId::HTML, aFlavor); + bValidData = rTransferable->isDataFlavorSupported(aFlavor); + } } return bValidData; @@ -2770,99 +2750,104 @@ bool EditEngine::HasValidData( const css::uno::Reference< css::datatransfer::XTr /** sets a link that is called at the beginning of a drag operation at an edit view */ void EditEngine::SetBeginDropHdl( const Link<EditView*,void>& rLink ) { - pImpEditEngine->SetBeginDropHdl( rLink ); + getImpl().SetBeginDropHdl(rLink); } Link<EditView*,void> const & EditEngine::GetBeginDropHdl() const { - return pImpEditEngine->GetBeginDropHdl(); + return getImpl().GetBeginDropHdl(); } /** sets a link that is called at the end of a drag operation at an edit view */ void EditEngine::SetEndDropHdl( const Link<EditView*,void>& rLink ) { - pImpEditEngine->SetEndDropHdl( rLink ); + getImpl().SetEndDropHdl(rLink); } Link<EditView*,void> const & EditEngine::GetEndDropHdl() const { - return pImpEditEngine->GetEndDropHdl(); + return getImpl().GetEndDropHdl(); } void EditEngine::SetFirstWordCapitalization( bool bCapitalize ) { - pImpEditEngine->SetFirstWordCapitalization( bCapitalize ); + getImpl().SetFirstWordCapitalization(bCapitalize); } void EditEngine::SetReplaceLeadingSingleQuotationMark( bool bReplace ) { - pImpEditEngine->SetReplaceLeadingSingleQuotationMark( bReplace ); + getImpl().SetReplaceLeadingSingleQuotationMark(bReplace); } bool EditEngine::IsHtmlImportHandlerSet() const { - return pImpEditEngine->aHtmlImportHdl.IsSet(); + return getImpl().maHtmlImportHdl.IsSet(); } bool EditEngine::IsRtfImportHandlerSet() const { - return pImpEditEngine->aRtfImportHdl.IsSet(); + return getImpl().maRtfImportHdl.IsSet(); } bool EditEngine::IsImportRTFStyleSheetsSet() const { - return pImpEditEngine->GetStatus().DoImportRTFStyleSheets(); + return getImpl().GetStatus().DoImportRTFStyleSheets(); } void EditEngine::CallHtmlImportHandler(HtmlImportInfo& rInfo) { - pImpEditEngine->aHtmlImportHdl.Call(rInfo); + getImpl().maHtmlImportHdl.Call(rInfo); } void EditEngine::CallRtfImportHandler(RtfImportInfo& rInfo) { - pImpEditEngine->aRtfImportHdl.Call(rInfo); + getImpl().maRtfImportHdl.Call(rInfo); } EditPaM EditEngine::InsertParaBreak(const EditSelection& rEditSelection) { - return pImpEditEngine->ImpInsertParaBreak(rEditSelection); + return getImpl().ImpInsertParaBreak(rEditSelection); } EditPaM EditEngine::InsertLineBreak(const EditSelection& rEditSelection) { - return pImpEditEngine->InsertLineBreak(rEditSelection); + return getImpl().InsertLineBreak(rEditSelection); } sal_Int32 EditEngine::GetOverflowingParaNum() const { - return pImpEditEngine->GetOverflowingParaNum(); + return getImpl().GetOverflowingParaNum(); } sal_Int32 EditEngine::GetOverflowingLineNum() const { - return pImpEditEngine->GetOverflowingLineNum(); + return getImpl().GetOverflowingLineNum(); } void EditEngine::ClearOverflowingParaNum() { - pImpEditEngine->ClearOverflowingParaNum(); + getImpl().ClearOverflowingParaNum(); } bool EditEngine::IsPageOverflow() { - pImpEditEngine->CheckPageOverflow(); - return pImpEditEngine->IsPageOverflow(); + getImpl().CheckPageOverflow(); + return getImpl().IsPageOverflow(); } void EditEngine::DisableAttributeExpanding() { - pImpEditEngine->GetEditDoc().DisableAttributeExpanding(); + getImpl().GetEditDoc().DisableAttributeExpanding(); +} + +void EditEngine::EnableSkipOutsideFormat(bool bValue) +{ + getImpl().EnableSkipOutsideFormat(bValue); } void EditEngine::SetLOKSpecialPaperSize(const Size& rSize) { - pImpEditEngine->SetLOKSpecialPaperSize(rSize); + getImpl().SetLOKSpecialPaperSize(rSize); } const Size& EditEngine::GetLOKSpecialPaperSize() const { - return pImpEditEngine->GetLOKSpecialPaperSize(); + return getImpl().GetLOKSpecialPaperSize(); } EFieldInfo::EFieldInfo() diff --git a/editeng/source/editeng/editobj.cxx b/editeng/source/editeng/editobj.cxx index 62ed45b20988..9b17e434e53d 100644 --- a/editeng/source/editeng/editobj.cxx +++ b/editeng/source/editeng/editobj.cxx @@ -22,12 +22,10 @@ #include <o3tl/safeint.hxx> #include <sal/log.hxx> -#include <editeng/fieldupdater.hxx> #include <editeng/macros.hxx> #include <editeng/section.hxx> #include "editobj2.hxx" #include <editeng/editdata.hxx> -#include <editattr.hxx> #include <editeng/editeng.hxx> #include <editeng/flditem.hxx> @@ -46,37 +44,32 @@ using std::endl; using namespace com::sun::star; -static XEditAttribute MakeXEditAttribute( SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 nStart, sal_Int32 nEnd ) -{ - // Create the new attribute in the pool - const SfxPoolItem& rNew = rPool.Put( rItem ); - - return XEditAttribute( rNew, nStart, nEnd ); -} - -XEditAttribute::XEditAttribute( const SfxPoolItem& rAttr, sal_Int32 nS, sal_Int32 nE ) - : pItem(&rAttr) - , nStart(nS) - , nEnd(nE) +XEditAttribute::XEditAttribute(SfxItemPool& rPool, const SfxPoolItem& rItem, sal_Int32 nS, sal_Int32 nE) +: maItemHolder(rPool, &rItem) +, nStart(nS) +, nEnd(nE) { } bool XEditAttribute::IsFeature() const { - sal_uInt16 nWhich = pItem->Which(); + sal_uInt16 nWhich = GetItem()->Which(); return ((nWhich >= EE_FEATURE_START) && (nWhich <= EE_FEATURE_END)); } -void XEditAttribute::SetItem(const SfxPoolItem& rNew) +void XEditAttribute::SetItem(SfxItemPool& rPool, const SfxPoolItem& rItem) { - pItem = &rNew; + maItemHolder = SfxPoolItemHolder(rPool, &rItem); } -XParaPortionList::XParaPortionList( - OutputDevice* pRefDev, sal_uInt32 nPW, sal_uInt16 _nStretchX, sal_uInt16 _nStretchY) +XParaPortionList::XParaPortionList(OutputDevice* pRefDev, sal_uInt32 nPW, + double fFontScaleX, double fFontScaleY, + double fSpacingScaleX, double fSpacingScaleY) : pRefDevPtr(pRefDev) - , nStretchX(_nStretchX) - , nStretchY(_nStretchY) + , mfFontScaleX(fFontScaleX) + , mfFontScaleY(fFontScaleY) + , mfSpacingScaleX(fSpacingScaleX) + , mfSpacingScaleY(fSpacingScaleY) , nPaperWidth(nPW) { } @@ -109,9 +102,7 @@ ContentInfo::ContentInfo( const ContentInfo& rCopyFrom, SfxItemPool& rPoolToUse for (const XEditAttribute & rAttr : rCopyFrom.maCharAttribs) { - XEditAttribute aMyAttr = MakeXEditAttribute( - rPoolToUse, *rAttr.GetItem(), rAttr.GetStart(), rAttr.GetEnd()); - maCharAttribs.push_back(aMyAttr); + maCharAttribs.emplace_back(rPoolToUse, *rAttr.GetItem(), rAttr.GetStart(), rAttr.GetEnd()); } if ( rCopyFrom.GetWrongList() ) @@ -120,8 +111,6 @@ ContentInfo::ContentInfo( const ContentInfo& rCopyFrom, SfxItemPool& rPoolToUse ContentInfo::~ContentInfo() { - for (auto const& charAttrib : maCharAttribs) - aParaAttribs.GetPool()->Remove(*charAttrib.GetItem()); maCharAttribs.clear(); } @@ -137,6 +126,12 @@ OUString ContentInfo::GetText() const return OUString(p); } +sal_Int32 ContentInfo::GetTextLen() const +{ + const rtl_uString* p = maText.getData(); + return p->length; +} + void ContentInfo::SetText( const OUString& rStr ) { maText = svl::SharedString(rStr.pData, nullptr); @@ -149,15 +144,15 @@ void ContentInfo::dumpAsXml(xmlTextWriterPtr pWriter) const (void)xmlTextWriterStartElement(pWriter, BAD_CAST("text")); OUString aText = GetText(); // TODO share code with sax_fastparser::FastSaxSerializer::write(). - (void)xmlTextWriterWriteString(pWriter, BAD_CAST(aText.replaceAll("", "	").toUtf8().getStr())); + (void)xmlTextWriterWriteString(pWriter, BAD_CAST(aText.replaceAll("\x01", "").toUtf8().getStr())); (void)xmlTextWriterEndElement(pWriter); aParaAttribs.dumpAsXml(pWriter); - for (size_t i=0; i<maCharAttribs.size(); ++i) + for (auto const& rCharAttribs : maCharAttribs) { (void)xmlTextWriterStartElement(pWriter, BAD_CAST("attribs")); - (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("start"), "%" SAL_PRIdINT32, maCharAttribs[i].GetStart()); - (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("end"), "%" SAL_PRIdINT32, maCharAttribs[i].GetEnd()); - maCharAttribs[i].GetItem()->dumpAsXml(pWriter); + (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("start"), "%" SAL_PRIdINT32, rCharAttribs.GetStart()); + (void)xmlTextWriterWriteFormatAttribute(pWriter, BAD_CAST("end"), "%" SAL_PRIdINT32, rCharAttribs.GetEnd()); + rCharAttribs.GetItem()->dumpAsXml(pWriter); (void)xmlTextWriterEndElement(pWriter); } (void)xmlTextWriterEndElement(pWriter); @@ -375,15 +370,9 @@ TextRotation EditTextObjectImpl::GetRotation() const XEditAttribute EditTextObjectImpl::CreateAttrib( const SfxPoolItem& rItem, sal_Int32 nStart, sal_Int32 nEnd ) { - return MakeXEditAttribute( *mpPool, rItem, nStart, nEnd ); -} - -void EditTextObjectImpl::DestroyAttrib( const XEditAttribute& rAttr ) -{ - mpPool->Remove( *rAttr.GetItem() ); + return XEditAttribute(*mpPool, rItem, nStart, nEnd); } - ContentInfo* EditTextObjectImpl::CreateAndInsertContent() { maContents.push_back(std::unique_ptr<ContentInfo>(new ContentInfo(*mpPool))); @@ -409,6 +398,14 @@ OUString EditTextObjectImpl::GetText(sal_Int32 nPara) const return maContents[nPara]->GetText(); } +sal_Int32 EditTextObjectImpl::GetTextLen(sal_Int32 nPara ) const +{ + if (nPara < 0 || o3tl::make_unsigned(nPara) >= maContents.size()) + return 0; + + return maContents[nPara]->GetTextLen(); +} + void EditTextObjectImpl::ClearPortionInfo() { mpPortionInfo.reset(); @@ -539,7 +536,6 @@ bool EditTextObjectImpl::RemoveCharAttribs( sal_uInt16 _nWhich ) XEditAttribute& rAttr = rC.maCharAttribs[--nAttr]; if ( !_nWhich || (rAttr.GetItem()->Which() == _nWhich) ) { - mpPool->Remove(*rAttr.GetItem()); rC.maCharAttribs.erase(rC.maCharAttribs.begin()+nAttr); bChanged = true; } diff --git a/editeng/source/editeng/editobj2.hxx b/editeng/source/editeng/editobj2.hxx index 250341fd4283..4392022b77a3 100644 --- a/editeng/source/editeng/editobj2.hxx +++ b/editeng/source/editeng/editobj2.hxx @@ -47,14 +47,14 @@ class SharedStringPool; class XEditAttribute { private: - const SfxPoolItem* pItem; + SfxPoolItemHolder maItemHolder; sal_Int32 nStart; sal_Int32 nEnd; public: - XEditAttribute( const SfxPoolItem& rAttr, sal_Int32 nStart, sal_Int32 nEnd ); + XEditAttribute(SfxItemPool&, const SfxPoolItem&, sal_Int32 nStart, sal_Int32 nEnd ); - const SfxPoolItem* GetItem() const { return pItem; } + const SfxPoolItem* GetItem() const { return maItemHolder.getItem(); } sal_Int32& GetStart() { return nStart; } sal_Int32& GetEnd() { return nEnd; } @@ -65,7 +65,7 @@ public: sal_Int32 GetLen() const { return nEnd-nStart; } bool IsFeature() const; - void SetItem(const SfxPoolItem& rNew); + void SetItem(SfxItemPool&, const SfxPoolItem&); inline bool operator==( const XEditAttribute& rCompare ) const; }; @@ -74,9 +74,7 @@ inline bool XEditAttribute::operator==( const XEditAttribute& rCompare ) const { return (nStart == rCompare.nStart) && (nEnd == rCompare.nEnd) && - ((pItem == rCompare.pItem) || - ((pItem->Which() == rCompare.pItem->Which()) && - (*pItem == *rCompare.pItem))); + SfxPoolItem::areSame(GetItem(), rCompare.GetItem()); } struct XParaPortion @@ -94,12 +92,14 @@ class XParaPortionList ListType maList; VclPtr<OutputDevice> pRefDevPtr; - sal_uInt16 nStretchX; - sal_uInt16 nStretchY; + double mfFontScaleX; + double mfFontScaleY; + double mfSpacingScaleX; + double mfSpacingScaleY; sal_uInt32 nPaperWidth; public: - XParaPortionList(OutputDevice* pRefDev, sal_uInt32 nPW, sal_uInt16 _nStretchX, sal_uInt16 _nStretchY); + XParaPortionList(OutputDevice* pRefDev, sal_uInt32 nPW, double fFontScaleX, double fFontScaleY, double fSpacingScaleX, double fSpacingScaleY); void push_back(XParaPortion* p); const XParaPortion& operator[](size_t i) const; @@ -108,8 +108,10 @@ public: sal_uInt32 GetPaperWidth() const { return nPaperWidth; } bool RefDevIsVirtual() const {return pRefDevPtr->IsVirtual();} const MapMode& GetRefMapMode() const { return pRefDevPtr->GetMapMode(); } - sal_uInt16 GetStretchX() const { return nStretchX; } - sal_uInt16 GetStretchY() const { return nStretchY; } + double getFontScaleX() const { return mfFontScaleX; } + double getFontScaleY() const { return mfFontScaleY; } + double getSpacingScaleX() const { return mfSpacingScaleX; } + double getSpacingScaleY() const { return mfSpacingScaleY; } }; class ContentInfo @@ -138,6 +140,7 @@ public: const svl::SharedString& GetSharedString() const { return maText;} OUString GetText() const; void SetText( const OUString& rStr ); + sal_Int32 GetTextLen() const; void dumpAsXml(xmlTextWriterPtr pWriter) const; @@ -212,7 +215,6 @@ public: ContentInfo* CreateAndInsertContent(); XEditAttribute CreateAttrib( const SfxPoolItem& rItem, sal_Int32 nStart, sal_Int32 nEnd ); - void DestroyAttrib( const XEditAttribute& rAttr ); ContentInfosType& GetContents() { return maContents;} const ContentInfosType& GetContents() const { return maContents;} @@ -224,6 +226,7 @@ public: virtual sal_Int32 GetParagraphCount() const override; virtual OUString GetText(sal_Int32 nParagraph) const override; + virtual sal_Int32 GetTextLen(sal_Int32 nParagraph) const override; virtual void ClearPortionInfo() override; diff --git a/editeng/source/editeng/editsel.cxx b/editeng/source/editeng/editsel.cxx index 3aeed7a6e357..4bdfff88155b 100644 --- a/editeng/source/editeng/editsel.cxx +++ b/editeng/source/editeng/editsel.cxx @@ -31,7 +31,7 @@ EditSelFunctionSet::EditSelFunctionSet() void EditSelFunctionSet::CreateAnchor() { if ( pCurView ) - pCurView->pImpEditView->CreateAnchor(); + pCurView->getImpl().CreateAnchor(); } void EditSelFunctionSet::DestroyAnchor() @@ -42,13 +42,13 @@ void EditSelFunctionSet::DestroyAnchor() void EditSelFunctionSet::SetCursorAtPoint( const Point& rPointPixel, bool ) { if ( pCurView ) - pCurView->pImpEditView->SetCursorAtPoint( rPointPixel ); + pCurView->getImpl().SetCursorAtPoint( rPointPixel ); } bool EditSelFunctionSet::IsSelectionAtPoint( const Point& rPointPixel ) { if ( pCurView ) - return pCurView->pImpEditView->IsSelectionAtPoint( rPointPixel ); + return pCurView->getImpl().IsSelectionAtPoint( rPointPixel ); return false; } @@ -69,7 +69,7 @@ void EditSelFunctionSet::BeginDrag() void EditSelFunctionSet::DeselectAll() { if ( pCurView ) - pCurView->pImpEditView->DeselectAll(); + pCurView->getImpl().DeselectAll(); } diff --git a/editeng/source/editeng/editstt2.hxx b/editeng/source/editeng/editstt2.hxx index 4474df8b429b..8cc09ff5dbe0 100644 --- a/editeng/source/editeng/editstt2.hxx +++ b/editeng/source/editeng/editstt2.hxx @@ -47,7 +47,9 @@ public: { return bool( nControlBits & EEControlBits::UNDOATTRIBS ); } bool OneCharPerLine() const - { return bool( nControlBits & EEControlBits::ONECHARPERLINE ); } + { + return bool(nControlBits & (EEControlBits::ONECHARPERLINE | EEControlBits::STACKED)); + } bool IsOutliner() const { return bool( nControlBits & EEControlBits::OUTLINER ); } @@ -86,11 +88,11 @@ public: bool DoAutoComplete() const { return bool( nControlBits & EEControlBits::AUTOCOMPLETE ); } - bool DoFormat100() const - { return bool( nControlBits & EEControlBits::FORMAT100 ); } - bool ULSpaceSummation() const { return bool( nControlBits & EEControlBits::ULSPACESUMMATION ); } + + bool IsSingleLine() const + { return bool( nControlBits & EEControlBits::SINGLELINE ); } }; /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/editundo.cxx b/editeng/source/editeng/editundo.cxx index dc9c3a104b6c..7ff299e7efbd 100644 --- a/editeng/source/editeng/editundo.cxx +++ b/editeng/source/editeng/editundo.cxx @@ -22,16 +22,17 @@ #include "editundo.hxx" #include <editeng/editview.hxx> #include <editeng/editeng.hxx> +#include <utility> #include <osl/diagnose.h> static void lcl_DoSetSelection( EditView const * pView, sal_uInt16 nPara ) { EPaM aEPaM( nPara, 0 ); - EditPaM aPaM( pView->GetImpEditEngine()->CreateEditPaM( aEPaM ) ); + EditPaM aPaM = pView->getImpEditEngine().CreateEditPaM(aEPaM); aPaM.SetIndex( aPaM.GetNode()->Len() ); EditSelection aSel( aPaM, aPaM ); - pView->GetImpEditView()->SetEditSelection( aSel ); + pView->getImpl().SetEditSelection( aSel ); } EditUndoManager::EditUndoManager(sal_uInt16 nMaxUndoActionCount ) @@ -63,18 +64,18 @@ bool EditUndoManager::Undo() } } - mpEditEngine->GetActiveView()->GetImpEditView()->DrawSelectionXOR(); // Remove the old selection + mpEditEngine->GetActiveView()->getImpl().DrawSelectionXOR(); // Remove the old selection mpEditEngine->SetUndoMode( true ); bool bDone = SfxUndoManager::Undo(); mpEditEngine->SetUndoMode( false ); - EditSelection aNewSel( mpEditEngine->GetActiveView()->GetImpEditView()->GetEditSelection() ); + EditSelection aNewSel( mpEditEngine->GetActiveView()->getImpl().GetEditSelection() ); DBG_ASSERT( !aNewSel.IsInvalid(), "Invalid selection after Undo () "); DBG_ASSERT( !aNewSel.DbgIsBuggy( mpEditEngine->GetEditDoc() ), "Broken selection afte Undo () "); aNewSel.Min() = aNewSel.Max(); - mpEditEngine->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel ); + mpEditEngine->GetActiveView()->getImpl().SetEditSelection( aNewSel ); if (mpEditEngine->IsUpdateLayout()) mpEditEngine->FormatAndLayout( mpEditEngine->GetActiveView(), true ); @@ -99,18 +100,18 @@ bool EditUndoManager::Redo() } } - mpEditEngine->GetActiveView()->GetImpEditView()->DrawSelectionXOR(); // Remove the old selection + mpEditEngine->GetActiveView()->getImpl().DrawSelectionXOR(); // Remove the old selection mpEditEngine->SetUndoMode( true ); bool bDone = SfxUndoManager::Redo(); mpEditEngine->SetUndoMode( false ); - EditSelection aNewSel( mpEditEngine->GetActiveView()->GetImpEditView()->GetEditSelection() ); + EditSelection aNewSel( mpEditEngine->GetActiveView()->getImpl().GetEditSelection() ); DBG_ASSERT( !aNewSel.IsInvalid(), "Invalid selection after Undo () "); DBG_ASSERT( !aNewSel.DbgIsBuggy( mpEditEngine->GetEditDoc() ), "Broken selection afte Undo () "); aNewSel.Min() = aNewSel.Max(); - mpEditEngine->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel ); + mpEditEngine->GetActiveView()->getImpl().SetEditSelection( aNewSel ); if (mpEditEngine->IsUpdateLayout()) mpEditEngine->FormatAndLayout( mpEditEngine->GetActiveView() ); @@ -121,7 +122,7 @@ EditUndo::EditUndo(sal_uInt16 nI, EditEngine* pEE) : nId(nI), mnViewShellId(-1), mpEditEngine(pEE) { const EditView* pEditView = mpEditEngine ? mpEditEngine->GetActiveView() : nullptr; - const OutlinerViewShell* pViewShell = pEditView ? pEditView->GetImpEditView()->GetViewShell() : nullptr; + const OutlinerViewShell* pViewShell = pEditView ? pEditView->getImpl().GetViewShell() : nullptr; if (pViewShell) mnViewShellId = pViewShell->GetViewShellId(); } @@ -156,26 +157,23 @@ ViewShellId EditUndo::GetViewShellId() const return mnViewShellId; } -EditUndoDelContent::EditUndoDelContent( - EditEngine* pEE, ContentNode* pNode, sal_Int32 nPortion) : - EditUndo(EDITUNDO_DELCONTENT, pEE), - bDelObject(true), - nNode(nPortion), - pContentNode(pNode) {} +EditUndoDelContent::EditUndoDelContent(EditEngine* pEE, std::unique_ptr<ContentNode> pNode, sal_Int32 nPortion) + : EditUndo(EDITUNDO_DELCONTENT, pEE) + , nNode(nPortion) + , mpContentNode(std::move(pNode)) +{} EditUndoDelContent::~EditUndoDelContent() { - if ( bDelObject ) - delete pContentNode; } void EditUndoDelContent::Undo() { DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" ); - GetEditEngine()->InsertContent( pContentNode, nNode ); - bDelObject = false; // belongs to the Engine again - EditSelection aSel( EditPaM( pContentNode, 0 ), EditPaM( pContentNode, pContentNode->Len() ) ); - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection(aSel); + ContentNode* pNode = mpContentNode.get(); + GetEditEngine()->InsertContent(std::move(mpContentNode), nNode); + EditSelection aSel(EditPaM(pNode, 0), EditPaM(pNode, pNode->Len())); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection(aSel); } void EditUndoDelContent::Redo() @@ -186,40 +184,42 @@ void EditUndoDelContent::Redo() // pNode is no longer correct, if the paragraphs where merged // in between Undos - pContentNode = pEE->GetEditDoc().GetObject( nNode ); - DBG_ASSERT( pContentNode, "EditUndoDelContent::Redo(): Node?!" ); + ContentNode* pNode = pEE->GetEditDoc().GetObject(nNode); + DBG_ASSERT(pNode, "EditUndoDelContent::Redo(): Node?!"); pEE->RemoveParaPortion(nNode); // Do not delete node, depends on the undo! - pEE->GetEditDoc().Release( nNode ); + mpContentNode = pEE->GetEditDoc().Release(nNode); + assert(mpContentNode.get() == pNode); + if (pEE->IsCallParaInsertedOrDeleted()) - pEE->ParagraphDeleted( nNode ); + pEE->ParagraphDeleted(nNode); - DeletedNodeInfo* pInf = new DeletedNodeInfo( pContentNode, nNode ); - pEE->AppendDeletedNodeInfo(pInf); + DeletedNodeInfo* pDeletedNodeInfo = new DeletedNodeInfo(pNode, nNode); + pEE->AppendDeletedNodeInfo(pDeletedNodeInfo); pEE->UpdateSelections(); - ContentNode* pN = ( nNode < pEE->GetEditDoc().Count() ) - ? pEE->GetEditDoc().GetObject( nNode ) - : pEE->GetEditDoc().GetObject( nNode-1 ); - DBG_ASSERT( pN && ( pN != pContentNode ), "?! RemoveContent !? " ); - EditPaM aPaM( pN, pN->Len() ); + ContentNode* pCheckNode = (nNode < pEE->GetEditDoc().Count()) + ? pEE->GetEditDoc().GetObject(nNode) + : pEE->GetEditDoc().GetObject(nNode - 1); + + DBG_ASSERT(pCheckNode && pCheckNode != mpContentNode.get(), "?! RemoveContent !? "); - bDelObject = true; // belongs to the Engine again + EditPaM aPaM(pCheckNode, pCheckNode->Len()); - pEE->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aPaM ) ); + pEE->GetActiveView()->getImpl().SetEditSelection( EditSelection( aPaM, aPaM ) ); } EditUndoConnectParas::EditUndoConnectParas( EditEngine* pEE, sal_Int32 nN, sal_uInt16 nSP, - const SfxItemSet& rLeftParaAttribs, const SfxItemSet& rRightParaAttribs, + SfxItemSet _aLeftParaAttribs, SfxItemSet _aRightParaAttribs, const SfxStyleSheet* pLeftStyle, const SfxStyleSheet* pRightStyle, bool bBkwrd) : EditUndo(EDITUNDO_CONNECTPARAS, pEE), nNode(nN), nSepPos(nSP), - aLeftParaAttribs(rLeftParaAttribs), - aRightParaAttribs(rRightParaAttribs), + aLeftParaAttribs(std::move(_aLeftParaAttribs)), + aRightParaAttribs(std::move(_aRightParaAttribs)), eLeftStyleFamily(SfxStyleFamily::All), eRightStyleFamily(SfxStyleFamily::All), bBackward(bBkwrd) @@ -270,7 +270,7 @@ void EditUndoConnectParas::Undo() GetEditEngine()->SetStyleSheet( nNode+1, static_cast<SfxStyleSheet*>(GetEditEngine()->GetStyleSheetPool()->Find( aRightStyleName, eRightStyleFamily )) ); } - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aPaM ) ); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( EditSelection( aPaM, aPaM ) ); } void EditUndoConnectParas::Redo() @@ -278,7 +278,7 @@ void EditUndoConnectParas::Redo() DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: Np Active View!" ); EditPaM aPaM = GetEditEngine()->ConnectContents( nNode, bBackward ); - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aPaM ) ); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( EditSelection( aPaM, aPaM ) ); } EditUndoSplitPara::EditUndoSplitPara( @@ -292,21 +292,21 @@ void EditUndoSplitPara::Undo() { DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" ); EditPaM aPaM = GetEditEngine()->ConnectContents(nNode, false); - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aPaM ) ); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( EditSelection( aPaM, aPaM ) ); } void EditUndoSplitPara::Redo() { DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" ); EditPaM aPaM = GetEditEngine()->SplitContent(nNode, nSepPos); - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aPaM ) ); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( EditSelection( aPaM, aPaM ) ); } EditUndoInsertChars::EditUndoInsertChars( - EditEngine* pEE, const EPaM& rEPaM, const OUString& rStr) : + EditEngine* pEE, const EPaM& rEPaM, OUString aStr) : EditUndo(EDITUNDO_INSERTCHARS, pEE), aEPaM(rEPaM), - aText(rStr) {} + aText(std::move(aStr)) {} void EditUndoInsertChars::Undo() { @@ -315,7 +315,7 @@ void EditUndoInsertChars::Undo() EditSelection aSel( aPaM, aPaM ); aSel.Max().SetIndex( aSel.Max().GetIndex() + aText.getLength() ); EditPaM aNewPaM( GetEditEngine()->DeleteSelection(aSel) ); - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aNewPaM, aNewPaM ) ); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( EditSelection( aNewPaM, aNewPaM ) ); } void EditUndoInsertChars::Redo() @@ -325,7 +325,7 @@ void EditUndoInsertChars::Redo() GetEditEngine()->InsertText(EditSelection(aPaM, aPaM), aText); EditPaM aNewPaM( aPaM ); aNewPaM.SetIndex( aNewPaM.GetIndex() + aText.getLength() ); - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( EditSelection( aPaM, aNewPaM ) ); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( EditSelection( aPaM, aNewPaM ) ); } bool EditUndoInsertChars::Merge( SfxUndoAction* pNextAction ) @@ -346,9 +346,9 @@ bool EditUndoInsertChars::Merge( SfxUndoAction* pNextAction ) } EditUndoRemoveChars::EditUndoRemoveChars( - EditEngine* pEE, const EPaM& rEPaM, const OUString& rStr) : + EditEngine* pEE, const EPaM& rEPaM, OUString aStr) : EditUndo(EDITUNDO_REMOVECHARS, pEE), - aEPaM(rEPaM), aText(rStr) {} + aEPaM(rEPaM), aText(std::move(aStr)) {} void EditUndoRemoveChars::Undo() { @@ -357,7 +357,7 @@ void EditUndoRemoveChars::Undo() EditSelection aSel( aPaM, aPaM ); GetEditEngine()->InsertText(aSel, aText); aSel.Max().SetIndex( aSel.Max().GetIndex() + aText.getLength() ); - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection(aSel); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection(aSel); } void EditUndoRemoveChars::Redo() @@ -367,7 +367,7 @@ void EditUndoRemoveChars::Redo() EditSelection aSel( aPaM, aPaM ); aSel.Max().SetIndex( aSel.Max().GetIndex() + aText.getLength() ); EditPaM aNewPaM = GetEditEngine()->DeleteSelection(aSel); - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection(aNewPaM); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection(aNewPaM); } EditUndoInsertFeature::EditUndoInsertFeature( @@ -392,7 +392,7 @@ void EditUndoInsertFeature::Undo() aSel.Max().SetIndex( aSel.Max().GetIndex()+1 ); GetEditEngine()->DeleteSelection(aSel); aSel.Max().SetIndex( aSel.Max().GetIndex()-1 ); // For Selection - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection(aSel); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection(aSel); } void EditUndoInsertFeature::Redo() @@ -404,7 +404,7 @@ void EditUndoInsertFeature::Redo() if ( pFeature->Which() == EE_FEATURE_FIELD ) GetEditEngine()->UpdateFieldsOnly(); aSel.Max().SetIndex( aSel.Max().GetIndex()+1 ); - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection(aSel); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection(aSel); } EditUndoMoveParagraphs::EditUndoMoveParagraphs( @@ -433,26 +433,26 @@ void EditUndoMoveParagraphs::Undo() nTmpDest += aTmpRange.Len(); EditSelection aNewSel = GetEditEngine()->MoveParagraphs(aTmpRange, nTmpDest); - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel ); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( aNewSel ); } void EditUndoMoveParagraphs::Redo() { DBG_ASSERT( GetEditEngine()->GetActiveView(), "Undo/Redo: No Active View!" ); EditSelection aNewSel = GetEditEngine()->MoveParagraphs(nParagraphs, nDest); - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel ); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection( aNewSel ); } EditUndoSetStyleSheet::EditUndoSetStyleSheet( - EditEngine* pEE, sal_Int32 nP, const OUString& rPrevName, SfxStyleFamily ePrevFam, - const OUString& rNewName, SfxStyleFamily eNewFam, const SfxItemSet& rPrevParaAttribs) : + EditEngine* pEE, sal_Int32 nP, OUString _aPrevName, SfxStyleFamily ePrevFam, + OUString _aNewName, SfxStyleFamily eNewFam, SfxItemSet _aPrevParaAttribs) : EditUndo(EDITUNDO_STYLESHEET, pEE), nPara(nP), - aPrevName(rPrevName), - aNewName(rNewName), + aPrevName(std::move(_aPrevName)), + aNewName(std::move(_aNewName)), ePrevFamily(ePrevFam), eNewFamily(eNewFam), - aPrevParaAttribs(rPrevParaAttribs) + aPrevParaAttribs(std::move(_aPrevParaAttribs)) { } @@ -476,11 +476,11 @@ void EditUndoSetStyleSheet::Redo() } EditUndoSetParaAttribs::EditUndoSetParaAttribs( - EditEngine* pEE, sal_Int32 nP, const SfxItemSet& rPrevItems, const SfxItemSet& rNewItems) : + EditEngine* pEE, sal_Int32 nP, SfxItemSet _aPrevItems, SfxItemSet _aNewItems) : EditUndo(EDITUNDO_PARAATTRIBS, pEE), nPara(nP), - aPrevItems(rPrevItems), - aNewItems(rNewItems) {} + aPrevItems(std::move(_aPrevItems)), + aNewItems(std::move(_aNewItems)) {} EditUndoSetParaAttribs::~EditUndoSetParaAttribs() {} @@ -498,10 +498,10 @@ void EditUndoSetParaAttribs::Redo() lcl_DoSetSelection( GetEditEngine()->GetActiveView(), nPara ); } -EditUndoSetAttribs::EditUndoSetAttribs(EditEngine* pEE, const ESelection& rESel, const SfxItemSet& rNewItems) : +EditUndoSetAttribs::EditUndoSetAttribs(EditEngine* pEE, const ESelection& rESel, SfxItemSet aNewItems) : EditUndo(EDITUNDO_ATTRIBS, pEE), aESel(rESel), - aNewAttribs(rNewItems), + aNewAttribs(std::move(aNewItems)), nSpecial(SetAttribsMode::NONE), m_bSetSelection(true), // When EditUndoSetAttribs actually is a RemoveAttribs this could be @@ -513,26 +513,8 @@ EditUndoSetAttribs::EditUndoSetAttribs(EditEngine* pEE, const ESelection& rESel, { } -namespace { - -struct RemoveAttribsFromPool -{ - SfxItemPool& mrPool; -public: - explicit RemoveAttribsFromPool(SfxItemPool& rPool) : mrPool(rPool) {} - void operator() (std::unique_ptr<ContentAttribsInfo> const & rInfo) - { - rInfo->RemoveAllCharAttribsFromPool(mrPool); - } -}; - -} - EditUndoSetAttribs::~EditUndoSetAttribs() { - // Get Items from Pool... - SfxItemPool* pPool = aNewAttribs.GetPool(); - std::for_each(aPrevAttribs.begin(), aPrevAttribs.end(), RemoveAttribsFromPool(*pPool)); } void EditUndoSetAttribs::Undo() @@ -595,7 +577,7 @@ void EditUndoSetAttribs::ImpSetSelection() { EditEngine* pEE = GetEditEngine(); EditSelection aSel = pEE->CreateSelection(aESel); - pEE->GetActiveView()->GetImpEditView()->SetEditSelection(aSel); + pEE->GetActiveView()->getImpl().SetEditSelection(aSel); } EditUndoTransliteration::EditUndoTransliteration(EditEngine* pEE, const ESelection& rESel, TransliterationFlags nM) : @@ -619,7 +601,7 @@ void EditUndoTransliteration::Undo() EditSelection aDelSel( aSel ); aSel = pEE->InsertParaBreak( aSel ); aDelSel.Max() = aSel.Min(); - aDelSel.Max().GetNode()->GetCharAttribs().DeleteEmptyAttribs( pEE->GetEditDoc().GetItemPool() ); + aDelSel.Max().GetNode()->GetCharAttribs().DeleteEmptyAttribs(); EditSelection aNewSel; if ( pTxtObj ) { @@ -640,7 +622,7 @@ void EditUndoTransliteration::Undo() aNewSel.Max().SetIndex( aNewSel.Max().GetIndex() + aDelSel.Min().GetIndex() ); } pEE->DeleteSelected( aDelSel ); - pEE->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel ); + pEE->GetActiveView()->getImpl().SetEditSelection( aNewSel ); } void EditUndoTransliteration::Redo() @@ -650,7 +632,7 @@ void EditUndoTransliteration::Redo() EditSelection aSel = pEE->CreateSelection(aOldESel); EditSelection aNewSel = pEE->TransliterateText( aSel, nMode ); - pEE->GetActiveView()->GetImpEditView()->SetEditSelection( aNewSel ); + pEE->GetActiveView()->getImpl().SetEditSelection( aNewSel ); } EditUndoMarkSelection::EditUndoMarkSelection(EditEngine* pEE, const ESelection& rSel) : @@ -666,7 +648,7 @@ void EditUndoMarkSelection::Undo() if ( GetEditEngine()->IsFormatted() ) GetEditEngine()->GetActiveView()->SetSelection( aSelection ); else - GetEditEngine()->GetActiveView()->GetImpEditView()->SetEditSelection( GetEditEngine()->CreateSelection(aSelection) ); + GetEditEngine()->GetActiveView()->getImpl().SetEditSelection(GetEditEngine()->CreateSelection(aSelection)); } } diff --git a/editeng/source/editeng/editundo.hxx b/editeng/source/editeng/editundo.hxx index f87180ba7dd7..d43ba9553a39 100644 --- a/editeng/source/editeng/editundo.hxx +++ b/editeng/source/editeng/editundo.hxx @@ -36,13 +36,10 @@ enum class TransliterationFlags; class EditUndoDelContent : public EditUndo { private: - bool bDelObject; - sal_Int32 nNode; - ContentNode* pContentNode; // Points to the valid, - // undestroyed object! - + sal_Int32 nNode; + std::unique_ptr<ContentNode> mpContentNode; // Points to the valid, undestroyed object! public: - EditUndoDelContent(EditEngine* pEE, ContentNode* pNode, sal_Int32 nPortion); + EditUndoDelContent(EditEngine* pEE, std::unique_ptr<ContentNode> pNode, sal_Int32 nPortion); virtual ~EditUndoDelContent() override; virtual void Undo() override; @@ -70,7 +67,7 @@ private: public: EditUndoConnectParas(EditEngine* pEE, sal_Int32 nNode, sal_uInt16 nSepPos, - const SfxItemSet& rLeftParaAttribs, const SfxItemSet& rRightParaAttribs, + SfxItemSet aLeftParaAttribs, SfxItemSet aRightParaAttribs, const SfxStyleSheet* pLeftStyle, const SfxStyleSheet* pRightStyle, bool bBackward); virtual ~EditUndoConnectParas() override; @@ -105,7 +102,7 @@ private: OUString aText; public: - EditUndoInsertChars(EditEngine* pEE, const EPaM& rEPaM, const OUString& rStr); + EditUndoInsertChars(EditEngine* pEE, const EPaM& rEPaM, OUString aStr); virtual void Undo() override; virtual void Redo() override; @@ -123,7 +120,7 @@ private: OUString aText; public: - EditUndoRemoveChars(EditEngine* pEE, const EPaM& rEPaM, const OUString& rStr); + EditUndoRemoveChars(EditEngine* pEE, const EPaM& rEPaM, OUString aStr); virtual void Undo() override; virtual void Redo() override; @@ -178,9 +175,9 @@ private: public: EditUndoSetStyleSheet(EditEngine* pEE, sal_Int32 nPara, - const OUString& rPrevName, SfxStyleFamily ePrevFamily, - const OUString& rNewName, SfxStyleFamily eNewFamily, - const SfxItemSet& rPrevParaAttribs); + OUString aPrevName, SfxStyleFamily ePrevFamily, + OUString aNewName, SfxStyleFamily eNewFamily, + SfxItemSet aPrevParaAttribs); virtual ~EditUndoSetStyleSheet() override; virtual void Undo() override; @@ -198,7 +195,7 @@ private: SfxItemSet aNewItems; public: - EditUndoSetParaAttribs(EditEngine* pEE, sal_Int32 nPara, const SfxItemSet& rPrevItems, const SfxItemSet& rNewItems); + EditUndoSetParaAttribs(EditEngine* pEE, sal_Int32 nPara, SfxItemSet aPrevItems, SfxItemSet aNewItems); virtual ~EditUndoSetParaAttribs() override; virtual void Undo() override; @@ -228,7 +225,7 @@ private: public: - EditUndoSetAttribs(EditEngine* pEE, const ESelection& rESel, const SfxItemSet& rNewItems); + EditUndoSetAttribs(EditEngine* pEE, const ESelection& rESel, SfxItemSet aNewItems); virtual ~EditUndoSetAttribs() override; SfxItemSet& GetNewAttribs() { return aNewAttribs; } diff --git a/editeng/source/editeng/editview.cxx b/editeng/source/editeng/editview.cxx index fe6711ff6eaf..81fbd2d10b39 100644 --- a/editeng/source/editeng/editview.cxx +++ b/editeng/source/editeng/editview.cxx @@ -19,12 +19,10 @@ #include <memory> -#include <sal/macros.h> #include <vcl/image.hxx> #include <com/sun/star/i18n/WordType.hpp> #include <com/sun/star/i18n/ScriptType.hpp> -#include <vcl/metric.hxx> #include <i18nlangtag/languagetag.hxx> #include <i18nlangtag/mslangid.hxx> @@ -36,6 +34,7 @@ #include <svl/srchitem.hxx> #include "impedit.hxx" +#include <comphelper/propertyvalue.hxx> #include <editeng/editeng.hxx> #include <editeng/editview.hxx> #include <editeng/flditem.hxx> @@ -50,7 +49,6 @@ #include <vcl/window.hxx> #include <editeng/acorrcfg.hxx> #include <editeng/unolingu.hxx> -#include <editeng/fontitem.hxx> #include <unotools/lingucfg.hxx> #include <com/sun/star/frame/XStorable.hpp> @@ -62,9 +60,9 @@ #include <LibreOfficeKit/LibreOfficeKitEnums.h> #include <comphelper/lok.hxx> #include <sfx2/viewsh.hxx> +#include <sfx2/lokhelper.hxx> #include <osl/diagnose.h> #include <boost/property_tree/json_parser.hpp> -#include <sfx2/dispatch.hxx> #include <com/sun/star/lang/XServiceInfo.hpp> @@ -90,7 +88,7 @@ LanguageType EditView::CheckLanguage( // If the result from language guessing does not provide a 'Country' // part, try to get it by looking up the locale setting of the office, - // "Tools/Options - Language Settings - Languages: Locale setting", if + // "Tools/Options - Languages and Locales - General: Locale setting", if // the language matches. if ( aGuessTag.getCountry().isEmpty() ) { @@ -117,16 +115,16 @@ LanguageType EditView::CheckLanguage( const AllSettings& rSettings = Application::GetSettings(); SvtLinguOptions aLinguOpt; SvtLinguConfig().GetOptions( aLinguOpt ); - // The default document language from "Tools/Options - Language Settings - Languages: Western" + // The default document language from "Tools/Options - Languages and Locales - General: Western" aLangList[0] = MsLangId::resolveSystemLanguageByScriptType( aLinguOpt.nDefaultLanguage, css::i18n::ScriptType::LATIN); - // The one from "Tools/Options - Language Settings - Languages: User interface" + // The one from "Tools/Options - Languages and Locales - General: User interface" aLangList[1] = rSettings.GetUILanguageTag().getLanguageType(); - // The one from "Tools/Options - Language Settings - Languages: Locale setting" + // The one from "Tools/Options - Languages and Locales - General: Locale setting" aLangList[2] = rSettings.GetLanguageTag().getLanguageType(); // en-US aLangList[3] = LANGUAGE_ENGLISH_US; -#ifdef DEBUG +#if OSL_DEBUG_LEVEL >= 2 lang::Locale a0( LanguageTag::convertToLocale( aLangList[0] ) ); lang::Locale a1( LanguageTag::convertToLocale( aLangList[1] ) ); lang::Locale a2( LanguageTag::convertToLocale( aLangList[2] ) ); @@ -154,9 +152,11 @@ EditViewCallbacks::~EditViewCallbacks() { } -EditView::EditView( EditEngine* pEng, vcl::Window* pWindow ) +EditView::EditView(EditEngine* pEditEngine, vcl::Window* pWindow) + : mpImpEditView(new ImpEditView(this, pEditEngine, pWindow)) { - pImpEditView.reset( new ImpEditView( this, pEng, pWindow ) ); + assert(pEditEngine); + getImpl().mbReadOnly = getImpl().mbReadOnly || SfxViewShell::IsCurrentLokViewReadOnly(); } EditView::~EditView() @@ -165,32 +165,32 @@ EditView::~EditView() void EditView::setEditViewCallbacks(EditViewCallbacks* pEditViewCallbacks) { - pImpEditView->setEditViewCallbacks(pEditViewCallbacks); + getImpl().setEditViewCallbacks(pEditViewCallbacks); } EditViewCallbacks* EditView::getEditViewCallbacks() const { - return pImpEditView->getEditViewCallbacks(); + return getImpl().getEditViewCallbacks(); } -ImpEditEngine* EditView::GetImpEditEngine() const +ImpEditEngine& EditView::getImpEditEngine() const { - return pImpEditView->pEditEngine->pImpEditEngine.get(); + return getImpl().getImpEditEngine(); } -EditEngine* EditView::GetEditEngine() const +EditEngine& EditView::getEditEngine() const { - return pImpEditView->pEditEngine; + return getImpl().getEditEngine(); } tools::Rectangle EditView::GetInvalidateRect() const { - if ( !pImpEditView->DoInvalidateMore() ) - return pImpEditView->aOutArea; + if (!getImpl().DoInvalidateMore()) + return getImpl().maOutputArea; else { - tools::Rectangle aRect( pImpEditView->aOutArea ); - tools::Long nMore = pImpEditView->GetOutputDevice().PixelToLogic( Size( pImpEditView->GetInvalidateMore(), 0 ) ).Width(); + tools::Rectangle aRect(getImpl().maOutputArea); + tools::Long nMore = getImpl().GetOutputDevice().PixelToLogic( Size( getImpl().GetInvalidateMore(), 0 ) ).Width(); aRect.AdjustLeft( -nMore ); aRect.AdjustRight(nMore ); aRect.AdjustTop( -nMore ); @@ -199,20 +199,31 @@ tools::Rectangle EditView::GetInvalidateRect() const } } +namespace { + +tools::Rectangle lcl_negateRectX(const tools::Rectangle& rRect) +{ + return tools::Rectangle(-rRect.Right(), rRect.Top(), -rRect.Left(), rRect.Bottom()); +} + +} + void EditView::InvalidateWindow(const tools::Rectangle& rClipRect) { - if (EditViewCallbacks* pEditViewCallbacks = pImpEditView->getEditViewCallbacks()) + LOKEditViewHistory::Update(); + bool bNegativeX = IsNegativeX(); + if (EditViewCallbacks* pEditViewCallbacks = getImpl().getEditViewCallbacks()) { // do not invalidate and trigger a global repaint, but forward // the need for change to the applied EditViewCallback, can e.g. // be used to visualize the active edit text in an OverlayObject - pEditViewCallbacks->EditViewInvalidate(rClipRect); + pEditViewCallbacks->EditViewInvalidate(bNegativeX ? lcl_negateRectX(rClipRect) : rClipRect); } else { // classic mode: invalidate and trigger full repaint // of the changed area - GetWindow()->Invalidate(rClipRect); + GetWindow()->Invalidate(bNegativeX ? lcl_negateRectX(rClipRect) : rClipRect); } } @@ -220,10 +231,14 @@ void EditView::InvalidateOtherViewWindows( const tools::Rectangle& rInvRect ) { if (comphelper::LibreOfficeKit::isActive()) { - for (auto& pWin : pImpEditView->aOutWindowSet) + bool bNegativeX = IsNegativeX(); + for (auto& pWin : getImpl().maOutWindowSet) { if (pWin) - pWin->Invalidate( rInvRect ); + { + if (!pWin->InvalidateByForeignEditView(this)) + pWin->Invalidate( bNegativeX ? lcl_negateRectX(rInvRect) : rInvRect ); + } } } } @@ -231,18 +246,20 @@ void EditView::InvalidateOtherViewWindows( const tools::Rectangle& rInvRect ) void EditView::Invalidate() { const tools::Rectangle& rInvRect = GetInvalidateRect(); - pImpEditView->InvalidateAtWindow(rInvRect); + + LOKEditViewHistory::Update(); + getImpl().InvalidateAtWindow(rInvRect); InvalidateOtherViewWindows(rInvRect); } void EditView::SetReadOnly( bool bReadOnly ) { - pImpEditView->bReadOnly = bReadOnly; + getImpl().mbReadOnly = bReadOnly || SfxViewShell::IsCurrentLokViewReadOnly(); } bool EditView::IsReadOnly() const { - return pImpEditView->bReadOnly; + return getImpl().mbReadOnly; } void EditView::SetSelection( const ESelection& rESel ) @@ -253,35 +270,35 @@ void EditView::SetSelection( const ESelection& rESel ) { // tdf#113591 Get node from EditDoc, as the selection might have a pointer to an // already deleted node. - const ContentNode* pNode = pImpEditView->pEditEngine->GetEditDoc().GetEndPaM().GetNode(); - pImpEditView->pEditEngine->CursorMoved( pNode ); + const ContentNode* pNode(getEditEngine().GetEditDoc().GetEndPaM().GetNode()); + if (nullptr != pNode) + pNode->checkAndDeleteEmptyAttribs(); } - EditSelection aNewSelection( pImpEditView->pEditEngine->pImpEditEngine->ConvertSelection( - rESel.nStartPara, rESel.nStartPos, rESel.nEndPara, rESel.nEndPos ) ); + EditSelection aNewSelection(getImpEditEngine().ConvertSelection(rESel.nStartPara, rESel.nStartPos, rESel.nEndPara, rESel.nEndPos)); // If the selection is manipulated after a KeyInput: - pImpEditView->pEditEngine->CheckIdleFormatter(); + getEditEngine().CheckIdleFormatter(); // Selection may not start/end at an invisible paragraph: - const ParaPortion* pPortion = pImpEditView->pEditEngine->FindParaPortion( aNewSelection.Min().GetNode() ); + const ParaPortion* pPortion = getEditEngine().FindParaPortion( aNewSelection.Min().GetNode() ); if ( !pPortion->IsVisible() ) { - pPortion = pImpEditView->pEditEngine->GetPrevVisPortion( pPortion ); - ContentNode* pNode = pPortion ? pPortion->GetNode() : pImpEditView->pEditEngine->GetEditDoc().GetObject( 0 ); + pPortion = getEditEngine().GetPrevVisPortion( pPortion ); + ContentNode* pNode = pPortion ? pPortion->GetNode() : getEditEngine().GetEditDoc().GetObject( 0 ); aNewSelection.Min() = EditPaM( pNode, pNode->Len() ); } - pPortion = pImpEditView->pEditEngine->FindParaPortion( aNewSelection.Max().GetNode() ); + pPortion = getEditEngine().FindParaPortion( aNewSelection.Max().GetNode() ); if ( !pPortion->IsVisible() ) { - pPortion = pImpEditView->pEditEngine->GetPrevVisPortion( pPortion ); - ContentNode* pNode = pPortion ? pPortion->GetNode() : pImpEditView->pEditEngine->GetEditDoc().GetObject( 0 ); + pPortion = getEditEngine().GetPrevVisPortion( pPortion ); + ContentNode* pNode = pPortion ? pPortion->GetNode() : getEditEngine().GetEditDoc().GetObject( 0 ); aNewSelection.Max() = EditPaM( pNode, pNode->Len() ); } - pImpEditView->DrawSelectionXOR(); - pImpEditView->SetEditSelection( aNewSelection ); - pImpEditView->DrawSelectionXOR(); - bool bGotoCursor = pImpEditView->DoAutoScroll(); + getImpl().DrawSelectionXOR(); + getImpl().SetEditSelection( aNewSelection ); + getImpl().DrawSelectionXOR(); + bool bGotoCursor = getImpl().DoAutoScroll(); // comments section in Writer: // don't scroll to the selection if it is @@ -294,66 +311,78 @@ ESelection EditView::GetSelection() const { ESelection aSelection; - aSelection.nStartPara = pImpEditView->pEditEngine->GetEditDoc().GetPos( pImpEditView->GetEditSelection().Min().GetNode() ); - aSelection.nEndPara = pImpEditView->pEditEngine->GetEditDoc().GetPos( pImpEditView->GetEditSelection().Max().GetNode() ); + aSelection.nStartPara = getEditEngine().GetEditDoc().GetPos( getImpl().GetEditSelection().Min().GetNode() ); + aSelection.nEndPara = getEditEngine().GetEditDoc().GetPos( getImpl().GetEditSelection().Max().GetNode() ); - aSelection.nStartPos = pImpEditView->GetEditSelection().Min().GetIndex(); - aSelection.nEndPos = pImpEditView->GetEditSelection().Max().GetIndex(); + aSelection.nStartPos = getImpl().GetEditSelection().Min().GetIndex(); + aSelection.nEndPos = getImpl().GetEditSelection().Max().GetIndex(); return aSelection; } bool EditView::HasSelection() const { - return pImpEditView->HasSelection(); + return getImpl().HasSelection(); +} + +bool EditView::IsSelectionFullPara() const +{ + return getImpl().IsSelectionFullPara(); +} + +bool EditView::IsSelectionWithinSinglePara() const +{ + return getImpl().IsSelectionInSinglePara(); } bool EditView::IsSelectionAtPoint(const Point& rPointPixel) { - return pImpEditView->IsSelectionAtPoint(rPointPixel); + return getImpl().IsSelectionAtPoint(rPointPixel); } void EditView::DeleteSelected() { - pImpEditView->DeleteSelected(); + getImpl().DeleteSelected(); } SvtScriptType EditView::GetSelectedScriptType() const { - return pImpEditView->pEditEngine->GetScriptType( pImpEditView->GetEditSelection() ); + return getEditEngine().GetScriptType( getImpl().GetEditSelection() ); } void EditView::GetSelectionRectangles(std::vector<tools::Rectangle>& rLogicRects) const { - return pImpEditView->GetSelectionRectangles(pImpEditView->GetEditSelection(), rLogicRects); + return getImpl().GetSelectionRectangles(getImpl().GetEditSelection(), rLogicRects); } void EditView::Paint( const tools::Rectangle& rRect, OutputDevice* pTargetDevice ) { - pImpEditView->pEditEngine->pImpEditEngine->Paint( pImpEditView.get(), rRect, pTargetDevice ); + getImpEditEngine().Paint(&getImpl(), rRect, pTargetDevice); } -void EditView::SetEditEngine( EditEngine* pEditEng ) +void EditView::setEditEngine(EditEngine* pEditEngine) { - pImpEditView->pEditEngine = pEditEng; - EditSelection aStartSel = pImpEditView->pEditEngine->GetEditDoc().GetStartPaM(); - pImpEditView->SetEditSelection( aStartSel ); + assert(pEditEngine); + + getImpl().mpEditEngine = pEditEngine; + EditSelection aStartSel = getEditEngine().GetEditDoc().GetStartPaM(); + getImpl().SetEditSelection( aStartSel ); } -void EditView::SetWindow( vcl::Window* pWin ) +void EditView::SetWindow(vcl::Window* pWindow) { - pImpEditView->pOutWin = pWin; - pImpEditView->pEditEngine->pImpEditEngine->GetSelEngine().Reset(); + getImpl().mpOutputWindow = pWindow; + getImpEditEngine().GetSelEngine().Reset(); } vcl::Window* EditView::GetWindow() const { - return pImpEditView->pOutWin; + return getImpl().mpOutputWindow; } OutputDevice& EditView::GetOutputDevice() const { - return pImpEditView->GetOutputDevice(); + return getImpl().GetOutputDevice(); } LanguageType EditView::GetInputLanguage() const @@ -366,7 +395,7 @@ LanguageType EditView::GetInputLanguage() const bool EditView::HasOtherViewWindow( vcl::Window* pWin ) { - OutWindowSet& rOutWindowSet = pImpEditView->aOutWindowSet; + OutWindowSet& rOutWindowSet = getImpl().maOutWindowSet; auto found = std::find(rOutWindowSet.begin(), rOutWindowSet.end(), pWin); return (found != rOutWindowSet.end()); } @@ -375,13 +404,13 @@ bool EditView::AddOtherViewWindow( vcl::Window* pWin ) { if (HasOtherViewWindow(pWin)) return false; - pImpEditView->aOutWindowSet.emplace_back(pWin); + getImpl().maOutWindowSet.emplace_back(pWin); return true; } bool EditView::RemoveOtherViewWindow( vcl::Window* pWin ) { - OutWindowSet& rOutWindowSet = pImpEditView->aOutWindowSet; + OutWindowSet& rOutWindowSet = getImpl().maOutWindowSet; auto found = std::find(rOutWindowSet.begin(), rOutWindowSet.end(), pWin); if (found == rOutWindowSet.end()) return false; @@ -391,180 +420,180 @@ bool EditView::RemoveOtherViewWindow( vcl::Window* pWin ) void EditView::SetVisArea( const tools::Rectangle& rRect ) { - pImpEditView->SetVisDocStartPos( rRect.TopLeft() ); + getImpl().SetVisDocStartPos( rRect.TopLeft() ); } tools::Rectangle EditView::GetVisArea() const { - return pImpEditView->GetVisDocArea(); + return getImpl().GetVisDocArea(); } void EditView::SetOutputArea( const tools::Rectangle& rRect ) { - pImpEditView->SetOutputArea( rRect ); + getImpl().SetOutputArea( rRect ); // the rest here only if it is an API call: - pImpEditView->CalcAnchorPoint(); - if ( pImpEditView->pEditEngine->pImpEditEngine->GetStatus().AutoPageSize() ) - pImpEditView->RecalcOutputArea(); - pImpEditView->ShowCursor( false, false ); + getImpl().CalcAnchorPoint(); + if (getImpEditEngine().GetStatus().AutoPageSize() ) + getImpl().RecalcOutputArea(); + getImpl().ShowCursor( false, false ); } const tools::Rectangle& EditView::GetOutputArea() const { - return pImpEditView->GetOutputArea(); + return getImpl().GetOutputArea(); } PointerStyle EditView::GetPointer() const { - return pImpEditView->GetPointer(); + return getImpl().GetPointer(); } vcl::Cursor* EditView::GetCursor() const { - return pImpEditView->pCursor.get(); + return getImpl().GetCursor(); } void EditView::InsertText( const OUString& rStr, bool bSelect, bool bLOKShowSelect ) { - EditEngine* pEE = pImpEditView->pEditEngine; + EditEngine& rEditEngine = getEditEngine(); if (bLOKShowSelect) - pImpEditView->DrawSelectionXOR(); + getImpl().DrawSelectionXOR(); EditPaM aPaM1; if ( bSelect ) { - EditSelection aTmpSel( pImpEditView->GetEditSelection() ); - aTmpSel.Adjust( pEE->GetEditDoc() ); + EditSelection aTmpSel( getImpl().GetEditSelection() ); + aTmpSel.Adjust(rEditEngine.GetEditDoc()); aPaM1 = aTmpSel.Min(); } - pEE->UndoActionStart( EDITUNDO_INSERT ); - EditPaM aPaM2( pEE->InsertText( pImpEditView->GetEditSelection(), rStr ) ); - pEE->UndoActionEnd(); + rEditEngine.UndoActionStart( EDITUNDO_INSERT ); + EditPaM aPaM2(rEditEngine.InsertText( getImpl().GetEditSelection(), rStr ) ); + rEditEngine.UndoActionEnd(); if ( bSelect ) { - DBG_ASSERT( !aPaM1.DbgIsBuggy( pEE->GetEditDoc() ), "Insert: PaM broken" ); - pImpEditView->SetEditSelection( EditSelection( aPaM1, aPaM2 ) ); + DBG_ASSERT( !aPaM1.DbgIsBuggy(rEditEngine.GetEditDoc()), "Insert: PaM broken" ); + getImpl().SetEditSelection( EditSelection( aPaM1, aPaM2 ) ); } else - pImpEditView->SetEditSelection( EditSelection( aPaM2, aPaM2 ) ); + getImpl().SetEditSelection( EditSelection( aPaM2, aPaM2 ) ); if (bLOKShowSelect) - pEE->FormatAndLayout( this ); + rEditEngine.FormatAndLayout( this ); } bool EditView::PostKeyEvent( const KeyEvent& rKeyEvent, vcl::Window const * pFrameWin ) { - return pImpEditView->PostKeyEvent( rKeyEvent, pFrameWin ); + return getImpl().PostKeyEvent( rKeyEvent, pFrameWin ); } bool EditView::MouseButtonUp( const MouseEvent& rMouseEvent ) { - return pImpEditView->MouseButtonUp( rMouseEvent ); + return getImpl().MouseButtonUp( rMouseEvent ); } void EditView::ReleaseMouse() { - return pImpEditView->ReleaseMouse(); + return getImpl().ReleaseMouse(); } bool EditView::MouseButtonDown( const MouseEvent& rMouseEvent ) { - return pImpEditView->MouseButtonDown( rMouseEvent ); + return getImpl().MouseButtonDown( rMouseEvent ); } bool EditView::MouseMove( const MouseEvent& rMouseEvent ) { - return pImpEditView->MouseMove( rMouseEvent ); + return getImpl().MouseMove( rMouseEvent ); } bool EditView::Command(const CommandEvent& rCEvt) { - return pImpEditView->Command(rCEvt); + return getImpl().Command(rCEvt); } void EditView::SetBroadcastLOKViewCursor(bool bSet) { - pImpEditView->SetBroadcastLOKViewCursor(bSet); + getImpl().SetBroadcastLOKViewCursor(bSet); } tools::Rectangle EditView::GetEditCursor() const { - return pImpEditView->GetEditCursor(); + return getImpl().GetEditCursor(); } void EditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor, bool bActivate ) { - if ( !pImpEditView->pEditEngine->HasView( this ) ) + if (!getEditEngine().HasView(this)) return; // The control word is more important: - if ( !pImpEditView->DoAutoScroll() ) + if ( !getImpl().DoAutoScroll() ) bGotoCursor = false; - pImpEditView->ShowCursor( bGotoCursor, bForceVisCursor ); + getImpl().ShowCursor( bGotoCursor, bForceVisCursor ); - if (pImpEditView->mpViewShell && !bActivate) + if (getImpl().mpViewShell && !bActivate) { - if (!pImpEditView->pOutWin) + if (!getImpl().mpOutputWindow) return; - VclPtr<vcl::Window> pParent = pImpEditView->pOutWin->GetParentWithLOKNotifier(); + VclPtr<vcl::Window> pParent = getImpl().mpOutputWindow->GetParentWithLOKNotifier(); if (pParent && pParent->GetLOKWindowId() != 0) return; static const OString aPayload = OString::boolean(true); - pImpEditView->mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, aPayload.getStr()); - pImpEditView->mpViewShell->NotifyOtherViews(LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible", aPayload); + getImpl().mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, aPayload); + getImpl().mpViewShell->NotifyOtherViews(LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible"_ostr, aPayload); } } void EditView::HideCursor(bool bDeactivate) { - pImpEditView->GetCursor()->Hide(); + getImpl().GetCursor()->Hide(); - if (pImpEditView->mpViewShell && !bDeactivate) + if (getImpl().mpViewShell && !bDeactivate) { - if (!pImpEditView->pOutWin) + if (!getImpl().mpOutputWindow) return; - VclPtr<vcl::Window> pParent = pImpEditView->pOutWin->GetParentWithLOKNotifier(); + VclPtr<vcl::Window> pParent = getImpl().mpOutputWindow->GetParentWithLOKNotifier(); if (pParent && pParent->GetLOKWindowId() != 0) return; OString aPayload = OString::boolean(false); - pImpEditView->mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, aPayload.getStr()); - pImpEditView->mpViewShell->NotifyOtherViews(LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible", aPayload); + getImpl().mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, aPayload); + getImpl().mpViewShell->NotifyOtherViews(LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible"_ostr, aPayload); } } Pair EditView::Scroll( tools::Long ndX, tools::Long ndY, ScrollRangeCheck nRangeCheck ) { - return pImpEditView->Scroll( ndX, ndY, nRangeCheck ); + return getImpl().Scroll( ndX, ndY, nRangeCheck ); } const SfxItemSet& EditView::GetEmptyItemSet() const { - return pImpEditView->pEditEngine->GetEmptyItemSet(); + return getEditEngine().GetEmptyItemSet(); } void EditView::SetAttribs( const SfxItemSet& rSet ) { - DBG_ASSERT( !pImpEditView->aEditSelection.IsInvalid(), "Blind Selection in..." ); + DBG_ASSERT(!getImpl().maEditSelection.IsInvalid(), "Blind Selection in..."); - pImpEditView->DrawSelectionXOR(); - pImpEditView->pEditEngine->SetAttribs( pImpEditView->GetEditSelection(), rSet, SetAttribsMode::WholeWord ); - if (pImpEditView->pEditEngine->IsUpdateLayout()) - pImpEditView->pEditEngine->FormatAndLayout( this ); + getImpl().DrawSelectionXOR(); + getEditEngine().SetAttribs( getImpl().GetEditSelection(), rSet, SetAttribsMode::WholeWord ); + if (getEditEngine().IsUpdateLayout()) + getEditEngine().FormatAndLayout( this ); } void EditView::RemoveAttribsKeepLanguages( bool bRemoveParaAttribs ) { - pImpEditView->DrawSelectionXOR(); - pImpEditView->pEditEngine->UndoActionStart( EDITUNDO_RESETATTRIBS ); - EditSelection aSelection( pImpEditView->GetEditSelection() ); + getImpl().DrawSelectionXOR(); + getEditEngine().UndoActionStart( EDITUNDO_RESETATTRIBS ); + EditSelection aSelection( getImpl().GetEditSelection() ); for (sal_uInt16 nWID = EE_ITEMS_START; nWID <= EE_ITEMS_END; ++nWID) { @@ -572,12 +601,12 @@ void EditView::RemoveAttribsKeepLanguages( bool bRemoveParaAttribs ) EE_CHAR_LANGUAGE_CJK == nWID || EE_CHAR_LANGUAGE_CTL == nWID; if (!bIsLang) - pImpEditView->pEditEngine->RemoveCharAttribs( aSelection, bRemoveParaAttribs, nWID ); + getEditEngine().RemoveCharAttribs( aSelection, bRemoveParaAttribs, nWID ); } - pImpEditView->pEditEngine->UndoActionEnd(); - if (pImpEditView->pEditEngine->IsUpdateLayout()) - pImpEditView->pEditEngine->FormatAndLayout( this ); + getEditEngine().UndoActionEnd(); + if (getEditEngine().IsUpdateLayout()) + getEditEngine().FormatAndLayout( this ); } void EditView::RemoveAttribs( bool bRemoveParaAttribs, sal_uInt16 nWhich ) @@ -588,50 +617,50 @@ void EditView::RemoveAttribs( bool bRemoveParaAttribs, sal_uInt16 nWhich ) void EditView::RemoveAttribs( EERemoveParaAttribsMode eMode, sal_uInt16 nWhich ) { - pImpEditView->DrawSelectionXOR(); - pImpEditView->pEditEngine->UndoActionStart( EDITUNDO_RESETATTRIBS ); - pImpEditView->pEditEngine->RemoveCharAttribs( pImpEditView->GetEditSelection(), eMode, nWhich ); - pImpEditView->pEditEngine->UndoActionEnd(); - if (pImpEditView->pEditEngine->IsUpdateLayout()) - pImpEditView->pEditEngine->FormatAndLayout( this ); + getImpl().DrawSelectionXOR(); + getEditEngine().UndoActionStart( EDITUNDO_RESETATTRIBS ); + getEditEngine().RemoveCharAttribs( getImpl().GetEditSelection(), eMode, nWhich ); + getEditEngine().UndoActionEnd(); + if (getEditEngine().IsUpdateLayout()) + getEditEngine().FormatAndLayout( this ); } void EditView::RemoveCharAttribs( sal_Int32 nPara, sal_uInt16 nWhich ) { - pImpEditView->pEditEngine->UndoActionStart( EDITUNDO_RESETATTRIBS ); - pImpEditView->pEditEngine->RemoveCharAttribs( nPara, nWhich ); - pImpEditView->pEditEngine->UndoActionEnd(); - if (pImpEditView->pEditEngine->IsUpdateLayout()) - pImpEditView->pEditEngine->FormatAndLayout( this ); + getEditEngine().UndoActionStart( EDITUNDO_RESETATTRIBS ); + getEditEngine().RemoveCharAttribs( nPara, nWhich ); + getEditEngine().UndoActionEnd(); + if (getEditEngine().IsUpdateLayout()) + getEditEngine().FormatAndLayout( this ); } SfxItemSet EditView::GetAttribs() { - DBG_ASSERT( !pImpEditView->aEditSelection.IsInvalid(), "Blind Selection in..." ); - return pImpEditView->pEditEngine->pImpEditEngine->GetAttribs( pImpEditView->GetEditSelection() ); + DBG_ASSERT(!getImpl().maEditSelection.IsInvalid(), "Blind Selection in..."); + return getImpEditEngine().GetAttribs( getImpl().GetEditSelection() ); } void EditView::Undo() { - pImpEditView->pEditEngine->Undo( this ); + getEditEngine().Undo( this ); } void EditView::Redo() { - pImpEditView->pEditEngine->Redo( this ); + getEditEngine().Redo( this ); } ErrCode EditView::Read( SvStream& rInput, EETextFormat eFormat, SvKeyValueIterator* pHTTPHeaderAttrs ) { - EditSelection aOldSel( pImpEditView->GetEditSelection() ); - pImpEditView->DrawSelectionXOR(); - pImpEditView->pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_READ ); - EditPaM aEndPaM = pImpEditView->pEditEngine->pImpEditEngine->Read( rInput, "", eFormat, aOldSel, pHTTPHeaderAttrs ); - pImpEditView->pEditEngine->pImpEditEngine->UndoActionEnd(); + EditSelection aOldSel( getImpl().GetEditSelection() ); + getImpl().DrawSelectionXOR(); + getImpEditEngine().UndoActionStart( EDITUNDO_READ ); + EditPaM aEndPaM = getImpEditEngine().Read( rInput, "", eFormat, aOldSel, pHTTPHeaderAttrs ); + getImpEditEngine().UndoActionEnd(); EditSelection aNewSel( aEndPaM, aEndPaM ); - pImpEditView->SetEditSelection( aNewSel ); - bool bGotoCursor = pImpEditView->DoAutoScroll(); + getImpl().SetEditSelection( aNewSel ); + bool bGotoCursor = getImpl().DoAutoScroll(); ShowCursor( bGotoCursor ); return rInput.GetError(); @@ -640,158 +669,158 @@ ErrCode EditView::Read( SvStream& rInput, EETextFormat eFormat, SvKeyValueIterat void EditView::Cut() { Reference<css::datatransfer::clipboard::XClipboard> aClipBoard(GetClipboard()); - pImpEditView->CutCopy( aClipBoard, true ); + getImpl().CutCopy( aClipBoard, true ); } Reference<css::datatransfer::clipboard::XClipboard> EditView::GetClipboard() const { - return pImpEditView->GetClipboard(); + return getImpl().GetClipboard(); } css::uno::Reference< css::datatransfer::XTransferable > EditView::GetTransferable() const { - uno::Reference< datatransfer::XTransferable > xData = - GetEditEngine()->CreateTransferable( pImpEditView->GetEditSelection() ); + uno::Reference< datatransfer::XTransferable > xData = getEditEngine().CreateTransferable( getImpl().GetEditSelection() ); return xData; } void EditView::Copy() { Reference<css::datatransfer::clipboard::XClipboard> aClipBoard(GetClipboard()); - pImpEditView->CutCopy( aClipBoard, false ); + getImpl().CutCopy( aClipBoard, false ); } void EditView::Paste() { Reference<css::datatransfer::clipboard::XClipboard> aClipBoard(GetClipboard()); - pImpEditView->Paste( aClipBoard ); + getImpl().Paste( aClipBoard ); } -void EditView::PasteSpecial() +void EditView::PasteSpecial(SotClipboardFormatId format) { Reference<css::datatransfer::clipboard::XClipboard> aClipBoard(GetClipboard()); - pImpEditView->Paste(aClipBoard, true ); + getImpl().Paste(aClipBoard, true, format ); } Point EditView::GetWindowPosTopLeft( sal_Int32 nParagraph ) { - Point aDocPos( pImpEditView->pEditEngine->GetDocPosTopLeft( nParagraph ) ); - return pImpEditView->GetWindowPos( aDocPos ); + Point aDocPos(getEditEngine().GetDocPosTopLeft(nParagraph)); + return getImpl().GetWindowPos( aDocPos ); } void EditView::SetSelectionMode( EESelectionMode eMode ) { - pImpEditView->SetSelectionMode( eMode ); + getImpl().SetSelectionMode( eMode ); } OUString EditView::GetSelected() const { - return pImpEditView->pEditEngine->pImpEditEngine->GetSelected( pImpEditView->GetEditSelection() ); + return getImpEditEngine().GetSelected( getImpl().GetEditSelection() ); } void EditView::MoveParagraphs( Range aParagraphs, sal_Int32 nNewPos ) { - pImpEditView->pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_MOVEPARAS ); - pImpEditView->pEditEngine->pImpEditEngine->MoveParagraphs( aParagraphs, nNewPos, this ); - pImpEditView->pEditEngine->pImpEditEngine->UndoActionEnd(); + getImpEditEngine().UndoActionStart( EDITUNDO_MOVEPARAS ); + getImpEditEngine().MoveParagraphs( aParagraphs, nNewPos, this ); + getImpEditEngine().UndoActionEnd(); } void EditView::MoveParagraphs( tools::Long nDiff ) { ESelection aSel = GetSelection(); Range aRange( aSel.nStartPara, aSel.nEndPara ); - aRange.Justify(); + aRange.Normalize(); tools::Long nDest = ( nDiff > 0 ? aRange.Max() : aRange.Min() ) + nDiff; if ( nDiff > 0 ) nDest++; - DBG_ASSERT( ( nDest >= 0 ) && ( nDest <= pImpEditView->pEditEngine->GetParagraphCount() ), "MoveParagraphs - wrong Parameters!" ); + DBG_ASSERT( ( nDest >= 0 ) && ( nDest <= getEditEngine().GetParagraphCount() ), "MoveParagraphs - wrong Parameters!" ); MoveParagraphs( aRange, sal::static_int_cast< sal_Int32 >( nDest ) ); } void EditView::SetBackgroundColor( const Color& rColor ) { - pImpEditView->SetBackgroundColor( rColor ); + getImpl().SetBackgroundColor( rColor ); + getEditEngine().SetBackgroundColor( rColor ); } Color const & EditView::GetBackgroundColor() const { - return pImpEditView->GetBackgroundColor(); + return getImpl().GetBackgroundColor(); } void EditView::RegisterViewShell(OutlinerViewShell* pViewShell) { - pImpEditView->RegisterViewShell(pViewShell); + getImpl().RegisterViewShell(pViewShell); } void EditView::RegisterOtherShell(OutlinerViewShell* pOtherShell) { - pImpEditView->RegisterOtherShell(pOtherShell); + getImpl().RegisterOtherShell(pOtherShell); } void EditView::SetControlWord( EVControlBits nWord ) { - pImpEditView->nControl = nWord; + getImpl().mnControl = nWord; } EVControlBits EditView::GetControlWord() const { - return pImpEditView->nControl; + return getImpl().mnControl; } std::unique_ptr<EditTextObject> EditView::CreateTextObject() { - return pImpEditView->pEditEngine->pImpEditEngine->CreateTextObject( pImpEditView->GetEditSelection() ); + return getImpEditEngine().CreateTextObject( getImpl().GetEditSelection() ); } void EditView::InsertText( const EditTextObject& rTextObject ) { - pImpEditView->DrawSelectionXOR(); + getImpl().DrawSelectionXOR(); - pImpEditView->pEditEngine->UndoActionStart( EDITUNDO_INSERT ); - EditSelection aTextSel( pImpEditView->pEditEngine->InsertText( rTextObject, pImpEditView->GetEditSelection() ) ); - pImpEditView->pEditEngine->UndoActionEnd(); + getEditEngine().UndoActionStart( EDITUNDO_INSERT ); + EditSelection aTextSel(getEditEngine().InsertText(rTextObject, getImpl().GetEditSelection())); + getEditEngine().UndoActionEnd(); aTextSel.Min() = aTextSel.Max(); // Selection not retained. - pImpEditView->SetEditSelection( aTextSel ); - if (pImpEditView->pEditEngine->IsUpdateLayout()) - pImpEditView->pEditEngine->FormatAndLayout( this ); + getImpl().SetEditSelection( aTextSel ); + if (getEditEngine().IsUpdateLayout()) + getEditEngine().FormatAndLayout( this ); } void EditView::InsertText( css::uno::Reference< css::datatransfer::XTransferable > const & xDataObj, const OUString& rBaseURL, bool bUseSpecial ) { - pImpEditView->pEditEngine->UndoActionStart( EDITUNDO_INSERT ); - pImpEditView->DeleteSelected(); + getEditEngine().UndoActionStart( EDITUNDO_INSERT ); + getImpl().DeleteSelected(); EditSelection aTextSel = - pImpEditView->pEditEngine->InsertText(xDataObj, rBaseURL, pImpEditView->GetEditSelection().Max(), bUseSpecial); - pImpEditView->pEditEngine->UndoActionEnd(); + getEditEngine().InsertText(xDataObj, rBaseURL, getImpl().GetEditSelection().Max(), bUseSpecial); + getEditEngine().UndoActionEnd(); aTextSel.Min() = aTextSel.Max(); // Selection not retained. - pImpEditView->SetEditSelection( aTextSel ); - if (pImpEditView->pEditEngine->IsUpdateLayout()) - pImpEditView->pEditEngine->FormatAndLayout( this ); + getImpl().SetEditSelection( aTextSel ); + if (getEditEngine().IsUpdateLayout()) + getEditEngine().FormatAndLayout( this ); } bool EditView::SetEditEngineUpdateLayout( bool bUpdate ) { - return pImpEditView->pEditEngine->pImpEditEngine->SetUpdateLayout( bUpdate, this ); + return getImpEditEngine().SetUpdateLayout( bUpdate, this ); } void EditView::ForceLayoutCalculation() { - pImpEditView->pEditEngine->pImpEditEngine->SetUpdateLayout( true, this, true ); + getImpEditEngine().SetUpdateLayout( true, this, true ); } SfxStyleSheet* EditView::GetStyleSheet() { - EditSelection aSel( pImpEditView->GetEditSelection() ); - aSel.Adjust( pImpEditView->pEditEngine->GetEditDoc() ); - sal_Int32 nStartPara = pImpEditView->pEditEngine->GetEditDoc().GetPos( aSel.Min().GetNode() ); - sal_Int32 nEndPara = pImpEditView->pEditEngine->GetEditDoc().GetPos( aSel.Max().GetNode() ); + EditSelection aSel( getImpl().GetEditSelection() ); + aSel.Adjust(getEditEngine().GetEditDoc()); + sal_Int32 nStartPara = getEditEngine().GetEditDoc().GetPos( aSel.Min().GetNode() ); + sal_Int32 nEndPara = getEditEngine().GetEditDoc().GetPos( aSel.Max().GetNode() ); SfxStyleSheet* pStyle = nullptr; for ( sal_Int32 n = nStartPara; n <= nEndPara; n++ ) { - SfxStyleSheet* pTmpStyle = pImpEditView->pEditEngine->GetStyleSheet( n ); + SfxStyleSheet* pTmpStyle = getEditEngine().GetStyleSheet( n ); if ( ( n != nStartPara ) && ( pStyle != pTmpStyle ) ) return nullptr; // Not unique. pStyle = pTmpStyle; @@ -806,76 +835,76 @@ const SfxStyleSheet* EditView::GetStyleSheet() const bool EditView::IsInsertMode() const { - return pImpEditView->IsInsertMode(); + return getImpl().IsInsertMode(); } void EditView::SetInsertMode( bool bInsert ) { - pImpEditView->SetInsertMode( bInsert ); + getImpl().SetInsertMode( bInsert ); } void EditView::SetAnchorMode( EEAnchorMode eMode ) { - pImpEditView->SetAnchorMode( eMode ); + getImpl().SetAnchorMode( eMode ); } EEAnchorMode EditView::GetAnchorMode() const { - return pImpEditView->GetAnchorMode(); + return getImpl().GetAnchorMode(); } void EditView::TransliterateText( TransliterationFlags nTransliterationMode ) { - EditSelection aOldSel( pImpEditView->GetEditSelection() ); - EditSelection aNewSel = pImpEditView->pEditEngine->TransliterateText( pImpEditView->GetEditSelection(), nTransliterationMode ); + EditSelection aOldSel( getImpl().GetEditSelection() ); + EditSelection aNewSel = getEditEngine().TransliterateText( getImpl().GetEditSelection(), nTransliterationMode ); if ( aNewSel != aOldSel ) { - pImpEditView->DrawSelectionXOR(); - pImpEditView->SetEditSelection( aNewSel ); - pImpEditView->DrawSelectionXOR(); + getImpl().DrawSelectionXOR(); + getImpl().SetEditSelection( aNewSel ); + getImpl().DrawSelectionXOR(); } } void EditView::CompleteAutoCorrect( vcl::Window const * pFrameWin ) { - if ( !HasSelection() && pImpEditView->pEditEngine->pImpEditEngine->GetStatus().DoAutoCorrect() ) + if ( !HasSelection() && getImpEditEngine().GetStatus().DoAutoCorrect() ) { - pImpEditView->DrawSelectionXOR(); - EditSelection aSel = pImpEditView->GetEditSelection(); - aSel = pImpEditView->pEditEngine->EndOfWord( aSel.Max() ); - aSel = pImpEditView->pEditEngine->pImpEditEngine->AutoCorrect( aSel, 0, !IsInsertMode(), pFrameWin ); - pImpEditView->SetEditSelection( aSel ); - if ( pImpEditView->pEditEngine->IsModified() ) - pImpEditView->pEditEngine->FormatAndLayout( this ); + getImpl().DrawSelectionXOR(); + EditSelection aSel = getImpl().GetEditSelection(); + aSel = getEditEngine().EndOfWord( aSel.Max() ); + aSel = getImpEditEngine().AutoCorrect( aSel, 0, !IsInsertMode(), pFrameWin ); + getImpl().SetEditSelection( aSel ); + if (getEditEngine().IsModified()) + getEditEngine().FormatAndLayout( this ); } } EESpellState EditView::StartSpeller(weld::Widget* pDialogParent, bool bMultipleDoc) { - if ( !pImpEditView->pEditEngine->pImpEditEngine->GetSpeller().is() ) + if (!getImpEditEngine().GetSpeller().is()) return EESpellState::NoSpeller; - return pImpEditView->pEditEngine->pImpEditEngine->Spell(this, pDialogParent, bMultipleDoc); + return getImpEditEngine().Spell(this, pDialogParent, bMultipleDoc); } EESpellState EditView::StartThesaurus(weld::Widget* pDialogParent) { - if ( !pImpEditView->pEditEngine->pImpEditEngine->GetSpeller().is() ) + if (!getImpEditEngine().GetSpeller().is()) return EESpellState::NoSpeller; - return pImpEditView->pEditEngine->pImpEditEngine->StartThesaurus(this, pDialogParent); + return getImpEditEngine().StartThesaurus(this, pDialogParent); } void EditView::StartTextConversion(weld::Widget* pDialogParent, LanguageType nSrcLang, LanguageType nDestLang, const vcl::Font *pDestFont, sal_Int32 nOptions, bool bIsInteractive, bool bMultipleDoc ) { - pImpEditView->pEditEngine->pImpEditEngine->Convert(this, pDialogParent, nSrcLang, nDestLang, pDestFont, nOptions, bIsInteractive, bMultipleDoc); + getImpEditEngine().Convert(this, pDialogParent, nSrcLang, nDestLang, pDestFont, nOptions, bIsInteractive, bMultipleDoc); } sal_Int32 EditView::StartSearchAndReplace( const SvxSearchItem& rSearchItem ) { - return pImpEditView->pEditEngine->pImpEditEngine->StartSearchAndReplace( this, rSearchItem ); + return getImpEditEngine().StartSearchAndReplace( this, rSearchItem ); } bool EditView::IsCursorAtWrongSpelledWord() @@ -883,18 +912,18 @@ bool EditView::IsCursorAtWrongSpelledWord() bool bIsWrong = false; if ( !HasSelection() ) { - EditPaM aPaM = pImpEditView->GetEditSelection().Max(); - bIsWrong = pImpEditView->IsWrongSpelledWord( aPaM, false/*bMarkIfWrong*/ ); + EditPaM aPaM = getImpl().GetEditSelection().Max(); + bIsWrong = getImpl().IsWrongSpelledWord( aPaM, false/*bMarkIfWrong*/ ); } return bIsWrong; } bool EditView::IsWrongSpelledWordAtPos( const Point& rPosPixel, bool bMarkIfWrong ) { - Point aPos(pImpEditView->GetOutputDevice().PixelToLogic(rPosPixel)); - aPos = pImpEditView->GetDocPos( aPos ); - EditPaM aPaM = pImpEditView->pEditEngine->GetPaM(aPos, false); - return pImpEditView->IsWrongSpelledWord( aPaM , bMarkIfWrong ); + Point aPos(getImpl().GetOutputDevice().PixelToLogic(rPosPixel)); + aPos = getImpl().GetDocPos( aPos ); + EditPaM aPaM = getEditEngine().GetPaM(aPos, false); + return getImpl().IsWrongSpelledWord( aPaM , bMarkIfWrong ); } static void LOKSendSpellPopupMenu(const weld::Menu& rMenu, LanguageType nGuessLangWord, @@ -915,7 +944,7 @@ static void LOKSendSpellPopupMenu(const weld::Menu& rMenu, LanguageType nGuessLa { for(int i = 0; i < nSuggestions; ++i) { - OString sItemId = OString::number(MN_ALTSTART + i); + OUString sItemId = OUString::number(MN_ALTSTART + i); OUString sText = rMenu.get_label(sItemId); aItemTree.put("text", sText.toUtf8().getStr()); aItemTree.put("type", "command"); @@ -967,28 +996,28 @@ static void LOKSendSpellPopupMenu(const weld::Menu& rMenu, LanguageType nGuessLa std::stringstream aStream; boost::property_tree::write_json(aStream, aRoot, true); - pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CONTEXT_MENU, aStream.str().c_str()); + pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CONTEXT_MENU, OString(aStream.str())); } -void EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbackInfo&,void> &rCallBack) +bool EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbackInfo&,void> &rCallBack) { - OutputDevice& rDevice = pImpEditView->GetOutputDevice(); + OutputDevice& rDevice = getImpl().GetOutputDevice(); Point aPos(rDevice.PixelToLogic(rPosPixel)); - aPos = pImpEditView->GetDocPos( aPos ); - EditPaM aPaM = pImpEditView->pEditEngine->GetPaM(aPos, false); - Reference< linguistic2::XSpellChecker1 > xSpeller( pImpEditView->pEditEngine->pImpEditEngine->GetSpeller() ); + aPos = getImpl().GetDocPos( aPos ); + EditPaM aPaM = getEditEngine().GetPaM(aPos, false); + Reference< linguistic2::XSpellChecker1 > xSpeller(getImpEditEngine().GetSpeller()); ESelection aOldSel = GetSelection(); - if ( !(xSpeller.is() && pImpEditView->IsWrongSpelledWord( aPaM, true )) ) - return; + if ( !(xSpeller.is() && getImpl().IsWrongSpelledWord( aPaM, true )) ) + return false; // PaMtoEditCursor returns Logical units - tools::Rectangle aTempRect = pImpEditView->pEditEngine->pImpEditEngine->PaMtoEditCursor( aPaM, GetCursorFlags::TextOnly ); + tools::Rectangle aTempRect = getImpEditEngine().PaMtoEditCursor(aPaM, CursorFlags{ .bTextOnly = true }); // GetWindowPos works in Logical units - aTempRect = pImpEditView->GetWindowPos(aTempRect); + aTempRect = getImpl().GetWindowPos(aTempRect); // Convert to pixels aTempRect = rDevice.LogicToPixel(aTempRect); - weld::Widget* pPopupParent = pImpEditView->GetPopupParent(aTempRect); + weld::Widget* pPopupParent = getImpl().GetPopupParent(aTempRect); std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(pPopupParent, "editeng/ui/spellmenu.ui")); std::unique_ptr<weld::Menu> xPopupMenu(xBuilder->weld_menu("editviewspellmenu")); std::unique_ptr<weld::Menu> xInsertMenu(xBuilder->weld_menu("insertmenu")); // add word to user-dictionaries @@ -1010,14 +1039,11 @@ void EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbac // than returning e.g. 16 suggestions and using only the // first 7. Thus we hand down the value to use to that // implementation here by providing an additional parameter. - Sequence< PropertyValue > aPropVals(1); - PropertyValue &rVal = aPropVals.getArray()[0]; - rVal.Name = UPN_MAX_NUMBER_OF_SUGGESTIONS; - rVal.Value <<= sal_Int16(7); + Sequence< PropertyValue > aPropVals { comphelper::makePropertyValue(UPN_MAX_NUMBER_OF_SUGGESTIONS, sal_Int16(7)) }; // Are there any replace suggestions? Reference< linguistic2::XSpellAlternatives > xSpellAlt = - xSpeller->spell( aSelected, static_cast<sal_uInt16>(pImpEditView->pEditEngine->pImpEditEngine->GetLanguage( aPaM2 )), aPropVals ); + xSpeller->spell( aSelected, static_cast<sal_uInt16>(getImpEditEngine().GetLanguage( aPaM2 ).nLang), aPropVals ); Reference< linguistic2::XLanguageGuessing > xLangGuesser( EditDLL::Get().GetGlobalData()->GetLanguageGuesser() ); @@ -1070,10 +1096,11 @@ void EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbac for ( sal_uInt16 nW = 0; nW < nWords; nW++ ) { OUString aAlternate( pAlt[nW] ); - xPopupMenu->append(OUString::number(MN_ALTSTART + nW), aAlternate); - xAutoMenu->append(OUString::number(MN_AUTOSTART + nW), aAlternate); + OUString sId(OUString::number(MN_ALTSTART + nW)); + xPopupMenu->insert(nW, sId, aAlternate, nullptr, nullptr, nullptr, TRISTATE_INDET); + xAutoMenu->append(sId, aAlternate); } - xPopupMenu->append_separator("separator2"); + xPopupMenu->insert_separator(nWords, "separator2"); } else { @@ -1097,7 +1124,7 @@ void EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbac aDics = xDicList->getDictionaries(); pDic = aDics.getConstArray(); - LanguageType nCheckedLanguage = pImpEditView->pEditEngine->pImpEditEngine->GetLanguage( aPaM2 ); + LanguageType nCheckedLanguage = getImpEditEngine().GetLanguage( aPaM2 ).nLang; sal_uInt16 nDicCount = static_cast<sal_uInt16>(aDics.getLength()); for (sal_uInt16 i = 0; i < nDicCount; i++) { @@ -1153,32 +1180,26 @@ void EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbac //because the loss of focus in the current editeng causes writer //annotations to save their contents, making the pContent of the //current EditPams invalid - EPaM aP = pImpEditView->pEditEngine->pImpEditEngine->CreateEPaM(aPaM); - EPaM aP2 = pImpEditView->pEditEngine->pImpEditEngine->CreateEPaM(aPaM2); + EPaM aP = getImpEditEngine().CreateEPaM(aPaM); + EPaM aP2 = getImpEditEngine().CreateEPaM(aPaM2); if (comphelper::LibreOfficeKit::isActive()) { xPopupMenu->remove("autocorrect"); xPopupMenu->remove("autocorrectdlg"); - // For mobile phones, send the context menu structure - const SfxViewShell* pViewShell = SfxViewShell::Current(); - if (pViewShell && pViewShell->isLOKMobilePhone()) - { - LOKSendSpellPopupMenu(*xPopupMenu, nGuessLangWord, nGuessLangPara, nWords); - return; - } - // note, there is special handling of this menu 'editviewspellmenu' by vcl's PopupMenu::ImplExecute + LOKSendSpellPopupMenu(*xPopupMenu, nGuessLangWord, nGuessLangPara, nWords); + return true; } - OString sId = xPopupMenu->popup_at_rect(pPopupParent, aTempRect); + OUString sId = xPopupMenu->popup_at_rect(pPopupParent, aTempRect); - aPaM2 = pImpEditView->pEditEngine->pImpEditEngine->CreateEditPaM(aP2); - aPaM = pImpEditView->pEditEngine->pImpEditEngine->CreateEditPaM(aP); + aPaM2 = getImpEditEngine().CreateEditPaM(aP2); + aPaM = getImpEditEngine().CreateEditPaM(aP); if (sId == "ignore") { - OUString aWord = pImpEditView->SpellIgnoreWord(); + OUString aWord = getImpl().SpellIgnoreWord(); SpellCallbackInfo aInf( SpellCallbackCommand::IGNOREWORD, aWord ); rCallBack.Call(aInf); SetSelection( aOldSel ); @@ -1188,7 +1209,7 @@ void EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbac LanguageType nLangToUse = (sId == "wordlanguage") ? nGuessLangWord : nGuessLangPara; SvtScriptType nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( nLangToUse ); - SfxItemSet aAttrs = GetEditEngine()->GetEmptyItemSet(); + SfxItemSet aAttrs = getEditEngine().GetEmptyItemSet(); if (nScriptType == SvtScriptType::LATIN) aAttrs.Put( SvxLanguageItem( nLangToUse, EE_CHAR_LANGUAGE ) ); if (nScriptType == SvtScriptType::COMPLEX) @@ -1203,7 +1224,7 @@ void EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbac SetSelection( aSel ); } SetAttribs( aAttrs ); - pImpEditView->pEditEngine->pImpEditEngine->StartOnlineSpellTimer(); + getImpEditEngine().StartOnlineSpellTimer(); SpellCallbackInfo aInf((sId == "wordlanguage") ? SpellCallbackCommand::WORDLANGUAGE : SpellCallbackCommand::PARALANGUAGE); rCallBack.Call(aInf); @@ -1224,6 +1245,7 @@ void EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbac OUString aDicName; if (sId.toInt32() >= MN_DICTSTART) { + assert(xInsertMenu && "this case only occurs when xInsertMenu exists"); // strip_mnemonic is necessary to retrieve the correct dictionary name aDicName = pPopupParent->strip_mnemonic(xInsertMenu->get_label(sId)); } @@ -1242,7 +1264,7 @@ void EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbac xSavDic->store(); aPaM.GetNode()->GetWrongList()->ResetInvalidRange(0, aPaM.GetNode()->Len()); - pImpEditView->pEditEngine->pImpEditEngine->StartOnlineSpellTimer(); + getImpEditEngine().StartOnlineSpellTimer(); SpellCallbackInfo aInf( SpellCallbackCommand::ADDTODICTIONARY, aSelected ); rCallBack.Call(aInf); @@ -1254,7 +1276,7 @@ void EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbac OUString aWord = pAlt[sId.toInt32() - MN_AUTOSTART]; SvxAutoCorrect* pAutoCorrect = SvxAutoCorrCfg::Get().GetAutoCorrect(); if ( pAutoCorrect ) - pAutoCorrect->PutText( aSelected, aWord, pImpEditView->pEditEngine->pImpEditEngine->GetLanguage( aPaM2 ) ); + pAutoCorrect->PutText( aSelected, aWord, getImpEditEngine().GetLanguage( aPaM2 ).nLang ); InsertText( aWord ); } else if ( sId.toInt32() >= MN_ALTSTART ) // Replace @@ -1267,45 +1289,46 @@ void EditView::ExecuteSpellPopup(const Point& rPosPixel, const Link<SpellCallbac { SetSelection( aOldSel ); } + return true; } OUString EditView::SpellIgnoreWord() { - return pImpEditView->SpellIgnoreWord(); + return getImpl().SpellIgnoreWord(); } void EditView::SelectCurrentWord( sal_Int16 nWordType ) { - EditSelection aCurSel( pImpEditView->GetEditSelection() ); - pImpEditView->DrawSelectionXOR(); - aCurSel = pImpEditView->pEditEngine->SelectWord(aCurSel.Max(), nWordType); - pImpEditView->SetEditSelection( aCurSel ); - pImpEditView->DrawSelectionXOR(); + EditSelection aCurSel( getImpl().GetEditSelection() ); + getImpl().DrawSelectionXOR(); + aCurSel = getEditEngine().SelectWord(aCurSel.Max(), nWordType); + getImpl().SetEditSelection( aCurSel ); + getImpl().DrawSelectionXOR(); ShowCursor( true, false ); } void EditView::InsertParaBreak() { - pImpEditView->pEditEngine->UndoActionStart(EDITUNDO_INSERT); - pImpEditView->DeleteSelected(); - EditPaM aPaM(pImpEditView->pEditEngine->InsertParaBreak(pImpEditView->GetEditSelection())); - pImpEditView->pEditEngine->UndoActionEnd(); - pImpEditView->SetEditSelection(EditSelection(aPaM, aPaM)); - if (pImpEditView->pEditEngine->IsUpdateLayout()) - pImpEditView->pEditEngine->FormatAndLayout(this); + getEditEngine().UndoActionStart(EDITUNDO_INSERT); + getImpl().DeleteSelected(); + EditPaM aPaM(getEditEngine().InsertParaBreak(getImpl().GetEditSelection())); + getEditEngine().UndoActionEnd(); + getImpl().SetEditSelection(EditSelection(aPaM, aPaM)); + if (getEditEngine().IsUpdateLayout()) + getEditEngine().FormatAndLayout(this); } void EditView::InsertField( const SvxFieldItem& rFld ) { - EditEngine* pEE = pImpEditView->pEditEngine; - pImpEditView->DrawSelectionXOR(); - pEE->UndoActionStart( EDITUNDO_INSERT ); - EditPaM aPaM( pEE->InsertField( pImpEditView->GetEditSelection(), rFld ) ); - pEE->UndoActionEnd(); - pImpEditView->SetEditSelection( EditSelection( aPaM, aPaM ) ); - pEE->UpdateFields(); - if (pImpEditView->pEditEngine->IsUpdateLayout()) - pEE->FormatAndLayout( this ); + EditEngine& rEditEngine = getImpl().getEditEngine(); + getImpl().DrawSelectionXOR(); + rEditEngine.UndoActionStart( EDITUNDO_INSERT ); + EditPaM aPaM(rEditEngine.InsertField(getImpl().GetEditSelection(), rFld)); + rEditEngine.UndoActionEnd(); + getImpl().SetEditSelection( EditSelection( aPaM, aPaM ) ); + rEditEngine.UpdateFields(); + if (rEditEngine.IsUpdateLayout()) + rEditEngine.FormatAndLayout( this ); } const SvxFieldItem* EditView::GetFieldUnderMousePointer() const @@ -1317,90 +1340,161 @@ const SvxFieldItem* EditView::GetFieldUnderMousePointer() const const SvxFieldItem* EditView::GetField( const Point& rPos, sal_Int32* pPara, sal_Int32* pPos ) const { - return pImpEditView->GetField( rPos, pPara, pPos ); + return getImpl().GetField( rPos, pPara, pPos ); } const SvxFieldItem* EditView::GetFieldUnderMousePointer( sal_Int32& nPara, sal_Int32& nPos ) const { Point aPos; - if (EditViewCallbacks* pEditViewCallbacks = pImpEditView->getEditViewCallbacks()) + if (EditViewCallbacks* pEditViewCallbacks = getImpl().getEditViewCallbacks()) aPos = pEditViewCallbacks->EditViewPointerPosPixel(); else - aPos = pImpEditView->GetWindow()->GetPointerPosPixel(); - OutputDevice& rDevice = pImpEditView->GetOutputDevice(); + aPos = getImpl().GetWindow()->GetPointerPosPixel(); + OutputDevice& rDevice = getImpl().GetOutputDevice(); aPos = rDevice.PixelToLogic(aPos); return GetField( aPos, &nPara, &nPos ); } -const SvxFieldItem* EditView::GetFieldAtSelection() const +const SvxFieldItem* EditView::GetFieldAtSelection(bool bAlsoCheckBeforeCursor) const +{ + bool* pIsBeforeCursor = bAlsoCheckBeforeCursor ? &bAlsoCheckBeforeCursor : nullptr; + return GetFieldAtSelection(pIsBeforeCursor); +} + +// If pIsBeforeCursor != nullptr, the position before the cursor will also be checked for a field +// and pIsBeforeCursor will return true if that fallback field is returned. +// If no field is returned, the value in pIsBeforeCursor is meaningless. +const SvxFieldItem* EditView::GetFieldAtSelection(bool* pIsBeforeCursor) const { - EditSelection aSel( pImpEditView->GetEditSelection() ); - aSel.Adjust( pImpEditView->pEditEngine->GetEditDoc() ); + // a field is a dummy character - so it cannot span nodes or be a selection larger than 1 + EditSelection aSel( getImpl().GetEditSelection() ); + if (aSel.Min().GetNode() != aSel.Max().GetNode()) + return nullptr; + + // normalize: min < max + aSel.Adjust(getEditEngine().GetEditDoc()); + + const sal_Int32 nMinIndex = aSel.Min().GetIndex(); + const sal_Int32 nMaxIndex = aSel.Max().GetIndex(); + if (nMaxIndex > nMinIndex + 1) + return nullptr; + // Only when cursor is in font of field, no selection, // or only selecting field - if ( ( aSel.Min().GetNode() == aSel.Max().GetNode() ) && - ( ( aSel.Max().GetIndex() == aSel.Min().GetIndex() ) || - ( aSel.Max().GetIndex() == aSel.Min().GetIndex()+1 ) ) ) + bool bAlsoCheckBeforeCursor = false; + if (pIsBeforeCursor) { - EditPaM aPaM = aSel.Min(); - const CharAttribList::AttribsType& rAttrs = aPaM.GetNode()->GetCharAttribs().GetAttribs(); - const sal_Int32 nXPos = aPaM.GetIndex(); - for (size_t nAttr = rAttrs.size(); nAttr; ) + *pIsBeforeCursor = false; + bAlsoCheckBeforeCursor = nMaxIndex == nMinIndex; + } + const SvxFieldItem* pFoundBeforeCursor = nullptr; + const CharAttribList::AttribsType& rAttrs = aSel.Min().GetNode()->GetCharAttribs().GetAttribs(); + for (const auto& rAttr: rAttrs) + { + if (rAttr->Which() == EE_FEATURE_FIELD) { - const EditCharAttrib& rAttr = *rAttrs[--nAttr]; - if (rAttr.GetStart() == nXPos) - if (rAttr.Which() == EE_FEATURE_FIELD) - { - DBG_ASSERT(dynamic_cast<const SvxFieldItem* >(rAttr.GetItem() ) != nullptr, "No FieldItem..."); - return static_cast<const SvxFieldItem*>(rAttr.GetItem()); - } + DBG_ASSERT(dynamic_cast<const SvxFieldItem*>(rAttr->GetItem()), "No FieldItem..."); + if (rAttr->GetStart() == nMinIndex) + return static_cast<const SvxFieldItem*>(rAttr->GetItem()); + + // perhaps the cursor is behind the field? + if (nMinIndex && rAttr->GetStart() == nMinIndex - 1) + pFoundBeforeCursor = static_cast<const SvxFieldItem*>(rAttr->GetItem()); } } + if (bAlsoCheckBeforeCursor) + { + *pIsBeforeCursor = /*(bool)*/pFoundBeforeCursor; + return pFoundBeforeCursor; + } return nullptr; } void EditView::SelectFieldAtCursor() { - const SvxFieldItem* pFieldItem = GetFieldAtSelection(); - if (pFieldItem) + bool bIsBeforeCursor = false; + const SvxFieldItem* pFieldItem = GetFieldAtSelection(&bIsBeforeCursor); + if (!pFieldItem) + return; + + // Make sure the whole field is selected + // A field is represented by a dummy character - so it cannot be a selection larger than 1 + ESelection aSel = GetSelection(); + if (aSel.nStartPos == aSel.nEndPos) // not yet selected { - // Make sure the whole field is selected - ESelection aSel = GetSelection(); - if (aSel.nStartPos == aSel.nEndPos) + if (bIsBeforeCursor) { - aSel.nEndPos++; - SetSelection(aSel); + assert (aSel.nStartPos); + --aSel.nStartPos; } + else + aSel.nEndPos++; + SetSelection(aSel); } + else + assert(std::abs(aSel.nStartPos - aSel.nEndPos) == 1); +} + +const SvxFieldData* EditView::GetFieldUnderMouseOrInSelectionOrAtCursor(bool bAlsoCheckBeforeCursor) const +{ + const SvxFieldItem* pFieldItem = GetFieldUnderMousePointer(); if (!pFieldItem) + pFieldItem = GetFieldAtSelection(bAlsoCheckBeforeCursor); + + return pFieldItem ? pFieldItem->GetField() : nullptr; +} + +sal_Int32 EditView::countFieldsOffsetSum(sal_Int32 nPara, sal_Int32 nPos, bool bCanOverflow) const +{ + int nOffset = 0; + + for (int nCurrentPara = 0; nCurrentPara <= nPara; nCurrentPara++) { - // Cursor probably behind the field - extend selection to select the field - ESelection aSel = GetSelection(); - if (aSel.nStartPos > 0 && aSel.nStartPos == aSel.nEndPos) + int nFields = getEditEngine().GetFieldCount( nCurrentPara ); + for (int nField = 0; nField < nFields; nField++) { - aSel.nStartPos--; - SetSelection(aSel); + EFieldInfo aFieldInfo = getEditEngine().GetFieldInfo( nCurrentPara, nField ); + + bool bLastPara = nCurrentPara == nPara; + sal_Int32 nFieldPos = aFieldInfo.aPosition.nIndex; + + if (bLastPara && nFieldPos >= nPos) + break; + + sal_Int32 nFieldLen = aFieldInfo.aCurrentText.getLength(); + + // position in the middle of a field + if (!bCanOverflow && bLastPara && nFieldPos + nFieldLen > nPos) + nFieldLen = nPos - nFieldPos; + + nOffset += nFieldLen - 1; } } + + return nOffset; } -const SvxFieldData* EditView::GetFieldAtCursor() const +sal_Int32 EditView::GetPosNoField(sal_Int32 nPara, sal_Int32 nPos) const { - const SvxFieldItem* pFieldItem = GetFieldUnderMousePointer(); - if (!pFieldItem) - pFieldItem = GetFieldAtSelection(); + sal_Int32 nOffset = countFieldsOffsetSum(nPara, nPos, false); + assert(nPos >= nOffset); + return nPos - nOffset; +} - return pFieldItem ? pFieldItem->GetField() : nullptr; +sal_Int32 EditView::GetPosWithField(sal_Int32 nPara, sal_Int32 nPos) const +{ + sal_Int32 nOffset = countFieldsOffsetSum(nPara, nPos, true); + return nPos + nOffset; } void EditView::SetInvalidateMore( sal_uInt16 nPixel ) { - pImpEditView->SetInvalidateMore( nPixel ); + getImpl().SetInvalidateMore( nPixel ); } sal_uInt16 EditView::GetInvalidateMore() const { - return pImpEditView->GetInvalidateMore(); + return getImpl().GetInvalidateMore(); } static void ChangeFontSizeImpl( EditView* pEditView, bool bGrow, const ESelection& rSel, const FontList* pFontList ) @@ -1421,7 +1515,7 @@ static void ChangeFontSizeImpl( EditView* pEditView, bool bGrow, const ESelectio void EditView::ChangeFontSize( bool bGrow, const FontList* pFontList ) { - EditEngine& rEditEngine = *pImpEditView->pEditEngine; + EditEngine& rEditEngine = getEditEngine(); ESelection aSel( GetSelection() ); ESelection aOldSelection( aSel ); @@ -1556,12 +1650,12 @@ bool EditView::ChangeFontSize( bool bGrow, SfxItemSet& rSet, const FontList* pFo OUString EditView::GetSurroundingText() const { - EditSelection aSel( pImpEditView->GetEditSelection() ); - aSel.Adjust( pImpEditView->pEditEngine->GetEditDoc() ); + EditSelection aSel( getImpl().GetEditSelection() ); + aSel.Adjust(getEditEngine().GetEditDoc()); if( HasSelection() ) { - OUString aStr = pImpEditView->pEditEngine->GetSelected(aSel); + OUString aStr = getEditEngine().GetSelected(aSel); // Stop reconversion if the selected text includes a line break. if ( aStr.indexOf( 0x0A ) == -1 ) @@ -1573,7 +1667,7 @@ OUString EditView::GetSurroundingText() const { aSel.Min().SetIndex( 0 ); aSel.Max().SetIndex( aSel.Max().GetNode()->Len() ); - return pImpEditView->pEditEngine->GetSelected(aSel); + return getEditEngine().GetSelected(aSel); } } @@ -1584,9 +1678,9 @@ Selection EditView::GetSurroundingTextSelection() const if( HasSelection() ) { - EditSelection aSel( pImpEditView->GetEditSelection() ); - aSel.Adjust( pImpEditView->pEditEngine->GetEditDoc() ); - OUString aStr = pImpEditView->pEditEngine->GetSelected(aSel); + EditSelection aSel( getImpl().GetEditSelection() ); + aSel.Adjust(getEditEngine().GetEditDoc()); + OUString aStr = getEditEngine().GetSelected(aSel); // Stop reconversion if the selected text includes a line break. if ( aStr.indexOf( 0x0A ) == -1 ) @@ -1613,79 +1707,99 @@ bool EditView::DeleteSurroundingText(const Selection& rRange) void EditView::SetCursorLogicPosition(const Point& rPosition, bool bPoint, bool bClearMark) { - Point aDocPos(pImpEditView->GetDocPos(rPosition)); - EditPaM aPaM = pImpEditView->pEditEngine->GetPaM(aDocPos); - EditSelection aSelection(pImpEditView->GetEditSelection()); + Point aDocPos(getImpl().GetDocPos(rPosition)); + EditPaM aPaM = getEditEngine().GetPaM(aDocPos); + EditSelection aSelection(getImpl().GetEditSelection()); // Explicitly create or delete the selection. if (bClearMark) { - pImpEditView->DeselectAll(); - aSelection = pImpEditView->GetEditSelection(); + getImpl().DeselectAll(); + aSelection = getImpl().GetEditSelection(); } else - pImpEditView->CreateAnchor(); + getImpl().CreateAnchor(); if (bPoint) aSelection.Max() = aPaM; else aSelection.Min() = aPaM; - if (pImpEditView->GetEditSelection().Min() != aSelection.Min()) - pImpEditView->pEditEngine->CursorMoved(pImpEditView->GetEditSelection().Min().GetNode()); - pImpEditView->DrawSelectionXOR(aSelection); - if (pImpEditView->GetEditSelection() != aSelection) - pImpEditView->SetEditSelection(aSelection); + if (getImpl().GetEditSelection().Min() != aSelection.Min()) + { + const ContentNode* pNode(getImpl().GetEditSelection().Min().GetNode()); + if (nullptr != pNode) + pNode->checkAndDeleteEmptyAttribs(); + } + + getImpl().DrawSelectionXOR(aSelection); + if (getImpl().GetEditSelection() != aSelection) + getImpl().SetEditSelection(aSelection); ShowCursor(/*bGotoCursor=*/false); } void EditView::DrawSelectionXOR(OutlinerViewShell* pOtherShell) { - pImpEditView->RegisterOtherShell(pOtherShell); - pImpEditView->DrawSelectionXOR(); - pImpEditView->RegisterOtherShell(nullptr); + getImpl().RegisterOtherShell(pOtherShell); + getImpl().DrawSelectionXOR(); + getImpl().RegisterOtherShell(nullptr); } void EditView::InitLOKSpecialPositioning(MapUnit eUnit, const tools::Rectangle& rOutputArea, const Point& rVisDocStartPos) { - pImpEditView->InitLOKSpecialPositioning(eUnit, rOutputArea, rVisDocStartPos); + getImpl().InitLOKSpecialPositioning(eUnit, rOutputArea, rVisDocStartPos); } void EditView::SetLOKSpecialOutputArea(const tools::Rectangle& rOutputArea) { - pImpEditView->SetLOKSpecialOutputArea(rOutputArea); + getImpl().SetLOKSpecialOutputArea(rOutputArea); } const tools::Rectangle & EditView::GetLOKSpecialOutputArea() const { - return pImpEditView->GetLOKSpecialOutputArea(); + return getImpl().GetLOKSpecialOutputArea(); } void EditView::SetLOKSpecialVisArea(const tools::Rectangle& rVisArea) { - pImpEditView->SetLOKSpecialVisArea(rVisArea); + getImpl().SetLOKSpecialVisArea(rVisArea); } tools::Rectangle EditView::GetLOKSpecialVisArea() const { - return pImpEditView->GetLOKSpecialVisArea(); + return getImpl().GetLOKSpecialVisArea(); } bool EditView::HasLOKSpecialPositioning() const { - return pImpEditView->HasLOKSpecialPositioning(); + return getImpl().HasLOKSpecialPositioning(); +} + +void EditView::SetLOKSpecialFlags(LOKSpecialFlags eFlags) +{ + getImpl().SetLOKSpecialFlags(eFlags); } void EditView::SuppressLOKMessages(bool bSet) { - pImpEditView->SuppressLOKMessages(bSet); + getImpl().SuppressLOKMessages(bSet); } bool EditView::IsSuppressLOKMessages() const { - return pImpEditView->IsSuppressLOKMessages(); + return getImpl().IsSuppressLOKMessages(); +} + +void EditView::SetNegativeX(bool bSet) +{ + getImpl().SetNegativeX(bSet); +} + +bool EditView::IsNegativeX() const +{ + return getImpl().IsNegativeX(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/edtspell.cxx b/editeng/source/editeng/edtspell.cxx index 5ff6beb29b8f..b989755d8be4 100644 --- a/editeng/source/editeng/edtspell.cxx +++ b/editeng/source/editeng/edtspell.cxx @@ -32,7 +32,6 @@ #include <com/sun/star/linguistic2/XDictionary.hpp> using namespace com::sun::star::uno; -using namespace com::sun::star::beans; using namespace com::sun::star::linguistic2; @@ -49,9 +48,9 @@ EditSpellWrapper::EditSpellWrapper(weld::Widget* pWindow, void EditSpellWrapper::SpellStart( SvxSpellArea eArea ) { - EditEngine* pEE = pEditView->GetEditEngine(); - ImpEditEngine* pImpEE = pEditView->GetImpEditEngine(); - SpellInfo* pSpellInfo = pImpEE->GetSpellInfo(); + EditEngine& rEditEngine = pEditView->getEditEngine(); + ImpEditEngine& rImpEditEngine = pEditView->getImpEditEngine(); + SpellInfo* pSpellInfo = rImpEditEngine.GetSpellInfo(); if ( eArea == SvxSpellArea::BodyStart ) { @@ -62,14 +61,13 @@ void EditSpellWrapper::SpellStart( SvxSpellArea eArea ) { pSpellInfo->bSpellToEnd = false; pSpellInfo->aSpellTo = pSpellInfo->aSpellStart; - pEditView->GetImpEditView()->SetEditSelection( - pEE->GetEditDoc().GetStartPaM() ); + pEditView->getImpl().SetEditSelection(rEditEngine.GetEditDoc().GetStartPaM()); } else { pSpellInfo->bSpellToEnd = true; - pSpellInfo->aSpellTo = pImpEE->CreateEPaM( - pEE->GetEditDoc().GetStartPaM() ); + pSpellInfo->aSpellTo = rImpEditEngine.CreateEPaM( + rEditEngine.GetEditDoc().GetStartPaM() ); } } else if ( eArea == SvxSpellArea::BodyEnd ) @@ -80,15 +78,14 @@ void EditSpellWrapper::SpellStart( SvxSpellArea eArea ) if ( !IsStartDone() ) { pSpellInfo->bSpellToEnd = true; - pSpellInfo->aSpellTo = pImpEE->CreateEPaM( - pEE->GetEditDoc().GetEndPaM() ); + pSpellInfo->aSpellTo = rImpEditEngine.CreateEPaM( + rEditEngine.GetEditDoc().GetEndPaM() ); } else { pSpellInfo->bSpellToEnd = false; pSpellInfo->aSpellTo = pSpellInfo->aSpellStart; - pEditView->GetImpEditView()->SetEditSelection( - pEE->GetEditDoc().GetEndPaM() ); + pEditView->getImpl().SetEditSelection(rEditEngine.GetEditDoc().GetEndPaM()); } } else if ( eArea == SvxSpellArea::Body ) @@ -103,24 +100,23 @@ void EditSpellWrapper::SpellStart( SvxSpellArea eArea ) void EditSpellWrapper::SpellContinue() { - SetLast( pEditView->GetImpEditEngine()->ImpSpell( pEditView ) ); + SetLast(pEditView->getImpEditEngine().ImpSpell(pEditView)); } bool EditSpellWrapper::SpellMore() { - EditEngine* pEE = pEditView->GetEditEngine(); - ImpEditEngine* pImpEE = pEditView->GetImpEditEngine(); - SpellInfo* pSpellInfo = pImpEE->GetSpellInfo(); + EditEngine& rEditEngine = pEditView->getEditEngine(); + ImpEditEngine& rImpEditEngine = pEditView->getImpEditEngine(); + SpellInfo* pSpellInfo = rImpEditEngine.GetSpellInfo(); bool bMore = false; if ( pSpellInfo->bMultipleDoc ) { - bMore = pEE->SpellNextDocument(); + bMore = rEditEngine.SpellNextDocument(); if ( bMore ) { // The text has been entered into the engine, when backwards then // it must be behind the selection. - pEditView->GetImpEditView()->SetEditSelection( - pEE->GetEditDoc().GetStartPaM() ); + pEditView->getImpl().SetEditSelection(rEditEngine.GetEditDoc().GetStartPaM()); } } return bMore; @@ -135,10 +131,10 @@ void EditSpellWrapper::ReplaceAll( const OUString &rNewText ) void EditSpellWrapper::CheckSpellTo() { - ImpEditEngine* pImpEE = pEditView->GetImpEditEngine(); - SpellInfo* pSpellInfo = pImpEE->GetSpellInfo(); - EditPaM aPaM( pEditView->GetImpEditView()->GetEditSelection().Max() ); - EPaM aEPaM = pImpEE->CreateEPaM( aPaM ); + ImpEditEngine& rImpEditEngine = pEditView->getImpEditEngine(); + SpellInfo* pSpellInfo = rImpEditEngine.GetSpellInfo(); + EditPaM aPaM( pEditView->getImpl().GetEditSelection().Max() ); + EPaM aEPaM = rImpEditEngine.CreateEPaM( aPaM ); if ( aEPaM.nPara == pSpellInfo->aSpellTo.nPara ) { // Check if SpellToEnd still has a valid Index, if replace has been @@ -572,7 +568,7 @@ void EdtAutoCorrDoc::SetAttr(sal_Int32 nStt, sal_Int32 nEnd, pPool = pPool->GetSecondaryPool(); } - sal_uInt16 nWhich = pPool->GetWhich( nSlotId ); + sal_uInt16 nWhich = pPool->GetWhichIDFromSlotID( nSlotId ); if ( nWhich ) { rItem.SetWhich( nWhich ); @@ -613,8 +609,8 @@ OUString const* EdtAutoCorrDoc::GetPrevPara(bool const) bAllowUndoAction = false; // Not anymore ... - EditDoc& rNodes = mpEditEngine->GetEditDoc(); - sal_Int32 nPos = rNodes.GetPos( pCurNode ); + EditDoc& rEditDoc = mpEditEngine->GetEditDoc(); + sal_Int32 nPos = rEditDoc.GetPos( pCurNode ); // Special case: Bullet => Paragraph start => simply return NULL... const SfxBoolItem& rBulletState = mpEditEngine->GetParaAttrib( nPos, EE_PARA_BULLETSTATE ); @@ -632,7 +628,7 @@ OUString const* EdtAutoCorrDoc::GetPrevPara(bool const) for ( sal_Int32 n = nPos; n; ) { n--; - ContentNode* pNode = rNodes[n]; + ContentNode* pNode = rEditDoc.GetObject(n); if ( pNode->Len() ) return & pNode->GetString(); } @@ -654,7 +650,7 @@ bool EdtAutoCorrDoc::ChgAutoCorrWord( sal_Int32& rSttPos, if( aShort.isEmpty() ) return bRet; - LanguageTag aLanguageTag( mpEditEngine->GetLanguage( EditPaM( pCurNode, rSttPos+1 ) )); + LanguageTag aLanguageTag( mpEditEngine->GetLanguage( EditPaM( pCurNode, rSttPos+1 ) ).nLang ); const SvxAutocorrWord* pFnd = rACorrect.SearchWordsInList( pCurNode->GetString(), rSttPos, nEndPos, *this, aLanguageTag); if( pFnd && pFnd->IsTextOnly() ) @@ -693,7 +689,7 @@ bool EdtAutoCorrDoc::TransliterateRTLWord( sal_Int32& /*rSttPos*/, LanguageType EdtAutoCorrDoc::GetLanguage( sal_Int32 nPos ) const { - return mpEditEngine->GetLanguage( EditPaM( pCurNode, nPos+1 ) ); + return mpEditEngine->GetLanguage( EditPaM( pCurNode, nPos+1 ) ).nLang; } void EdtAutoCorrDoc::ImplStartUndoAction() diff --git a/editeng/source/editeng/eehtml.cxx b/editeng/source/editeng/eehtml.cxx index a3de37005ffc..b3ed28395506 100644 --- a/editeng/source/editeng/eehtml.cxx +++ b/editeng/source/editeng/eehtml.cxx @@ -31,12 +31,13 @@ #include <tools/tenccvt.hxx> #include <editeng/editeng.hxx> +#include <utility> #define STYLE_PRE 101 -EditHTMLParser::EditHTMLParser( SvStream& rIn, const OUString& rBaseURL, SvKeyValueIterator* pHTTPHeaderAttrs ) +EditHTMLParser::EditHTMLParser( SvStream& rIn, OUString _aBaseURL, SvKeyValueIterator* pHTTPHeaderAttrs ) : HTMLParser( rIn, true ), - aBaseURL( rBaseURL ), + aBaseURL(std::move( _aBaseURL )), mpEditEngine(nullptr), bInPara(false), bWasInPara(false), @@ -179,26 +180,19 @@ void EditHTMLParser::NextToken( HtmlTokenId nToken ) if ( !bInPara ) StartPara( false ); - OUString aText = aToken; + OUString aText = aToken.toString(); if ( aText.startsWith(" ") && ThrowAwayBlank() && !IsReadPRE() ) aText = aText.copy( 1 ); - if ( pCurAnchor ) + if ( moCurAnchor ) { - pCurAnchor->aText += aText; + moCurAnchor->aText += aText; } else { // Only written until HTML with 319? if ( IsReadPRE() ) - { - sal_Int32 nTabPos = aText.indexOf( '\t'); - while ( nTabPos != -1 ) - { - aText = aText.replaceAt( nTabPos, 1, u" " ); - nTabPos = aText.indexOf( '\t', nTabPos+8 ); - } - } + aText = aText.replaceAll(u"\t", u" "); ImpInsertText( aText ); } } @@ -745,7 +739,7 @@ bool EditHTMLParser::HasTextInCurrentPara() void EditHTMLParser::AnchorStart() { // ignore anchor in anchor - if ( pCurAnchor ) + if ( moCurAnchor ) return; const HTMLOptions& aOptions = GetOptions(); @@ -768,20 +762,20 @@ void EditHTMLParser::AnchorStart() aRootURL.GetNewAbsURL( aRef, &aTargetURL ); aURL = aTargetURL.GetMainURL( INetURLObject::DecodeMechanism::ToIUri ); } - pCurAnchor.reset( new AnchorInfo ); - pCurAnchor->aHRef = aURL; + moCurAnchor.emplace(); + moCurAnchor->aHRef = aURL; } void EditHTMLParser::AnchorEnd() { - if ( !pCurAnchor ) + if ( !moCurAnchor ) return; // Insert as URL-Field... - SvxFieldItem aFld( SvxURLField( pCurAnchor->aHRef, pCurAnchor->aText, SvxURLFormat::Repr ), EE_FEATURE_FIELD ); + SvxFieldItem aFld( SvxURLField( moCurAnchor->aHRef, moCurAnchor->aText, SvxURLFormat::Repr ), EE_FEATURE_FIELD ); aCurSel = mpEditEngine->InsertField(aCurSel, aFld); bFieldsInserted = true; - pCurAnchor.reset(); + moCurAnchor.reset(); if (mpEditEngine->IsHtmlImportHandlerSet()) { diff --git a/editeng/source/editeng/eehtml.hxx b/editeng/source/editeng/eehtml.hxx index a2aa0e0448af..fddd567ac6ba 100644 --- a/editeng/source/editeng/eehtml.hxx +++ b/editeng/source/editeng/eehtml.hxx @@ -20,6 +20,7 @@ #pragma once #include <memory> +#include <optional> #include <editdoc.hxx> #include <rtl/ustrbuf.hxx> #include <svtools/parhtml.hxx> @@ -40,8 +41,7 @@ private: EditSelection aCurSel; OUString aBaseURL; EditEngine* mpEditEngine; - std::unique_ptr<AnchorInfo> - pCurAnchor; + std::optional<AnchorInfo> moCurAnchor; bool bInPara:1; bool bWasInPara:1; // Remember bInPara before HeadingStart, because afterwards it will be gone. @@ -71,7 +71,7 @@ protected: virtual void NextToken( HtmlTokenId nToken ) override; public: - EditHTMLParser(SvStream& rIn, const OUString& rBaseURL, SvKeyValueIterator* pHTTPHeaderAttrs); + EditHTMLParser(SvStream& rIn, OUString aBaseURL, SvKeyValueIterator* pHTTPHeaderAttrs); virtual ~EditHTMLParser() override; SvParserState CallParser(EditEngine* pEE, const EditPaM& rPaM); diff --git a/editeng/source/editeng/eerdll.cxx b/editeng/source/editeng/eerdll.cxx index 2ec4519b6446..732c85ee18cd 100644 --- a/editeng/source/editeng/eerdll.cxx +++ b/editeng/source/editeng/eerdll.cxx @@ -35,8 +35,8 @@ #include <editeng/scriptspaceitem.hxx> #include <editeng/hngpnctitem.hxx> #include <editeng/forbiddenruleitem.hxx> -#include <svl/itempool.hxx> #include <svl/grabbagitem.hxx> +#include <svl/voiditem.hxx> #include <vcl/svapp.hxx> #include <vcl/virdev.hxx> @@ -65,106 +65,151 @@ #include <editeng/forbiddencharacterstable.hxx> #include <editeng/justifyitem.hxx> #include <tools/mapunit.hxx> +#include <vcl/lazydelete.hxx> +#include <svl/itempool.hxx> +#include <editeng/editids.hrc> using namespace ::com::sun::star; EditDLL& EditDLL::Get() { - static EditDLL theEditDLL; - return theEditDLL; + /** + Prevent use-after-free errors during application shutdown. + Previously this data was function-static, but then data in i18npool would + be torn down before the destructor here ran, causing a crash. + */ + static vcl::DeleteOnDeinit< EditDLL > gaEditDll; + return *gaEditDll.get(); } -DefItems::DefItems() - : mvDefItems(EDITITEMCOUNT) +ItemInfoPackage& getItemInfoPackageEditEngine() { - std::vector<SfxPoolItem*>& rDefItems = mvDefItems; - - // Paragraph attributes: - SvxNumRule aDefaultNumRule( SvxNumRuleFlags::NONE, 0, false ); - - rDefItems[0] = new SvxFrameDirectionItem( SvxFrameDirection::Horizontal_LR_TB, EE_PARA_WRITINGDIR ); - rDefItems[1] = new SvXMLAttrContainerItem( EE_PARA_XMLATTRIBS ); - rDefItems[2] = new SvxHangingPunctuationItem(false, EE_PARA_HANGINGPUNCTUATION); - rDefItems[3] = new SvxForbiddenRuleItem(true, EE_PARA_FORBIDDENRULES); - rDefItems[4] = new SvxScriptSpaceItem( true, EE_PARA_ASIANCJKSPACING ); - rDefItems[5] = new SvxNumBulletItem( aDefaultNumRule, EE_PARA_NUMBULLET ); - rDefItems[6] = new SfxBoolItem( EE_PARA_HYPHENATE, false ); - rDefItems[7] = new SfxBoolItem( EE_PARA_HYPHENATE_NO_CAPS, false ); - rDefItems[8] = new SfxBoolItem( EE_PARA_BULLETSTATE, true ); - rDefItems[9] = new SvxLRSpaceItem( EE_PARA_OUTLLRSPACE ); - rDefItems[10] = new SfxInt16Item( EE_PARA_OUTLLEVEL, -1 ); - rDefItems[11] = new SvxBulletItem( EE_PARA_BULLET ); - rDefItems[12] = new SvxLRSpaceItem( EE_PARA_LRSPACE ); - rDefItems[13] = new SvxULSpaceItem( EE_PARA_ULSPACE ); - rDefItems[14] = new SvxLineSpacingItem( 0, EE_PARA_SBL ); - rDefItems[15] = new SvxAdjustItem( SvxAdjust::Left, EE_PARA_JUST ); - rDefItems[16] = new SvxTabStopItem( 0, 0, SvxTabAdjust::Left, EE_PARA_TABS ); - rDefItems[17] = new SvxJustifyMethodItem( SvxCellJustifyMethod::Auto, EE_PARA_JUST_METHOD ); - rDefItems[18] = new SvxVerJustifyItem( SvxCellVerJustify::Standard, EE_PARA_VER_JUST ); - - // Character attributes: - rDefItems[19] = new SvxColorItem( COL_AUTO, EE_CHAR_COLOR ); - rDefItems[20] = new SvxFontItem( EE_CHAR_FONTINFO ); - rDefItems[21] = new SvxFontHeightItem( 240, 100, EE_CHAR_FONTHEIGHT ); - rDefItems[22] = new SvxCharScaleWidthItem( 100, EE_CHAR_FONTWIDTH ); - rDefItems[23] = new SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT ); - rDefItems[24] = new SvxUnderlineItem( LINESTYLE_NONE, EE_CHAR_UNDERLINE ); - rDefItems[25] = new SvxCrossedOutItem( STRIKEOUT_NONE, EE_CHAR_STRIKEOUT ); - rDefItems[26] = new SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC ); - rDefItems[27] = new SvxContourItem( false, EE_CHAR_OUTLINE ); - rDefItems[28] = new SvxShadowedItem( false, EE_CHAR_SHADOW ); - rDefItems[29] = new SvxEscapementItem( 0, 100, EE_CHAR_ESCAPEMENT ); - rDefItems[30] = new SvxAutoKernItem( false, EE_CHAR_PAIRKERNING ); - rDefItems[31] = new SvxKerningItem( 0, EE_CHAR_KERNING ); - rDefItems[32] = new SvxWordLineModeItem( false, EE_CHAR_WLM ); - rDefItems[33] = new SvxLanguageItem( LANGUAGE_DONTKNOW, EE_CHAR_LANGUAGE ); - rDefItems[34] = new SvxLanguageItem( LANGUAGE_DONTKNOW, EE_CHAR_LANGUAGE_CJK ); - rDefItems[35] = new SvxLanguageItem( LANGUAGE_DONTKNOW, EE_CHAR_LANGUAGE_CTL ); - rDefItems[36] = new SvxFontItem( EE_CHAR_FONTINFO_CJK ); - rDefItems[37] = new SvxFontItem( EE_CHAR_FONTINFO_CTL ); - rDefItems[38] = new SvxFontHeightItem( 240, 100, EE_CHAR_FONTHEIGHT_CJK ); - rDefItems[39] = new SvxFontHeightItem( 240, 100, EE_CHAR_FONTHEIGHT_CTL ); - rDefItems[40] = new SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT_CJK ); - rDefItems[41] = new SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT_CTL ); - rDefItems[42] = new SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC_CJK ); - rDefItems[43] = new SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC_CTL ); - rDefItems[44] = new SvxEmphasisMarkItem( FontEmphasisMark::NONE, EE_CHAR_EMPHASISMARK ); - rDefItems[45] = new SvxCharReliefItem( FontRelief::NONE, EE_CHAR_RELIEF ); - rDefItems[46] = new SfxVoidItem( EE_CHAR_RUBI_DUMMY ); - rDefItems[47] = new SvXMLAttrContainerItem( EE_CHAR_XMLATTRIBS ); - rDefItems[48] = new SvxOverlineItem( LINESTYLE_NONE, EE_CHAR_OVERLINE ); - rDefItems[49] = new SvxCaseMapItem( SvxCaseMap::NotMapped, EE_CHAR_CASEMAP ); - rDefItems[50] = new SfxGrabBagItem( EE_CHAR_GRABBAG ); - rDefItems[51] = new SvxColorItem( COL_AUTO, EE_CHAR_BKGCOLOR ); - // Features - rDefItems[52] = new SfxVoidItem( EE_FEATURE_TAB ); - rDefItems[53] = new SfxVoidItem( EE_FEATURE_LINEBR ); - rDefItems[54] = new SvxColorItem( COL_RED, EE_FEATURE_NOTCONV ); - rDefItems[55] = new SvxFieldItem( SvxFieldData(), EE_FEATURE_FIELD ); - - assert(EDITITEMCOUNT == 56 && "ITEMCOUNT changed, adjust DefItems!"); - - // Init DefFonts: - GetDefaultFonts( *static_cast<SvxFontItem*>(rDefItems[EE_CHAR_FONTINFO - EE_ITEMS_START]), - *static_cast<SvxFontItem*>(rDefItems[EE_CHAR_FONTINFO_CJK - EE_ITEMS_START]), - *static_cast<SvxFontItem*>(rDefItems[EE_CHAR_FONTINFO_CTL - EE_ITEMS_START]) ); -} + class ItemInfoPackageEditEngine : public ItemInfoPackage + { + typedef std::array<ItemInfoStatic, EE_ITEMS_END - EE_ITEMS_START + 1> ItemInfoArrayEditEngine; + ItemInfoArrayEditEngine maItemInfos {{ + // m_nWhich, m_pItem, m_nSlotID, m_nItemInfoFlags + { EE_PARA_WRITINGDIR, new SvxFrameDirectionItem( SvxFrameDirection::Horizontal_LR_TB, EE_PARA_WRITINGDIR ), SID_ATTR_FRAMEDIRECTION, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_XMLATTRIBS, new SvXMLAttrContainerItem( EE_PARA_XMLATTRIBS ), 0, SFX_ITEMINFOFLAG_SUPPORT_SURROGATE }, + { EE_PARA_HANGINGPUNCTUATION, new SvxHangingPunctuationItem(false, EE_PARA_HANGINGPUNCTUATION), SID_ATTR_PARA_HANGPUNCTUATION, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_FORBIDDENRULES, new SvxForbiddenRuleItem(true, EE_PARA_FORBIDDENRULES), SID_ATTR_PARA_FORBIDDEN_RULES, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_ASIANCJKSPACING, new SvxScriptSpaceItem( true, EE_PARA_ASIANCJKSPACING ), SID_ATTR_PARA_SCRIPTSPACE, SFX_ITEMINFOFLAG_NONE }, -DefItems::~DefItems() -{ - for (const auto& rItem : mvDefItems) - delete rItem; -} + // need to use dynamic default for this Item, the office tends to crash at shutdown + // due to static stuff/cleanup at ~SvxNumRule (pStdNumFmt/pStdOutlineNumFmt) + { EE_PARA_NUMBULLET, nullptr, SID_ATTR_NUMBERING_RULE, SFX_ITEMINFOFLAG_NONE }, -std::shared_ptr<DefItems> GlobalEditData::GetDefItems() -{ - auto xDefItems = m_xDefItems.lock(); - if (!xDefItems) - { - xDefItems = std::make_shared<DefItems>(); - m_xDefItems = xDefItems; - } - return xDefItems; + { EE_PARA_HYPHENATE, new SfxBoolItem( EE_PARA_HYPHENATE, false ), 0, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_HYPHENATE_NO_CAPS, new SfxBoolItem( EE_PARA_HYPHENATE_NO_CAPS, false ), 0, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_HYPHENATE_NO_LAST_WORD, new SfxBoolItem( EE_PARA_HYPHENATE_NO_LAST_WORD, false ), 0, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_BULLETSTATE, new SfxBoolItem( EE_PARA_BULLETSTATE, true ), 0, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_OUTLLRSPACE, new SvxLRSpaceItem( EE_PARA_OUTLLRSPACE ), 0, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_OUTLLEVEL, new SfxInt16Item( EE_PARA_OUTLLEVEL, -1 ), SID_ATTR_PARA_OUTLLEVEL, SFX_ITEMINFOFLAG_NONE }, + + // needs on-demand initialization + { EE_PARA_BULLET, nullptr, SID_ATTR_PARA_BULLET, SFX_ITEMINFOFLAG_NONE }, + + { EE_PARA_LRSPACE, new SvxLRSpaceItem( EE_PARA_LRSPACE ), SID_ATTR_LRSPACE, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_ULSPACE, new SvxULSpaceItem( EE_PARA_ULSPACE ), SID_ATTR_ULSPACE, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_SBL, new SvxLineSpacingItem( 0, EE_PARA_SBL ), SID_ATTR_PARA_LINESPACE, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_JUST, new SvxAdjustItem( SvxAdjust::Left, EE_PARA_JUST ), SID_ATTR_PARA_ADJUST, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_TABS, new SvxTabStopItem( 0, 0, SvxTabAdjust::Left, EE_PARA_TABS ), SID_ATTR_TABSTOP, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_JUST_METHOD, new SvxJustifyMethodItem( SvxCellJustifyMethod::Auto, EE_PARA_JUST_METHOD ), SID_ATTR_ALIGN_HOR_JUSTIFY_METHOD, SFX_ITEMINFOFLAG_NONE }, + { EE_PARA_VER_JUST, new SvxVerJustifyItem( SvxCellVerJustify::Standard, EE_PARA_VER_JUST ), SID_ATTR_ALIGN_VER_JUSTIFY, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_COLOR, new SvxColorItem( COL_AUTO, EE_CHAR_COLOR ), SID_ATTR_CHAR_COLOR, SFX_ITEMINFOFLAG_SUPPORT_SURROGATE }, + + // EE_CHAR_FONTINFO, EE_CHAR_FONTINFO_CJK and EE_CHAR_FONTINFO_CTL need on-demand initialization + { EE_CHAR_FONTINFO, nullptr, SID_ATTR_CHAR_FONT, SFX_ITEMINFOFLAG_SUPPORT_SURROGATE }, + + { EE_CHAR_FONTHEIGHT, new SvxFontHeightItem( 240, 100, EE_CHAR_FONTHEIGHT ), SID_ATTR_CHAR_FONTHEIGHT, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_FONTWIDTH, new SvxCharScaleWidthItem( 100, EE_CHAR_FONTWIDTH ), SID_ATTR_CHAR_SCALEWIDTH, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_WEIGHT, new SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT ), SID_ATTR_CHAR_WEIGHT, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_UNDERLINE, new SvxUnderlineItem( LINESTYLE_NONE, EE_CHAR_UNDERLINE ), SID_ATTR_CHAR_UNDERLINE, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_STRIKEOUT, new SvxCrossedOutItem( STRIKEOUT_NONE, EE_CHAR_STRIKEOUT ), SID_ATTR_CHAR_STRIKEOUT, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_ITALIC, new SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC ), SID_ATTR_CHAR_POSTURE, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_OUTLINE, new SvxContourItem( false, EE_CHAR_OUTLINE ), SID_ATTR_CHAR_CONTOUR, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_SHADOW, new SvxShadowedItem( false, EE_CHAR_SHADOW ), SID_ATTR_CHAR_SHADOWED, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_ESCAPEMENT, new SvxEscapementItem( 0, 100, EE_CHAR_ESCAPEMENT ), SID_ATTR_CHAR_ESCAPEMENT, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_PAIRKERNING, new SvxAutoKernItem( false, EE_CHAR_PAIRKERNING ), SID_ATTR_CHAR_AUTOKERN, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_KERNING, new SvxKerningItem( 0, EE_CHAR_KERNING ), SID_ATTR_CHAR_KERNING, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_WLM, new SvxWordLineModeItem( false, EE_CHAR_WLM ), SID_ATTR_CHAR_WORDLINEMODE, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_LANGUAGE, new SvxLanguageItem( LANGUAGE_DONTKNOW, EE_CHAR_LANGUAGE ), SID_ATTR_CHAR_LANGUAGE, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_LANGUAGE_CJK, new SvxLanguageItem( LANGUAGE_DONTKNOW, EE_CHAR_LANGUAGE_CJK ), SID_ATTR_CHAR_CJK_LANGUAGE, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_LANGUAGE_CTL, new SvxLanguageItem( LANGUAGE_DONTKNOW, EE_CHAR_LANGUAGE_CTL ), SID_ATTR_CHAR_CTL_LANGUAGE, SFX_ITEMINFOFLAG_NONE }, + + // see EE_CHAR_FONTINFO above + { EE_CHAR_FONTINFO_CJK, nullptr, SID_ATTR_CHAR_CJK_FONT, SFX_ITEMINFOFLAG_SUPPORT_SURROGATE }, + { EE_CHAR_FONTINFO_CTL, nullptr, SID_ATTR_CHAR_CTL_FONT, SFX_ITEMINFOFLAG_SUPPORT_SURROGATE }, + + { EE_CHAR_FONTHEIGHT_CJK, new SvxFontHeightItem( 240, 100, EE_CHAR_FONTHEIGHT_CJK ), SID_ATTR_CHAR_CJK_FONTHEIGHT, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_FONTHEIGHT_CTL, new SvxFontHeightItem( 240, 100, EE_CHAR_FONTHEIGHT_CTL ), SID_ATTR_CHAR_CTL_FONTHEIGHT, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_WEIGHT_CJK, new SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT_CJK ), SID_ATTR_CHAR_CJK_WEIGHT, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_WEIGHT_CTL, new SvxWeightItem( WEIGHT_NORMAL, EE_CHAR_WEIGHT_CTL ), SID_ATTR_CHAR_CTL_WEIGHT, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_ITALIC_CJK, new SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC_CJK ), SID_ATTR_CHAR_CJK_POSTURE, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_ITALIC_CTL, new SvxPostureItem( ITALIC_NONE, EE_CHAR_ITALIC_CTL ), SID_ATTR_CHAR_CTL_POSTURE, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_EMPHASISMARK, new SvxEmphasisMarkItem( FontEmphasisMark::NONE, EE_CHAR_EMPHASISMARK ), SID_ATTR_CHAR_EMPHASISMARK, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_RELIEF, new SvxCharReliefItem( FontRelief::NONE, EE_CHAR_RELIEF ), SID_ATTR_CHAR_RELIEF, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_XMLATTRIBS, new SvXMLAttrContainerItem( EE_CHAR_XMLATTRIBS ), 0, SFX_ITEMINFOFLAG_SUPPORT_SURROGATE }, + { EE_CHAR_OVERLINE, new SvxOverlineItem( LINESTYLE_NONE, EE_CHAR_OVERLINE ), SID_ATTR_CHAR_OVERLINE, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_CASEMAP, new SvxCaseMapItem( SvxCaseMap::NotMapped, EE_CHAR_CASEMAP ), SID_ATTR_CHAR_CASEMAP, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_GRABBAG, new SfxGrabBagItem( EE_CHAR_GRABBAG ), SID_ATTR_CHAR_GRABBAG, SFX_ITEMINFOFLAG_NONE }, + { EE_CHAR_BKGCOLOR, new SvxColorItem( COL_AUTO, EE_CHAR_BKGCOLOR ), SID_ATTR_CHAR_BACK_COLOR, SFX_ITEMINFOFLAG_NONE }, + { EE_FEATURE_TAB, new SfxVoidItem( EE_FEATURE_TAB ), 0, SFX_ITEMINFOFLAG_NONE }, + { EE_FEATURE_LINEBR, new SfxVoidItem( EE_FEATURE_LINEBR ), 0, SFX_ITEMINFOFLAG_NONE }, + { EE_FEATURE_NOTCONV, new SvxColorItem( COL_RED, EE_FEATURE_NOTCONV ), SID_ATTR_CHAR_CHARSETCOLOR, SFX_ITEMINFOFLAG_NONE }, + { EE_FEATURE_FIELD, new SvxFieldItem( SvxFieldData(), EE_FEATURE_FIELD ), SID_FIELD, SFX_ITEMINFOFLAG_SUPPORT_SURROGATE } + }}; + + virtual const ItemInfoStatic& getItemInfoStatic(size_t nIndex) const override { return maItemInfos[nIndex]; } + + public: + ItemInfoPackageEditEngine() + { + // on-demand (but only once) as static defaults - above (and also + // in constructor) the needed OutputDevice::Font stuff is not yet + // initialized + setItemAtItemInfoStatic( + new SvxBulletItem(EE_PARA_BULLET), + maItemInfos[EE_PARA_BULLET - EE_ITEMS_START]); + + // same for EE_CHAR_FONTINFO/EE_CHAR_FONTINFO_CJK/EE_CHAR_FONTINFO_CTL + // doing here as static default will be done only once for LO runtime + SvxFontItem* pFont(new SvxFontItem(EE_CHAR_FONTINFO)); + SvxFontItem* pFontCJK(new SvxFontItem(EE_CHAR_FONTINFO_CJK)); + SvxFontItem* pFontCTL(new SvxFontItem(EE_CHAR_FONTINFO_CTL)); + + // Init DefFonts: + GetDefaultFonts(*pFont, *pFontCJK, *pFontCTL); + + setItemAtItemInfoStatic(pFont, maItemInfos[EE_CHAR_FONTINFO - EE_ITEMS_START]); + setItemAtItemInfoStatic(pFontCJK, maItemInfos[EE_CHAR_FONTINFO_CJK - EE_ITEMS_START]); + setItemAtItemInfoStatic(pFontCTL, maItemInfos[EE_CHAR_FONTINFO_CTL - EE_ITEMS_START]); + } + + virtual size_t size() const override { return maItemInfos.size(); } + virtual const ItemInfo& getItemInfo(size_t nIndex, SfxItemPool& /*rPool*/) override + { + const ItemInfo& rRetval(maItemInfos[nIndex]); + + // return immediately if we have the static entry and Item + if (nullptr != rRetval.getItem()) + return rRetval; + + // check for dynamic ItemInfo creation, needed here for SvxNumBulletItem + if (EE_PARA_NUMBULLET == rRetval.getWhich()) + return *new ItemInfoDynamic( + rRetval, + new SvxNumBulletItem( SvxNumRule( SvxNumRuleFlags::NONE, 0, false ), EE_PARA_NUMBULLET )); + + // return in any case + return rRetval; + } + }; + + static std::unique_ptr<ItemInfoPackageEditEngine> g_aItemInfoPackageEditEngine; + if (!g_aItemInfoPackageEditEngine) + g_aItemInfoPackageEditEngine.reset(new ItemInfoPackageEditEngine); + return *g_aItemInfoPackageEditEngine; } std::shared_ptr<SvxForbiddenCharactersTable> const & GlobalEditData::GetForbiddenCharsTable() diff --git a/editeng/source/editeng/eertfpar.cxx b/editeng/source/editeng/eertfpar.cxx index 3006caf21594..557081f8496f 100644 --- a/editeng/source/editeng/eertfpar.cxx +++ b/editeng/source/editeng/eertfpar.cxx @@ -31,6 +31,7 @@ #include <svtools/rtftoken.h> #include <svtools/htmltokn.h> +#include <comphelper/configuration.hxx> using namespace com::sun::star; @@ -55,10 +56,6 @@ RtfImportInfo::RtfImportInfo( RtfImportState eSt, SvParser<int>* pPrsrs, const E nTokenValue = 0; } -RtfImportInfo::~RtfImportInfo() -{ -} - constexpr MapUnit gRTFMapUnit = MapUnit::MapTwip; EditRTFParser::EditRTFParser( @@ -206,7 +203,6 @@ void EditRTFParser::NextToken( int nToken ) SkipGroup(); } break; - case RTF_PGDSCTBL: // #i29453# ignore \*\pgdsctbl destination case RTF_LISTTEXT: { SkipGroup(); @@ -307,7 +303,6 @@ void EditRTFParser::SetAttrInDoc( SvxRTFItemStackType &rSet ) EditPaM aEndPaM( pEndNode, rSet.GetEndCnt() ); // If possible adjust the Escapement-Item: - const SfxPoolItem* pItem; // #i66167# adapt font heights to destination MapUnit if necessary const MapUnit eDestUnit = mpEditEngine->GetEditDoc().GetItemPool().GetMetric(0); @@ -316,6 +311,7 @@ void EditRTFParser::SetAttrInDoc( SvxRTFItemStackType &rSet ) sal_uInt16 const aFntHeightIems[3] = { EE_CHAR_FONTHEIGHT, EE_CHAR_FONTHEIGHT_CJK, EE_CHAR_FONTHEIGHT_CTL }; for (unsigned short aFntHeightIem : aFntHeightIems) { + const SfxPoolItem* pItem; if (SfxItemState::SET == rSet.GetAttrSet().GetItemState( aFntHeightIem, false, &pItem )) { sal_uInt32 nHeight = static_cast<const SvxFontHeightItem*>(pItem)->GetHeight(); @@ -331,23 +327,29 @@ void EditRTFParser::SetAttrInDoc( SvxRTFItemStackType &rSet ) } } - if( SfxItemState::SET == rSet.GetAttrSet().GetItemState( EE_CHAR_ESCAPEMENT, false, &pItem )) + if( const SvxEscapementItem* pItem = rSet.GetAttrSet().GetItemIfSet( EE_CHAR_ESCAPEMENT, false ) ) { // the correct one - tools::Long nEsc = static_cast<const SvxEscapementItem*>(pItem)->GetEsc(); + tools::Long nEsc = pItem->GetEsc(); tools::Long nEscFontHeight = 0; if( ( DFLT_ESC_AUTO_SUPER != nEsc ) && ( DFLT_ESC_AUTO_SUB != nEsc ) ) { nEsc *= 10; //HalfPoints => Twips was embezzled in RTFITEM.CXX! SvxFont aFont; - mpEditEngine->SeekCursor(aStartPaM.GetNode(), aStartPaM.GetIndex()+1, aFont); + if (comphelper::IsFuzzing()) + { + // ofz#24932 detecting RTL vs LTR is slow + aFont = aStartPaM.GetNode()->GetCharAttribs().GetDefFont(); + } + else + mpEditEngine->SeekCursor(aStartPaM.GetNode(), aStartPaM.GetIndex()+1, aFont); nEscFontHeight = aFont.GetFontSize().Height(); } if (nEscFontHeight) { nEsc = nEsc * 100 / nEscFontHeight; - SvxEscapementItem aEscItem( static_cast<short>(nEsc), static_cast<const SvxEscapementItem*>(pItem)->GetProportionalHeight(), EE_CHAR_ESCAPEMENT ); + SvxEscapementItem aEscItem( static_cast<short>(nEsc), pItem->GetProportionalHeight(), EE_CHAR_ESCAPEMENT ); rSet.GetAttrSet().Put( aEscItem ); } } diff --git a/editeng/source/editeng/fieldupdater.cxx b/editeng/source/editeng/fieldupdater.cxx index 41d9be7aeee7..05eca4575590 100644 --- a/editeng/source/editeng/fieldupdater.cxx +++ b/editeng/source/editeng/fieldupdater.cxx @@ -47,7 +47,7 @@ public: // Create a new table field with the new ID, and set it to the // attribute object. SvxFieldItem aNewItem(SvxTableField(nTab), EE_FEATURE_FIELD); - rAttr.SetItem(pPool->Put(aNewItem)); + rAttr.SetItem(*pPool, aNewItem); } } } diff --git a/editeng/source/editeng/impedit.cxx b/editeng/source/editeng/impedit.cxx index 3b44e851b821..94d707cf902e 100644 --- a/editeng/source/editeng/impedit.cxx +++ b/editeng/source/editeng/impedit.cxx @@ -22,6 +22,7 @@ #include <editeng/editeng.hxx> #include <editeng/editview.hxx> #include <editeng/outliner.hxx> +#include <editeng/urlfieldhelper.hxx> #include <tools/poly.hxx> #include <editeng/unolingu.hxx> #include <com/sun/star/linguistic2/XDictionary.hpp> @@ -45,9 +46,7 @@ #include <sfx2/lokhelper.hxx> #include <boost/property_tree/ptree.hpp> -using namespace ::com::sun::star; -using namespace ::com::sun::star::uno; -using namespace ::com::sun::star::linguistic2; +using namespace css; #define SCRLRANGE 20 // Scroll 1/20 of the width/height, when in QueryDrop @@ -69,7 +68,8 @@ LOKSpecialPositioning::LOKSpecialPositioning(const ImpEditView& rImpEditView, Ma mrImpEditView(rImpEditView), maOutArea(rOutputArea), maVisDocStartPos(rVisDocStartPos), - meUnit(eUnit) + meUnit(eUnit), + meFlags(LOKSpecialFlags::NONE) { } @@ -178,30 +178,30 @@ Point LOKSpecialPositioning::GetRefPoint() const // class ImpEditView -ImpEditView::ImpEditView( EditView* pView, EditEngine* pEng, vcl::Window* pWindow ) : - pEditView(pView), - mpViewShell(nullptr), - mpOtherShell(nullptr), - pEditEngine(pEng), - pOutWin(pWindow), - nInvMore(1), - nControl(EVControlBits::AUTOSCROLL | EVControlBits::ENABLEPASTE), - nTravelXPos(TRAVEL_X_DONTKNOW), - nExtraCursorFlags(GetCursorFlags::NONE), - nCursorBidiLevel(CURSOR_BIDILEVEL_DONTKNOW), - nScrollDiffX(0), - bReadOnly(false), - bClickedInSelection(false), - bActiveDragAndDropListener(false), - aOutArea( Point(), pEng->GetPaperSize() ), - eSelectionMode(EESelectionMode::Std), - eAnchorMode(EEAnchorMode::TopLeft), - mpEditViewCallbacks(nullptr), - mbBroadcastLOKViewCursor(comphelper::LibreOfficeKit::isActive()), - mbSuppressLOKMessages(false) -{ - aEditSelection.Min() = pEng->GetEditDoc().GetStartPaM(); - aEditSelection.Max() = pEng->GetEditDoc().GetEndPaM(); +ImpEditView::ImpEditView(EditView* pView, EditEngine* pEditEngine, vcl::Window* pWindow) + : mpEditView(pView) + , mpViewShell(nullptr) + , mpOtherShell(nullptr) + , mpEditEngine(pEditEngine) + , mpOutputWindow(pWindow) + , mnInvalidateMore(1) + , mnControl(EVControlBits::AUTOSCROLL | EVControlBits::ENABLEPASTE) + , mnTravelXPos(TRAVEL_X_DONTKNOW) + , mnCursorBidiLevel(CURSOR_BIDILEVEL_DONTKNOW) + , mnScrollDiffX(0) + , mbReadOnly(false) + , mbClickedInSelection(false) + , mbActiveDragAndDropListener(false) + , maOutputArea(Point(), mpEditEngine->GetPaperSize()) + , meSelectionMode(EESelectionMode::Std) + , meAnchorMode(EEAnchorMode::TopLeft) + , mpEditViewCallbacks(nullptr) + , mbBroadcastLOKViewCursor(comphelper::LibreOfficeKit::isActive()) + , mbSuppressLOKMessages(false) + , mbNegativeX(false) +{ + maEditSelection.Min() = mpEditEngine->GetEditDoc().GetStartPaM(); + maEditSelection.Max() = mpEditEngine->GetEditDoc().GetEndPaM(); SelectionChanged(); } @@ -210,8 +210,8 @@ ImpEditView::~ImpEditView() { RemoveDragAndDropListeners(); - if ( pOutWin && ( pOutWin->GetCursor() == pCursor.get() ) ) - pOutWin->SetCursor( nullptr ); + if (mpOutputWindow && (mpOutputWindow->GetCursor() == mpCursor.get())) + mpOutputWindow->SetCursor( nullptr ); } void ImpEditView::SetBackgroundColor( const Color& rColor ) @@ -241,21 +241,20 @@ const OutlinerViewShell* ImpEditView::GetViewShell() const void ImpEditView::SetEditSelection( const EditSelection& rEditSelection ) { - if (aEditSelection == rEditSelection) - return; - // set state before notification - aEditSelection = rEditSelection; + maEditSelection = rEditSelection; SelectionChanged(); if (comphelper::LibreOfficeKit::isActive()) + { // Tiled rendering: selections are only painted when we are in selection mode. - pEditEngine->SetInSelectionMode(aEditSelection.HasRange()); + getEditEngine().SetInSelectionMode(maEditSelection.HasRange()); + } - if ( pEditEngine->pImpEditEngine->GetNotifyHdl().IsSet() ) + if (getImpEditEngine().GetNotifyHdl().IsSet() ) { - const EditDoc& rDoc = pEditEngine->GetEditDoc(); + const EditDoc& rDoc = getEditEngine().GetEditDoc(); const EditPaM pmEnd = rDoc.GetEndPaM(); EENotifyType eNotifyType; if (rDoc.Count() > 1 && @@ -269,12 +268,13 @@ void ImpEditView::SetEditSelection( const EditSelection& rEditSelection ) eNotifyType = EE_NOTIFY_TEXTVIEWSELECTIONCHANGED; } EENotify aNotify( eNotifyType ); - pEditEngine->pImpEditEngine->GetNotifyHdl().Call( aNotify ); + getImpEditEngine().GetNotifyHdl().Call( aNotify ); } - if(pEditEngine->pImpEditEngine->IsFormatted()) + + if (getImpEditEngine().IsFormatted()) { EENotify aNotify(EE_NOTIFY_PROCESSNOTIFICATIONS); - pEditEngine->pImpEditEngine->GetNotifyHdl().Call(aNotify); + getImpEditEngine().GetNotifyHdl().Call(aNotify); } } @@ -323,13 +323,13 @@ void ImpEditView::SelectionChanged() // This function is also called when a text's font || size is changed. Because its highlight rectangle must be updated. void ImpEditView::lokSelectionCallback(const std::optional<tools::PolyPolygon> &pPolyPoly, bool bStartHandleVisible, bool bEndHandleVisible) { - VclPtr<vcl::Window> pParent = pOutWin->GetParentWithLOKNotifier(); + VclPtr<vcl::Window> pParent = mpOutputWindow->GetParentWithLOKNotifier(); vcl::Region aRegion( *pPolyPoly ); if (pParent && pParent->GetLOKWindowId() != 0) { - const tools::Long nX = pOutWin->GetOutOffXPixel() - pParent->GetOutOffXPixel(); - const tools::Long nY = pOutWin->GetOutOffYPixel() - pParent->GetOutOffYPixel(); + const tools::Long nX = mpOutputWindow->GetOutOffXPixel() - pParent->GetOutOffXPixel(); + const tools::Long nY = mpOutputWindow->GetOutOffYPixel() - pParent->GetOutOffYPixel(); std::vector<tools::Rectangle> aRectangles; aRegion.GetRegionRectangles(aRectangles); @@ -337,7 +337,7 @@ void ImpEditView::lokSelectionCallback(const std::optional<tools::PolyPolygon> & std::vector<OString> v; for (tools::Rectangle & rRectangle : aRectangles) { - rRectangle = pOutWin->LogicToPixel(rRectangle); + rRectangle = mpOutputWindow->LogicToPixel(rRectangle); rRectangle.Move(nX, nY); v.emplace_back(rRectangle.toString().getStr()); } @@ -350,34 +350,33 @@ void ImpEditView::lokSelectionCallback(const std::optional<tools::PolyPolygon> & aItems.emplace_back("endHandleVisible", OString::boolean(bEndHandleVisible)); pNotifier->notifyWindow(pParent->GetLOKWindowId(), "text_selection", aItems); } - else + else if (mpViewShell) { - pOutWin->GetOutDev()->Push(vcl::PushFlags::MAPMODE); - if (pOutWin->GetMapMode().GetMapUnit() == MapUnit::MapTwip) + mpOutputWindow->GetOutDev()->Push(vcl::PushFlags::MAPMODE); + if (mpOutputWindow->GetMapMode().GetMapUnit() == MapUnit::MapTwip) { // Find the parent that is not right // on top of us to use its offset. - vcl::Window* parent = pOutWin->GetParent(); + vcl::Window* parent = mpOutputWindow->GetParent(); while (parent && - parent->GetOutOffXPixel() == pOutWin->GetOutOffXPixel() && - parent->GetOutOffYPixel() == pOutWin->GetOutOffYPixel()) + parent->GetOutOffXPixel() == mpOutputWindow->GetOutOffXPixel() && + parent->GetOutOffYPixel() == mpOutputWindow->GetOutOffYPixel()) { parent = parent->GetParent(); } if (parent) { - lcl_translateTwips(*parent->GetOutDev(), *pOutWin->GetOutDev()); + lcl_translateTwips(*parent->GetOutDev(), *mpOutputWindow->GetOutDev()); } } - bool bMm100ToTwip = !mpLOKSpecialPositioning && - (pOutWin->GetMapMode().GetMapUnit() == MapUnit::Map100thMM); + bool bMm100ToTwip = !mpLOKSpecialPositioning && (mpOutputWindow->GetMapMode().GetMapUnit() == MapUnit::Map100thMM); Point aOrigin; - if (pOutWin->GetMapMode().GetMapUnit() == MapUnit::MapTwip) + if (mpOutputWindow->GetMapMode().GetMapUnit() == MapUnit::MapTwip) // Writer comments: they use editeng, but are separate widgets. - aOrigin = pOutWin->GetMapMode().GetOrigin(); + aOrigin = mpOutputWindow->GetMapMode().GetOrigin(); OString sRectangle; OString sRefPoint; @@ -389,13 +388,13 @@ void ImpEditView::lokSelectionCallback(const std::optional<tools::PolyPolygon> & if (!aRectangles.empty()) { - if (pOutWin->IsChart()) + if (mpOutputWindow->IsChart()) { const vcl::Window* pViewShellWindow = mpViewShell->GetEditWindowForActiveOLEObj(); - if (pViewShellWindow && pViewShellWindow->IsAncestorOf(*pOutWin)) + if (pViewShellWindow && pViewShellWindow->IsAncestorOf(*mpOutputWindow)) { - Point aOffsetPx = pOutWin->GetOffsetPixelFrom(*pViewShellWindow); - Point aLogicOffset = pOutWin->PixelToLogic(aOffsetPx); + Point aOffsetPx = mpOutputWindow->GetOffsetPixelFrom(*pViewShellWindow); + Point aLogicOffset = mpOutputWindow->PixelToLogic(aOffsetPx); for (tools::Rectangle& rRect : aRectangles) rRect.Move(aLogicOffset.getX(), aLogicOffset.getY()); } @@ -423,7 +422,7 @@ void ImpEditView::lokSelectionCallback(const std::optional<tools::PolyPolygon> & if (mpLOKSpecialPositioning) aPayload += ":: " + sRefPoint; - mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION_START, aPayload.getStr()); + mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION_START, aPayload); tools::Rectangle& rEnd = aRectangles.back(); tools::Rectangle aEnd(rEnd.Right() - 1, rEnd.Top(), rEnd.Right(), rEnd.Bottom()); @@ -432,22 +431,22 @@ void ImpEditView::lokSelectionCallback(const std::optional<tools::PolyPolygon> & if (mpLOKSpecialPositioning) aPayload += ":: " + sRefPoint; - mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION_END, aPayload.getStr()); + mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION_END, aPayload); } if (mpOtherShell) { // Another shell wants to know about our existing selection. if (mpViewShell != mpOtherShell) - mpViewShell->NotifyOtherView(mpOtherShell, LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", sRectangle); + mpViewShell->NotifyOtherView(mpOtherShell, LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection"_ostr, sRectangle); } else { - mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION, sRectangle.getStr()); - mpViewShell->NotifyOtherViews(LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", sRectangle); + mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION, sRectangle); + mpViewShell->NotifyOtherViews(LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection"_ostr, sRectangle); } - pOutWin->GetOutDev()->Pop(); + mpOutputWindow->GetOutDev()->Pop(); } } @@ -472,7 +471,7 @@ void ImpEditView::DrawSelectionXOR( EditSelection aTmpSel, vcl::Region* pRegion, return; } - if ( eSelectionMode == EESelectionMode::Hidden ) + if (meSelectionMode == EESelectionMode::Hidden) return; // It must be ensured before rendering the selection, that the contents of @@ -491,9 +490,9 @@ void ImpEditView::DrawSelectionXOR( EditSelection aTmpSel, vcl::Region* pRegion, if ( !pRegion && !comphelper::LibreOfficeKit::isActive()) { - if ( !pEditEngine->pImpEditEngine->IsUpdateLayout() ) + if (!getImpEditEngine().IsUpdateLayout()) return; - if ( pEditEngine->pImpEditEngine->IsInUndo() ) + if (getImpEditEngine().IsInUndo()) return; if ( !aTmpSel.HasRange() ) @@ -501,30 +500,32 @@ void ImpEditView::DrawSelectionXOR( EditSelection aTmpSel, vcl::Region* pRegion, // aTmpOutArea: if OutputArea > Paper width and // Text > Paper width ( over large fields ) - tools::Rectangle aTmpOutArea( aOutArea ); - if ( aTmpOutArea.GetWidth() > pEditEngine->pImpEditEngine->GetPaperSize().Width() ) - aTmpOutArea.SetRight( aTmpOutArea.Left() + pEditEngine->pImpEditEngine->GetPaperSize().Width() ); + tools::Rectangle aTmpOutArea(maOutputArea); + if ( aTmpOutArea.GetWidth() > getImpEditEngine().GetPaperSize().Width() ) + aTmpOutArea.SetRight( aTmpOutArea.Left() + getImpEditEngine().GetPaperSize().Width() ); rTarget.IntersectClipRegion( aTmpOutArea ); - if (pOutWin && pOutWin->GetCursor()) - pOutWin->GetCursor()->Hide(); + if (mpOutputWindow && mpOutputWindow->GetCursor()) + mpOutputWindow->GetCursor()->Hide(); } if (comphelper::LibreOfficeKit::isActive() || pRegion) pPolyPoly = tools::PolyPolygon(); - DBG_ASSERT( !pEditEngine->IsIdleFormatterActive(), "DrawSelectionXOR: Not formatted!" ); - aTmpSel.Adjust( pEditEngine->GetEditDoc() ); + DBG_ASSERT(!getEditEngine().IsIdleFormatterActive(), "DrawSelectionXOR: Not formatted!"); + aTmpSel.Adjust(getEditEngine().GetEditDoc()); ContentNode* pStartNode = aTmpSel.Min().GetNode(); ContentNode* pEndNode = aTmpSel.Max().GetNode(); - const sal_Int32 nStartPara = pEditEngine->GetEditDoc().GetPos(pStartNode); - const sal_Int32 nEndPara = pEditEngine->GetEditDoc().GetPos(pEndNode); + const sal_Int32 nStartPara = getEditEngine().GetEditDoc().GetPos(pStartNode); + const sal_Int32 nEndPara = getEditEngine().GetEditDoc().GetPos(pEndNode); if (nStartPara == EE_PARA_NOT_FOUND || nEndPara == EE_PARA_NOT_FOUND) return; bool bStartHandleVisible = false; bool bEndHandleVisible = false; + bool bLOKCalcRTL = mpLOKSpecialPositioning && + (mpLOKSpecialPositioning->IsLayoutRTL() || getEditEngine().IsRightToLeft(nStartPara)); auto DrawHighlight = [&, nStartLine = sal_Int32(0), nEndLine = sal_Int32(0)]( const ImpEditEngine::LineAreaInfo& rInfo) mutable { @@ -575,9 +576,8 @@ void ImpEditView::DrawSelectionXOR( EditSelection aTmpSel, vcl::Region* pRegion, if (nEndIndex < nStartIndex) nEndIndex = nStartIndex; - tools::Rectangle aTmpRect(pEditEngine->pImpEditEngine->GetEditCursor( - &rInfo.rPortion, rInfo.pLine, nStartIndex, GetCursorFlags::NONE)); - const Size aLineOffset = pEditEngine->pImpEditEngine->getTopLeftDocOffset(rInfo.aArea); + tools::Rectangle aTmpRect(getImpEditEngine().GetEditCursor(rInfo.rPortion, *rInfo.pLine, nStartIndex, CursorFlags())); + const Size aLineOffset = getImpEditEngine().getTopLeftDocOffset(rInfo.aArea); aTmpRect.Move(0, aLineOffset.Height()); // Only paint if in the visible range ... @@ -595,13 +595,12 @@ void ImpEditView::DrawSelectionXOR( EditSelection aTmpSel, vcl::Region* pRegion, // Now that we have Bidi, the first/last index doesn't have to be the 'most outside' position if (!bPartOfLine) { - Range aLineXPosStartEnd - = pEditEngine->GetLineXPosStartEnd(&rInfo.rPortion, rInfo.pLine); + Range aLineXPosStartEnd = getEditEngine().GetLineXPosStartEnd(rInfo.rPortion, *rInfo.pLine); aTmpRect.SetLeft(aLineXPosStartEnd.Min()); aTmpRect.SetRight(aLineXPosStartEnd.Max()); aTmpRect.Move(aLineOffset.Width(), 0); ImplDrawHighlightRect(rTarget, aTmpRect.TopLeft(), aTmpRect.BottomRight(), - pPolyPoly ? &*pPolyPoly : nullptr); + pPolyPoly ? &*pPolyPoly : nullptr, bLOKCalcRTL); } else { @@ -610,33 +609,31 @@ void ImpEditView::DrawSelectionXOR( EditSelection aTmpSel, vcl::Region* pRegion, while (nTmpStartIndex < nEndIndex) { - pEditEngine->pImpEditEngine->GetRightToLeft(rInfo.nPortion, nTmpStartIndex + 1, + getImpEditEngine().GetRightToLeft(rInfo.nPortion, nTmpStartIndex + 1, &nWritingDirStart, &nTmpEndIndex); if (nTmpEndIndex > nEndIndex) nTmpEndIndex = nEndIndex; DBG_ASSERT(nTmpEndIndex > nTmpStartIndex, "DrawSelectionXOR, Start >= End?"); - tools::Long nX1 - = pEditEngine->GetXPos(&rInfo.rPortion, rInfo.pLine, nTmpStartIndex, true); - tools::Long nX2 - = pEditEngine->GetXPos(&rInfo.rPortion, rInfo.pLine, nTmpEndIndex); + tools::Long nX1 = getEditEngine().GetXPos(rInfo.rPortion, *rInfo.pLine, nTmpStartIndex, true); + tools::Long nX2 = getEditEngine().GetXPos(rInfo.rPortion, *rInfo.pLine, nTmpEndIndex); aTmpRect.SetLeft(std::min(nX1, nX2)); aTmpRect.SetRight(std::max(nX1, nX2)); aTmpRect.Move(aLineOffset.Width(), 0); ImplDrawHighlightRect(rTarget, aTmpRect.TopLeft(), aTmpRect.BottomRight(), - pPolyPoly ? &*pPolyPoly : nullptr); + pPolyPoly ? &*pPolyPoly : nullptr, bLOKCalcRTL); nTmpStartIndex = nTmpEndIndex; } } } return ImpEditEngine::CallbackResult::Continue; }; - pEditEngine->pImpEditEngine->IterateLineAreas(DrawHighlight, ImpEditEngine::IterFlag::none); + getImpEditEngine().IterateLineAreas(DrawHighlight, ImpEditEngine::IterFlag::none); - if (comphelper::LibreOfficeKit::isActive() && mpViewShell && pOutWin) + if (comphelper::LibreOfficeKit::isActive() && mpViewShell && mpOutputWindow) lokSelectionCallback(pPolyPoly, bStartHandleVisible, bEndHandleVisible); if (pRegion || comphelper::LibreOfficeKit::isActive()) @@ -647,8 +644,8 @@ void ImpEditView::DrawSelectionXOR( EditSelection aTmpSel, vcl::Region* pRegion, } else { - if (pOutWin && pOutWin->GetCursor()) - pOutWin->GetCursor()->Show(); + if (mpOutputWindow && mpOutputWindow->GetCursor()) + mpOutputWindow->GetCursor()->Show(); if (bClipRegion) rTarget.SetClipRegion(aOldRegion); @@ -664,7 +661,7 @@ void ImpEditView::GetSelectionRectangles(EditSelection aTmpSel, std::vector<tool aRegion.GetRegionRectangles(rLogicRects); } -void ImpEditView::ImplDrawHighlightRect( OutputDevice& rTarget, const Point& rDocPosTopLeft, const Point& rDocPosBottomRight, tools::PolyPolygon* pPolyPoly ) +void ImpEditView::ImplDrawHighlightRect( OutputDevice& rTarget, const Point& rDocPosTopLeft, const Point& rDocPosBottomRight, tools::PolyPolygon* pPolyPoly, bool bLOKCalcRTL ) { if ( rDocPosTopLeft.X() == rDocPosBottomRight.X() ) return; @@ -677,6 +674,13 @@ void ImpEditView::ImplDrawHighlightRect( OutputDevice& rTarget, const Point& rDo Point aRefPointLogical = GetOutputArea().TopLeft(); // Get the relative coordinates w.r.t refpoint in display units. aSelRect.Move(-aRefPointLogical.X(), -aRefPointLogical.Y()); + if (bLOKCalcRTL) + { + tools::Long nMirrorW = GetOutputArea().GetWidth(); + tools::Long nLeft = aSelRect.Left(), nRight = aSelRect.Right(); + aSelRect.SetLeft(nMirrorW - nRight); + aSelRect.SetRight(nMirrorW - nLeft); + } // Convert from display unit to twips. aSelRect = OutputDevice::LogicToLogic(aSelRect, MapMode(eDevUnit), MapMode(MapUnit::MapTwip)); @@ -738,12 +742,12 @@ void ImpEditView::ImplDrawHighlightRect( OutputDevice& rTarget, const Point& rDo bool ImpEditView::IsVertical() const { - return pEditEngine->pImpEditEngine->IsEffectivelyVertical(); + return getImpEditEngine().IsEffectivelyVertical(); } bool ImpEditView::IsTopToBottom() const { - return pEditEngine->pImpEditEngine->IsTopToBottom(); + return getImpEditEngine().IsTopToBottom(); } tools::Rectangle ImpEditView::GetVisDocArea() const @@ -756,22 +760,22 @@ Point ImpEditView::GetDocPos( const Point& rWindowPos ) const // Window Position => Position Document Point aPoint; - if ( !pEditEngine->pImpEditEngine->IsEffectivelyVertical() ) + if (!getImpEditEngine().IsEffectivelyVertical()) { - aPoint.setX( rWindowPos.X() - aOutArea.Left() + GetVisDocLeft() ); - aPoint.setY( rWindowPos.Y() - aOutArea.Top() + GetVisDocTop() ); + aPoint.setX( rWindowPos.X() - maOutputArea.Left() + GetVisDocLeft() ); + aPoint.setY( rWindowPos.Y() - maOutputArea.Top() + GetVisDocTop() ); } else { - if (pEditEngine->pImpEditEngine->IsTopToBottom()) + if (getImpEditEngine().IsTopToBottom()) { - aPoint.setX( rWindowPos.Y() - aOutArea.Top() + GetVisDocLeft() ); - aPoint.setY( aOutArea.Right() - rWindowPos.X() + GetVisDocTop() ); + aPoint.setX( rWindowPos.Y() - maOutputArea.Top() + GetVisDocLeft() ); + aPoint.setY( maOutputArea.Right() - rWindowPos.X() + GetVisDocTop() ); } else { - aPoint.setX( aOutArea.Bottom() - rWindowPos.Y() + GetVisDocLeft() ); - aPoint.setY( rWindowPos.X() - aOutArea.Left() + GetVisDocTop() ); + aPoint.setX( maOutputArea.Bottom() - rWindowPos.Y() + GetVisDocLeft() ); + aPoint.setY( rWindowPos.X() - maOutputArea.Left() + GetVisDocTop() ); } } @@ -783,22 +787,22 @@ Point ImpEditView::GetWindowPos( const Point& rDocPos ) const // Document position => window position Point aPoint; - if ( !pEditEngine->pImpEditEngine->IsEffectivelyVertical() ) + if (!getImpEditEngine().IsEffectivelyVertical()) { - aPoint.setX( rDocPos.X() + aOutArea.Left() - GetVisDocLeft() ); - aPoint.setY( rDocPos.Y() + aOutArea.Top() - GetVisDocTop() ); + aPoint.setX( rDocPos.X() + maOutputArea.Left() - GetVisDocLeft() ); + aPoint.setY( rDocPos.Y() + maOutputArea.Top() - GetVisDocTop() ); } else { - if (pEditEngine->pImpEditEngine->IsTopToBottom()) + if (getImpEditEngine().IsTopToBottom()) { - aPoint.setX( aOutArea.Right() - rDocPos.Y() + GetVisDocTop() ); - aPoint.setY( rDocPos.X() + aOutArea.Top() - GetVisDocLeft() ); + aPoint.setX( maOutputArea.Right() - rDocPos.Y() + GetVisDocTop() ); + aPoint.setY( rDocPos.X() + maOutputArea.Top() - GetVisDocLeft() ); } else { - aPoint.setX( aOutArea.Left() + rDocPos.Y() - GetVisDocTop() ); - aPoint.setY( aOutArea.Bottom() - rDocPos.X() + GetVisDocLeft() ); + aPoint.setX( maOutputArea.Left() + rDocPos.Y() - GetVisDocTop() ); + aPoint.setY( maOutputArea.Bottom() - rDocPos.X() + GetVisDocLeft() ); } } @@ -811,7 +815,7 @@ tools::Rectangle ImpEditView::GetWindowPos( const tools::Rectangle& rDocRect ) c Point aPos( GetWindowPos( rDocRect.TopLeft() ) ); Size aSz = rDocRect.GetSize(); tools::Rectangle aRect; - if ( !pEditEngine->pImpEditEngine->IsEffectivelyVertical() ) + if (!getImpEditEngine().IsEffectivelyVertical()) { aRect = tools::Rectangle( aPos, aSz ); } @@ -826,10 +830,10 @@ tools::Rectangle ImpEditView::GetWindowPos( const tools::Rectangle& rDocRect ) c void ImpEditView::SetSelectionMode( EESelectionMode eNewMode ) { - if ( eSelectionMode != eNewMode ) + if (meSelectionMode != eNewMode) { DrawSelectionXOR(); - eSelectionMode = eNewMode; + meSelectionMode = eNewMode; DrawSelectionXOR(); // redraw } } @@ -838,7 +842,7 @@ OutputDevice& ImpEditView::GetOutputDevice() const { if (EditViewCallbacks* pCallbacks = getEditViewCallbacks()) return pCallbacks->EditViewOutputDevice(); - return *pOutWin->GetOutDev(); + return *mpOutputWindow->GetOutDev(); } weld::Widget* ImpEditView::GetPopupParent(tools::Rectangle& rRect) const @@ -849,7 +853,7 @@ weld::Widget* ImpEditView::GetPopupParent(tools::Rectangle& rRect) const if (pParent) return pParent; } - return weld::GetPopupParent(*pOutWin, rRect); + return weld::GetPopupParent(*mpOutputWindow, rRect); } void ImpEditView::SetOutputArea( const tools::Rectangle& rRect ) @@ -858,13 +862,22 @@ void ImpEditView::SetOutputArea( const tools::Rectangle& rRect ) // should be better be aligned on pixels! tools::Rectangle aNewRect(rOutDev.LogicToPixel(rRect)); aNewRect = rOutDev.PixelToLogic(aNewRect); - aOutArea = aNewRect; - if ( !aOutArea.IsWidthEmpty() && aOutArea.Right() < aOutArea.Left() ) - aOutArea.SetRight( aOutArea.Left() ); - if ( !aOutArea.IsHeightEmpty() && aOutArea.Bottom() < aOutArea.Top() ) - aOutArea.SetBottom( aOutArea.Top() ); + maOutputArea = aNewRect; + if (!maOutputArea.IsWidthEmpty() && maOutputArea.Right() < maOutputArea.Left()) + maOutputArea.SetRight(maOutputArea.Left()); + if (!maOutputArea.IsHeightEmpty() && maOutputArea.Bottom() < maOutputArea.Top()) + maOutputArea.SetBottom(maOutputArea.Top()); + + SetScrollDiffX( static_cast<sal_uInt16>(maOutputArea.GetWidth()) * 2 / 10 ); +} + +namespace { + +tools::Rectangle lcl_negateRectX(const tools::Rectangle& rRect) +{ + return tools::Rectangle(-rRect.Right(), rRect.Top(), -rRect.Left(), rRect.Bottom()); +} - SetScrollDiffX( static_cast<sal_uInt16>(aOutArea.GetWidth()) * 2 / 10 ); } void ImpEditView::InvalidateAtWindow(const tools::Rectangle& rRect) @@ -874,107 +887,107 @@ void ImpEditView::InvalidateAtWindow(const tools::Rectangle& rRect) // do not invalidate and trigger a global repaint, but forward // the need for change to the applied EditViewCallback, can e.g. // be used to visualize the active edit text in an OverlayObject - pCallbacks->EditViewInvalidate(rRect); + pCallbacks->EditViewInvalidate(mbNegativeX ? lcl_negateRectX(rRect) : rRect); } else { // classic mode: invalidate and trigger full repaint // of the changed area - GetWindow()->Invalidate(rRect); + GetWindow()->Invalidate(mbNegativeX ? lcl_negateRectX(rRect) : rRect); } } void ImpEditView::ResetOutputArea( const tools::Rectangle& rRect ) { // remember old out area - const tools::Rectangle aOldArea(aOutArea); + const tools::Rectangle aOldArea(maOutputArea); // apply new one SetOutputArea(rRect); // invalidate surrounding areas if update is true - if(aOldArea.IsEmpty() || !pEditEngine->pImpEditEngine->IsUpdateLayout()) + if(aOldArea.IsEmpty() || !getImpEditEngine().IsUpdateLayout()) return; // #i119885# use grown area if needed; do when getting bigger OR smaller - const sal_Int32 nMore(DoInvalidateMore() ? GetOutputDevice().PixelToLogic(Size(nInvMore, 0)).Width() : 0); + const sal_Int32 nMore(DoInvalidateMore() ? GetOutputDevice().PixelToLogic(Size(mnInvalidateMore, 0)).Width() : 0); - if(aOldArea.Left() > aOutArea.Left()) + if (aOldArea.Left() > maOutputArea.Left()) { - const tools::Rectangle aRect(aOutArea.Left() - nMore, aOldArea.Top() - nMore, aOldArea.Left(), aOldArea.Bottom() + nMore); + const tools::Rectangle aRect(maOutputArea.Left() - nMore, aOldArea.Top() - nMore, aOldArea.Left(), aOldArea.Bottom() + nMore); InvalidateAtWindow(aRect); } - else if(aOldArea.Left() < aOutArea.Left()) + else if (aOldArea.Left() < maOutputArea.Left()) { - const tools::Rectangle aRect(aOldArea.Left() - nMore, aOldArea.Top() - nMore, aOutArea.Left(), aOldArea.Bottom() + nMore); + const tools::Rectangle aRect(aOldArea.Left() - nMore, aOldArea.Top() - nMore, maOutputArea.Left(), aOldArea.Bottom() + nMore); InvalidateAtWindow(aRect); } - if(aOldArea.Right() > aOutArea.Right()) + if (aOldArea.Right() > maOutputArea.Right()) { - const tools::Rectangle aRect(aOutArea.Right(), aOldArea.Top() - nMore, aOldArea.Right() + nMore, aOldArea.Bottom() + nMore); + const tools::Rectangle aRect(maOutputArea.Right(), aOldArea.Top() - nMore, aOldArea.Right() + nMore, aOldArea.Bottom() + nMore); InvalidateAtWindow(aRect); } - else if(aOldArea.Right() < aOutArea.Right()) + else if (aOldArea.Right() < maOutputArea.Right()) { - const tools::Rectangle aRect(aOldArea.Right(), aOldArea.Top() - nMore, aOutArea.Right() + nMore, aOldArea.Bottom() + nMore); + const tools::Rectangle aRect(aOldArea.Right(), aOldArea.Top() - nMore, maOutputArea.Right() + nMore, aOldArea.Bottom() + nMore); InvalidateAtWindow(aRect); } - if(aOldArea.Top() > aOutArea.Top()) + if (aOldArea.Top() > maOutputArea.Top()) { - const tools::Rectangle aRect(aOldArea.Left() - nMore, aOutArea.Top() - nMore, aOldArea.Right() + nMore, aOldArea.Top()); + const tools::Rectangle aRect(aOldArea.Left() - nMore, maOutputArea.Top() - nMore, aOldArea.Right() + nMore, aOldArea.Top()); InvalidateAtWindow(aRect); } - else if(aOldArea.Top() < aOutArea.Top()) + else if (aOldArea.Top() < maOutputArea.Top()) { - const tools::Rectangle aRect(aOldArea.Left() - nMore, aOldArea.Top() - nMore, aOldArea.Right() + nMore, aOutArea.Top()); + const tools::Rectangle aRect(aOldArea.Left() - nMore, aOldArea.Top() - nMore, aOldArea.Right() + nMore, maOutputArea.Top()); InvalidateAtWindow(aRect); } - if(aOldArea.Bottom() > aOutArea.Bottom()) + if (aOldArea.Bottom() > maOutputArea.Bottom()) { - const tools::Rectangle aRect(aOldArea.Left() - nMore, aOutArea.Bottom(), aOldArea.Right() + nMore, aOldArea.Bottom() + nMore); + const tools::Rectangle aRect(aOldArea.Left() - nMore, maOutputArea.Bottom(), aOldArea.Right() + nMore, aOldArea.Bottom() + nMore); InvalidateAtWindow(aRect); } - else if(aOldArea.Bottom() < aOutArea.Bottom()) + else if (aOldArea.Bottom() < maOutputArea.Bottom()) { - const tools::Rectangle aRect(aOldArea.Left() - nMore, aOldArea.Bottom(), aOldArea.Right() + nMore, aOutArea.Bottom() + nMore); + const tools::Rectangle aRect(aOldArea.Left() - nMore, aOldArea.Bottom(), aOldArea.Right() + nMore, maOutputArea.Bottom() + nMore); InvalidateAtWindow(aRect); } } void ImpEditView::RecalcOutputArea() { - Point aNewTopLeft( aOutArea.TopLeft() ); - Size aNewSz( aOutArea.GetSize() ); + Point aNewTopLeft(maOutputArea.TopLeft()); + Size aNewSz(maOutputArea.GetSize()); // X: if ( DoAutoWidth() ) { - if ( pEditEngine->pImpEditEngine->GetStatus().AutoPageWidth() ) - aNewSz.setWidth( pEditEngine->pImpEditEngine->GetPaperSize().Width() ); - switch ( eAnchorMode ) + if (getImpEditEngine().GetStatus().AutoPageWidth()) + aNewSz.setWidth(getImpEditEngine().GetPaperSize().Width()); + switch (meAnchorMode) { case EEAnchorMode::TopLeft: case EEAnchorMode::VCenterLeft: case EEAnchorMode::BottomLeft: { - aNewTopLeft.setX( aAnchorPoint.X() ); + aNewTopLeft.setX(maAnchorPoint.X()); } break; case EEAnchorMode::TopHCenter: case EEAnchorMode::VCenterHCenter: case EEAnchorMode::BottomHCenter: { - aNewTopLeft.setX( aAnchorPoint.X() - aNewSz.Width() / 2 ); + aNewTopLeft.setX(maAnchorPoint.X() - aNewSz.Width() / 2); } break; case EEAnchorMode::TopRight: case EEAnchorMode::VCenterRight: case EEAnchorMode::BottomRight: { - aNewTopLeft.setX( aAnchorPoint.X() - aNewSz.Width() - 1 ); + aNewTopLeft.setX(maAnchorPoint.X() - aNewSz.Width() - 1); } break; } @@ -983,29 +996,29 @@ void ImpEditView::RecalcOutputArea() // Y: if ( DoAutoHeight() ) { - if ( pEditEngine->pImpEditEngine->GetStatus().AutoPageHeight() ) - aNewSz.setHeight( pEditEngine->pImpEditEngine->GetPaperSize().Height() ); - switch ( eAnchorMode ) + if (getImpEditEngine().GetStatus().AutoPageHeight()) + aNewSz.setHeight(getImpEditEngine().GetPaperSize().Height()); + switch (meAnchorMode) { case EEAnchorMode::TopLeft: case EEAnchorMode::TopHCenter: case EEAnchorMode::TopRight: { - aNewTopLeft.setY( aAnchorPoint.Y() ); + aNewTopLeft.setY(maAnchorPoint.Y()); } break; case EEAnchorMode::VCenterLeft: case EEAnchorMode::VCenterHCenter: case EEAnchorMode::VCenterRight: { - aNewTopLeft.setY( aAnchorPoint.Y() - aNewSz.Height() / 2 ); + aNewTopLeft.setY(maAnchorPoint.Y() - aNewSz.Height() / 2); } break; case EEAnchorMode::BottomLeft: case EEAnchorMode::BottomHCenter: case EEAnchorMode::BottomRight: { - aNewTopLeft.setY( aAnchorPoint.Y() - aNewSz.Height() - 1 ); + aNewTopLeft.setY(maAnchorPoint.Y() - aNewSz.Height() - 1); } break; } @@ -1013,9 +1026,9 @@ void ImpEditView::RecalcOutputArea() ResetOutputArea( tools::Rectangle( aNewTopLeft, aNewSz ) ); } -void ImpEditView::SetAnchorMode( EEAnchorMode eMode ) +void ImpEditView::SetAnchorMode(EEAnchorMode eMode) { - eAnchorMode = eMode; + meAnchorMode = eMode; CalcAnchorPoint(); } @@ -1024,53 +1037,53 @@ void ImpEditView::CalcAnchorPoint() // GetHeight() and GetWidth() -1, because rectangle calculation not preferred. // X: - switch ( eAnchorMode ) + switch (meAnchorMode) { case EEAnchorMode::TopLeft: case EEAnchorMode::VCenterLeft: case EEAnchorMode::BottomLeft: { - aAnchorPoint.setX( aOutArea.Left() ); + maAnchorPoint.setX(maOutputArea.Left()); } break; case EEAnchorMode::TopHCenter: case EEAnchorMode::VCenterHCenter: case EEAnchorMode::BottomHCenter: { - aAnchorPoint.setX( aOutArea.Left() + (aOutArea.GetWidth()-1) / 2 ); + maAnchorPoint.setX(maOutputArea.Left() + (maOutputArea.GetWidth() - 1) / 2); } break; case EEAnchorMode::TopRight: case EEAnchorMode::VCenterRight: case EEAnchorMode::BottomRight: { - aAnchorPoint.setX( aOutArea.Right() ); + maAnchorPoint.setX(maOutputArea.Right()); } break; } // Y: - switch ( eAnchorMode ) + switch (meAnchorMode) { case EEAnchorMode::TopLeft: case EEAnchorMode::TopHCenter: case EEAnchorMode::TopRight: { - aAnchorPoint.setY( aOutArea.Top() ); + maAnchorPoint.setY(maOutputArea.Top()); } break; case EEAnchorMode::VCenterLeft: case EEAnchorMode::VCenterHCenter: case EEAnchorMode::VCenterRight: { - aAnchorPoint.setY( aOutArea.Top() + (aOutArea.GetHeight()-1) / 2 ); + maAnchorPoint.setY(maOutputArea.Top() + (maOutputArea.GetHeight() - 1) / 2); } break; case EEAnchorMode::BottomLeft: case EEAnchorMode::BottomHCenter: case EEAnchorMode::BottomRight: { - aAnchorPoint.setY( aOutArea.Bottom() - 1 ); + maAnchorPoint.setY(maOutputArea.Bottom() - 1); } break; } @@ -1090,36 +1103,35 @@ boost::property_tree::ptree getHyperlinkPropTree(const OUString& sText, const OU } // End of anon namespace -tools::Rectangle ImpEditView::ImplGetEditCursor(EditPaM& aPaM, GetCursorFlags nShowCursorFlags, sal_Int32& nTextPortionStart, - const ParaPortion* pParaPortion) const +tools::Rectangle ImpEditView::ImplGetEditCursor(EditPaM& aPaM, CursorFlags aShowCursorFlags, sal_Int32& nTextPortionStart, ParaPortion const& rParaPortion) const { - tools::Rectangle aEditCursor = pEditEngine->pImpEditEngine->PaMtoEditCursor( aPaM, nShowCursorFlags ); - if ( !IsInsertMode() && !aEditSelection.HasRange() ) + tools::Rectangle aEditCursor = getImpEditEngine().PaMtoEditCursor(aPaM, aShowCursorFlags); + if (!IsInsertMode() && !maEditSelection.HasRange()) { if ( aPaM.GetNode()->Len() && ( aPaM.GetIndex() < aPaM.GetNode()->Len() ) ) { // If we are behind a portion, and the next portion has other direction, we must change position... - aEditCursor.SetLeft( pEditEngine->pImpEditEngine->PaMtoEditCursor( aPaM, GetCursorFlags::TextOnly|GetCursorFlags::PreferPortionStart ).Left() ); + aEditCursor.SetLeft(getImpEditEngine().PaMtoEditCursor(aPaM, CursorFlags{.bTextOnly = true, .bPreferPortionStart = true}).Left()); aEditCursor.SetRight( aEditCursor.Left() ); - sal_Int32 nTextPortion = pParaPortion->GetTextPortions().FindPortion( aPaM.GetIndex(), nTextPortionStart, true ); - const TextPortion& rTextPortion = pParaPortion->GetTextPortions()[nTextPortion]; + sal_Int32 nTextPortion = rParaPortion.GetTextPortions().FindPortion( aPaM.GetIndex(), nTextPortionStart, true ); + const TextPortion& rTextPortion = rParaPortion.GetTextPortions()[nTextPortion]; if ( rTextPortion.GetKind() == PortionKind::TAB ) { aEditCursor.AdjustRight(rTextPortion.GetSize().Width() ); } else { - EditPaM aNext = pEditEngine->CursorRight( aPaM ); - tools::Rectangle aTmpRect = pEditEngine->pImpEditEngine->PaMtoEditCursor( aNext, GetCursorFlags::TextOnly ); + EditPaM aNext = getEditEngine().CursorRight( aPaM ); + tools::Rectangle aTmpRect = getImpEditEngine().PaMtoEditCursor(aNext, CursorFlags{ .bTextOnly = true }); if ( aTmpRect.Top() != aEditCursor.Top() ) - aTmpRect = pEditEngine->pImpEditEngine->PaMtoEditCursor( aNext, GetCursorFlags::TextOnly|GetCursorFlags::EndOfLine ); + aTmpRect = getImpEditEngine().PaMtoEditCursor(aNext, CursorFlags{ .bTextOnly = true, .bEndOfLine = true }); aEditCursor.SetRight( aTmpRect.Left() ); } } } - tools::Long nMaxHeight = !IsVertical() ? aOutArea.GetHeight() : aOutArea.GetWidth(); + tools::Long nMaxHeight = !IsVertical() ? maOutputArea.GetHeight() : maOutputArea.GetWidth(); if ( aEditCursor.GetHeight() > nMaxHeight ) { aEditCursor.SetBottom( aEditCursor.Top() + nMaxHeight - 1 ); @@ -1130,16 +1142,17 @@ tools::Rectangle ImpEditView::ImplGetEditCursor(EditPaM& aPaM, GetCursorFlags nS tools::Rectangle ImpEditView::GetEditCursor() const { - EditPaM aPaM( aEditSelection.Max() ); + EditPaM aPaM(maEditSelection.Max()); sal_Int32 nTextPortionStart = 0; - sal_Int32 nPara = pEditEngine->GetEditDoc().GetPos( aPaM.GetNode() ); + sal_Int32 nPara = getEditEngine().GetEditDoc().GetPos( aPaM.GetNode() ); if (nPara == EE_PARA_NOT_FOUND) // #i94322 return tools::Rectangle(); - const ParaPortion& rParaPortion = pEditEngine->GetParaPortions()[nPara]; + ParaPortion const& rParaPortion = getEditEngine().GetParaPortions().getRef(nPara); - GetCursorFlags nShowCursorFlags = nExtraCursorFlags | GetCursorFlags::TextOnly; + CursorFlags aShowCursorFlags = maExtraCursorFlags; + aShowCursorFlags.bTextOnly = true; // Use CursorBidiLevel 0/1 in meaning of // 0: prefer portion end, normal mode @@ -1147,46 +1160,47 @@ tools::Rectangle ImpEditView::GetEditCursor() const if ( ( GetCursorBidiLevel() != CURSOR_BIDILEVEL_DONTKNOW ) && GetCursorBidiLevel() ) { - nShowCursorFlags |= GetCursorFlags::PreferPortionStart; + aShowCursorFlags.bPreferPortionStart = true; } - return ImplGetEditCursor(aPaM, nShowCursorFlags, nTextPortionStart, &rParaPortion); + return ImplGetEditCursor(aPaM, aShowCursorFlags, nTextPortionStart, rParaPortion); } void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) { // No ShowCursor in an empty View ... - if (aOutArea.IsEmpty()) + if (maOutputArea.IsEmpty()) return; - if ( ( aOutArea.Left() >= aOutArea.Right() ) && ( aOutArea.Top() >= aOutArea.Bottom() ) ) + if ( (maOutputArea.Left() >= maOutputArea.Right() ) && ( maOutputArea.Top() >= maOutputArea.Bottom() ) ) return; - pEditEngine->CheckIdleFormatter(); - if (!pEditEngine->IsFormatted()) - pEditEngine->pImpEditEngine->FormatDoc(); + getEditEngine().CheckIdleFormatter(); + if (!getEditEngine().IsFormatted()) + getImpEditEngine().FormatDoc(); // For some reasons I end up here during the formatting, if the Outliner // is initialized in Paint, because no SetPool(); - if ( pEditEngine->pImpEditEngine->IsFormatting() ) + if (getImpEditEngine().IsFormatting()) return; - if ( !pEditEngine->pImpEditEngine->IsUpdateLayout() ) + if (!getImpEditEngine().IsUpdateLayout()) return; - if ( pEditEngine->pImpEditEngine->IsInUndo() ) + if (getImpEditEngine().IsInUndo()) return; - if (pOutWin && pOutWin->GetCursor() != GetCursor()) - pOutWin->SetCursor(GetCursor()); + if (mpOutputWindow && mpOutputWindow->GetCursor() != GetCursor()) + mpOutputWindow->SetCursor(GetCursor()); - EditPaM aPaM( aEditSelection.Max() ); + EditPaM aPaM(maEditSelection.Max()); sal_Int32 nTextPortionStart = 0; - sal_Int32 nPara = pEditEngine->GetEditDoc().GetPos( aPaM.GetNode() ); + sal_Int32 nPara = getEditEngine().GetEditDoc().GetPos( aPaM.GetNode() ); if (nPara == EE_PARA_NOT_FOUND) // #i94322 return; - const ParaPortion& rParaPortion = pEditEngine->GetParaPortions()[nPara]; + ParaPortion const& rParaPortion = getEditEngine().GetParaPortions().getRef(nPara); - GetCursorFlags nShowCursorFlags = nExtraCursorFlags | GetCursorFlags::TextOnly; + CursorFlags aShowCursorFlags = maExtraCursorFlags; + aShowCursorFlags.bTextOnly = true; // Use CursorBidiLevel 0/1 in meaning of // 0: prefer portion end, normal mode @@ -1194,12 +1208,12 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) if ( ( GetCursorBidiLevel() != CURSOR_BIDILEVEL_DONTKNOW ) && GetCursorBidiLevel() ) { - nShowCursorFlags |= GetCursorFlags::PreferPortionStart; + aShowCursorFlags.bPreferPortionStart = true; } - tools::Rectangle aEditCursor = ImplGetEditCursor(aPaM, nShowCursorFlags, nTextPortionStart, &rParaPortion); + tools::Rectangle aEditCursor = ImplGetEditCursor(aPaM, aShowCursorFlags, nTextPortionStart, rParaPortion); - if ( bGotoCursor ) // && (!pEditEngine->pImpEditEngine->GetStatus().AutoPageSize() ) ) + if ( bGotoCursor ) // && (!getImpEditEngine().GetStatus().AutoPageSize() ) ) { // check if scrolling is necessary... // if scrolling, then update () and Scroll ()! @@ -1209,7 +1223,7 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) tools::Rectangle aTmpVisArea( GetVisDocArea() ); // aTmpOutArea: if OutputArea > Paper width and // Text > Paper width ( over large fields ) - tools::Long nMaxTextWidth = !IsVertical() ? pEditEngine->pImpEditEngine->GetPaperSize().Width() : pEditEngine->pImpEditEngine->GetPaperSize().Height(); + tools::Long nMaxTextWidth = !IsVertical() ? getImpEditEngine().GetPaperSize().Width() : getImpEditEngine().GetPaperSize().Height(); if ( aTmpVisArea.GetWidth() > nMaxTextWidth ) aTmpVisArea.SetRight( aTmpVisArea.Left() + nMaxTextWidth ); @@ -1263,11 +1277,11 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) tools::Long nDiffY = !IsVertical() ? nDocDiffY : (IsTopToBottom() ? nDocDiffX : -nDocDiffX); if ( nDiffX ) - pEditEngine->GetInternalEditStatus().GetStatusWord() = pEditEngine->GetInternalEditStatus().GetStatusWord() | EditStatusFlags::HSCROLL; + getEditEngine().GetInternalEditStatus().GetStatusWord() = getEditEngine().GetInternalEditStatus().GetStatusWord() | EditStatusFlags::HSCROLL; if ( nDiffY ) - pEditEngine->GetInternalEditStatus().GetStatusWord() = pEditEngine->GetInternalEditStatus().GetStatusWord() | EditStatusFlags::VSCROLL; + getEditEngine().GetInternalEditStatus().GetStatusWord() = getEditEngine().GetInternalEditStatus().GetStatusWord() | EditStatusFlags::VSCROLL; Scroll( -nDiffX, -nDiffY ); - pEditEngine->pImpEditEngine->DelayedCallStatusHdl(); + getImpEditEngine().DelayedCallStatusHdl(); } } @@ -1339,6 +1353,13 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) Point aRefPointLogical = GetOutputArea().TopLeft(); // Get the relative coordinates w.r.t refpoint in display hmm. aCursorRectPureLogical.Move(-aRefPointLogical.X(), -aRefPointLogical.Y()); + if (getEditEngine().IsRightToLeft(nPara) || mpLOKSpecialPositioning->IsLayoutRTL()) + { + tools::Long nMirrorW = GetOutputArea().GetWidth(); + tools::Long nLeft = aCursorRectPureLogical.Left(), nRight = aCursorRectPureLogical.Right(); + aCursorRectPureLogical.SetLeft(nMirrorW - nRight); + aCursorRectPureLogical.SetRight(nMirrorW - nLeft); + } // Convert to twips. aCursorRectPureLogical = OutputDevice::LogicToLogic(aCursorRectPureLogical, MapMode(eDevUnit), MapMode(MapUnit::MapTwip)); // "refpoint" in print twips. @@ -1347,13 +1368,13 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) aMessageParams.put("refpoint", aRefPoint.toString()); } - if (pOutWin && pOutWin->IsChart()) + if (mpOutputWindow && mpOutputWindow->IsChart()) { const vcl::Window* pViewShellWindow = mpViewShell->GetEditWindowForActiveOLEObj(); - if (pViewShellWindow && pViewShellWindow->IsAncestorOf(*pOutWin)) + if (pViewShellWindow && pViewShellWindow->IsAncestorOf(*mpOutputWindow)) { - Point aOffsetPx = pOutWin->GetOffsetPixelFrom(*pViewShellWindow); - Point aLogicOffset = pOutWin->PixelToLogic(aOffsetPx); + Point aOffsetPx = mpOutputWindow->GetOffsetPixelFrom(*pViewShellWindow); + Point aLogicOffset = mpOutputWindow->PixelToLogic(aOffsetPx); aPos.Move(aLogicOffset.getX(), aLogicOffset.getY()); } } @@ -1391,21 +1412,19 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) else { // is cursor at a misspelled word ? - Reference< linguistic2::XSpellChecker1 > xSpeller( pEditEngine->pImpEditEngine->GetSpeller() ); + uno::Reference<linguistic2::XSpellChecker1> xSpeller(getImpEditEngine().GetSpeller()); bool bIsWrong = xSpeller.is() && IsWrongSpelledWord(aPaM, /*bMarkIfWrong*/ false); + EditView* pActiveView = GetEditViewPtr(); boost::property_tree::ptree aHyperlinkTree; - if (const SvxFieldItem* pFld = GetField(aPos, nullptr, nullptr)) + if (pActiveView && URLFieldHelper::IsCursorAtURLField(*pActiveView)) { - if (auto pUrlField = dynamic_cast<const SvxURLField*>(pFld->GetField())) - { - aHyperlinkTree = getHyperlinkPropTree(pUrlField->GetRepresentation(), pUrlField->GetURL()); - } + if (const SvxFieldItem* pFld = GetField(aPos, nullptr, nullptr)) + if (auto pUrlField = dynamic_cast<const SvxURLField*>(pFld->GetField())) + aHyperlinkTree = getHyperlinkPropTree(pUrlField->GetRepresentation(), pUrlField->GetURL()); } else if (GetEditSelection().HasRange()) { - EditView* pActiveView = GetEditViewPtr(); - if (pActiveView) { const SvxFieldItem* pFieldItem = pActiveView->GetFieldAtSelection(); @@ -1432,14 +1451,14 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, aMessageParams); else pThisShell->libreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, - aMessageParams.get<std::string>("rectangle").c_str()); + OString(aMessageParams.get<std::string>("rectangle"))); } } CursorDirection nCursorDir = CursorDirection::NONE; - if ( IsInsertMode() && !aEditSelection.HasRange() && ( pEditEngine->pImpEditEngine->HasDifferentRTLLevels( aPaM.GetNode() ) ) ) + if ( IsInsertMode() && !maEditSelection.HasRange() && (getImpEditEngine().HasDifferentRTLLevels(aPaM.GetNode()) ) ) { - sal_uInt16 nTextPortion = rParaPortion.GetTextPortions().FindPortion( aPaM.GetIndex(), nTextPortionStart, bool(nShowCursorFlags & GetCursorFlags::PreferPortionStart) ); + sal_uInt16 nTextPortion = rParaPortion.GetTextPortions().FindPortion( aPaM.GetIndex(), nTextPortionStart, aShowCursorFlags.bPreferPortionStart); const TextPortion& rTextPortion = rParaPortion.GetTextPortions()[nTextPortion]; if (rTextPortion.IsRightToLeft()) nCursorDir = CursorDirection::RTL; @@ -1453,9 +1472,9 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) GetCursor()->Show(); { SvxFont aFont; - pEditEngine->SeekCursor( aPaM.GetNode(), aPaM.GetIndex()+1, aFont ); + getEditEngine().SeekCursor( aPaM.GetNode(), aPaM.GetIndex()+1, aFont ); - InputContext aInputContext(aFont, InputContextFlags::Text | InputContextFlags::ExtText); + InputContext aInputContext(std::move(aFont), InputContextFlags::Text | InputContextFlags::ExtText); if (EditViewCallbacks* pCallbacks = getEditViewCallbacks()) pCallbacks->EditViewInputContext(aInputContext); else if (auto xWindow = GetWindow()) @@ -1464,7 +1483,7 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) } else { - pEditEngine->pImpEditEngine->GetStatus().GetStatusWord() = pEditEngine->pImpEditEngine->GetStatus().GetStatusWord() | EditStatusFlags::CURSOROUT; + getImpEditEngine().GetStatus().GetStatusWord() = getImpEditEngine().GetStatus().GetStatusWord() | EditStatusFlags::CURSOROUT; GetCursor()->Hide(); GetCursor()->SetPos( Point( -1, -1 ) ); GetCursor()->SetSize( Size( 0, 0 ) ); @@ -1482,17 +1501,17 @@ void ImpEditView::ScrollStateChange() Pair ImpEditView::Scroll( tools::Long ndX, tools::Long ndY, ScrollRangeCheck nRangeCheck ) { - DBG_ASSERT( pEditEngine->pImpEditEngine->IsFormatted(), "Scroll: Not formatted!" ); + DBG_ASSERT(getImpEditEngine().IsFormatted(), "Scroll: Not formatted!"); if ( !ndX && !ndY ) return Pair( 0, 0 ); const OutputDevice& rOutDev = GetOutputDevice(); #ifdef DBG_UTIL - tools::Rectangle aR( aOutArea ); + tools::Rectangle aR(maOutputArea); aR = rOutDev.LogicToPixel( aR ); aR = rOutDev.PixelToLogic( aR ); - SAL_WARN_IF( aR != aOutArea, "editeng", "OutArea before Scroll not aligned" ); + SAL_WARN_IF(aR != maOutputArea, "editeng", "OutArea before Scroll not aligned"); #endif tools::Rectangle aNewVisArea( GetVisDocArea() ); @@ -1516,10 +1535,10 @@ Pair ImpEditView::Scroll( tools::Long ndX, tools::Long ndY, ScrollRangeCheck nRa aNewVisArea.AdjustBottom( -ndX ); } } - if ( ( nRangeCheck == ScrollRangeCheck::PaperWidthTextSize ) && ( aNewVisArea.Bottom() > static_cast<tools::Long>(pEditEngine->pImpEditEngine->GetTextHeight()) ) ) + if ( ( nRangeCheck == ScrollRangeCheck::PaperWidthTextSize ) && ( aNewVisArea.Bottom() > static_cast<tools::Long>(getImpEditEngine().GetTextHeight()) ) ) { // GetTextHeight still optimizing! - tools::Long nDiff = pEditEngine->pImpEditEngine->GetTextHeight() - aNewVisArea.Bottom(); // negative + tools::Long nDiff = getImpEditEngine().GetTextHeight() - aNewVisArea.Bottom(); // negative aNewVisArea.Move( 0, nDiff ); // could end up in the negative area... } if ( aNewVisArea.Top() < 0 ) @@ -1544,9 +1563,9 @@ Pair ImpEditView::Scroll( tools::Long ndX, tools::Long ndY, ScrollRangeCheck nRa aNewVisArea.AdjustRight(ndY ); } } - if ( ( nRangeCheck == ScrollRangeCheck::PaperWidthTextSize ) && ( aNewVisArea.Right() > static_cast<tools::Long>(pEditEngine->pImpEditEngine->CalcTextWidth( false )) ) ) + if ( ( nRangeCheck == ScrollRangeCheck::PaperWidthTextSize ) && ( aNewVisArea.Right() > static_cast<tools::Long>(getImpEditEngine().CalcTextWidth( false )) ) ) { - tools::Long nDiff = pEditEngine->pImpEditEngine->CalcTextWidth( false ) - aNewVisArea.Right(); // negative + tools::Long nDiff = getImpEditEngine().CalcTextWidth( false ) - aNewVisArea.Right(); // negative aNewVisArea.Move( nDiff, 0 ); // could end up in the negative area... } if ( aNewVisArea.Left() < 0 ) @@ -1569,48 +1588,48 @@ Pair ImpEditView::Scroll( tools::Long ndX, tools::Long ndY, ScrollRangeCheck nRa vcl::Cursor* pCrsr = GetCursor(); bool bVisCursor = pCrsr->IsVisible(); pCrsr->Hide(); - if (pOutWin) - pOutWin->PaintImmediately(); - if ( !IsVertical() ) - aVisDocStartPos.Move( -nRealDiffX, -nRealDiffY ); + if (mpOutputWindow) + mpOutputWindow->PaintImmediately(); + if (!IsVertical()) + maVisDocStartPos.Move(-nRealDiffX, -nRealDiffY); else { if (IsTopToBottom()) - aVisDocStartPos.Move(-nRealDiffY, nRealDiffX); + maVisDocStartPos.Move(-nRealDiffY, nRealDiffX); else - aVisDocStartPos.Move(nRealDiffY, -nRealDiffX); + maVisDocStartPos.Move(nRealDiffY, -nRealDiffX); } // Move by aligned value does not necessarily result in aligned // rectangle ... - aVisDocStartPos = rOutDev.LogicToPixel( aVisDocStartPos ); - aVisDocStartPos = rOutDev.PixelToLogic( aVisDocStartPos ); - tools::Rectangle aRect( aOutArea ); + maVisDocStartPos = rOutDev.LogicToPixel(maVisDocStartPos); + maVisDocStartPos = rOutDev.PixelToLogic(maVisDocStartPos); + tools::Rectangle aRect(maOutputArea); - if (pOutWin) + if (mpOutputWindow) { - pOutWin->Scroll( nRealDiffX, nRealDiffY, aRect, ScrollFlags::Clip ); + mpOutputWindow->Scroll( nRealDiffX, nRealDiffY, aRect, ScrollFlags::Clip ); } if (comphelper::LibreOfficeKit::isActive() || getEditViewCallbacks()) { // Need to invalidate the window, otherwise no tile will be re-painted. - pEditView->Invalidate(); + GetEditViewPtr()->Invalidate(); } - if (pOutWin) - pOutWin->PaintImmediately(); + if (mpOutputWindow) + mpOutputWindow->PaintImmediately(); pCrsr->SetPos( pCrsr->GetPos() + Point( nRealDiffX, nRealDiffY ) ); if ( bVisCursor ) { tools::Rectangle aCursorRect( pCrsr->GetPos(), pCrsr->GetSize() ); - if ( aOutArea.Contains( aCursorRect ) ) + if (maOutputArea.Contains(aCursorRect)) pCrsr->Show(); } - if ( pEditEngine->pImpEditEngine->GetNotifyHdl().IsSet() ) + if (getImpEditEngine().GetNotifyHdl().IsSet()) { EENotify aNotify( EE_NOTIFY_TEXTVIEWSCROLLED ); - pEditEngine->pImpEditEngine->GetNotifyHdl().Call( aNotify ); + getImpEditEngine().GetNotifyHdl().Call( aNotify ); } if (EditViewCallbacks* pCallbacks = getEditViewCallbacks()) @@ -1625,7 +1644,7 @@ Pair ImpEditView::Scroll( tools::Long ndX, tools::Long ndY, ScrollRangeCheck nRa return Pair( nRealDiffX, nRealDiffY ); } -Reference<css::datatransfer::clipboard::XClipboard> ImpEditView::GetClipboard() const +uno::Reference<datatransfer::clipboard::XClipboard> ImpEditView::GetClipboard() const { if (EditViewCallbacks* pCallbacks = getEditViewCallbacks()) return pCallbacks->GetClipboard(); @@ -1646,9 +1665,9 @@ bool ImpEditView::PostKeyEvent( const KeyEvent& rKeyEvent, vcl::Window const * p { case KeyFuncType::CUT: { - if ( !bReadOnly ) + if (!mbReadOnly) { - Reference<css::datatransfer::clipboard::XClipboard> aClipBoard(GetClipboard()); + uno::Reference<datatransfer::clipboard::XClipboard> aClipBoard(GetClipboard()); CutCopy( aClipBoard, true ); bDone = true; } @@ -1656,19 +1675,19 @@ bool ImpEditView::PostKeyEvent( const KeyEvent& rKeyEvent, vcl::Window const * p break; case KeyFuncType::COPY: { - Reference<css::datatransfer::clipboard::XClipboard> aClipBoard(GetClipboard()); + uno::Reference<datatransfer::clipboard::XClipboard> aClipBoard(GetClipboard()); CutCopy( aClipBoard, false ); bDone = true; } break; case KeyFuncType::PASTE: { - if ( !bReadOnly && IsPasteEnabled() ) + if (!mbReadOnly && IsPasteEnabled()) { - pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_PASTE ); - Reference<css::datatransfer::clipboard::XClipboard> aClipBoard(GetClipboard()); - Paste( aClipBoard, pEditEngine->pImpEditEngine->GetStatus().AllowPasteSpecial() ); - pEditEngine->pImpEditEngine->UndoActionEnd(); + getImpEditEngine().UndoActionStart( EDITUNDO_PASTE ); + uno::Reference<datatransfer::clipboard::XClipboard> aClipBoard(GetClipboard()); + Paste( aClipBoard, getImpEditEngine().GetStatus().AllowPasteSpecial() ); + getImpEditEngine().UndoActionEnd(); bDone = true; } } @@ -1679,57 +1698,60 @@ bool ImpEditView::PostKeyEvent( const KeyEvent& rKeyEvent, vcl::Window const * p } if( !bDone ) - bDone = pEditEngine->PostKeyEvent( rKeyEvent, GetEditViewPtr(), pFrameWin ); + bDone = getEditEngine().PostKeyEvent( rKeyEvent, GetEditViewPtr(), pFrameWin ); return bDone; } bool ImpEditView::MouseButtonUp( const MouseEvent& rMouseEvent ) { - nTravelXPos = TRAVEL_X_DONTKNOW; - nCursorBidiLevel = CURSOR_BIDILEVEL_DONTKNOW; - nExtraCursorFlags = GetCursorFlags::NONE; - bClickedInSelection = false; + mnTravelXPos = TRAVEL_X_DONTKNOW; + mnCursorBidiLevel = CURSOR_BIDILEVEL_DONTKNOW; + maExtraCursorFlags = CursorFlags(); + mbClickedInSelection = false; - if ( rMouseEvent.IsMiddle() && !bReadOnly && + if ( rMouseEvent.IsMiddle() && !mbReadOnly && Application::GetSettings().GetMouseSettings().GetMiddleButtonAction() == MouseMiddleButtonAction::PasteSelection ) { - Reference<css::datatransfer::clipboard::XClipboard> aClipBoard(GetSystemPrimarySelection()); + uno::Reference<datatransfer::clipboard::XClipboard> aClipBoard(GetSystemPrimarySelection()); Paste( aClipBoard ); } else if ( rMouseEvent.IsLeft() && GetEditSelection().HasRange() ) { - Reference<css::datatransfer::clipboard::XClipboard> aClipBoard(GetSystemPrimarySelection()); + uno::Reference<datatransfer::clipboard::XClipboard> aClipBoard(GetSystemPrimarySelection()); CutCopy( aClipBoard, false ); } - return pEditEngine->pImpEditEngine->MouseButtonUp( rMouseEvent, GetEditViewPtr() ); + return getImpEditEngine().MouseButtonUp( rMouseEvent, GetEditViewPtr() ); } void ImpEditView::ReleaseMouse() { - pEditEngine->pImpEditEngine->ReleaseMouse(); + getImpEditEngine().ReleaseMouse(); } bool ImpEditView::MouseButtonDown( const MouseEvent& rMouseEvent ) { - pEditEngine->CheckIdleFormatter(); // If fast typing and mouse button downs - nTravelXPos = TRAVEL_X_DONTKNOW; - nExtraCursorFlags = GetCursorFlags::NONE; - nCursorBidiLevel = CURSOR_BIDILEVEL_DONTKNOW; - bClickedInSelection = IsSelectionAtPoint( rMouseEvent.GetPosPixel() ); - return pEditEngine->pImpEditEngine->MouseButtonDown( rMouseEvent, GetEditViewPtr() ); + getEditEngine().CheckIdleFormatter(); // If fast typing and mouse button downs + mnTravelXPos = TRAVEL_X_DONTKNOW; + maExtraCursorFlags = CursorFlags(); + mnCursorBidiLevel = CURSOR_BIDILEVEL_DONTKNOW; + bool bPrevUpdateLayout = getImpEditEngine().SetUpdateLayout(true); + mbClickedInSelection = IsSelectionAtPoint( rMouseEvent.GetPosPixel() ); + bool bRet = getImpEditEngine().MouseButtonDown( rMouseEvent, GetEditViewPtr() ); + getImpEditEngine().SetUpdateLayout(bPrevUpdateLayout); + return bRet; } bool ImpEditView::MouseMove( const MouseEvent& rMouseEvent ) { - return pEditEngine->pImpEditEngine->MouseMove( rMouseEvent, GetEditViewPtr() ); + return getImpEditEngine().MouseMove( rMouseEvent, GetEditViewPtr() ); } bool ImpEditView::Command(const CommandEvent& rCEvt) { - pEditEngine->CheckIdleFormatter(); // If fast typing and mouse button down - return pEditEngine->pImpEditEngine->Command(rCEvt, GetEditViewPtr()); + getEditEngine().CheckIdleFormatter(); // If fast typing and mouse button down + return getImpEditEngine().Command(rCEvt, GetEditViewPtr()); } @@ -1737,7 +1759,7 @@ void ImpEditView::SetInsertMode( bool bInsert ) { if ( bInsert != IsInsertMode() ) { - SetFlags( nControl, EVControlBits::OVERWRITE, !bInsert ); + SetFlags(mnControl, EVControlBits::OVERWRITE, !bInsert); ShowCursor( DoAutoScroll(), false ); } } @@ -1747,7 +1769,7 @@ bool ImpEditView::IsWrongSpelledWord( const EditPaM& rPaM, bool bMarkIfWrong ) bool bIsWrong = false; if ( rPaM.GetNode()->GetWrongList() ) { - EditSelection aSel = pEditEngine->SelectWord( rPaM, css::i18n::WordType::DICTIONARY_WORD ); + EditSelection aSel = getEditEngine().SelectWord( rPaM, css::i18n::WordType::DICTIONARY_WORD ); bIsWrong = rPaM.GetNode()->GetWrongList()->HasWrong( aSel.Min().GetIndex(), aSel.Max().GetIndex() ); if ( bIsWrong && bMarkIfWrong ) { @@ -1762,17 +1784,17 @@ bool ImpEditView::IsWrongSpelledWord( const EditPaM& rPaM, bool bMarkIfWrong ) OUString ImpEditView::SpellIgnoreWord() { OUString aWord; - if ( pEditEngine->pImpEditEngine->GetSpeller().is() ) + if (getImpEditEngine().GetSpeller().is()) { EditPaM aPaM = GetEditSelection().Max(); if ( !HasSelection() ) { - EditSelection aSel = pEditEngine->SelectWord(aPaM); - aWord = pEditEngine->pImpEditEngine->GetSelected( aSel ); + EditSelection aSel = getEditEngine().SelectWord(aPaM); + aWord = getImpEditEngine().GetSelected( aSel ); } else { - aWord = pEditEngine->pImpEditEngine->GetSelected( GetEditSelection() ); + aWord = getImpEditEngine().GetSelected( GetEditSelection() ); // And deselect DrawSelectionXOR(); SetEditSelection( EditSelection( aPaM, aPaM ) ); @@ -1781,18 +1803,18 @@ OUString ImpEditView::SpellIgnoreWord() if ( !aWord.isEmpty() ) { - Reference< XDictionary > xDic = LinguMgr::GetIgnoreAllList(); + uno::Reference<linguistic2::XDictionary> xDic = LinguMgr::GetIgnoreAllList(); if (xDic.is()) xDic->add( aWord, false, OUString() ); - EditDoc& rDoc = pEditEngine->GetEditDoc(); + EditDoc& rDoc = getEditEngine().GetEditDoc(); sal_Int32 nNodes = rDoc.Count(); for ( sal_Int32 n = 0; n < nNodes; n++ ) { ContentNode* pNode = rDoc.GetObject( n ); pNode->GetWrongList()->MarkWrongsInvalid(); } - pEditEngine->pImpEditEngine->DoOnlineSpelling( aPaM.GetNode() ); - pEditEngine->pImpEditEngine->StartOnlineSpellTimer(); + getImpEditEngine().DoOnlineSpelling( aPaM.GetNode() ); + getImpEditEngine().StartOnlineSpellTimer(); } } return aWord; @@ -1802,17 +1824,17 @@ void ImpEditView::DeleteSelected() { DrawSelectionXOR(); - pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_DELETE ); + getImpEditEngine().UndoActionStart( EDITUNDO_DELETE ); - EditPaM aPaM = pEditEngine->pImpEditEngine->DeleteSelected( GetEditSelection() ); + EditPaM aPaM = getImpEditEngine().DeleteSelected( GetEditSelection() ); - pEditEngine->pImpEditEngine->UndoActionEnd(); + getImpEditEngine().UndoActionEnd(); SetEditSelection( EditSelection( aPaM, aPaM ) ); DrawSelectionXOR(); - pEditEngine->pImpEditEngine->FormatAndLayout( GetEditViewPtr() ); + getImpEditEngine().FormatAndLayout( GetEditViewPtr() ); ShowCursor( DoAutoScroll(), true ); } @@ -1822,7 +1844,7 @@ const SvxFieldItem* ImpEditView::GetField( const Point& rPos, sal_Int32* pPara, return nullptr; Point aDocPos( GetDocPos( rPos ) ); - EditPaM aPaM = pEditEngine->GetPaM(aDocPos, false); + EditPaM aPaM = getEditEngine().GetPaM(aDocPos, false); if (!aPaM) return nullptr; @@ -1843,7 +1865,7 @@ const SvxFieldItem* ImpEditView::GetField( const Point& rPos, sal_Int32* pPara, { DBG_ASSERT(dynamic_cast<const SvxFieldItem*>(rAttr.GetItem()), "No FieldItem..."); if ( pPara ) - *pPara = pEditEngine->GetEditDoc().GetPos( aPaM.GetNode() ); + *pPara = getEditEngine().GetEditDoc().GetPos( aPaM.GetNode() ); if ( pPos ) *pPos = rAttr.GetStart(); return static_cast<const SvxFieldItem*>(rAttr.GetItem()); @@ -1862,16 +1884,16 @@ bool ImpEditView::IsBulletArea( const Point& rPos, sal_Int32* pPara ) return false; Point aDocPos( GetDocPos( rPos ) ); - EditPaM aPaM = pEditEngine->GetPaM(aDocPos, false); + EditPaM aPaM = getEditEngine().GetPaM(aDocPos, false); if (!aPaM) return false; if ( aPaM.GetIndex() == 0 ) { - sal_Int32 nPara = pEditEngine->GetEditDoc().GetPos( aPaM.GetNode() ); - tools::Rectangle aBulletArea = pEditEngine->GetBulletArea( nPara ); - tools::Long nY = pEditEngine->GetDocPosTopLeft( nPara ).Y(); - const ParaPortion& rParaPortion = pEditEngine->GetParaPortions()[nPara]; + sal_Int32 nPara = getEditEngine().GetEditDoc().GetPos( aPaM.GetNode() ); + tools::Rectangle aBulletArea = getEditEngine().GetBulletArea( nPara ); + tools::Long nY = getEditEngine().GetDocPosTopLeft( nPara ).Y(); + ParaPortion const& rParaPortion = getEditEngine().GetParaPortions().getRef(nPara); nY += rParaPortion.GetFirstLineOffset(); if ( ( aDocPos.Y() > ( nY + aBulletArea.Top() ) ) && ( aDocPos.Y() < ( nY + aBulletArea.Bottom() ) ) && @@ -1887,12 +1909,12 @@ bool ImpEditView::IsBulletArea( const Point& rPos, sal_Int32* pPara ) return false; } -void ImpEditView::CutCopy( css::uno::Reference< css::datatransfer::clipboard::XClipboard > const & rxClipboard, bool bCut ) +void ImpEditView::CutCopy(uno::Reference<datatransfer::clipboard::XClipboard> const & rxClipboard, bool bCut ) { if ( !(rxClipboard.is() && HasSelection()) ) return; - uno::Reference<datatransfer::XTransferable> xData = pEditEngine->CreateTransferable( GetEditSelection() ); + uno::Reference<datatransfer::XTransferable> xData = getEditEngine().CreateTransferable( GetEditSelection() ); { SolarMutexReleaser aReleaser; @@ -1914,18 +1936,18 @@ void ImpEditView::CutCopy( css::uno::Reference< css::datatransfer::clipboard::XC if (bCut) { - pEditEngine->pImpEditEngine->UndoActionStart(EDITUNDO_CUT); + getImpEditEngine().UndoActionStart(EDITUNDO_CUT); DeleteSelected(); - pEditEngine->pImpEditEngine->UndoActionEnd(); + getImpEditEngine().UndoActionEnd(); } } -void ImpEditView::Paste( css::uno::Reference< css::datatransfer::clipboard::XClipboard > const & rxClipboard, bool bUseSpecial ) +void ImpEditView::Paste(uno::Reference<datatransfer::clipboard::XClipboard> const & rxClipboard, bool bUseSpecial, SotClipboardFormatId format) { if ( !rxClipboard.is() ) return; - uno::Reference< datatransfer::XTransferable > xDataObj; + uno::Reference<datatransfer::XTransferable> xDataObj; try { @@ -1939,18 +1961,18 @@ void ImpEditView::Paste( css::uno::Reference< css::datatransfer::clipboard::XCli if ( !xDataObj.is() || !EditEngine::HasValidData( xDataObj ) ) return; - pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_PASTE ); + getImpEditEngine().UndoActionStart( EDITUNDO_PASTE ); EditSelection aSel( GetEditSelection() ); if ( aSel.HasRange() ) { DrawSelectionXOR(); - aSel = pEditEngine->DeleteSelection(aSel); + aSel = getEditEngine().DeleteSelection(aSel); } PasteOrDropInfos aPasteOrDropInfos; - aPasteOrDropInfos.nStartPara = pEditEngine->GetEditDoc().GetPos( aSel.Min().GetNode() ); - pEditEngine->HandleBeginPasteOrDrop(aPasteOrDropInfos); + aPasteOrDropInfos.nStartPara = getEditEngine().GetEditDoc().GetPos( aSel.Min().GetNode() ); + getEditEngine().HandleBeginPasteOrDrop(aPasteOrDropInfos); if ( DoSingleLinePaste() ) { @@ -1965,7 +1987,7 @@ void ImpEditView::Paste( css::uno::Reference< css::datatransfer::clipboard::XCli aData >>= aTmpText; OUString aText(convertLineEnd(aTmpText, LINEEND_LF)); aText = aText.replaceAll( OUStringChar(LINE_SEP), " " ); - aSel = pEditEngine->InsertText(aSel, aText); + aSel = getEditEngine().InsertText(aSel, aText); } catch( ... ) { @@ -1978,18 +2000,18 @@ void ImpEditView::Paste( css::uno::Reference< css::datatransfer::clipboard::XCli // Prevent notifications of paragraph inserts et al that would trigger // a11y to format content in a half-ready state when obtaining // paragraphs. Collect and broadcast when done instead. - aSel = pEditEngine->InsertText( + aSel = getEditEngine().InsertText( xDataObj, OUString(), aSel.Min(), - bUseSpecial && pEditEngine->GetInternalEditStatus().AllowPasteSpecial()); + bUseSpecial && getEditEngine().GetInternalEditStatus().AllowPasteSpecial(), format); } - aPasteOrDropInfos.nEndPara = pEditEngine->GetEditDoc().GetPos( aSel.Max().GetNode() ); - pEditEngine->HandleEndPasteOrDrop(aPasteOrDropInfos); + aPasteOrDropInfos.nEndPara = getEditEngine().GetEditDoc().GetPos( aSel.Max().GetNode() ); + getEditEngine().HandleEndPasteOrDrop(aPasteOrDropInfos); - pEditEngine->pImpEditEngine->UndoActionEnd(); + getImpEditEngine().UndoActionEnd(); SetEditSelection( aSel ); - pEditEngine->pImpEditEngine->UpdateSelections(); - pEditEngine->pImpEditEngine->FormatAndLayout( GetEditViewPtr() ); + getImpEditEngine().UpdateSelections(); + getImpEditEngine().FormatAndLayout( GetEditViewPtr() ); ShowCursor( DoAutoScroll(), true ); } @@ -2000,11 +2022,11 @@ bool ImpEditView::IsInSelection( const EditPaM& rPaM ) if ( !aSel.HasRange() ) return false; - aSel.Adjust( pEditEngine->GetEditDoc() ); + aSel.Adjust(getEditEngine().GetEditDoc()); - sal_Int32 nStartNode = pEditEngine->GetEditDoc().GetPos( aSel.Min().GetNode() ); - sal_Int32 nEndNode = pEditEngine->GetEditDoc().GetPos( aSel.Max().GetNode() ); - sal_Int32 nCurNode = pEditEngine->GetEditDoc().GetPos( rPaM.GetNode() ); + sal_Int32 nStartNode = getEditEngine().GetEditDoc().GetPos( aSel.Min().GetNode() ); + sal_Int32 nEndNode = getEditEngine().GetEditDoc().GetPos( aSel.Max().GetNode() ); + sal_Int32 nCurNode = getEditEngine().GetEditDoc().GetPos( rPaM.GetNode() ); if ( ( nCurNode > nStartNode ) && ( nCurNode < nEndNode ) ) return true; @@ -2023,9 +2045,32 @@ bool ImpEditView::IsInSelection( const EditPaM& rPaM ) return false; } +bool ImpEditView::IsSelectionFullPara() const +{ + if (!IsSelectionInSinglePara()) + return false; + + sal_Int32 nSelectionStartPos = GetEditSelection().Min().GetIndex(); + sal_Int32 nSelectionEndPos = GetEditSelection().Max().GetIndex(); + + if (nSelectionStartPos > nSelectionEndPos) + std::swap(nSelectionStartPos, nSelectionEndPos); + + if (nSelectionStartPos != 0) + return false; + + const ContentNode* pNode = GetEditSelection().Min().GetNode(); + return pNode->Len() == nSelectionEndPos; +} + +bool ImpEditView::IsSelectionInSinglePara() const +{ + return GetEditSelection().Min().GetNode() == GetEditSelection().Max().GetNode(); +} + void ImpEditView::CreateAnchor() { - pEditEngine->SetInSelectionMode(true); + getEditEngine().SetInSelectionMode(true); EditSelection aNewSelection(GetEditSelection()); aNewSelection.Min() = aNewSelection.Max(); SetEditSelection(aNewSelection); @@ -2034,16 +2079,16 @@ void ImpEditView::CreateAnchor() void ImpEditView::DeselectAll() { - pEditEngine->SetInSelectionMode(false); + getEditEngine().SetInSelectionMode(false); DrawSelectionXOR(); EditSelection aNewSelection(GetEditSelection()); aNewSelection.Min() = aNewSelection.Max(); SetEditSelection(aNewSelection); // const_cast<EditPaM&>(GetEditSelection().Min()) = GetEditSelection().Max(); - if (comphelper::LibreOfficeKit::isActive() && mpViewShell && pOutWin) + if (comphelper::LibreOfficeKit::isActive() && mpViewShell && mpOutputWindow) { - VclPtr<vcl::Window> pParent = pOutWin->GetParentWithLOKNotifier(); + VclPtr<vcl::Window> pParent = mpOutputWindow->GetParentWithLOKNotifier(); if (pParent && pParent->GetLOKWindowId()) { const vcl::ILibreOfficeKitNotifier* pNotifier = pParent->GetLOKNotifier(); @@ -2056,26 +2101,26 @@ void ImpEditView::DeselectAll() bool ImpEditView::IsSelectionAtPoint( const Point& rPosPixel ) { - if ( pDragAndDropInfo && pDragAndDropInfo->pField ) + if (mpDragAndDropInfo && mpDragAndDropInfo->pField) return true; // Logical units ... const OutputDevice& rOutDev = GetOutputDevice(); Point aMousePos = rOutDev.PixelToLogic(rPosPixel); - if ( ( !GetOutputArea().Contains( aMousePos ) ) && !pEditEngine->pImpEditEngine->IsInSelectionMode() ) + if ( ( !GetOutputArea().Contains( aMousePos ) ) && !getImpEditEngine().IsInSelectionMode() ) { return false; } Point aDocPos( GetDocPos( aMousePos ) ); - EditPaM aPaM = pEditEngine->GetPaM(aDocPos, false); + EditPaM aPaM = getEditEngine().GetPaM(aDocPos, false); return IsInSelection( aPaM ); } bool ImpEditView::SetCursorAtPoint( const Point& rPointPixel ) { - pEditEngine->CheckIdleFormatter(); + getEditEngine().CheckIdleFormatter(); Point aMousePos( rPointPixel ); @@ -2083,7 +2128,7 @@ bool ImpEditView::SetCursorAtPoint( const Point& rPointPixel ) const OutputDevice& rOutDev = GetOutputDevice(); aMousePos = rOutDev.PixelToLogic( aMousePos ); - if ( ( !GetOutputArea().Contains( aMousePos ) ) && !pEditEngine->pImpEditEngine->IsInSelectionMode() ) + if ( ( !GetOutputArea().Contains( aMousePos ) ) && !getImpEditEngine().IsInSelectionMode() ) { return false; } @@ -2093,7 +2138,7 @@ bool ImpEditView::SetCursorAtPoint( const Point& rPointPixel ) // Can be optimized: first go through the lines within a paragraph for PAM, // then again with the PaM for the Rect, even though the line is already // known... This must not be, though! - EditPaM aPaM = pEditEngine->GetPaM(aDocPos); + EditPaM aPaM = getEditEngine().GetPaM(aDocPos); bool bGotoCursor = DoAutoScroll(); // aTmpNewSel: Diff between old and new, not the new selection, unless for tiled rendering @@ -2104,10 +2149,14 @@ bool ImpEditView::SetCursorAtPoint( const Point& rPointPixel ) EditSelection aNewEditSelection( GetEditSelection() ); aNewEditSelection.Max() = aPaM; - if (!pEditEngine->GetSelectionEngine().HasAnchor()) + if (!getEditEngine().GetSelectionEngine().HasAnchor()) { if ( aNewEditSelection.Min() != aPaM ) - pEditEngine->CursorMoved(aNewEditSelection.Min().GetNode()); + { + const ContentNode* pNode(aNewEditSelection.Min().GetNode()); + if (nullptr != pNode) + pNode->checkAndDeleteEmptyAttribs(); + } aNewEditSelection.Min() = aPaM; } else @@ -2121,29 +2170,29 @@ bool ImpEditView::SetCursorAtPoint( const Point& rPointPixel ) SetEditSelection( aNewEditSelection ); } - bool bForceCursor = pDragAndDropInfo == nullptr && !pEditEngine->pImpEditEngine->IsInSelectionMode(); + bool bForceCursor = mpDragAndDropInfo == nullptr && !getImpEditEngine().IsInSelectionMode(); ShowCursor( bGotoCursor, bForceCursor ); return true; } void ImpEditView::HideDDCursor() { - if ( pDragAndDropInfo && pDragAndDropInfo->bVisCursor ) + if (mpDragAndDropInfo && mpDragAndDropInfo->bVisCursor) { OutputDevice& rOutDev = GetOutputDevice(); - rOutDev.DrawOutDev( pDragAndDropInfo->aCurSavedCursor.TopLeft(), pDragAndDropInfo->aCurSavedCursor.GetSize(), - Point(0,0), pDragAndDropInfo->aCurSavedCursor.GetSize(),*pDragAndDropInfo->pBackground ); - pDragAndDropInfo->bVisCursor = false; + rOutDev.DrawOutDev(mpDragAndDropInfo->aCurSavedCursor.TopLeft(), mpDragAndDropInfo->aCurSavedCursor.GetSize(), + Point(0,0), mpDragAndDropInfo->aCurSavedCursor.GetSize(),*mpDragAndDropInfo->pBackground); + mpDragAndDropInfo->bVisCursor = false; } } void ImpEditView::ShowDDCursor( const tools::Rectangle& rRect ) { - if ( !pDragAndDropInfo || pDragAndDropInfo->bVisCursor ) + if (!mpDragAndDropInfo || mpDragAndDropInfo->bVisCursor) return; - if (pOutWin && pOutWin->GetCursor()) - pOutWin->GetCursor()->Hide(); + if (mpOutputWindow && mpOutputWindow->GetCursor()) + mpOutputWindow->GetCursor()->Hide(); OutputDevice& rOutDev = GetOutputDevice(); Color aOldFillColor = rOutDev.GetFillColor(); @@ -2155,58 +2204,54 @@ void ImpEditView::ShowDDCursor( const tools::Rectangle& rRect ) aSaveRect.AdjustRight(1 ); aSaveRect.AdjustBottom(1 ); -#ifdef DBG_UTIL - Size aNewSzPx( aSaveRect.GetSize() ); -#endif - if ( !pDragAndDropInfo->pBackground ) + if (!mpDragAndDropInfo->pBackground) { - pDragAndDropInfo->pBackground = VclPtr<VirtualDevice>::Create(rOutDev); + mpDragAndDropInfo->pBackground = VclPtr<VirtualDevice>::Create(rOutDev); MapMode aMapMode( rOutDev.GetMapMode() ); aMapMode.SetOrigin( Point( 0, 0 ) ); - pDragAndDropInfo->pBackground->SetMapMode( aMapMode ); + mpDragAndDropInfo->pBackground->SetMapMode( aMapMode ); } -#ifdef DBG_UTIL - Size aCurSzPx( pDragAndDropInfo->pBackground->GetOutputSizePixel() ); + Size aNewSzPx( aSaveRect.GetSize() ); + Size aCurSzPx(mpDragAndDropInfo->pBackground->GetOutputSizePixel()); if ( ( aCurSzPx.Width() < aNewSzPx.Width() ) ||( aCurSzPx.Height() < aNewSzPx.Height() ) ) { - bool bDone = pDragAndDropInfo->pBackground->SetOutputSizePixel( aNewSzPx ); + bool bDone = mpDragAndDropInfo->pBackground->SetOutputSizePixel( aNewSzPx ); DBG_ASSERT( bDone, "Virtual Device broken?" ); } -#endif aSaveRect = rOutDev.PixelToLogic( aSaveRect ); - pDragAndDropInfo->pBackground->DrawOutDev( Point(0,0), aSaveRect.GetSize(), + mpDragAndDropInfo->pBackground->DrawOutDev( Point(0,0), aSaveRect.GetSize(), aSaveRect.TopLeft(), aSaveRect.GetSize(), rOutDev ); - pDragAndDropInfo->aCurSavedCursor = aSaveRect; + mpDragAndDropInfo->aCurSavedCursor = aSaveRect; // Draw Cursor... rOutDev.DrawRect( rRect ); - pDragAndDropInfo->bVisCursor = true; - pDragAndDropInfo->aCurCursor = rRect; + mpDragAndDropInfo->bVisCursor = true; + mpDragAndDropInfo->aCurCursor = rRect; rOutDev.SetFillColor( aOldFillColor ); } void ImpEditView::dragGestureRecognized(const css::datatransfer::dnd::DragGestureEvent& rDGE) { - DBG_ASSERT( !pDragAndDropInfo, "dragGestureRecognized - DragAndDropInfo exist!" ); + DBG_ASSERT(!mpDragAndDropInfo, "dragGestureRecognized - DragAndDropInfo exist!"); SolarMutexGuard aVclGuard; - pDragAndDropInfo.reset(); + mpDragAndDropInfo.reset(); Point aMousePosPixel( rDGE.DragOriginX, rDGE.DragOriginY ); EditSelection aCopySel( GetEditSelection() ); - aCopySel.Adjust( pEditEngine->GetEditDoc() ); + aCopySel.Adjust(getEditEngine().GetEditDoc()); - if ( HasSelection() && bClickedInSelection ) + if (HasSelection() && mbClickedInSelection) { - pDragAndDropInfo.reset(new DragAndDropInfo()); + mpDragAndDropInfo.reset(new DragAndDropInfo); } else { @@ -2217,9 +2262,9 @@ void ImpEditView::dragGestureRecognized(const css::datatransfer::dnd::DragGestur const SvxFieldItem* pField = GetField( aMousePos, &nPara, &nPos ); if ( pField ) { - pDragAndDropInfo.reset(new DragAndDropInfo()); - pDragAndDropInfo->pField = pField; - ContentNode* pNode = pEditEngine->GetEditDoc().GetObject( nPara ); + mpDragAndDropInfo.reset(new DragAndDropInfo); + mpDragAndDropInfo->pField = pField; + ContentNode* pNode = getEditEngine().GetEditDoc().GetObject( nPara ); aCopySel = EditSelection( EditPaM( pNode, nPos ), EditPaM( pNode, nPos+1 ) ); SetEditSelection(aCopySel); DrawSelectionXOR(); @@ -2228,17 +2273,17 @@ void ImpEditView::dragGestureRecognized(const css::datatransfer::dnd::DragGestur } else if ( IsBulletArea( aMousePos, &nPara ) ) { - pDragAndDropInfo.reset(new DragAndDropInfo()); - pDragAndDropInfo->bOutlinerMode = true; - EditPaM aStartPaM( pEditEngine->GetEditDoc().GetObject( nPara ), 0 ); + mpDragAndDropInfo.reset(new DragAndDropInfo); + mpDragAndDropInfo->bOutlinerMode = true; + EditPaM aStartPaM(getEditEngine().GetEditDoc().GetObject(nPara), 0); EditPaM aEndPaM( aStartPaM ); - const SfxInt16Item& rLevel = pEditEngine->GetParaAttrib( nPara, EE_PARA_OUTLLEVEL ); - for ( sal_Int32 n = nPara +1; n < pEditEngine->GetEditDoc().Count(); n++ ) + const SfxInt16Item& rLevel = getEditEngine().GetParaAttrib(nPara, EE_PARA_OUTLLEVEL); + for ( sal_Int32 n = nPara +1; n < getEditEngine().GetEditDoc().Count(); n++ ) { - const SfxInt16Item& rL = pEditEngine->GetParaAttrib( n, EE_PARA_OUTLLEVEL ); + const SfxInt16Item& rL = getEditEngine().GetParaAttrib( n, EE_PARA_OUTLLEVEL ); if ( rL.GetValue() > rLevel.GetValue() ) { - aEndPaM.SetNode( pEditEngine->GetEditDoc().GetObject( n ) ); + aEndPaM.SetNode( getEditEngine().GetEditDoc().GetObject( n ) ); } else { @@ -2250,22 +2295,22 @@ void ImpEditView::dragGestureRecognized(const css::datatransfer::dnd::DragGestur } } - if ( !pDragAndDropInfo ) + if (!mpDragAndDropInfo) return; - pDragAndDropInfo->bStarterOfDD = true; + mpDragAndDropInfo->bStarterOfDD = true; // Sensitive area to be scrolled. Size aSz( 5, 0 ); aSz = GetOutputDevice().PixelToLogic( aSz ); - pDragAndDropInfo->nSensibleRange = static_cast<sal_uInt16>(aSz.Width()); - pDragAndDropInfo->nCursorWidth = static_cast<sal_uInt16>(aSz.Width()) / 2; - pDragAndDropInfo->aBeginDragSel = pEditEngine->pImpEditEngine->CreateESel( aCopySel ); + mpDragAndDropInfo->nSensibleRange = static_cast<sal_uInt16>(aSz.Width()); + mpDragAndDropInfo->nCursorWidth = static_cast<sal_uInt16>(aSz.Width()) / 2; + mpDragAndDropInfo->aBeginDragSel = getImpEditEngine().CreateESel( aCopySel ); - uno::Reference<datatransfer::XTransferable> xData = pEditEngine->CreateTransferable(aCopySel); + uno::Reference<datatransfer::XTransferable> xData = getEditEngine().CreateTransferable(aCopySel); - sal_Int8 nActions = bReadOnly ? datatransfer::dnd::DNDConstants::ACTION_COPY : datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE; + sal_Int8 nActions = mbReadOnly ? datatransfer::dnd::DNDConstants::ACTION_COPY : datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE; rDGE.DragSource->startDrag( rDGE, nActions, 0 /*cursor*/, 0 /*image*/, xData, mxDnDListener ); // If Drag&Move in an Engine, then Copy&Del has to be optional! @@ -2276,37 +2321,37 @@ void ImpEditView::dragDropEnd( const css::datatransfer::dnd::DragSourceDropEvent { SolarMutexGuard aVclGuard; - DBG_ASSERT( pDragAndDropInfo, "ImpEditView::dragDropEnd: pDragAndDropInfo is NULL!" ); + DBG_ASSERT(mpDragAndDropInfo, "ImpEditView::dragDropEnd: mpDragAndDropInfo is NULL!"); // #123688# Shouldn't happen, but seems to happen... - if ( !pDragAndDropInfo ) + if (!mpDragAndDropInfo) return; - if ( !bReadOnly && rDSDE.DropSuccess && !pDragAndDropInfo->bOutlinerMode && ( rDSDE.DropAction & datatransfer::dnd::DNDConstants::ACTION_MOVE ) ) + if (!mbReadOnly && rDSDE.DropSuccess && !mpDragAndDropInfo->bOutlinerMode && ( rDSDE.DropAction & datatransfer::dnd::DNDConstants::ACTION_MOVE ) ) { - if ( pDragAndDropInfo->bStarterOfDD && pDragAndDropInfo->bDroppedInMe ) + if (mpDragAndDropInfo->bStarterOfDD && mpDragAndDropInfo->bDroppedInMe ) { // DropPos: Where was it dropped, irrespective of length. - ESelection aDropPos( pDragAndDropInfo->aDropSel.nStartPara, pDragAndDropInfo->aDropSel.nStartPos, pDragAndDropInfo->aDropSel.nStartPara, pDragAndDropInfo->aDropSel.nStartPos ); - ESelection aToBeDelSel = pDragAndDropInfo->aBeginDragSel; - ESelection aNewSel( pDragAndDropInfo->aDropSel.nEndPara, pDragAndDropInfo->aDropSel.nEndPos, - pDragAndDropInfo->aDropSel.nEndPara, pDragAndDropInfo->aDropSel.nEndPos ); - bool bBeforeSelection = aDropPos < pDragAndDropInfo->aBeginDragSel; - sal_Int32 nParaDiff = pDragAndDropInfo->aBeginDragSel.nEndPara - pDragAndDropInfo->aBeginDragSel.nStartPara; + ESelection aDropPos(mpDragAndDropInfo->aDropSel.nStartPara, mpDragAndDropInfo->aDropSel.nStartPos, mpDragAndDropInfo->aDropSel.nStartPara, mpDragAndDropInfo->aDropSel.nStartPos ); + ESelection aToBeDelSel = mpDragAndDropInfo->aBeginDragSel; + ESelection aNewSel( mpDragAndDropInfo->aDropSel.nEndPara, mpDragAndDropInfo->aDropSel.nEndPos, + mpDragAndDropInfo->aDropSel.nEndPara, mpDragAndDropInfo->aDropSel.nEndPos ); + bool bBeforeSelection = aDropPos < mpDragAndDropInfo->aBeginDragSel; + sal_Int32 nParaDiff = mpDragAndDropInfo->aBeginDragSel.nEndPara - mpDragAndDropInfo->aBeginDragSel.nStartPara; if ( bBeforeSelection ) { // Adjust aToBeDelSel. - DBG_ASSERT( pDragAndDropInfo->aBeginDragSel.nStartPara >= pDragAndDropInfo->aDropSel.nStartPara, "But not before? "); + DBG_ASSERT(mpDragAndDropInfo->aBeginDragSel.nStartPara >= mpDragAndDropInfo->aDropSel.nStartPara, "But not before? "); aToBeDelSel.nStartPara = aToBeDelSel.nStartPara + nParaDiff; aToBeDelSel.nEndPara = aToBeDelSel.nEndPara + nParaDiff; // To correct the character? - if ( aToBeDelSel.nStartPara == pDragAndDropInfo->aDropSel.nEndPara ) + if ( aToBeDelSel.nStartPara == mpDragAndDropInfo->aDropSel.nEndPara ) { sal_uInt16 nMoreChars; - if ( pDragAndDropInfo->aDropSel.nStartPara == pDragAndDropInfo->aDropSel.nEndPara ) - nMoreChars = pDragAndDropInfo->aDropSel.nEndPos - pDragAndDropInfo->aDropSel.nStartPos; + if (mpDragAndDropInfo->aDropSel.nStartPara == mpDragAndDropInfo->aDropSel.nEndPara ) + nMoreChars = mpDragAndDropInfo->aDropSel.nEndPos - mpDragAndDropInfo->aDropSel.nStartPos; else - nMoreChars = pDragAndDropInfo->aDropSel.nEndPos; + nMoreChars = mpDragAndDropInfo->aDropSel.nEndPos; aToBeDelSel.nStartPos = aToBeDelSel.nStartPos + nMoreChars; if ( aToBeDelSel.nStartPara == aToBeDelSel.nEndPara ) @@ -2318,17 +2363,17 @@ void ImpEditView::dragDropEnd( const css::datatransfer::dnd::DragSourceDropEvent { // aToBeDelSel is ok, but the selection of the View // has to be adapted, if it was deleted before! - DBG_ASSERT( pDragAndDropInfo->aBeginDragSel.nStartPara <= pDragAndDropInfo->aDropSel.nStartPara, "But not before? "); + DBG_ASSERT(mpDragAndDropInfo->aBeginDragSel.nStartPara <= mpDragAndDropInfo->aDropSel.nStartPara, "But not before? "); aNewSel.nStartPara = aNewSel.nStartPara - nParaDiff; aNewSel.nEndPara = aNewSel.nEndPara - nParaDiff; // To correct the character? - if ( pDragAndDropInfo->aBeginDragSel.nEndPara == pDragAndDropInfo->aDropSel.nStartPara ) + if (mpDragAndDropInfo->aBeginDragSel.nEndPara == mpDragAndDropInfo->aDropSel.nStartPara ) { sal_uInt16 nLessChars; - if ( pDragAndDropInfo->aBeginDragSel.nStartPara == pDragAndDropInfo->aBeginDragSel.nEndPara ) - nLessChars = pDragAndDropInfo->aBeginDragSel.nEndPos - pDragAndDropInfo->aBeginDragSel.nStartPos; + if (mpDragAndDropInfo->aBeginDragSel.nStartPara == mpDragAndDropInfo->aBeginDragSel.nEndPara ) + nLessChars = mpDragAndDropInfo->aBeginDragSel.nEndPos - mpDragAndDropInfo->aBeginDragSel.nStartPos; else - nLessChars = pDragAndDropInfo->aBeginDragSel.nEndPos; + nLessChars = mpDragAndDropInfo->aBeginDragSel.nEndPos; aNewSel.nStartPos = aNewSel.nStartPos - nLessChars; if ( aNewSel.nStartPara == aNewSel.nEndPara ) aNewSel.nEndPos = aNewSel.nEndPos - nLessChars; @@ -2336,89 +2381,89 @@ void ImpEditView::dragDropEnd( const css::datatransfer::dnd::DragSourceDropEvent } DrawSelectionXOR(); - EditSelection aDelSel( pEditEngine->pImpEditEngine->CreateSel( aToBeDelSel ) ); - DBG_ASSERT( !aDelSel.DbgIsBuggy( pEditEngine->GetEditDoc() ), "ToBeDel is buggy!" ); - pEditEngine->DeleteSelection(aDelSel); + EditSelection aDelSel(getImpEditEngine().CreateSel(aToBeDelSel)); + DBG_ASSERT( !aDelSel.DbgIsBuggy(getEditEngine().GetEditDoc()), "ToBeDel is buggy!"); + getEditEngine().DeleteSelection(aDelSel); if ( !bBeforeSelection ) { - DBG_ASSERT( !pEditEngine->pImpEditEngine->CreateSel( aNewSel ).DbgIsBuggy(pEditEngine->GetEditDoc()), "Bad" ); - SetEditSelection( pEditEngine->pImpEditEngine->CreateSel( aNewSel ) ); + DBG_ASSERT(!getImpEditEngine().CreateSel(aNewSel).DbgIsBuggy(getEditEngine().GetEditDoc()), "Bad"); + SetEditSelection(getImpEditEngine().CreateSel(aNewSel)); } - pEditEngine->pImpEditEngine->FormatAndLayout( pEditEngine->pImpEditEngine->GetActiveView() ); + getImpEditEngine().FormatAndLayout(getImpEditEngine().GetActiveView()); DrawSelectionXOR(); } else { // other EditEngine ... - if (pEditEngine->HasText()) // #88630# SC is removing the content when switching the task + if (getEditEngine().HasText()) // #88630# SC is removing the content when switching the task DeleteSelected(); } } - if ( pDragAndDropInfo->bUndoAction ) - pEditEngine->pImpEditEngine->UndoActionEnd(); + if (mpDragAndDropInfo->bUndoAction) + getImpEditEngine().UndoActionEnd(); HideDDCursor(); ShowCursor( DoAutoScroll(), true ); - pDragAndDropInfo.reset(); - pEditEngine->GetEndDropHdl().Call(GetEditViewPtr()); + mpDragAndDropInfo.reset(); + getEditEngine().GetEndDropHdl().Call(GetEditViewPtr()); } void ImpEditView::drop( const css::datatransfer::dnd::DropTargetDropEvent& rDTDE ) { SolarMutexGuard aVclGuard; - DBG_ASSERT( pDragAndDropInfo, "Drop - No Drag&Drop info?!" ); + DBG_ASSERT(mpDragAndDropInfo, "Drop - No Drag&Drop info?!"); - if ( !(pDragAndDropInfo && pDragAndDropInfo->bDragAccepted) ) + if (!(mpDragAndDropInfo && mpDragAndDropInfo->bDragAccepted)) return; - pEditEngine->GetBeginDropHdl().Call(GetEditViewPtr()); + getEditEngine().GetBeginDropHdl().Call(GetEditViewPtr()); bool bChanges = false; HideDDCursor(); - if ( pDragAndDropInfo->bStarterOfDD ) + if (mpDragAndDropInfo->bStarterOfDD) { - pEditEngine->pImpEditEngine->UndoActionStart( EDITUNDO_DRAGANDDROP ); - pDragAndDropInfo->bUndoAction = true; + getImpEditEngine().UndoActionStart( EDITUNDO_DRAGANDDROP ); + mpDragAndDropInfo->bUndoAction = true; } - if ( pDragAndDropInfo->bOutlinerMode ) + if (mpDragAndDropInfo->bOutlinerMode) { bChanges = true; - GetEditViewPtr()->MoveParagraphs( Range( pDragAndDropInfo->aBeginDragSel.nStartPara, pDragAndDropInfo->aBeginDragSel.nEndPara ), pDragAndDropInfo->nOutlinerDropDest ); + GetEditViewPtr()->MoveParagraphs(Range(mpDragAndDropInfo->aBeginDragSel.nStartPara, mpDragAndDropInfo->aBeginDragSel.nEndPara ), mpDragAndDropInfo->nOutlinerDropDest); } else { - uno::Reference< datatransfer::XTransferable > xDataObj = rDTDE.Transferable; + uno::Reference<datatransfer::XTransferable> xDataObj = rDTDE.Transferable; if ( xDataObj.is() ) { bChanges = true; // remove Selection ... DrawSelectionXOR(); - EditPaM aPaM( pDragAndDropInfo->aDropDest ); + EditPaM aPaM(mpDragAndDropInfo->aDropDest); PasteOrDropInfos aPasteOrDropInfos; - aPasteOrDropInfos.nStartPara = pEditEngine->GetEditDoc().GetPos( aPaM.GetNode() ); - pEditEngine->HandleBeginPasteOrDrop(aPasteOrDropInfos); + aPasteOrDropInfos.nStartPara = getEditEngine().GetEditDoc().GetPos( aPaM.GetNode() ); + getEditEngine().HandleBeginPasteOrDrop(aPasteOrDropInfos); - EditSelection aNewSel = pEditEngine->InsertText( - xDataObj, OUString(), aPaM, pEditEngine->GetInternalEditStatus().AllowPasteSpecial()); + EditSelection aNewSel = getEditEngine().InsertText( + xDataObj, OUString(), aPaM, getEditEngine().GetInternalEditStatus().AllowPasteSpecial()); - aPasteOrDropInfos.nEndPara = pEditEngine->GetEditDoc().GetPos( aNewSel.Max().GetNode() ); - pEditEngine->HandleEndPasteOrDrop(aPasteOrDropInfos); + aPasteOrDropInfos.nEndPara = getEditEngine().GetEditDoc().GetPos( aNewSel.Max().GetNode() ); + getEditEngine().HandleEndPasteOrDrop(aPasteOrDropInfos); SetEditSelection( aNewSel ); - pEditEngine->pImpEditEngine->FormatAndLayout( pEditEngine->pImpEditEngine->GetActiveView() ); - if ( pDragAndDropInfo->bStarterOfDD ) + getImpEditEngine().FormatAndLayout(getImpEditEngine().GetActiveView()); + if (mpDragAndDropInfo->bStarterOfDD) { // Only set if the same engine! - pDragAndDropInfo->aDropSel.nStartPara = pEditEngine->GetEditDoc().GetPos( aPaM.GetNode() ); - pDragAndDropInfo->aDropSel.nStartPos = aPaM.GetIndex(); - pDragAndDropInfo->aDropSel.nEndPara = pEditEngine->GetEditDoc().GetPos( aNewSel.Max().GetNode() ); - pDragAndDropInfo->aDropSel.nEndPos = aNewSel.Max().GetIndex(); - pDragAndDropInfo->bDroppedInMe = true; + mpDragAndDropInfo->aDropSel.nStartPara = getEditEngine().GetEditDoc().GetPos( aPaM.GetNode() ); + mpDragAndDropInfo->aDropSel.nStartPos = aPaM.GetIndex(); + mpDragAndDropInfo->aDropSel.nEndPara = getEditEngine().GetEditDoc().GetPos( aNewSel.Max().GetNode() ); + mpDragAndDropInfo->aDropSel.nEndPos = aNewSel.Max().GetIndex(); + mpDragAndDropInfo->bDroppedInMe = true; } } } @@ -2428,9 +2473,9 @@ void ImpEditView::drop( const css::datatransfer::dnd::DropTargetDropEvent& rDTDE rDTDE.Context->acceptDrop( rDTDE.DropAction ); } - if ( !pDragAndDropInfo->bStarterOfDD ) + if (!mpDragAndDropInfo->bStarterOfDD) { - pDragAndDropInfo.reset(); + mpDragAndDropInfo.reset(); } rDTDE.Context->dropComplete( bChanges ); @@ -2440,10 +2485,10 @@ void ImpEditView::dragEnter( const css::datatransfer::dnd::DropTargetDragEnterEv { SolarMutexGuard aVclGuard; - if ( !pDragAndDropInfo ) - pDragAndDropInfo.reset(new DragAndDropInfo()); + if (!mpDragAndDropInfo) + mpDragAndDropInfo.reset(new DragAndDropInfo); - pDragAndDropInfo->bHasValidData = false; + mpDragAndDropInfo->bHasValidData = false; // Check for supported format... // Only check for text, will also be there if bin or rtf @@ -2455,7 +2500,7 @@ void ImpEditView::dragEnter( const css::datatransfer::dnd::DropTargetDragEnterEv { if( TransferableDataHelper::IsEqual( pFlavors[n], aTextFlavor ) ) { - pDragAndDropInfo->bHasValidData = true; + mpDragAndDropInfo->bHasValidData = true; break; } } @@ -2469,9 +2514,9 @@ void ImpEditView::dragExit( const css::datatransfer::dnd::DropTargetEvent& ) HideDDCursor(); - if ( pDragAndDropInfo && !pDragAndDropInfo->bStarterOfDD ) + if (mpDragAndDropInfo && !mpDragAndDropInfo->bStarterOfDD) { - pDragAndDropInfo.reset(); + mpDragAndDropInfo.reset(); } } @@ -2486,9 +2531,9 @@ void ImpEditView::dragOver(const css::datatransfer::dnd::DropTargetDragEvent& rD bool bAccept = false; - if ( GetOutputArea().Contains( aMousePos ) && !bReadOnly ) + if (GetOutputArea().Contains( aMousePos ) && !mbReadOnly) { - if ( pDragAndDropInfo && pDragAndDropInfo->bHasValidData ) + if (mpDragAndDropInfo && mpDragAndDropInfo->bHasValidData) { bAccept = true; @@ -2498,14 +2543,14 @@ void ImpEditView::dragOver(const css::datatransfer::dnd::DropTargetDragEvent& rD tools::Long nScrollX = 0; tools::Long nScrollY = 0; // Check if in the sensitive area - if ( ( (aMousePos.X()-pDragAndDropInfo->nSensibleRange) < GetOutputArea().Left() ) && ( ( aMousePos.X() + pDragAndDropInfo->nSensibleRange ) > GetOutputArea().Left() ) ) + if ( ( (aMousePos.X() - mpDragAndDropInfo->nSensibleRange) < GetOutputArea().Left() ) && ( ( aMousePos.X() + mpDragAndDropInfo->nSensibleRange ) > GetOutputArea().Left() ) ) nScrollX = GetOutputArea().GetWidth() / SCRLRANGE; - else if ( ( (aMousePos.X()+pDragAndDropInfo->nSensibleRange) > GetOutputArea().Right() ) && ( ( aMousePos.X() - pDragAndDropInfo->nSensibleRange ) < GetOutputArea().Right() ) ) + else if ( ( (aMousePos.X() + mpDragAndDropInfo->nSensibleRange) > GetOutputArea().Right() ) && ( ( aMousePos.X() - mpDragAndDropInfo->nSensibleRange ) < GetOutputArea().Right() ) ) nScrollX = -( GetOutputArea().GetWidth() / SCRLRANGE ); - if ( ( (aMousePos.Y()-pDragAndDropInfo->nSensibleRange) < GetOutputArea().Top() ) && ( ( aMousePos.Y() + pDragAndDropInfo->nSensibleRange ) > GetOutputArea().Top() ) ) + if ( ( (aMousePos.Y() - mpDragAndDropInfo->nSensibleRange) < GetOutputArea().Top() ) && ( ( aMousePos.Y() + mpDragAndDropInfo->nSensibleRange ) > GetOutputArea().Top() ) ) nScrollY = GetOutputArea().GetHeight() / SCRLRANGE; - else if ( ( (aMousePos.Y()+pDragAndDropInfo->nSensibleRange) > GetOutputArea().Bottom() ) && ( ( aMousePos.Y() - pDragAndDropInfo->nSensibleRange ) < GetOutputArea().Bottom() ) ) + else if ( ( (aMousePos.Y() + mpDragAndDropInfo->nSensibleRange) > GetOutputArea().Bottom() ) && ( ( aMousePos.Y() - mpDragAndDropInfo->nSensibleRange ) < GetOutputArea().Bottom() ) ) nScrollY = -( GetOutputArea().GetHeight() / SCRLRANGE ); if ( nScrollX || nScrollY ) @@ -2516,27 +2561,27 @@ void ImpEditView::dragOver(const css::datatransfer::dnd::DropTargetDragEvent& rD } Point aDocPos( GetDocPos( aMousePos ) ); - EditPaM aPaM = pEditEngine->GetPaM( aDocPos ); - pDragAndDropInfo->aDropDest = aPaM; - if ( pDragAndDropInfo->bOutlinerMode ) + EditPaM aPaM = getEditEngine().GetPaM( aDocPos ); + mpDragAndDropInfo->aDropDest = aPaM; + if (mpDragAndDropInfo->bOutlinerMode) { - sal_Int32 nPara = pEditEngine->GetEditDoc().GetPos( aPaM.GetNode() ); - ParaPortion* pPPortion = pEditEngine->GetParaPortions().SafeGetObject( nPara ); + sal_Int32 nPara = getEditEngine().GetEditDoc().GetPos( aPaM.GetNode() ); + ParaPortion* pPPortion = getEditEngine().GetParaPortions().SafeGetObject( nPara ); if (pPPortion) { - tools::Long nDestParaStartY = pEditEngine->GetParaPortions().GetYOffset( pPPortion ); + tools::Long nDestParaStartY = getEditEngine().GetParaPortions().GetYOffset( pPPortion ); tools::Long nRel = aDocPos.Y() - nDestParaStartY; if ( nRel < ( pPPortion->GetHeight() / 2 ) ) { - pDragAndDropInfo->nOutlinerDropDest = nPara; + mpDragAndDropInfo->nOutlinerDropDest = nPara; } else { - pDragAndDropInfo->nOutlinerDropDest = nPara+1; + mpDragAndDropInfo->nOutlinerDropDest = nPara+1; } - if( ( pDragAndDropInfo->nOutlinerDropDest >= pDragAndDropInfo->aBeginDragSel.nStartPara ) && - ( pDragAndDropInfo->nOutlinerDropDest <= (pDragAndDropInfo->aBeginDragSel.nEndPara+1) ) ) + if ((mpDragAndDropInfo->nOutlinerDropDest >= mpDragAndDropInfo->aBeginDragSel.nStartPara) && + (mpDragAndDropInfo->nOutlinerDropDest <= (mpDragAndDropInfo->aBeginDragSel.nEndPara + 1))) { bAccept = false; } @@ -2545,9 +2590,9 @@ void ImpEditView::dragOver(const css::datatransfer::dnd::DropTargetDragEvent& rD else if ( HasSelection() ) { // it must not be dropped into a selection - EPaM aP = pEditEngine->pImpEditEngine->CreateEPaM( aPaM ); + EPaM aP = getImpEditEngine().CreateEPaM( aPaM ); ESelection aDestSel( aP.nPara, aP.nIndex, aP.nPara, aP.nIndex); - ESelection aCurSel = pEditEngine->pImpEditEngine->CreateESel( GetEditSelection() ); + ESelection aCurSel = getImpEditEngine().CreateESel( GetEditSelection() ); aCurSel.Adjust(); if ( !(aDestSel < aCurSel) && !(aDestSel > aCurSel) ) { @@ -2557,25 +2602,25 @@ void ImpEditView::dragOver(const css::datatransfer::dnd::DropTargetDragEvent& rD if ( bAccept ) { tools::Rectangle aEditCursor; - if ( pDragAndDropInfo->bOutlinerMode ) + if (mpDragAndDropInfo->bOutlinerMode) { tools::Long nDDYPos(0); - if ( pDragAndDropInfo->nOutlinerDropDest < pEditEngine->GetEditDoc().Count() ) + if (mpDragAndDropInfo->nOutlinerDropDest < getEditEngine().GetEditDoc().Count()) { - ParaPortion* pPPortion = pEditEngine->GetParaPortions().SafeGetObject( pDragAndDropInfo->nOutlinerDropDest ); + ParaPortion* pPPortion = getEditEngine().GetParaPortions().SafeGetObject(mpDragAndDropInfo->nOutlinerDropDest); if (pPPortion) - nDDYPos = pEditEngine->GetParaPortions().GetYOffset( pPPortion ); + nDDYPos = getEditEngine().GetParaPortions().GetYOffset( pPPortion ); } else { - nDDYPos = pEditEngine->pImpEditEngine->GetTextHeight(); + nDDYPos = getImpEditEngine().GetTextHeight(); } Point aStartPos( 0, nDDYPos ); aStartPos = GetWindowPos( aStartPos ); Point aEndPos( GetOutputArea().GetWidth(), nDDYPos ); aEndPos = GetWindowPos( aEndPos ); aEditCursor = rOutDev.LogicToPixel( tools::Rectangle( aStartPos, aEndPos ) ); - if ( !pEditEngine->IsEffectivelyVertical() ) + if (!getEditEngine().IsEffectivelyVertical()) { aEditCursor.AdjustTop( -1 ); aEditCursor.AdjustBottom( 1 ); @@ -2597,21 +2642,21 @@ void ImpEditView::dragOver(const css::datatransfer::dnd::DropTargetDragEvent& rD } else { - aEditCursor = pEditEngine->pImpEditEngine->PaMtoEditCursor( aPaM ); + aEditCursor = getImpEditEngine().PaMtoEditCursor( aPaM ); Point aTopLeft( GetWindowPos( aEditCursor.TopLeft() ) ); aEditCursor.SetPos( aTopLeft ); - aEditCursor.SetRight( aEditCursor.Left() + pDragAndDropInfo->nCursorWidth ); + aEditCursor.SetRight(aEditCursor.Left() + mpDragAndDropInfo->nCursorWidth); aEditCursor = rOutDev.LogicToPixel( aEditCursor ); aEditCursor = rOutDev.PixelToLogic( aEditCursor ); } - bool bCursorChanged = !pDragAndDropInfo->bVisCursor || ( pDragAndDropInfo->aCurCursor != aEditCursor ); + bool bCursorChanged = !mpDragAndDropInfo->bVisCursor || (mpDragAndDropInfo->aCurCursor != aEditCursor); if ( bCursorChanged ) { HideDDCursor(); ShowDDCursor(aEditCursor ); } - pDragAndDropInfo->bDragAccepted = true; + mpDragAndDropInfo->bDragAccepted = true; rDTDE.Context->acceptDrag( rDTDE.DropAction ); } } @@ -2620,18 +2665,18 @@ void ImpEditView::dragOver(const css::datatransfer::dnd::DropTargetDragEvent& rD if ( !bAccept ) { HideDDCursor(); - if (pDragAndDropInfo) - pDragAndDropInfo->bDragAccepted = false; + if (mpDragAndDropInfo) + mpDragAndDropInfo->bDragAccepted = false; rDTDE.Context->rejectDrag(); } } void ImpEditView::AddDragAndDropListeners() { - if (bActiveDragAndDropListener) + if (mbActiveDragAndDropListener) return; - css::uno::Reference<css::datatransfer::dnd::XDropTarget> xDropTarget; + uno::Reference<datatransfer::dnd::XDropTarget> xDropTarget; if (EditViewCallbacks* pCallbacks = getEditViewCallbacks()) xDropTarget = pCallbacks->GetDropTarget(); else if (auto xWindow = GetWindow()) @@ -2642,7 +2687,7 @@ void ImpEditView::AddDragAndDropListeners() mxDnDListener = new vcl::unohelper::DragAndDropWrapper(this); - css::uno::Reference<css::datatransfer::dnd::XDragGestureRecognizer> xDragGestureRecognizer(xDropTarget, uno::UNO_QUERY); + uno::Reference<datatransfer::dnd::XDragGestureRecognizer> xDragGestureRecognizer(xDropTarget, uno::UNO_QUERY); if (xDragGestureRecognizer.is()) { uno::Reference<datatransfer::dnd::XDragGestureListener> xDGL(mxDnDListener, uno::UNO_QUERY); @@ -2654,32 +2699,32 @@ void ImpEditView::AddDragAndDropListeners() xDropTarget->setActive(true); xDropTarget->setDefaultActions(datatransfer::dnd::DNDConstants::ACTION_COPY_OR_MOVE); - bActiveDragAndDropListener = true; + mbActiveDragAndDropListener = true; } void ImpEditView::RemoveDragAndDropListeners() { - if (!bActiveDragAndDropListener) + if (!mbActiveDragAndDropListener) return; - css::uno::Reference<css::datatransfer::dnd::XDropTarget> xDropTarget; + uno::Reference<datatransfer::dnd::XDropTarget> xDropTarget; if (EditViewCallbacks* pCallbacks = getEditViewCallbacks()) xDropTarget = pCallbacks->GetDropTarget(); else if (auto xWindow = GetWindow()) xDropTarget = xWindow->GetDropTarget(); - if (!xDropTarget.is()) - return; - - css::uno::Reference<css::datatransfer::dnd::XDragGestureRecognizer> xDragGestureRecognizer(xDropTarget, uno::UNO_QUERY); - if (xDragGestureRecognizer.is()) + if (xDropTarget.is()) { - uno::Reference<datatransfer::dnd::XDragGestureListener> xDGL(mxDnDListener, uno::UNO_QUERY); - xDragGestureRecognizer->removeDragGestureListener(xDGL); - } + uno::Reference<datatransfer::dnd::XDragGestureRecognizer> xDragGestureRecognizer(xDropTarget, uno::UNO_QUERY); + if (xDragGestureRecognizer.is()) + { + uno::Reference<datatransfer::dnd::XDragGestureListener> xDGL(mxDnDListener, uno::UNO_QUERY); + xDragGestureRecognizer->removeDragGestureListener(xDGL); + } - uno::Reference<datatransfer::dnd::XDropTargetListener> xDTL(mxDnDListener, uno::UNO_QUERY); - xDropTarget->removeDropTargetListener(xDTL); + uno::Reference<datatransfer::dnd::XDropTargetListener> xDTL(mxDnDListener, uno::UNO_QUERY); + xDropTarget->removeDropTargetListener(xDTL); + } if ( mxDnDListener.is() ) { @@ -2687,7 +2732,7 @@ void ImpEditView::RemoveDragAndDropListeners() mxDnDListener.clear(); } - bActiveDragAndDropListener = false; + mbActiveDragAndDropListener = false; } void ImpEditView::InitLOKSpecialPositioning(MapUnit eUnit, @@ -2729,4 +2774,10 @@ bool ImpEditView::HasLOKSpecialPositioning() const return bool(mpLOKSpecialPositioning); } +void ImpEditView::SetLOKSpecialFlags(LOKSpecialFlags eFlags) +{ + assert(mpLOKSpecialPositioning); + mpLOKSpecialPositioning->SetFlags(eFlags); +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/impedit.hxx b/editeng/source/editeng/impedit.hxx index 7e22687aba7c..07f6af002358 100644 --- a/editeng/source/editeng/impedit.hxx +++ b/editeng/source/editeng/impedit.hxx @@ -70,7 +70,6 @@ class SvxLRSpaceItem; class TextRanger; class SvKeyValueIterator; class SvxForbiddenCharactersTable; -class SvtCTLOptions; namespace vcl { class Window; } class SvxNumberFormat; namespace com::sun::star::datatransfer::clipboard { @@ -91,63 +90,65 @@ namespace editeng { #define ATTRSPECIAL_WHOLEWORD 1 #define ATTRSPECIAL_EDGE 2 -enum class GetCursorFlags { - NONE = 0x0000, - TextOnly = 0x0001, - StartOfLine = 0x0002, - EndOfLine = 0x0004, - PreferPortionStart = 0x0008, +struct CursorFlags +{ + bool bTextOnly : 1 = false; + bool bStartOfLine : 1 = false; + bool bEndOfLine : 1 = false; + bool bPreferPortionStart : 1 = false; }; -namespace o3tl { - template<> struct typed_flags<GetCursorFlags> : is_typed_flags<GetCursorFlags, 0x0f> {}; -} - struct DragAndDropInfo { - tools::Rectangle aCurCursor; - tools::Rectangle aCurSavedCursor; - sal_uInt16 nSensibleRange; - sal_uInt16 nCursorWidth; - ESelection aBeginDragSel; - EditPaM aDropDest; - sal_Int32 nOutlinerDropDest; - ESelection aDropSel; - VclPtr<VirtualDevice> pBackground; - const SvxFieldItem* pField; - bool bVisCursor : 1; - bool bDroppedInMe : 1; - bool bStarterOfDD : 1; - bool bHasValidData : 1; - bool bUndoAction : 1; - bool bOutlinerMode : 1; - bool bDragAccepted : 1; - - DragAndDropInfo() - : nSensibleRange(0), nCursorWidth(0), nOutlinerDropDest(0), pBackground(nullptr), - pField(nullptr), bVisCursor(false), bDroppedInMe(false), bStarterOfDD(false), - bHasValidData(false), bUndoAction(false), bOutlinerMode(false), bDragAccepted(false) - { - } + tools::Rectangle aCurCursor; + tools::Rectangle aCurSavedCursor; + sal_uInt16 nSensibleRange = 0; + sal_uInt16 nCursorWidth = 0; + ESelection aBeginDragSel; + EditPaM aDropDest; + sal_Int32 nOutlinerDropDest = 0; + ESelection aDropSel; + VclPtr<VirtualDevice> pBackground = nullptr; + const SvxFieldItem* pField = nullptr; + bool bVisCursor : 1 = false; + bool bDroppedInMe : 1 = false; + bool bStarterOfDD : 1 = false; + bool bHasValidData : 1 = false; + bool bUndoAction : 1 = false; + bool bOutlinerMode : 1 = false; + bool bDragAccepted : 1 = false; + ~DragAndDropInfo() { - pBackground.disposeAndClear(); + pBackground.disposeAndClear(); } }; struct ImplIMEInfos { - OUString aOldTextAfterStartPos; + OUString aOldTextAfterStartPos; std::unique_ptr<ExtTextInputAttr[]> pAttribs; - EditPaM aPos; - sal_Int32 nLen; - bool bWasCursorOverwrite; + EditPaM aPos; + sal_Int32 nLen = 0; + bool bWasCursorOverwrite = false; - ImplIMEInfos( const EditPaM& rPos, const OUString& rOldTextAfterStartPos ); - ~ImplIMEInfos(); + ImplIMEInfos(const EditPaM& rPos, OUString _aOldTextAfterStartPos) + : aOldTextAfterStartPos(std::move(_aOldTextAfterStartPos)) + , aPos(rPos) + {} - void CopyAttribs( const ExtTextInputAttr* pA, sal_uInt16 nL ); - void DestroyAttribs(); + void CopyAttribs(const ExtTextInputAttr* pInputAttributes, sal_uInt16 nInputLength) + { + nLen = nInputLength; + pAttribs.reset(new ExtTextInputAttr[nInputLength]); + memcpy(pAttribs.get(), pInputAttributes, nInputLength * sizeof(ExtTextInputAttr)); + } + + void DestroyAttribs() + { + pAttribs.reset(); + nLen = 0; + } }; // #i18881# to be able to identify the positions of changed words @@ -156,56 +157,55 @@ typedef std::vector<EditSelection> SpellContentSelections; struct SpellInfo { - EditPaM aCurSentenceStart; - svx::SpellPortions aLastSpellPortions; - SpellContentSelections aLastSpellContentSelections; - EESpellState eState; - EPaM aSpellStart; - EPaM aSpellTo; - bool bSpellToEnd; - bool bMultipleDoc; - SpellInfo() : eState(EESpellState::Ok), bSpellToEnd(true), bMultipleDoc(false) - { } + EditPaM aCurSentenceStart; + svx::SpellPortions aLastSpellPortions; + SpellContentSelections aLastSpellContentSelections; + EESpellState eState = EESpellState::Ok; + EPaM aSpellStart; + EPaM aSpellTo; + bool bSpellToEnd : 1 = true; + bool bMultipleDoc : 1 = false; }; // used for text conversion struct ConvInfo { - EPaM aConvStart; - EPaM aConvTo; - EPaM aConvContinue; // position to start search for next text portion (word) with - bool bConvToEnd; - bool bMultipleDoc; - - ConvInfo() : bConvToEnd(true), bMultipleDoc(false) {} + EPaM aConvStart; + EPaM aConvTo; + EPaM aConvContinue; // position to start search for next text portion (word) with + bool bConvToEnd : 1 = true; + bool bMultipleDoc : 1 = false; }; struct FormatterFontMetric { - sal_uInt16 nMaxAscent; - sal_uInt16 nMaxDescent; + sal_uInt16 nMaxAscent = 0; + sal_uInt16 nMaxDescent = 0; - FormatterFontMetric() : nMaxAscent(0), nMaxDescent(0) { /* nMinLeading = 0xFFFF; */ } - sal_uInt16 GetHeight() const { return nMaxAscent+nMaxDescent; } + sal_uInt16 GetHeight() const + { + return nMaxAscent + nMaxDescent; + } }; class IdleFormattter : public Idle { private: - EditView* pView; - int nRestarts; + EditView* mpView = nullptr; + int mnRestarts = 0; public: - IdleFormattter(); - virtual ~IdleFormattter() override; + IdleFormattter(); + virtual ~IdleFormattter() override; - void DoIdleFormat( EditView* pV ); - void ForceTimeout(); - void ResetRestarts() { nRestarts = 0; } - EditView* GetView() { return pView; } + void DoIdleFormat(EditView* pView); + void ForceTimeout(); + void ResetRestarts() { mnRestarts = 0; } + EditView* GetView() { return mpView; } }; class ImpEditView; + /// This is meant just for Calc, where all positions in logical units (twips for LOK) are computed by /// doing independent pixel-alignment for each cell's size. LOKSpecialPositioning stores /// both 'output-area' and 'visible-doc-position' in pure logical unit (twips for LOK). @@ -234,6 +234,9 @@ public: Point GetWindowPos(const Point& rDocPos, MapUnit eDocPosUnit) const; tools::Rectangle GetWindowPos(const tools::Rectangle& rDocRect, MapUnit eDocRectUnit) const; + void SetFlags(LOKSpecialFlags eFlags) { meFlags = eFlags; } + bool IsLayoutRTL() { return bool(meFlags & LOKSpecialFlags::LayoutRTL); } + Point GetRefPoint() const; private: @@ -244,6 +247,7 @@ private: tools::Rectangle maOutArea; Point maVisDocStartPos; MapUnit meUnit; + LOKSpecialFlags meFlags; }; @@ -258,38 +262,37 @@ class ImpEditView : public vcl::unohelper::DragAndDropClient using vcl::unohelper::DragAndDropClient::dragOver; private: - EditView* pEditView; - std::unique_ptr<vcl::Cursor, o3tl::default_delete<vcl::Cursor>> pCursor; - std::optional<Color> mxBackgroundColor; + EditView* mpEditView; + std::unique_ptr<vcl::Cursor, o3tl::default_delete<vcl::Cursor>> mpCursor; + std::optional<Color> mxBackgroundColor; /// Containing view shell, if any. - OutlinerViewShell* mpViewShell; + OutlinerViewShell* mpViewShell; /// Another shell, just listening to our state, if any. - OutlinerViewShell* mpOtherShell; - EditEngine* pEditEngine; - VclPtr<vcl::Window> pOutWin; - EditView::OutWindowSet aOutWindowSet; - std::optional<PointerStyle> mxPointer; - std::unique_ptr<DragAndDropInfo> pDragAndDropInfo; - - css::uno::Reference< css::datatransfer::dnd::XDragSourceListener > mxDnDListener; - - - tools::Long nInvMore; - EVControlBits nControl; - sal_uInt32 nTravelXPos; - GetCursorFlags nExtraCursorFlags; - sal_uInt16 nCursorBidiLevel; - sal_uInt16 nScrollDiffX; - bool bReadOnly; - bool bClickedInSelection; - bool bActiveDragAndDropListener; - - Point aAnchorPoint; - tools::Rectangle aOutArea; - Point aVisDocStartPos; - EESelectionMode eSelectionMode; - EditSelection aEditSelection; - EEAnchorMode eAnchorMode; + OutlinerViewShell* mpOtherShell; + EditEngine* mpEditEngine; + VclPtr<vcl::Window> mpOutputWindow; + EditView::OutWindowSet maOutWindowSet; + std::optional<PointerStyle> mxPointer; + std::unique_ptr<DragAndDropInfo> mpDragAndDropInfo; + + css::uno::Reference<css::datatransfer::dnd::XDragSourceListener> mxDnDListener; + + tools::Long mnInvalidateMore; + EVControlBits mnControl; + sal_uInt32 mnTravelXPos; + CursorFlags maExtraCursorFlags; + sal_uInt16 mnCursorBidiLevel; + sal_uInt16 mnScrollDiffX; + bool mbReadOnly; + bool mbClickedInSelection; + bool mbActiveDragAndDropListener; + + Point maAnchorPoint; + tools::Rectangle maOutputArea; + Point maVisDocStartPos; + EESelectionMode meSelectionMode; + EditSelection maEditSelection; + EEAnchorMode meAnchorMode; /// mechanism to change from the classic refresh mode that simply // invalidates the area where text was changed. When set, the invalidate @@ -302,6 +305,7 @@ private: std::unique_ptr<LOKSpecialPositioning> mpLOKSpecialPositioning; bool mbBroadcastLOKViewCursor:1; bool mbSuppressLOKMessages:1; + bool mbNegativeX:1; EditViewCallbacks* getEditViewCallbacks() const { @@ -337,21 +341,24 @@ protected: void ShowDDCursor( const tools::Rectangle& rRect ); void HideDDCursor(); - void ImplDrawHighlightRect(OutputDevice& rTarget, const Point& rDocPosTopLeft, const Point& rDocPosBottomRight, tools::PolyPolygon* pPolyPoly); - tools::Rectangle ImplGetEditCursor(EditPaM& aPaM, GetCursorFlags nShowCursorFlags, - sal_Int32& nTextPortionStart, const ParaPortion* pParaPortion) const; + void ImplDrawHighlightRect(OutputDevice& rTarget, const Point& rDocPosTopLeft, const Point& rDocPosBottomRight, tools::PolyPolygon* pPolyPoly, bool bLOKCalcRTL); + tools::Rectangle ImplGetEditCursor(EditPaM& aPaM, CursorFlags aShowCursorFlags, sal_Int32& nTextPortionStart, ParaPortion const& rParaPortion) const; public: - ImpEditView( EditView* pView, EditEngine* pEng, vcl::Window* pWindow ); - virtual ~ImpEditView() override; + ImpEditView(EditView* pView, EditEngine* pEditEngine, vcl::Window* pWindow); + virtual ~ImpEditView() override; + + EditView* GetEditViewPtr() { return mpEditView; } - EditView* GetEditViewPtr() { return pEditView; } + EditEngine& getEditEngine() const { return *mpEditEngine; } + ImpEditEngine& getImpEditEngine() const { return getEditEngine().getImpl(); } - sal_uInt16 GetScrollDiffX() const { return nScrollDiffX; } - void SetScrollDiffX( sal_uInt16 n ) { nScrollDiffX = n; } - sal_uInt16 GetCursorBidiLevel() const { return nCursorBidiLevel; } - void SetCursorBidiLevel( sal_uInt16 n ) { nCursorBidiLevel = n; } + sal_uInt16 GetScrollDiffX() const { return mnScrollDiffX; } + void SetScrollDiffX(sal_uInt16 n) { mnScrollDiffX = n; } + + sal_uInt16 GetCursorBidiLevel() const { return mnCursorBidiLevel; } + void SetCursorBidiLevel(sal_uInt16 n) { mnCursorBidiLevel = n; } Point GetDocPos( const Point& rWindowPos ) const; Point GetWindowPos( const Point& rDocPos ) const; @@ -359,7 +366,7 @@ public: void SetOutputArea( const tools::Rectangle& rRect ); void ResetOutputArea( const tools::Rectangle& rRect ); - const tools::Rectangle& GetOutputArea() const { return aOutArea; } + const tools::Rectangle& GetOutputArea() const { return maOutputArea; } bool IsVertical() const; bool IsTopToBottom() const; @@ -373,22 +380,31 @@ public: bool Command(const CommandEvent& rCEvt); void CutCopy( css::uno::Reference< css::datatransfer::clipboard::XClipboard > const & rxClipboard, bool bCut ); - void Paste( css::uno::Reference< css::datatransfer::clipboard::XClipboard > const & rxClipboard, bool bUseSpecial = false ); + void Paste( css::uno::Reference< css::datatransfer::clipboard::XClipboard > const & rxClipboard, bool bUseSpecial = false, SotClipboardFormatId format = SotClipboardFormatId::NONE); - void SetVisDocStartPos( const Point& rPos ) { aVisDocStartPos = rPos; } + void SetVisDocStartPos(const Point& rPos) { maVisDocStartPos = rPos; } - tools::Long GetVisDocLeft() const { return aVisDocStartPos.X(); } - tools::Long GetVisDocTop() const { return aVisDocStartPos.Y(); } - tools::Long GetVisDocRight() const { return aVisDocStartPos.X() + ( !IsVertical() ? aOutArea.GetWidth() : aOutArea.GetHeight() ); } - tools::Long GetVisDocBottom() const { return aVisDocStartPos.Y() + ( !IsVertical() ? aOutArea.GetHeight() : aOutArea.GetWidth() ); } + tools::Long GetVisDocLeft() const { return maVisDocStartPos.X(); } + tools::Long GetVisDocTop() const { return maVisDocStartPos.Y(); } + tools::Long GetVisDocRight() const + { + return maVisDocStartPos.X() + ( !IsVertical() ? maOutputArea.GetWidth() : maOutputArea.GetHeight() ); + } + tools::Long GetVisDocBottom() const + { + return maVisDocStartPos.Y() + ( !IsVertical() ? maOutputArea.GetHeight() : maOutputArea.GetWidth() ); + } tools::Rectangle GetVisDocArea() const; - const EditSelection& GetEditSelection() const { return aEditSelection; } - void SetEditSelection( const EditSelection& rEditSelection ); - bool HasSelection() const { return aEditSelection.HasRange(); } + const EditSelection& GetEditSelection() const { return maEditSelection; } + void SetEditSelection(const EditSelection& rEditSelection); + bool HasSelection() const { return maEditSelection.HasRange(); } void SelectionChanged(); - void DrawSelectionXOR() { DrawSelectionXOR( aEditSelection ); } + void DrawSelectionXOR() + { + DrawSelectionXOR(maEditSelection); + } void DrawSelectionXOR( EditSelection, vcl::Region* pRegion = nullptr, OutputDevice* pTargetDevice = nullptr ); void GetSelectionRectangles(EditSelection aTmpSel, std::vector<tools::Rectangle>& rLogicRects); @@ -396,13 +412,36 @@ public: OutputDevice& GetOutputDevice() const; weld::Widget* GetPopupParent(tools::Rectangle& rRect) const; - vcl::Window* GetWindow() const { return pOutWin; } + vcl::Window* GetWindow() const { return mpOutputWindow; } void SetSelectionMode( EESelectionMode eMode ); - inline PointerStyle GetPointer(); + PointerStyle GetPointer() + { + if ( !mxPointer ) + { + mxPointer = IsVertical() ? PointerStyle::TextVertical : PointerStyle::Text; + return *mxPointer; + } + + if(PointerStyle::Text == *mxPointer && IsVertical()) + { + mxPointer = PointerStyle::TextVertical; + } + else if(PointerStyle::TextVertical == *mxPointer && !IsVertical()) + { + mxPointer = PointerStyle::Text; + } + + return *mxPointer; + } - inline vcl::Cursor* GetCursor(); + vcl::Cursor* GetCursor() + { + if (!mpCursor) + mpCursor.reset(new vcl::Cursor); + return mpCursor.get(); + } void AddDragAndDropListeners(); void RemoveDragAndDropListeners(); @@ -416,9 +455,11 @@ public: bool IsSelectionAtPoint( const Point& rPosPixel ); bool IsInSelection( const EditPaM& rPaM ); + bool IsSelectionFullPara() const; + bool IsSelectionInSinglePara() const; void SetAnchorMode( EEAnchorMode eMode ); - EEAnchorMode GetAnchorMode() const { return eAnchorMode; } + EEAnchorMode GetAnchorMode() const { return meAnchorMode; } void CalcAnchorPoint(); void RecalcOutputArea(); @@ -427,17 +468,17 @@ public: void ShowCursor( bool bGotoCursor, bool bForceVisCursor ); Pair Scroll( tools::Long ndX, tools::Long ndY, ScrollRangeCheck nRangeCheck = ScrollRangeCheck::NoNegative ); - void SetInsertMode( bool bInsert ); - bool IsInsertMode() const { return !( nControl & EVControlBits::OVERWRITE ); } + void SetInsertMode( bool bInsert ); + bool IsInsertMode() const { return !(mnControl & EVControlBits::OVERWRITE); } - bool IsPasteEnabled() const { return bool( nControl & EVControlBits::ENABLEPASTE ); } + bool IsPasteEnabled() const { return bool(mnControl & EVControlBits::ENABLEPASTE); } - bool DoSingleLinePaste() const { return bool( nControl & EVControlBits::SINGLELINEPASTE ); } - bool DoAutoScroll() const { return bool( nControl & EVControlBits::AUTOSCROLL ); } - bool DoAutoSize() const { return bool( nControl & EVControlBits::AUTOSIZE ); } - bool DoAutoWidth() const { return bool( nControl & EVControlBits::AUTOSIZEX); } - bool DoAutoHeight() const { return bool( nControl & EVControlBits::AUTOSIZEY); } - bool DoInvalidateMore() const { return bool( nControl & EVControlBits::INVONEMORE ); } + bool DoSingleLinePaste() const { return bool(mnControl & EVControlBits::SINGLELINEPASTE); } + bool DoAutoScroll() const { return bool(mnControl & EVControlBits::AUTOSCROLL); } + bool DoAutoSize() const { return bool(mnControl & EVControlBits::AUTOSIZE); } + bool DoAutoWidth() const { return bool(mnControl & EVControlBits::AUTOSIZEX); } + bool DoAutoHeight() const { return bool(mnControl & EVControlBits::AUTOSIZEY); } + bool DoInvalidateMore() const { return bool(mnControl & EVControlBits::INVONEMORE ); } void SetBackgroundColor( const Color& rColor ); const Color& GetBackgroundColor() const; @@ -455,8 +496,14 @@ public: void DeleteSelected(); // If possible invalidate more than OutputArea, for the DrawingEngine text frame - void SetInvalidateMore( sal_uInt16 nPixel ) { nInvMore = nPixel; } - sal_uInt16 GetInvalidateMore() const { return static_cast<sal_uInt16>(nInvMore); } + void SetInvalidateMore(sal_uInt16 nPixel) + { + mnInvalidateMore = nPixel; + } + sal_uInt16 GetInvalidateMore() const + { + return sal_uInt16(mnInvalidateMore); + } void InitLOKSpecialPositioning(MapUnit eUnit, const tools::Rectangle& rOutputArea, const Point& rVisDocStartPos); @@ -466,15 +513,20 @@ public: tools::Rectangle GetLOKSpecialVisArea() const; bool HasLOKSpecialPositioning() const; + void SetLOKSpecialFlags(LOKSpecialFlags eFlags); + void SuppressLOKMessages(bool bSet) { mbSuppressLOKMessages = bSet; } bool IsSuppressLOKMessages() const { return mbSuppressLOKMessages; } + + void SetNegativeX(bool bSet) { mbNegativeX = bSet; } + bool IsNegativeX() const { return mbNegativeX; } }; // ImpEditEngine -class ImpEditEngine : public SfxListener +class ImpEditEngine : public SfxListener, public svl::StyleSheetUser { friend class EditEngine; @@ -483,82 +535,77 @@ class ImpEditEngine : public SfxListener private: std::shared_ptr<editeng::SharedVclResources> pSharedVCL; - - // Data ... - - // Document Specific data ... - ParaPortionList aParaPortionList; // Formatting - Size aPaperSize; // Layout - Size aMinAutoPaperSize; // Layout ? - Size aMaxAutoPaperSize; // Layout ? + ParaPortionList maParaPortionList; // Formatting + Size maPaperSize; // Layout + Size maMinAutoPaperSize; // Layout ? + Size maMaxAutoPaperSize; // Layout ? tools::Long mnMinColumnWrapHeight = 0; // Corresponds to graphic object height - EditDoc aEditDoc; // Document content + EditDoc maEditDoc; // Document content // Engine Specific data ... - EditEngine* pEditEngine; - ViewsType aEditViews; - EditView* pActiveView; - std::unique_ptr<TextRanger> pTextRanger; + EditEngine* mpEditEngine; + ViewsType maEditViews; + EditView* mpActiveView; + std::unique_ptr<TextRanger> mpTextRanger; - SfxStyleSheetPool* pStylePool; - SfxItemPool* pTextObjectPool; + SfxStyleSheetPool* mpStylePool; + SfxItemPool* mpTextObjectPool; - VclPtr< VirtualDevice> pVirtDev; - VclPtr< OutputDevice > pRefDev; + VclPtr<VirtualDevice> mpVirtDev; + VclPtr<OutputDevice> mpRefDev; VclPtr<VirtualDevice> mpOwnDev; svtools::ColorConfig maColorConfig; - mutable std::unique_ptr<SvtCTLOptions> pCTLOptions; mutable std::unique_ptr<SfxItemSet> pEmptyItemSet; - EditUndoManager* pUndoManager; - std::unique_ptr<ESelection> pUndoMarkSelection; + EditUndoManager* mpUndoManager; + std::optional<ESelection> moUndoMarkSelection; std::unique_ptr<ImplIMEInfos> mpIMEInfos; - OUString aWordDelimiters; + OUString maWordDelimiters; - EditSelFunctionSet aSelFuncSet; - EditSelectionEngine aSelEngine; + EditSelFunctionSet maSelFuncSet; + EditSelectionEngine maSelEngine; Color maBackgroundColor; - sal_uInt16 nStretchX; - sal_uInt16 nStretchY; + ScalingParameters maCustomScalingParameters; + ScalingParameters maScalingParameters; + bool mbRoundToNearestPt; - CharCompressType nAsianCompressionMode; + CharCompressType mnAsianCompressionMode; - EEHorizontalTextDirection eDefaultHorizontalTextDirection; + EEHorizontalTextDirection meDefaultHorizontalTextDirection; - sal_Int32 nBigTextObjectStart; - css::uno::Reference< css::linguistic2::XSpellChecker1 > xSpeller; - css::uno::Reference< css::linguistic2::XHyphenator > xHyphenator; - std::unique_ptr<SpellInfo> pSpellInfo; - mutable css::uno::Reference < css::i18n::XBreakIterator > xBI; - mutable css::uno::Reference < css::i18n::XExtendedInputSequenceChecker > xISC; + sal_Int32 mnBigTextObjectStart; + css::uno::Reference<css::linguistic2::XSpellChecker1> mxSpeller; + css::uno::Reference<css::linguistic2::XHyphenator> mxHyphenator; + std::unique_ptr<SpellInfo> mpSpellInfo; + mutable css::uno::Reference <css::i18n::XBreakIterator> mxBI; + mutable css::uno::Reference <css::i18n::XExtendedInputSequenceChecker> mxISC; - std::unique_ptr<ConvInfo> pConvInfo; + std::unique_ptr<ConvInfo> mpConvInfo; - OUString aAutoCompleteText; + OUString maAutoCompleteText; - InternalEditStatus aStatus; + InternalEditStatus maStatus; - LanguageType eDefLanguage; + LanguageType meDefLanguage; - OnDemandLocaleDataWrapper xLocaleDataWrapper; - OnDemandTransliterationWrapper xTransliterationWrapper; + OnDemandLocaleDataWrapper mxLocaleDataWrapper; + OnDemandTransliterationWrapper mxTransliterationWrapper; // For Formatting / Update... - std::vector<std::unique_ptr<DeletedNodeInfo> > aDeletedNodes; - tools::Rectangle aInvalidRect; - tools::Long nCurTextHeight; - tools::Long nCurTextHeightNTP; // without trailing empty paragraphs - sal_uInt16 nOnePixelInRef; + std::vector<std::unique_ptr<DeletedNodeInfo>> maDeletedNodes; + tools::Rectangle maInvalidRect; + tools::Long mnCurTextHeight; + tools::Long mnCurTextHeightNTP; // without trailing empty paragraphs + sal_uInt16 mnOnePixelInRef; - IdleFormattter aIdleFormatter; - - Timer aOnlineSpellTimer; + IdleFormattter maIdleFormatter; + Timer maOnlineSpellTimer; // For Chaining sal_Int32 mnOverflowingPara = -1; @@ -570,51 +617,52 @@ private: // If it is detected at one point that the StatusHdl has to be called, but // this should not happen immediately (critical section): - Timer aStatusTimer; - Size aLOKSpecialPaperSize; - - Link<EditStatus&,void> aStatusHdlLink; - Link<EENotify&,void> aNotifyHdl; - Link<HtmlImportInfo&,void> aHtmlImportHdl; - Link<RtfImportInfo&,void> aRtfImportHdl; - Link<MoveParagraphsInfo&,void> aBeginMovingParagraphsHdl; - Link<MoveParagraphsInfo&,void> aEndMovingParagraphsHdl; - Link<PasteOrDropInfos&,void> aBeginPasteOrDropHdl; - Link<PasteOrDropInfos&,void> aEndPasteOrDropHdl; - Link<LinkParamNone*,void> aModifyHdl; + Timer maStatusTimer; + Size maLOKSpecialPaperSize; + + Link<EditStatus&,void> maStatusHdlLink; + Link<EENotify&,void> maNotifyHdl; + Link<HtmlImportInfo&,void> maHtmlImportHdl; + Link<RtfImportInfo&,void> maRtfImportHdl; + Link<MoveParagraphsInfo&,void> maBeginMovingParagraphsHdl; + Link<MoveParagraphsInfo&,void> maEndMovingParagraphsHdl; + Link<PasteOrDropInfos&,void> maBeginPasteOrDropHdl; + Link<PasteOrDropInfos&,void> maEndPasteOrDropHdl; + Link<LinkParamNone*,void> maModifyHdl; Link<EditView*,void> maBeginDropHdl; Link<EditView*,void> maEndDropHdl; - bool bKernAsianPunctuation:1; - bool bAddExtLeading:1; - bool bIsFormatting:1; - bool bFormatted:1; - bool bInSelection:1; - bool bIsInUndo:1; - bool bUpdateLayout:1; - bool bUndoEnabled:1; - bool bDowning:1; - bool bUseAutoColor:1; - bool bForceAutoColor:1; - bool bCallParaInsertedOrDeleted:1; - bool bFirstWordCapitalization:1; // specifies if auto-correction should capitalize the first word or not - bool mbLastTryMerge:1; - bool mbReplaceLeadingSingleQuotationMark:1; - - bool mbNbspRunNext; // can't be a bitfield as it is passed as bool& - + bool mbKernAsianPunctuation : 1; + bool mbAddExtLeading : 1; + bool mbIsFormatting : 1; + bool mbFormatted : 1; + bool mbInSelection : 1; + bool mbIsInUndo : 1; + bool mbUpdateLayout : 1; + bool mbUndoEnabled : 1; + bool mbDowning : 1; + bool mbUseAutoColor : 1; + bool mbForceAutoColor : 1; + bool mbCallParaInsertedOrDeleted : 1; + bool mbFirstWordCapitalization : 1; // specifies if auto-correction should capitalize the first word or not + bool mbLastTryMerge : 1; + bool mbReplaceLeadingSingleQuotationMark : 1; + bool mbSkipOutsideFormat : 1; + bool mbFuzzing : 1; + + bool mbNbspRunNext; // can't be a bitfield as it is passed as bool& // Methods... - void CursorMoved( const ContentNode* pPrevNode ); void ParaAttribsChanged( ContentNode const * pNode, bool bIgnoreUndoCheck = false ); void TextModified(); - void CalcHeight( ParaPortion* pPortion ); + void CalcHeight(ParaPortion& rParaPortion); + bool isInEmptyClusterAtTheEnd(ParaPortion& rParaPortion); void InsertUndo( std::unique_ptr<EditUndo> pUndo, bool bTryMerge = false ); void ResetUndoManager(); - bool HasUndoManager() const { return pUndoManager != nullptr; } + bool HasUndoManager() const { return mpUndoManager != nullptr; } std::unique_ptr<EditUndoSetAttribs> CreateAttribUndo( EditSelection aSel, const SfxItemSet& rSet ); @@ -623,10 +671,10 @@ private: std::tuple<const ParaPortion*, const EditLine*, tools::Long> GetPortionAndLine(Point aDocPos); EditPaM GetPaM( Point aDocPos, bool bSmart = true ); bool IsTextPos(const Point& rDocPos, sal_uInt16 nBorder); - tools::Long GetXPos(const ParaPortion* pParaPortion, const EditLine* pLine, sal_Int32 nIndex, bool bPreferPortionStart = false) const; - tools::Long GetPortionXOffset(const ParaPortion* pParaPortion, const EditLine* pLine, sal_Int32 nTextPortion) const; - sal_Int32 GetChar(const ParaPortion* pParaPortion, const EditLine* pLine, tools::Long nX, bool bSmart = true); - Range GetLineXPosStartEnd( const ParaPortion* pParaPortion, const EditLine* pLine ) const; + tools::Long GetXPos(ParaPortion const& rParaPortion, EditLine const& rLine, sal_Int32 nIndex, bool bPreferPortionStart = false) const; + tools::Long GetPortionXOffset(ParaPortion const& rParaPortion, EditLine const& rLine, sal_Int32 nTextPortion) const; + sal_Int32 GetChar(ParaPortion const& rParaPortion, EditLine const& rLine, tools::Long nX, bool bSmart = true); + Range GetLineXPosStartEnd(ParaPortion const& rParaPortion, EditLine const& rLine) const; void ParaAttribsToCharAttribs( ContentNode* pNode ); void GetCharAttribs( sal_Int32 nPara, std::vector<EECharAttrib>& rLst ) const; @@ -634,24 +682,28 @@ private: std::unique_ptr<EditTextObject> CreateTextObject(EditSelection aSelection, SfxItemPool*, bool bAllowBigObjects = false, sal_Int32 nBigObjStart = 0); EditSelection InsertTextObject( const EditTextObject&, EditPaM aPaM ); - EditSelection PasteText( css::uno::Reference< css::datatransfer::XTransferable > const & rxDataObj, const OUString& rBaseURL, const EditPaM& rPaM, bool bUseSpecial ); + EditSelection PasteText( css::uno::Reference< css::datatransfer::XTransferable > const & rxDataObj, const OUString& rBaseURL, const EditPaM& rPaM, bool bUseSpecial, SotClipboardFormatId format = SotClipboardFormatId::NONE); void CheckPageOverflow(); void Clear(); EditPaM RemoveText(); - bool CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ); - void CreateAndInsertEmptyLine( ParaPortion* pParaPortion ); - bool FinishCreateLines( ParaPortion* pParaPortion ); - void CreateTextPortions( ParaPortion* pParaPortion, sal_Int32& rStartPos /*, sal_Bool bCreateBlockPortions */ ); - void RecalcTextPortion( ParaPortion* pParaPortion, sal_Int32 nStartPos, sal_Int32 nNewChars ); - sal_Int32 SplitTextPortion( ParaPortion* pParaPortion, sal_Int32 nPos, EditLine* pCurLine = nullptr ); + + bool createLinesForEmptyParagraph(ParaPortion& rParaPortion); + tools::Long calculateMaxLineWidth(tools::Long nStartX, SvxLRSpaceItem const& rLRItem); + bool CreateLines(sal_Int32 nPara, sal_uInt32 nStartPosY); + + void CreateAndInsertEmptyLine(ParaPortion& rParaPortion); + bool FinishCreateLines(ParaPortion& rParaPortion); + void CreateTextPortions(ParaPortion& rParaPortion, sal_Int32& rStartPos); + void RecalcTextPortion(ParaPortion& rParaPortion, sal_Int32 nStartPos, sal_Int32 nNewChars); + sal_Int32 SplitTextPortion(ParaPortion& rParaPortion, sal_Int32 nPos, EditLine* pCurLine = nullptr); void SeekCursor( ContentNode* pNode, sal_Int32 nPos, SvxFont& rFont, OutputDevice* pOut = nullptr ); void RecalcFormatterFontMetrics( FormatterFontMetric& rCurMetrics, SvxFont& rFont ); void CheckAutoPageSize(); - void ImpBreakLine( ParaPortion* pParaPortion, EditLine* pLine, TextPortion const * pPortion, sal_Int32 nPortionStart, tools::Long nRemainingWidth, bool bCanHyphenate ); - void ImpAdjustBlocks( ParaPortion* pParaPortion, EditLine* pLine, tools::Long nRemainingSpace ); + void ImpBreakLine(ParaPortion& rParaPortion, EditLine& rLine, TextPortion const * pPortion, sal_Int32 nPortionStart, tools::Long nRemainingWidth, bool bCanHyphenate); + void ImpAdjustBlocks(ParaPortion& rParaPortion, EditLine& rLine, tools::Long nRemainingSpace ); EditPaM ImpConnectParagraphs( ContentNode* pLeft, ContentNode* pRight, bool bBackward = false ); EditPaM ImpDeleteSelection(const EditSelection& rCurSel); EditPaM ImpInsertParaBreak( EditPaM& rPaM, bool bKeepEndingAttribs = true ); @@ -665,13 +717,11 @@ private: EditPaM ImpFastInsertText( EditPaM aPaM, const OUString& rStr ); EditPaM ImpFastInsertParagraph( sal_Int32 nPara ); - bool ImpCheckRefMapMode(); - bool ImplHasText() const; void ImpFindKashidas( ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEnd, std::vector<sal_Int32>& rArray ); - void InsertContent( ContentNode* pNode, sal_Int32 nPos ); + void InsertContent(std::unique_ptr<ContentNode> pNode, sal_Int32 nPos); EditPaM SplitContent( sal_Int32 nNode, sal_Int32 nSepPos ); EditPaM ConnectContents( sal_Int32 nLeftNode, bool bBackward ); @@ -693,7 +743,7 @@ private: EditPaM WordRight( const EditPaM& rPaM, sal_Int16 nWordType = css::i18n::WordType::ANYWORD_IGNOREWHITESPACES ); EditPaM StartOfWord( const EditPaM& rPaM ); EditPaM EndOfWord( const EditPaM& rPaM ); - EditSelection SelectWord( const EditSelection& rCurSelection, sal_Int16 nWordType = css::i18n::WordType::ANYWORD_IGNOREWHITESPACES, bool bAcceptStartOfWord = true ); + EditSelection SelectWord( const EditSelection& rCurSelection, sal_Int16 nWordType = css::i18n::WordType::ANYWORD_IGNOREWHITESPACES, bool bAcceptStartOfWord = true, bool bAcceptEndOfWord = false ); EditSelection SelectSentence( const EditSelection& rCurSel ) const; EditPaM CursorVisualLeftRight( EditView const * pEditView, const EditPaM& rPaM, sal_uInt16 nCharacterIteratorMode, bool bToLeft ); EditPaM CursorVisualStartEnd( EditView const * pEditView, const EditPaM& rPaM, bool bStart ); @@ -707,11 +757,11 @@ private: bool ImplCalcAsianCompression( ContentNode* pNode, TextPortion* pTextPortion, sal_Int32 nStartPos, sal_Int32* pDXArray, sal_uInt16 n100thPercentFromMax, bool bManipulateDXArray ); - void ImplExpandCompressedPortions( EditLine* pLine, ParaPortion* pParaPortion, tools::Long nRemainingWidth ); + void ImplExpandCompressedPortions(EditLine& rLine, ParaPortion& rParaPortion, tools::Long nRemainingWidth); void ImplInitLayoutMode(OutputDevice& rOutDev, sal_Int32 nPara, sal_Int32 nIndex); - LanguageType ImplCalcDigitLang(LanguageType eCurLang) const; - void ImplInitDigitMode(OutputDevice& rOutDev, LanguageType eLang); + static LanguageType ImplCalcDigitLang(LanguageType eCurLang); + static void ImplInitDigitMode(OutputDevice& rOutDev, LanguageType eLang); static OUString convertDigits(std::u16string_view rString, sal_Int32 nStt, sal_Int32 nLen, LanguageType eDigitLang); EditPaM ReadText( SvStream& rInput, EditSelection aSel ); @@ -728,11 +778,40 @@ private: std::vector<std::unique_ptr<SvxFontItem>>& rFontTable, SvxColorList& rColorList ); sal_Int32 LogicToTwips( sal_Int32 n ); - inline short GetXValue( short nXValue ) const; - inline tools::Long GetXValue( tools::Long nXValue ) const; + double scaleXSpacingValue(tools::Long nXValue) const + { + if (!maStatus.DoStretch() || maScalingParameters.fSpacingX == 1.0) + return nXValue; + + return double(nXValue) * maScalingParameters.fSpacingX; + } + + double scaleYSpacingValue(sal_uInt16 nYValue) const + { + if (!maStatus.DoStretch() || maScalingParameters.fSpacingY == 1.0) + return nYValue; + + return double(nYValue) * maScalingParameters.fSpacingY; + } + + double scaleXFontValue(tools::Long nXValue) const + { + if (!maStatus.DoStretch() || (maScalingParameters.fFontX == 1.0)) + return nXValue; - inline short GetYValue( short nYValue ) const; - inline sal_uInt16 GetYValue( sal_uInt16 nYValue ) const; + return double(nXValue) * maScalingParameters.fFontX; + } + + double scaleYFontValue(sal_uInt16 nYValue) const + { + if (!maStatus.DoStretch() || (maScalingParameters.fFontY == 1.0)) + return nYValue; + + return double(nYValue) * maScalingParameters.fFontY; + } + + void setRoundToNearestPt(bool bRound) { mbRoundToNearestPt = bRound; } + double roundToNearestPt(double fInput) const; ContentNode* GetPrevVisNode( ContentNode const * pCurNode ); ContentNode* GetNextVisNode( ContentNode const * pCurNode ); @@ -746,13 +825,31 @@ private: tools::Long CalcVertLineSpacing(Point& rStartPos) const; Color GetAutoColor() const; - void EnableAutoColor( bool b ) { bUseAutoColor = b; } - bool IsAutoColorEnabled() const { return bUseAutoColor; } - void ForceAutoColor( bool b ) { bForceAutoColor = b; } - bool IsForceAutoColor() const { return bForceAutoColor; } + void EnableAutoColor( bool b ) { mbUseAutoColor = b; } + bool IsAutoColorEnabled() const { return mbUseAutoColor; } + void ForceAutoColor( bool b ) { mbForceAutoColor = b; } + bool IsForceAutoColor() const { return mbForceAutoColor; } + + VirtualDevice* GetVirtualDevice(const MapMode& rMapMode, DrawModeFlags nDrawMode) + { + if (!mpVirtDev) + mpVirtDev = VclPtr<VirtualDevice>::Create(); + + if ((mpVirtDev->GetMapMode().GetMapUnit() != rMapMode.GetMapUnit()) || + (mpVirtDev->GetMapMode().GetScaleX() != rMapMode.GetScaleX()) || + (mpVirtDev->GetMapMode().GetScaleY() != rMapMode.GetScaleY()) ) + { + MapMode aMapMode(rMapMode); + aMapMode.SetOrigin(Point(0, 0)); + mpVirtDev->SetMapMode(aMapMode); + } - inline VirtualDevice* GetVirtualDevice( const MapMode& rMapMode, DrawModeFlags nDrawMode ); - void EraseVirtualDevice() { pVirtDev.disposeAndClear(); } + mpVirtDev->SetDrawMode(nDrawMode); + + return mpVirtDev; + } + + void EraseVirtualDevice() { mpVirtDev.disposeAndClear(); } DECL_LINK( StatusTimerHdl, Timer *, void); DECL_LINK( IdleFormatHdl, Timer *, void); @@ -761,8 +858,19 @@ private: void CheckIdleFormatter(); - inline const ParaPortion& FindParaPortion( const ContentNode* pNode ) const; - inline ParaPortion& FindParaPortion( ContentNode const * pNode ); + const ParaPortion* FindParaPortion(const ContentNode* pNode) const + { + sal_Int32 nPos = maEditDoc.GetPos( pNode ); + DBG_ASSERT( nPos < GetParaPortions().Count(), "Portionloser Node?" ); + return GetParaPortions().SafeGetObject(nPos); + } + + ParaPortion* FindParaPortion(ContentNode const * pNode) + { + sal_Int32 nPos = maEditDoc.GetPos( pNode ); + DBG_ASSERT( nPos < GetParaPortions().Count(), "Portionloser Node?" ); + return GetParaPortions().SafeGetObject(nPos); + } css::uno::Reference< css::datatransfer::XTransferable > CreateTransferable( const EditSelection& rSelection ); @@ -780,15 +888,15 @@ private: ImpEditEngine(EditEngine* pEditEngine, SfxItemPool* pPool); void InitDoc(bool bKeepParaAttribs); - EditDoc& GetEditDoc() { return aEditDoc; } - const EditDoc& GetEditDoc() const { return aEditDoc; } + EditDoc& GetEditDoc() { return maEditDoc; } + const EditDoc& GetEditDoc() const { return maEditDoc; } - const ParaPortionList& GetParaPortions() const { return aParaPortionList; } - ParaPortionList& GetParaPortions() { return aParaPortionList; } + const ParaPortionList& GetParaPortions() const { return maParaPortionList; } + ParaPortionList& GetParaPortions() { return maParaPortionList; } tools::Long Calc1ColumnTextHeight(tools::Long* pHeightNTP); - void IdleFormatAndLayout(EditView* pCurView) { aIdleFormatter.DoIdleFormat(pCurView); } + void IdleFormatAndLayout(EditView* pCurView) { maIdleFormatter.DoIdleFormat(pCurView); } protected: virtual void Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) override; @@ -798,18 +906,44 @@ public: ImpEditEngine(const ImpEditEngine&) = delete; ImpEditEngine& operator=(const ImpEditEngine&) = delete; - inline EditUndoManager& GetUndoManager(); - inline SfxUndoManager* SetUndoManager(SfxUndoManager* pNew); + EditUndoManager& GetUndoManager() + { + if (!mpUndoManager) + { + mpUndoManager = new EditUndoManager(); + mpUndoManager->SetEditEngine(mpEditEngine); + } + return *mpUndoManager; + } + + EditUndoManager* SetUndoManager(EditUndoManager* pNew) + { + EditUndoManager* pRetval = mpUndoManager; + + if (mpUndoManager) + { + mpUndoManager->SetEditEngine(nullptr); + } + + mpUndoManager = pNew; + + if (mpUndoManager) + { + mpUndoManager->SetEditEngine(mpEditEngine); + } + + return pRetval; + } // @return the previous bUpdateLayout state bool SetUpdateLayout( bool bUpdate, EditView* pCurView = nullptr, bool bForceUpdate = false ); - bool IsUpdateLayout() const { return bUpdateLayout; } + bool IsUpdateLayout() const { return mbUpdateLayout; } - ViewsType& GetEditViews() { return aEditViews; } - const ViewsType& GetEditViews() const { return aEditViews; } + ViewsType& GetEditViews() { return maEditViews; } + const ViewsType& GetEditViews() const { return maEditViews; } - const Size& GetPaperSize() const { return aPaperSize; } - void SetPaperSize( const Size& rSz ) { aPaperSize = rSz; } + const Size& GetPaperSize() const { return maPaperSize; } + void SetPaperSize(const Size& rSize) { maPaperSize = rSize; } void SetVertical( bool bVertical); bool IsEffectivelyVertical() const { return GetEditDoc().IsEffectivelyVertical(); } @@ -825,8 +959,8 @@ public: void SetFixedCellHeight( bool bUseFixedCellHeight ); bool IsFixedCellHeight() const { return GetEditDoc().IsFixedCellHeight(); } - void SetDefaultHorizontalTextDirection( EEHorizontalTextDirection eHTextDir ) { eDefaultHorizontalTextDirection = eHTextDir; } - EEHorizontalTextDirection GetDefaultHorizontalTextDirection() const { return eDefaultHorizontalTextDirection; } + void SetDefaultHorizontalTextDirection( EEHorizontalTextDirection eHTextDir ) { meDefaultHorizontalTextDirection = eHTextDir; } + EEHorizontalTextDirection GetDefaultHorizontalTextDirection() const { return meDefaultHorizontalTextDirection; } void InitWritingDirections( sal_Int32 nPara ); @@ -835,18 +969,21 @@ public: bool HasDifferentRTLLevels( const ContentNode* pNode ); void SetTextRanger( std::unique_ptr<TextRanger> pRanger ); - TextRanger* GetTextRanger() const { return pTextRanger.get(); } + TextRanger* GetTextRanger() const { return mpTextRanger.get(); } - const Size& GetMinAutoPaperSize() const { return aMinAutoPaperSize; } - void SetMinAutoPaperSize( const Size& rSz ) { aMinAutoPaperSize = rSz; } + const Size& GetMinAutoPaperSize() const { return maMinAutoPaperSize; } + void SetMinAutoPaperSize(const Size& rSize) { maMinAutoPaperSize = rSize; } - const Size& GetMaxAutoPaperSize() const { return aMaxAutoPaperSize; } - void SetMaxAutoPaperSize( const Size& rSz ) { aMaxAutoPaperSize = rSz; } + const Size& GetMaxAutoPaperSize() const { return maMaxAutoPaperSize; } + void SetMaxAutoPaperSize(const Size& rSize) { maMaxAutoPaperSize = rSize; } void SetMinColumnWrapHeight(tools::Long nVal) { mnMinColumnWrapHeight = nVal; } - void FormatDoc(); - void FormatFullDoc(); + tools::Long FormatParagraphs(o3tl::sorted_vector<sal_Int32>& rRepaintParagraphs); + void ScaleContentToFitWindow(o3tl::sorted_vector<sal_Int32>& rRepaintParagraphs); + void FormatDoc(); + void FormatFullDoc(); + void UpdateViews( EditView* pCurView = nullptr ); void Paint( ImpEditView* pView, const tools::Rectangle& rRect, OutputDevice* pTargetDevice ); void Paint(OutputDevice& rOutDev, tools::Rectangle aClipRect, Point aStartPos, bool bStripOnly = false, Degree10 nOrientation = 0_deg10); @@ -857,7 +994,7 @@ public: bool MouseMove( const MouseEvent& rMouseEvent, EditView* pView ); bool Command(const CommandEvent& rCEvt, EditView* pView); - EditSelectionEngine& GetSelEngine() { return aSelEngine; } + EditSelectionEngine& GetSelEngine() { return maSelEngine; } OUString GetSelected( const EditSelection& rSel ) const; const SfxItemSet& GetEmptyItemSet() const; @@ -865,15 +1002,15 @@ public: void UpdateSelections(); void EnableUndo( bool bEnable ); - bool IsUndoEnabled() const { return bUndoEnabled; } - void SetUndoMode( bool b ) { bIsInUndo = b; } - bool IsInUndo() const { return bIsInUndo; } + bool IsUndoEnabled() const { return mbUndoEnabled; } + void SetUndoMode( bool b ) { mbIsInUndo = b; } + bool IsInUndo() const { return mbIsInUndo; } - void SetCallParaInsertedOrDeleted( bool b ) { bCallParaInsertedOrDeleted = b; } - bool IsCallParaInsertedOrDeleted() const { return bCallParaInsertedOrDeleted; } + void SetCallParaInsertedOrDeleted( bool b ) { mbCallParaInsertedOrDeleted = b; } + bool IsCallParaInsertedOrDeleted() const { return mbCallParaInsertedOrDeleted; } - bool IsFormatted() const { return bFormatted; } - bool IsFormatting() const { return bIsFormatting; } + bool IsFormatted() const { return mbFormatted; } + bool IsFormatting() const { return mbIsFormatting; } void SetText(const OUString& rText); EditPaM DeleteSelected(const EditSelection& rEditSelection); @@ -904,13 +1041,13 @@ public: sal_uInt32 GetTextHeightNTP() const; sal_uInt32 CalcTextWidth( bool bIgnoreExtraSpace); sal_uInt32 CalcParaWidth( sal_Int32 nParagraph, bool bIgnoreExtraSpace ); - sal_uInt32 CalcLineWidth( ParaPortion* pPortion, EditLine* pLine, bool bIgnoreExtraSpace); + sal_uInt32 CalcLineWidth(ParaPortion const& rPortion, EditLine const& rLine, bool bIgnoreExtraSpace); sal_Int32 GetLineCount( sal_Int32 nParagraph ) const; sal_Int32 GetLineLen( sal_Int32 nParagraph, sal_Int32 nLine ) const; void GetLineBoundaries( /*out*/sal_Int32& rStart, /*out*/sal_Int32& rEnd, sal_Int32 nParagraph, sal_Int32 nLine ) const; sal_Int32 GetLineNumberAtIndex( sal_Int32 nPara, sal_Int32 nIndex ) const; sal_uInt16 GetLineHeight( sal_Int32 nParagraph, sal_Int32 nLine ); - sal_uInt32 GetParaHeight( sal_Int32 nParagraph ); + sal_uInt32 GetParaHeight(sal_Int32 nParagraph) const; SfxItemSet GetAttribs( sal_Int32 nPara, sal_Int32 nStart, sal_Int32 nEnd, GetAttribsFlags nFlags = GetAttribsFlags::ALL ) const; SfxItemSet GetAttribs( EditSelection aSel, EditEngineAttribs nOnlyHardAttrib = EditEngineAttribs::All ); @@ -930,16 +1067,14 @@ public: return static_cast<const T&>(GetParaAttrib(nPara, sal_uInt16(nWhich))); } - tools::Rectangle PaMtoEditCursor( EditPaM aPaM, GetCursorFlags nFlags = GetCursorFlags::NONE ); - tools::Rectangle GetEditCursor(const ParaPortion* pPortion, const EditLine* pLine, - sal_Int32 nIndex, GetCursorFlags nFlags); + tools::Rectangle PaMtoEditCursor(EditPaM aPaM, CursorFlags aFlags = CursorFlags()); + tools::Rectangle GetEditCursor(ParaPortion const& rPortion, EditLine const& rLine, sal_Int32 nIndex, CursorFlags aFlags); - bool IsModified() const { return aEditDoc.IsModified(); } - void SetModifyFlag( bool b ) { aEditDoc.SetModified( b ); } - void SetModifyHdl( const Link<LinkParamNone*,void>& rLink ) { aModifyHdl = rLink; } - const Link<LinkParamNone*,void>& GetModifyHdl() const { return aModifyHdl; } + bool IsModified() const { return maEditDoc.IsModified(); } + void SetModifyFlag(bool b) { maEditDoc.SetModified( b ); } + void SetModifyHdl( const Link<LinkParamNone*,void>& rLink ) { maModifyHdl = rLink; } - bool IsInSelectionMode() const { return bInSelection; } + bool IsInSelectionMode() const { return mbInSelection; } // For Undo/Redo void Undo( EditView* pView ); @@ -950,26 +1085,61 @@ public: EditPaM InsertParagraph( sal_Int32 nPara ); std::optional<EditSelection> SelectParagraph( sal_Int32 nPara ); - void SetStatusEventHdl( const Link<EditStatus&, void>& rLink ) { aStatusHdlLink = rLink; } - const Link<EditStatus&,void>& GetStatusEventHdl() const { return aStatusHdlLink; } + void SetStatusEventHdl( const Link<EditStatus&, void>& rLink ) { maStatusHdlLink = rLink; } + const Link<EditStatus&,void>& GetStatusEventHdl() const { return maStatusHdlLink; } - void SetNotifyHdl( const Link<EENotify&,void>& rLink ) { aNotifyHdl = rLink; } - const Link<EENotify&,void>& GetNotifyHdl() const { return aNotifyHdl; } + void SetNotifyHdl( const Link<EENotify&,void>& rLink ) { maNotifyHdl = rLink; } + const Link<EENotify&,void>& GetNotifyHdl() const { return maNotifyHdl; } void FormatAndLayout( EditView* pCurView = nullptr, bool bCalledFromUndo = false ); const svtools::ColorConfig& GetColorConfig() const { return maColorConfig; } - bool IsVisualCursorTravelingEnabled(); - bool DoVisualCursorTraveling(); + static bool IsVisualCursorTravelingEnabled(); + static bool DoVisualCursorTraveling(); EditSelection ConvertSelection( sal_Int32 nStartPara, sal_Int32 nStartPos, sal_Int32 nEndPara, sal_Int32 nEndPos ); - inline EPaM CreateEPaM( const EditPaM& rPaM ) const; - inline EditPaM CreateEditPaM( const EPaM& rEPaM ); - inline ESelection CreateESel( const EditSelection& rSel ) const; - inline EditSelection CreateSel( const ESelection& rSel ); + + EPaM CreateEPaM( const EditPaM& rPaM ) const + { + const ContentNode* pNode = rPaM.GetNode(); + return EPaM(maEditDoc.GetPos(pNode), rPaM.GetIndex()); + } + + EditPaM CreateEditPaM( const EPaM& rEPaM ) + { + DBG_ASSERT( rEPaM.nPara < maEditDoc.Count(), "CreateEditPaM: invalid paragraph" ); + DBG_ASSERT(maEditDoc.GetObject(rEPaM.nPara)->Len() >= rEPaM.nIndex, "CreateEditPaM: invalid Index"); + return EditPaM(maEditDoc.GetObject(rEPaM.nPara), rEPaM.nIndex); + } + + ESelection CreateESel(const EditSelection& rSel) const + { + const ContentNode* pStartNode = rSel.Min().GetNode(); + const ContentNode* pEndNode = rSel.Max().GetNode(); + ESelection aESel; + aESel.nStartPara = maEditDoc.GetPos( pStartNode ); + aESel.nStartPos = rSel.Min().GetIndex(); + aESel.nEndPara = maEditDoc.GetPos( pEndNode ); + aESel.nEndPos = rSel.Max().GetIndex(); + return aESel; + } + + EditSelection CreateSel(const ESelection& rSel) + { + DBG_ASSERT( rSel.nStartPara < maEditDoc.Count(), "CreateSel: invalid start paragraph" ); + DBG_ASSERT( rSel.nEndPara < maEditDoc.Count(), "CreateSel: invalid end paragraph" ); + EditSelection aSel; + aSel.Min().SetNode(maEditDoc.GetObject(rSel.nStartPara)); + aSel.Min().SetIndex( rSel.nStartPos ); + aSel.Max().SetNode(maEditDoc.GetObject(rSel.nEndPara)); + aSel.Max().SetIndex( rSel.nEndPos ); + DBG_ASSERT( !aSel.DbgIsBuggy( maEditDoc ), "CreateSel: incorrect selection!" ); + return aSel; + + } void SetStyleSheetPool( SfxStyleSheetPool* pSPool ); - SfxStyleSheetPool* GetStyleSheetPool() const { return pStylePool; } + SfxStyleSheetPool* GetStyleSheetPool() const { return mpStylePool; } void SetStyleSheet( EditSelection aSel, SfxStyleSheet* pStyle ); void SetStyleSheet( sal_Int32 nPara, SfxStyleSheet* pStyle ); @@ -979,41 +1149,45 @@ public: void UpdateParagraphsWithStyleSheet( SfxStyleSheet* pStyle ); void RemoveStyleFromParagraphs( SfxStyleSheet const * pStyle ); - OutputDevice* GetRefDevice() const { return pRefDev.get(); } - void SetRefDevice( OutputDevice* pRefDef ); + bool isUsedByModel() const override { return true; } + + OutputDevice* GetRefDevice() const { return mpRefDev.get(); } + void SetRefDevice(OutputDevice* mpRefDef); + + const MapMode& GetRefMapMode() const { return mpRefDev->GetMapMode(); } + void SetRefMapMode(const MapMode& rMapMode); - const MapMode& GetRefMapMode() const { return pRefDev->GetMapMode(); } - void SetRefMapMode( const MapMode& rMapMode ); + InternalEditStatus& GetStatus() { return maStatus; } + InternalEditStatus const& GetStatus() const{ return maStatus; } - InternalEditStatus& GetStatus() { return aStatus; } void CallStatusHdl(); - void DelayedCallStatusHdl() { aStatusTimer.Start(); } + void DelayedCallStatusHdl() { maStatusTimer.Start(); } void UndoActionStart( sal_uInt16 nId ); void UndoActionStart( sal_uInt16 nId, const ESelection& rSel ); void UndoActionEnd(); - EditView* GetActiveView() const { return pActiveView; } + EditView* GetActiveView() const { return mpActiveView; } void SetActiveView( EditView* pView ); css::uno::Reference< css::linguistic2::XSpellChecker1 > const & GetSpeller(); void SetSpeller( css::uno::Reference< css::linguistic2::XSpellChecker1 > const &xSpl ) - { xSpeller = xSpl; } + { mxSpeller = xSpl; } const css::uno::Reference< css::linguistic2::XHyphenator >& - GetHyphenator() const { return xHyphenator; } + GetHyphenator() const { return mxHyphenator; } void SetHyphenator( css::uno::Reference< css::linguistic2::XHyphenator > const &xHyph ) - { xHyphenator = xHyph; } + { mxHyphenator = xHyph; } void GetAllMisspellRanges( std::vector<editeng::MisspellRanges>& rRanges ) const; void SetAllMisspellRanges( const std::vector<editeng::MisspellRanges>& rRanges ); - SpellInfo* GetSpellInfo() const { return pSpellInfo.get(); } + SpellInfo* GetSpellInfo() const { return mpSpellInfo.get(); } - void SetDefaultLanguage( LanguageType eLang ) { eDefLanguage = eLang; } - LanguageType GetDefaultLanguage() const { return eDefLanguage; } + void SetDefaultLanguage(LanguageType eLang) { meDefLanguage = eLang; } + LanguageType GetDefaultLanguage() const { return meDefLanguage; } - LanguageType GetLanguage( const EditPaM& rPaM, sal_Int32* pEndPos = nullptr ) const; + editeng::LanguageSpan GetLanguage( const EditPaM& rPaM, sal_Int32* pEndPos = nullptr ) const; css::lang::Locale GetLocale( const EditPaM& rPaM ) const; void DoOnlineSpelling( ContentNode* pThisNodeOnly = nullptr, bool bSpellAtCursorPos = false, bool bInterruptible = true ); @@ -1028,7 +1202,7 @@ public: void Convert(EditView* pEditView, weld::Widget* pDialogParent, LanguageType nSrcLang, LanguageType nDestLang, const vcl::Font *pDestFont, sal_Int32 nOptions, bool bIsInteractive, bool bMultipleDoc); void ImpConvert( OUString &rConvTxt, LanguageType &rConvTxtLang, EditView* pEditView, LanguageType nSrcLang, const ESelection &rConvRange, bool bAllowImplicitChangesForNotConvertibleText, LanguageType nTargetLang, const vcl::Font *pTargetFont ); - ConvInfo * GetConvInfo() const { return pConvInfo.get(); } + ConvInfo * GetConvInfo() const { return mpConvInfo.get(); } bool HasConvertibleTextPortion( LanguageType nLang ); void SetLanguageAndFont( const ESelection &rESel, LanguageType nLang, sal_uInt16 nLangWhichId, @@ -1064,8 +1238,8 @@ public: sal_Int32 StartSearchAndReplace( EditView* pEditView, const SvxSearchItem& rSearchItem ); bool HasText( const SvxSearchItem& rSearchItem ); - void SetEditTextObjectPool( SfxItemPool* pP ) { pTextObjectPool = pP; } - SfxItemPool* GetEditTextObjectPool() const { return pTextObjectPool; } + void SetEditTextObjectPool( SfxItemPool* pP ) { mpTextObjectPool = pP; } + SfxItemPool* GetEditTextObjectPool() const { return mpTextObjectPool; } const SvxNumberFormat * GetNumberFormat( const ContentNode* pNode ) const; sal_Int32 GetSpaceBeforeAndMinLabelWidth( const ContentNode *pNode, sal_Int32 *pnSpaceBefore = nullptr, sal_Int32 *pnMinLabelWidth = nullptr ) const; @@ -1075,27 +1249,36 @@ public: SvxCellJustifyMethod GetJustifyMethod( sal_Int32 nPara ) const; SvxCellVerJustify GetVerJustification( sal_Int32 nPara ) const; - void SetCharStretching( sal_uInt16 nX, sal_uInt16 nY ); - inline void GetCharStretching( sal_uInt16& rX, sal_uInt16& rY ) const; + void setScalingParameters(ScalingParameters const& rScalingParameters); + + void resetScalingParameters() + { + setScalingParameters(ScalingParameters()); + } + + ScalingParameters getScalingParameters() + { + return maScalingParameters; + } - sal_Int32 GetBigTextObjectStart() const { return nBigTextObjectStart; } + sal_Int32 GetBigTextObjectStart() const { return mnBigTextObjectStart; } - EditEngine* GetEditEnginePtr() const { return pEditEngine; } + EditEngine* GetEditEnginePtr() const { return mpEditEngine; } - void StartOnlineSpellTimer() { aOnlineSpellTimer.Start(); } - void StopOnlineSpellTimer() { aOnlineSpellTimer.Stop(); } + void StartOnlineSpellTimer() { maOnlineSpellTimer.Start(); } + void StopOnlineSpellTimer() { maOnlineSpellTimer.Stop(); } - const OUString& GetAutoCompleteText() const { return aAutoCompleteText; } + const OUString& GetAutoCompleteText() const { return maAutoCompleteText; } void SetAutoCompleteText(const OUString& rStr, bool bUpdateTipWindow); EditSelection TransliterateText( const EditSelection& rSelection, TransliterationFlags nTransliterationMode ); short ReplaceTextOnly( ContentNode* pNode, sal_Int32 nCurrentStart, std::u16string_view rText, const css::uno::Sequence< sal_Int32 >& rOffsets ); void SetAsianCompressionMode( CharCompressType n ); - CharCompressType GetAsianCompressionMode() const { return nAsianCompressionMode; } + CharCompressType GetAsianCompressionMode() const { return mnAsianCompressionMode; } void SetKernAsianPunctuation( bool b ); - bool IsKernAsianPunctuation() const { return bKernAsianPunctuation; } + bool IsKernAsianPunctuation() const { return mbKernAsianPunctuation; } sal_Int32 GetOverflowingParaNum() const { return mnOverflowingPara; } sal_Int32 GetOverflowingLineNum() const { return mnOverflowingLine; } @@ -1103,7 +1286,7 @@ public: void SetAddExtLeading( bool b ); - bool IsAddExtLeading() const { return bAddExtLeading; } + bool IsAddExtLeading() const { return mbAddExtLeading; } static std::shared_ptr<SvxForbiddenCharactersTable> const & GetForbiddenCharsTable(); static void SetForbiddenCharsTable( const std::shared_ptr<SvxForbiddenCharactersTable>& xForbiddenChars ); @@ -1117,8 +1300,8 @@ public: const Link<EditView*,void>& GetEndDropHdl() const { return maEndDropHdl; } /// specifies if auto-correction should capitalize the first word or not (default is on) - void SetFirstWordCapitalization( bool bCapitalize ) { bFirstWordCapitalization = bCapitalize; } - bool IsFirstWordCapitalization() const { return bFirstWordCapitalization; } + void SetFirstWordCapitalization( bool bCapitalize ) { mbFirstWordCapitalization = bCapitalize; } + bool IsFirstWordCapitalization() const { return mbFirstWordCapitalization; } /** specifies if auto-correction should replace a leading single quotation mark (apostrophe) or not (default is on) */ @@ -1128,9 +1311,11 @@ public: /** Whether last AutoCorrect inserted a NO-BREAK SPACE that may need to be removed again. */ bool IsNbspRunNext() const { return mbNbspRunNext; } + void EnableSkipOutsideFormat(bool set) { mbSkipOutsideFormat = set; } + void Dispose(); - void SetLOKSpecialPaperSize(const Size& rSize) { aLOKSpecialPaperSize = rSize; } - const Size& GetLOKSpecialPaperSize() const { return aLOKSpecialPaperSize; } + void SetLOKSpecialPaperSize(const Size& rSize) { maLOKSpecialPaperSize = rSize; } + const Size& GetLOKSpecialPaperSize() const { return maLOKSpecialPaperSize; } enum class CallbackResult { @@ -1175,176 +1360,9 @@ public: Size getTopLeftDocOffset(const tools::Rectangle& rect) const; }; -inline EPaM ImpEditEngine::CreateEPaM( const EditPaM& rPaM ) const -{ - const ContentNode* pNode = rPaM.GetNode(); - return EPaM( aEditDoc.GetPos( pNode ), rPaM.GetIndex() ); -} - -inline EditPaM ImpEditEngine::CreateEditPaM( const EPaM& rEPaM ) -{ - DBG_ASSERT( rEPaM.nPara < aEditDoc.Count(), "CreateEditPaM: invalid paragraph" ); - DBG_ASSERT( aEditDoc[ rEPaM.nPara ]->Len() >= rEPaM.nIndex, "CreateEditPaM: invalid Index" ); - return EditPaM( aEditDoc[ rEPaM.nPara], rEPaM.nIndex ); -} - -inline ESelection ImpEditEngine::CreateESel( const EditSelection& rSel ) const -{ - const ContentNode* pStartNode = rSel.Min().GetNode(); - const ContentNode* pEndNode = rSel.Max().GetNode(); - ESelection aESel; - aESel.nStartPara = aEditDoc.GetPos( pStartNode ); - aESel.nStartPos = rSel.Min().GetIndex(); - aESel.nEndPara = aEditDoc.GetPos( pEndNode ); - aESel.nEndPos = rSel.Max().GetIndex(); - return aESel; -} - -inline EditSelection ImpEditEngine::CreateSel( const ESelection& rSel ) -{ - DBG_ASSERT( rSel.nStartPara < aEditDoc.Count(), "CreateSel: invalid start paragraph" ); - DBG_ASSERT( rSel.nEndPara < aEditDoc.Count(), "CreateSel: invalid end paragraph" ); - EditSelection aSel; - aSel.Min().SetNode( aEditDoc[ rSel.nStartPara ] ); - aSel.Min().SetIndex( rSel.nStartPos ); - aSel.Max().SetNode( aEditDoc[ rSel.nEndPara ] ); - aSel.Max().SetIndex( rSel.nEndPos ); - DBG_ASSERT( !aSel.DbgIsBuggy( aEditDoc ), "CreateSel: incorrect selection!" ); - return aSel; -} - -inline VirtualDevice* ImpEditEngine::GetVirtualDevice( const MapMode& rMapMode, DrawModeFlags nDrawMode ) -{ - if ( !pVirtDev ) - pVirtDev = VclPtr<VirtualDevice>::Create(); - - if ( ( pVirtDev->GetMapMode().GetMapUnit() != rMapMode.GetMapUnit() ) || - ( pVirtDev->GetMapMode().GetScaleX() != rMapMode.GetScaleX() ) || - ( pVirtDev->GetMapMode().GetScaleY() != rMapMode.GetScaleY() ) ) - { - MapMode aMapMode( rMapMode ); - aMapMode.SetOrigin( Point( 0, 0 ) ); - pVirtDev->SetMapMode( aMapMode ); - } - - pVirtDev->SetDrawMode( nDrawMode ); - - return pVirtDev; -} - -inline EditUndoManager& ImpEditEngine::GetUndoManager() -{ - if ( !pUndoManager ) - { - pUndoManager = new EditUndoManager(); - pUndoManager->SetEditEngine(pEditEngine); - } - return *pUndoManager; -} - -inline SfxUndoManager* ImpEditEngine::SetUndoManager(SfxUndoManager* pNew) -{ - SfxUndoManager* pRetval = pUndoManager; - - if(pUndoManager) - { - pUndoManager->SetEditEngine(nullptr); - } - - pUndoManager = dynamic_cast< EditUndoManager* >(pNew); - - if(pUndoManager) - { - pUndoManager->SetEditEngine(pEditEngine); - } - - return pRetval; -} - -inline const ParaPortion& ImpEditEngine::FindParaPortion( const ContentNode* pNode ) const -{ - sal_Int32 nPos = aEditDoc.GetPos( pNode ); - DBG_ASSERT( nPos < GetParaPortions().Count(), "Portionloser Node?" ); - return GetParaPortions()[ nPos ]; -} - -inline ParaPortion& ImpEditEngine::FindParaPortion( ContentNode const * pNode ) -{ - sal_Int32 nPos = aEditDoc.GetPos( pNode ); - DBG_ASSERT( nPos < GetParaPortions().Count(), "Portionloser Node?" ); - return GetParaPortions()[ nPos ]; -} - -inline void ImpEditEngine::GetCharStretching( sal_uInt16& rX, sal_uInt16& rY ) const -{ - rX = nStretchX; - rY = nStretchY; -} - -inline short ImpEditEngine::GetXValue( short nXValue ) const -{ - if ( !aStatus.DoStretch() || ( nStretchX == 100 ) ) - return nXValue; - - return static_cast<short>(static_cast<tools::Long>(nXValue)*nStretchX/100); -} - - -inline tools::Long ImpEditEngine::GetXValue( tools::Long nXValue ) const -{ - if ( !aStatus.DoStretch() || ( nStretchX == 100 ) ) - return nXValue; - - return nXValue*nStretchX/100; -} - -inline short ImpEditEngine::GetYValue( short nYValue ) const -{ - if ( !aStatus.DoStretch() || ( nStretchY == 100 ) ) - return nYValue; - - return static_cast<short>(static_cast<tools::Long>(nYValue)*nStretchY/100); -} - -inline sal_uInt16 ImpEditEngine::GetYValue( sal_uInt16 nYValue ) const -{ - if ( !aStatus.DoStretch() || ( nStretchY == 100 ) ) - return nYValue; - - return static_cast<sal_uInt16>(static_cast<tools::Long>(nYValue)*nStretchY/100); -} - -inline PointerStyle ImpEditView::GetPointer() -{ - if ( !mxPointer ) - { - mxPointer = IsVertical() ? PointerStyle::TextVertical : PointerStyle::Text; - return *mxPointer; - } - - if(PointerStyle::Text == *mxPointer && IsVertical()) - { - mxPointer = PointerStyle::TextVertical; - } - else if(PointerStyle::TextVertical == *mxPointer && !IsVertical()) - { - mxPointer = PointerStyle::Text; - } - - return *mxPointer; -} - -inline vcl::Cursor* ImpEditView::GetCursor() -{ - if ( !pCursor ) - pCursor.reset( new vcl::Cursor ); - return pCursor.get(); -} - void ConvertItem( std::unique_ptr<SfxPoolItem>& rPoolItem, MapUnit eSourceUnit, MapUnit eDestUnit ); void ConvertAndPutItems( SfxItemSet& rDest, const SfxItemSet& rSource, const MapUnit* pSourceUnit = nullptr, const MapUnit* pDestUnit = nullptr ); AsianCompressionFlags GetCharTypeForCompression( sal_Unicode cChar ); -Point Rotate( const Point& rPoint, Degree10 nOrientation, const Point& rOrigin ); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/impedit2.cxx b/editeng/source/editeng/impedit2.cxx index 47672cb090f3..da4d851b3315 100644 --- a/editeng/source/editeng/impedit2.cxx +++ b/editeng/source/editeng/impedit2.cxx @@ -30,6 +30,8 @@ #include "eeobj.hxx" #include <editeng/txtrange.hxx> #include <sfx2/app.hxx> +#include <sfx2/mieclip.hxx> +#include <sfx2/viewsh.hxx> #include <svtools/colorcfg.hxx> #include <svl/ctloptions.hxx> #include <unotools/securityoptions.hxx> @@ -39,6 +41,7 @@ #include <editeng/adjustitem.hxx> #include <editeng/frmdiritem.hxx> #include <editeng/justifyitem.hxx> +#include <editeng/udlnitem.hxx> #include <com/sun/star/i18n/CharacterIteratorMode.hpp> #include <com/sun/star/i18n/WordType.hpp> @@ -48,6 +51,7 @@ #include <com/sun/star/system/SystemShellExecute.hpp> #include <com/sun/star/system/SystemShellExecuteFlags.hpp> #include <com/sun/star/system/XSystemShellExecute.hpp> +#include <com/sun/star/i18n/UnicodeType.hpp> #include <rtl/character.hxx> @@ -57,12 +61,13 @@ #include <sot/exchange.hxx> #include <sot/formats.hxx> #include <svl/asiancfg.hxx> +#include <svl/voiditem.hxx> #include <i18nutil/unicode.hxx> -#include <tools/diagnose_ex.h> +#include <comphelper/diagnose_ex.hxx> #include <comphelper/flagguard.hxx> #include <comphelper/lok.hxx> #include <comphelper/processfactory.hxx> -#include <unotools/configmgr.hxx> +#include <comphelper/configuration.hxx> #include <unicode/ubidi.h> #include <algorithm> @@ -84,69 +89,71 @@ static sal_uInt16 lcl_CalcExtraSpace( const SvxLineSpacingItem& rLSItem ) return nExtra; } +constexpr tools::Long constMaxPaperSize = 0x7FFFFFFF; + ImpEditEngine::ImpEditEngine( EditEngine* pEE, SfxItemPool* pItemPool ) : pSharedVCL(EditDLL::Get().GetSharedVclResources()), - aPaperSize( 0x7FFFFFFF, 0x7FFFFFFF ), - aMinAutoPaperSize( 0x0, 0x0 ), - aMaxAutoPaperSize( 0x7FFFFFFF, 0x7FFFFFFF ), - aEditDoc( pItemPool ), - pEditEngine(pEE), - pActiveView(nullptr), - pStylePool(nullptr), - pTextObjectPool(nullptr), - pUndoManager(nullptr), - aWordDelimiters(" .,;:-`'?!_=\"{}()[]"), + maPaperSize(constMaxPaperSize, constMaxPaperSize), + maMinAutoPaperSize(0, 0), + maMaxAutoPaperSize(constMaxPaperSize, constMaxPaperSize), + maEditDoc( pItemPool ), + mpEditEngine(pEE), + mpActiveView(nullptr), + mpStylePool(nullptr), + mpTextObjectPool(nullptr), + mpUndoManager(nullptr), + maWordDelimiters(" .,;:-`'?!_=\"{}()[]"), maBackgroundColor(COL_AUTO), - nStretchX(100), - nStretchY(100), - nAsianCompressionMode(CharCompressType::NONE), - eDefaultHorizontalTextDirection(EEHorizontalTextDirection::Default), - nBigTextObjectStart(20), - eDefLanguage(LANGUAGE_DONTKNOW), - nCurTextHeight(0), - nCurTextHeightNTP(0), - aOnlineSpellTimer( "editeng::ImpEditEngine aOnlineSpellTimer" ), - aStatusTimer( "editeng::ImpEditEngine aStatusTimer" ), - bKernAsianPunctuation(false), - bAddExtLeading(false), - bIsFormatting(false), - bFormatted(false), - bInSelection(false), - bIsInUndo(false), - bUpdateLayout(true), - bUndoEnabled(true), - bDowning(false), - bUseAutoColor(true), - bForceAutoColor(false), - bCallParaInsertedOrDeleted(false), - bFirstWordCapitalization(true), + mbRoundToNearestPt(false), + mnAsianCompressionMode(CharCompressType::NONE), + meDefaultHorizontalTextDirection(EEHorizontalTextDirection::Default), + mnBigTextObjectStart(20), + meDefLanguage(LANGUAGE_DONTKNOW), + mnCurTextHeight(0), + mnCurTextHeightNTP(0), + maOnlineSpellTimer("editeng::ImpEditEngine aOnlineSpellTimer"), + maStatusTimer("editeng::ImpEditEngine aStatusTimer"), + mbKernAsianPunctuation(false), + mbAddExtLeading(false), + mbIsFormatting(false), + mbFormatted(false), + mbInSelection(false), + mbIsInUndo(false), + mbUpdateLayout(true), + mbUndoEnabled(true), + mbDowning(false), + mbUseAutoColor(true), + mbForceAutoColor(false), + mbCallParaInsertedOrDeleted(false), + mbFirstWordCapitalization(true), mbLastTryMerge(false), mbReplaceLeadingSingleQuotationMark(true), + mbSkipOutsideFormat(false), + mbFuzzing(comphelper::IsFuzzing()), mbNbspRunNext(false) { - aStatus.GetControlWord() = EEControlBits::USECHARATTRIBS | EEControlBits::DOIDLEFORMAT | + maStatus.GetControlWord() = EEControlBits::USECHARATTRIBS | EEControlBits::DOIDLEFORMAT | EEControlBits::PASTESPECIAL | EEControlBits::UNDOATTRIBS | - EEControlBits::ALLOWBIGOBJS | EEControlBits::RTFSTYLESHEETS | - EEControlBits::FORMAT100; + EEControlBits::ALLOWBIGOBJS | EEControlBits::RTFSTYLESHEETS; - aSelEngine.SetFunctionSet( &aSelFuncSet ); + maSelEngine.SetFunctionSet(&maSelFuncSet); - aStatusTimer.SetTimeout( 200 ); - aStatusTimer.SetInvokeHandler( LINK( this, ImpEditEngine, StatusTimerHdl ) ); + maStatusTimer.SetTimeout(200); + maStatusTimer.SetInvokeHandler(LINK(this, ImpEditEngine, StatusTimerHdl)); - aIdleFormatter.SetPriority( TaskPriority::REPAINT ); - aIdleFormatter.SetInvokeHandler( LINK( this, ImpEditEngine, IdleFormatHdl ) ); + maIdleFormatter.SetPriority(TaskPriority::REPAINT); + maIdleFormatter.SetInvokeHandler(LINK(this, ImpEditEngine, IdleFormatHdl)); - aOnlineSpellTimer.SetTimeout( 100 ); - aOnlineSpellTimer.SetInvokeHandler( LINK( this, ImpEditEngine, OnlineSpellHdl ) ); + maOnlineSpellTimer.SetTimeout(100); + maOnlineSpellTimer.SetInvokeHandler(LINK( this, ImpEditEngine, OnlineSpellHdl)); // Access data already from here on! SetRefDevice( nullptr ); InitDoc( false ); - bCallParaInsertedOrDeleted = true; + mbCallParaInsertedOrDeleted = true; - aEditDoc.SetModifyHdl( LINK( this, ImpEditEngine, DocModified ) ); + maEditDoc.SetModifyHdl( LINK( this, ImpEditEngine, DocModified ) ); StartListening(*SfxGetpApp()); } @@ -156,43 +163,42 @@ void ImpEditEngine::Dispose() auto pApp = SfxApplication::Get(); if(pApp) EndListening(*pApp); - pVirtDev.disposeAndClear(); + mpVirtDev.disposeAndClear(); mpOwnDev.disposeAndClear(); pSharedVCL.reset(); } ImpEditEngine::~ImpEditEngine() { - aStatusTimer.Stop(); - aOnlineSpellTimer.Stop(); - aIdleFormatter.Stop(); + maStatusTimer.Stop(); + maOnlineSpellTimer.Stop(); + maIdleFormatter.Stop(); // Destroying templates may otherwise cause unnecessary formatting, // when a parent template is destroyed. // And this after the destruction of the data! - bDowning = true; + mbDowning = true; SetUpdateLayout( false ); Dispose(); - // it's only legal to delete the pUndoManager if it was created by + // it's only legal to delete the mpUndoManager if it was created by // ImpEditEngine; if it was set by SetUndoManager() it must be cleared // before destroying the ImpEditEngine! - assert(!pUndoManager || typeid(*pUndoManager) == typeid(EditUndoManager)); - delete pUndoManager; - pTextRanger.reset(); + assert(!mpUndoManager || typeid(*mpUndoManager) == typeid(EditUndoManager)); + delete mpUndoManager; + mpTextRanger.reset(); mpIMEInfos.reset(); - pCTLOptions.reset(); - pSpellInfo.reset(); + mpSpellInfo.reset(); } -void ImpEditEngine::SetRefDevice( OutputDevice* pRef ) +void ImpEditEngine::SetRefDevice(OutputDevice* pRef) { if (pRef) - pRefDev = pRef; + mpRefDev = pRef; else - pRefDev = pSharedVCL->GetVirtualDevice(); + mpRefDev = pSharedVCL->GetVirtualDevice(); - nOnePixelInRef = static_cast<sal_uInt16>(pRefDev->PixelToLogic( Size( 1, 0 ) ).Width()); + mnOnePixelInRef = static_cast<sal_uInt16>(mpRefDev->PixelToLogic( Size( 1, 0 ) ).Width()); if ( IsFormatted() ) { @@ -208,12 +214,12 @@ void ImpEditEngine::SetRefMapMode( const MapMode& rMapMode ) mpOwnDev.disposeAndClear(); mpOwnDev = VclPtr<VirtualDevice>::Create(); - pRefDev = mpOwnDev; - pRefDev->SetMapMode(MapMode(MapUnit::MapTwip)); - SetRefDevice( pRefDev ); + mpRefDev = mpOwnDev; + mpRefDev->SetMapMode(MapMode(MapUnit::MapTwip)); + SetRefDevice(mpRefDev); - pRefDev->SetMapMode( rMapMode ); - nOnePixelInRef = static_cast<sal_uInt16>(pRefDev->PixelToLogic( Size( 1, 0 ) ).Width()); + mpRefDev->SetMapMode( rMapMode ); + mnOnePixelInRef = static_cast<sal_uInt16>(mpRefDev->PixelToLogic(Size(1, 0)).Width()); if ( IsFormatted() ) { FormatFullDoc(); @@ -223,23 +229,23 @@ void ImpEditEngine::SetRefMapMode( const MapMode& rMapMode ) void ImpEditEngine::InitDoc(bool bKeepParaAttribs) { - sal_Int32 nParas = aEditDoc.Count(); + sal_Int32 nParas = maEditDoc.Count(); for ( sal_Int32 n = bKeepParaAttribs ? 1 : 0; n < nParas; n++ ) { - if ( aEditDoc[n]->GetStyleSheet() ) - EndListening( *aEditDoc[n]->GetStyleSheet() ); + if (maEditDoc.GetObject(n)->GetStyleSheet()) + EndListening( *maEditDoc.GetObject(n)->GetStyleSheet() ); } if ( bKeepParaAttribs ) - aEditDoc.RemoveText(); + maEditDoc.RemoveText(); else - aEditDoc.Clear(); + maEditDoc.Clear(); GetParaPortions().Reset(); - GetParaPortions().Insert(0, ParaPortion( aEditDoc[0] )); + GetParaPortions().Insert(0, std::make_unique<ParaPortion>(maEditDoc.GetObject(0))); - bFormatted = false; + mbFormatted = false; if ( IsCallParaInsertedOrDeleted() ) { @@ -248,7 +254,7 @@ void ImpEditEngine::InitDoc(bool bKeepParaAttribs) } if ( GetStatus().DoOnlineSpelling() ) - aEditDoc.GetObject( 0 )->CreateWrongList(); + maEditDoc.GetObject( 0 )->CreateWrongList(); } EditPaM ImpEditEngine::DeleteSelected(const EditSelection& rSel) @@ -263,12 +269,12 @@ OUString ImpEditEngine::GetSelected( const EditSelection& rSel ) const return OUString(); EditSelection aSel( rSel ); - aSel.Adjust( aEditDoc ); + aSel.Adjust( maEditDoc ); ContentNode* pStartNode = aSel.Min().GetNode(); ContentNode* pEndNode = aSel.Max().GetNode(); - sal_Int32 nStartNode = aEditDoc.GetPos( pStartNode ); - sal_Int32 nEndNode = aEditDoc.GetPos( pEndNode ); + sal_Int32 nStartNode = maEditDoc.GetPos( pStartNode ); + sal_Int32 nEndNode = maEditDoc.GetPos( pEndNode ); OSL_ENSURE( nStartNode <= nEndNode, "Selection not sorted ?" ); @@ -278,8 +284,8 @@ OUString ImpEditEngine::GetSelected( const EditSelection& rSel ) const // iterate over the paragraphs ... for ( sal_Int32 nNode = nStartNode; nNode <= nEndNode; nNode++ ) { - OSL_ENSURE( aEditDoc.GetObject( nNode ), "Node not found: GetSelected" ); - const ContentNode* pNode = aEditDoc.GetObject( nNode ); + const ContentNode* pNode = maEditDoc.GetObject( nNode ); + assert(pNode); const sal_Int32 nStartPos = nNode==nStartNode ? aSel.Min().GetIndex() : 0; const sal_Int32 nEndPos = nNode==nEndNode ? aSel.Max().GetIndex() : pNode->Len(); // can also be == nStart! @@ -301,33 +307,33 @@ bool ImpEditEngine::MouseButtonDown( const MouseEvent& rMEvt, EditView* pView ) GetSelEngine().SelMouseButtonDown( rMEvt ); // Special treatment - EditSelection aCurSel( pView->pImpEditView->GetEditSelection() ); - if ( !rMEvt.IsShift() ) + EditSelection aCurSel( pView->getImpl().GetEditSelection() ); + if ( rMEvt.IsShift() ) + return true; + + if ( rMEvt.GetClicks() == 2 ) { - if ( rMEvt.GetClicks() == 2 ) - { - // So that the SelectionEngine knows about the anchor. - aSelEngine.CursorPosChanging( true, false ); - - EditSelection aNewSelection( SelectWord( aCurSel ) ); - pView->pImpEditView->DrawSelectionXOR(); - pView->pImpEditView->SetEditSelection( aNewSelection ); - pView->pImpEditView->DrawSelectionXOR(); - pView->ShowCursor(); - } - else if ( rMEvt.GetClicks() == 3 ) - { - // So that the SelectionEngine knows about the anchor. - aSelEngine.CursorPosChanging( true, false ); - - EditSelection aNewSelection( aCurSel ); - aNewSelection.Min().SetIndex( 0 ); - aNewSelection.Max().SetIndex( aCurSel.Min().GetNode()->Len() ); - pView->pImpEditView->DrawSelectionXOR(); - pView->pImpEditView->SetEditSelection( aNewSelection ); - pView->pImpEditView->DrawSelectionXOR(); - pView->ShowCursor(); - } + // So that the SelectionEngine knows about the anchor. + maSelEngine.CursorPosChanging( true, false ); + + EditSelection aNewSelection( SelectWord( aCurSel ) ); + pView->getImpl().DrawSelectionXOR(); + pView->getImpl().SetEditSelection( aNewSelection ); + pView->getImpl().DrawSelectionXOR(); + pView->ShowCursor(); + } + else if ( rMEvt.GetClicks() == 3 ) + { + // So that the SelectionEngine knows about the anchor. + maSelEngine.CursorPosChanging( true, false ); + + EditSelection aNewSelection( aCurSel ); + aNewSelection.Min().SetIndex( 0 ); + aNewSelection.Max().SetIndex( aCurSel.Min().GetNode()->Len() ); + pView->getImpl().DrawSelectionXOR(); + pView->getImpl().SetEditSelection( aNewSelection ); + pView->getImpl().DrawSelectionXOR(); + pView->ShowCursor(); } return true; } @@ -340,61 +346,69 @@ bool ImpEditEngine::Command( const CommandEvent& rCEvt, EditView* pView ) SetActiveView( pView ); if ( rCEvt.GetCommand() == CommandEventId::StartExtTextInput ) { - pView->DeleteSelected(); - mpIMEInfos.reset(); - EditPaM aPaM = pView->GetImpEditView()->GetEditSelection().Max(); - OUString aOldTextAfterStartPos = aPaM.GetNode()->Copy( aPaM.GetIndex() ); - sal_Int32 nMax = aOldTextAfterStartPos.indexOf( CH_FEATURE ); - if ( nMax != -1 ) // don't overwrite features! - aOldTextAfterStartPos = aOldTextAfterStartPos.copy( 0, nMax ); - mpIMEInfos.reset( new ImplIMEInfos( aPaM, aOldTextAfterStartPos ) ); - mpIMEInfos->bWasCursorOverwrite = !pView->IsInsertMode(); - UndoActionStart( EDITUNDO_INSERT ); + if (!pView->IsReadOnly()) + { + pView->DeleteSelected(); + mpIMEInfos.reset(); + EditPaM aPaM = pView->getImpl().GetEditSelection().Max(); + OUString aOldTextAfterStartPos = aPaM.GetNode()->Copy( aPaM.GetIndex() ); + sal_Int32 nMax = aOldTextAfterStartPos.indexOf( CH_FEATURE ); + if ( nMax != -1 ) // don't overwrite features! + aOldTextAfterStartPos = aOldTextAfterStartPos.copy( 0, nMax ); + mpIMEInfos.reset( new ImplIMEInfos( aPaM, aOldTextAfterStartPos ) ); + mpIMEInfos->bWasCursorOverwrite = !pView->IsInsertMode(); + UndoActionStart( EDITUNDO_INSERT ); + } } else if ( rCEvt.GetCommand() == CommandEventId::EndExtTextInput ) { - OSL_ENSURE( mpIMEInfos, "CommandEventId::EndExtTextInput => No start ?" ); - if( mpIMEInfos ) + if (!pView->IsReadOnly()) { - // #102812# convert quotes in IME text - // works on the last input character, this is especially in Korean text often done - // quotes that are inside of the string are not replaced! - // Borrowed from sw: edtwin.cxx - if ( mpIMEInfos->nLen ) + OSL_ENSURE( mpIMEInfos, "CommandEventId::EndExtTextInput => No start ?" ); + if( mpIMEInfos ) { - EditSelection aSel( mpIMEInfos->aPos ); - aSel.Min().SetIndex( aSel.Min().GetIndex() + mpIMEInfos->nLen-1 ); - aSel.Max().SetIndex( aSel.Max().GetIndex() + mpIMEInfos->nLen ); // #102812# convert quotes in IME text // works on the last input character, this is especially in Korean text often done // quotes that are inside of the string are not replaced! - const sal_Unicode nCharCode = aSel.Min().GetNode()->GetChar( aSel.Min().GetIndex() ); - if ( ( GetStatus().DoAutoCorrect() ) && ( ( nCharCode == '\"' ) || ( nCharCode == '\'' ) ) ) + // Borrowed from sw: edtwin.cxx + if ( mpIMEInfos->nLen ) { - aSel = DeleteSelected( aSel ); - aSel = AutoCorrect( aSel, nCharCode, mpIMEInfos->bWasCursorOverwrite ); - pView->pImpEditView->SetEditSelection( aSel ); + EditSelection aSel( mpIMEInfos->aPos ); + aSel.Min().SetIndex( aSel.Min().GetIndex() + mpIMEInfos->nLen-1 ); + aSel.Max().SetIndex( aSel.Max().GetIndex() + mpIMEInfos->nLen ); + // #102812# convert quotes in IME text + // works on the last input character, this is especially in Korean text often done + // quotes that are inside of the string are not replaced! + // See also tdf#155350 + const sal_Unicode nCharCode = aSel.Min().GetNode()->GetChar( aSel.Min().GetIndex() ); + if ( ( GetStatus().DoAutoCorrect() ) && SvxAutoCorrect::IsAutoCorrectChar(nCharCode) ) + { + aSel = DeleteSelected( aSel ); + aSel = AutoCorrect( aSel, nCharCode, mpIMEInfos->bWasCursorOverwrite ); + pView->getImpl().SetEditSelection( aSel ); + } } - } - ParaPortion& rPortion = FindParaPortion( mpIMEInfos->aPos.GetNode() ); - rPortion.MarkSelectionInvalid( mpIMEInfos->aPos.GetIndex() ); + ParaPortion* pPortion = FindParaPortion( mpIMEInfos->aPos.GetNode() ); + if (pPortion) + pPortion->MarkSelectionInvalid( mpIMEInfos->aPos.GetIndex() ); - bool bWasCursorOverwrite = mpIMEInfos->bWasCursorOverwrite; + bool bWasCursorOverwrite = mpIMEInfos->bWasCursorOverwrite; - mpIMEInfos.reset(); + mpIMEInfos.reset(); - FormatAndLayout( pView ); + FormatAndLayout( pView ); - pView->SetInsertMode( !bWasCursorOverwrite ); + pView->SetInsertMode( !bWasCursorOverwrite ); + } + UndoActionEnd(); } - UndoActionEnd(); } else if ( rCEvt.GetCommand() == CommandEventId::ExtTextInput ) { - OSL_ENSURE( mpIMEInfos, "CommandEventId::ExtTextInput => No Start ?" ); - if( mpIMEInfos ) + if( mpIMEInfos && !pView->IsReadOnly()) { + OSL_ENSURE( mpIMEInfos, "CommandEventId::ExtTextInput => No Start ?" ); const CommandExtTextInputData* pData = rCEvt.GetExtTextInputData(); if ( !pData->IsOnlyCursorChanged() ) @@ -443,8 +457,8 @@ bool ImpEditEngine::Command( const CommandEvent& rCEvt, EditView* pView ) mpIMEInfos->nLen = pData->GetText().getLength(); } - ParaPortion& rPortion = FindParaPortion( mpIMEInfos->aPos.GetNode() ); - rPortion.MarkSelectionInvalid( mpIMEInfos->aPos.GetIndex() ); + ParaPortion* pPortion = FindParaPortion( mpIMEInfos->aPos.GetNode() ); + pPortion->MarkSelectionInvalid( mpIMEInfos->aPos.GetIndex() ); FormatAndLayout( pView ); } @@ -465,7 +479,7 @@ bool ImpEditEngine::Command( const CommandEvent& rCEvt, EditView* pView ) { if (mpIMEInfos) { - EditPaM aPaM( pView->pImpEditView->GetEditSelection().Max() ); + EditPaM aPaM( pView->getImpl().GetEditSelection().Max() ); tools::Rectangle aR1 = PaMtoEditCursor( aPaM ); sal_Int32 nInputEnd = mpIMEInfos->aPos.GetIndex() + mpIMEInfos->nLen; @@ -480,8 +494,8 @@ bool ImpEditEngine::Command( const CommandEvent& rCEvt, EditView* pView ) const EditLine& rLine = pParaPortion->GetLines()[nLine]; if ( nInputEnd > rLine.GetEnd() ) nInputEnd = rLine.GetEnd(); - tools::Rectangle aR2 = PaMtoEditCursor( EditPaM( aPaM.GetNode(), nInputEnd ), GetCursorFlags::EndOfLine ); - tools::Rectangle aRect = pView->GetImpEditView()->GetWindowPos( aR1 ); + tools::Rectangle aR2 = PaMtoEditCursor( EditPaM( aPaM.GetNode(), nInputEnd ), CursorFlags{ .bEndOfLine = true }); + tools::Rectangle aRect = pView->getImpl().GetWindowPos( aR1 ); auto nExtTextInputWidth = aR2.Left() - aR1.Right(); if (EditViewCallbacks* pEditViewCallbacks = pView->getEditViewCallbacks()) pEditViewCallbacks->EditViewCursorRect(aRect, nExtTextInputWidth); @@ -524,7 +538,7 @@ bool ImpEditEngine::Command( const CommandEvent& rCEvt, EditView* pView ) if ( aSelection.nStartPara != aSelection.nEndPara ) { - sal_Int32 aParaLen = pEditEngine->GetTextLen( aSelection.nStartPara ); + sal_Int32 aParaLen = mpEditEngine->GetTextLen( aSelection.nStartPara ); aSelection.nEndPara = aSelection.nStartPara; aSelection.nEndPos = aParaLen; pView->SetSelection( aSelection ); @@ -535,7 +549,7 @@ bool ImpEditEngine::Command( const CommandEvent& rCEvt, EditView* pView ) { if (mpIMEInfos) { - EditPaM aPaM( pView->pImpEditView->GetEditSelection().Max() ); + EditPaM aPaM( pView->getImpl().GetEditSelection().Max() ); if ( !IsFormatted() ) FormatDoc(); @@ -566,10 +580,9 @@ bool ImpEditEngine::Command( const CommandEvent& rCEvt, EditView* pView ) { if (rInfo.pLine->IsIn(n)) { - tools::Rectangle aR = GetEditCursor(pParaPortion, rInfo.pLine, n, - GetCursorFlags::NONE); + tools::Rectangle aR = GetEditCursor(*pParaPortion, *rInfo.pLine, n, CursorFlags()); aR.Move(getTopLeftDocOffset(rInfo.aArea)); - aRects[n - nMinPos] = pView->GetImpEditView()->GetWindowPos(aR); + aRects[n - nMinPos] = pView->getImpl().GetWindowPos(aR); } } } @@ -599,36 +612,40 @@ bool ImpEditEngine::MouseButtonUp( const MouseEvent& rMEvt, EditView* pView ) // non-tiled-rendering case, but it has been here since 2000 (and before) // so who knows what corner case it was supposed to solve back then if (!comphelper::LibreOfficeKit::isActive()) - bInSelection = false; + mbInSelection = false; // Special treatments - EditSelection aCurSel( pView->pImpEditView->GetEditSelection() ); - if ( !aCurSel.HasRange() ) + EditSelection aCurSel( pView->getImpl().GetEditSelection() ); + if ( aCurSel.HasRange() ) + return true; + + if ( ( rMEvt.GetClicks() != 1 ) || !rMEvt.IsLeft() || rMEvt.IsMod2() ) + return true; + + const OutputDevice& rOutDev = pView->getEditViewCallbacks() ? pView->getEditViewCallbacks()->EditViewOutputDevice() : *pView->GetWindow()->GetOutDev(); + Point aLogicClick = rOutDev.PixelToLogic(rMEvt.GetPosPixel()); + const SvxFieldItem* pFld = pView->GetField(aLogicClick); + if (!pFld) + return true; + + // tdf#121039 When in edit mode, editeng is responsible for opening the URL on mouse click + bool bUrlOpened = GetEditEnginePtr()->FieldClicked( *pFld ); + if (bUrlOpened) + return true; + + if (auto pUrlField = dynamic_cast<const SvxURLField*>(pFld->GetField())) { - if ( ( rMEvt.GetClicks() == 1 ) && rMEvt.IsLeft() && !rMEvt.IsMod2() ) + bool bCtrlClickHappened = rMEvt.IsMod1(); + bool bCtrlClickSecOption + = SvtSecurityOptions::IsOptionSet(SvtSecurityOptions::EOption::CtrlClickHyperlink); + if ((bCtrlClickHappened && bCtrlClickSecOption) + || (!bCtrlClickHappened && !bCtrlClickSecOption)) { - const OutputDevice& rOutDev = pView->getEditViewCallbacks() ? pView->getEditViewCallbacks()->EditViewOutputDevice() : *pView->GetWindow()->GetOutDev(); - Point aLogicClick = rOutDev.PixelToLogic(rMEvt.GetPosPixel()); - if (const SvxFieldItem* pFld = pView->GetField(aLogicClick)) - { - // tdf#121039 When in edit mode, editeng is responsible for opening the URL on mouse click - if (auto pUrlField = dynamic_cast<const SvxURLField*>(pFld->GetField())) - { - bool bCtrlClickHappened = rMEvt.IsMod1(); - bool bCtrlClickSecOption - = SvtSecurityOptions::IsOptionSet(SvtSecurityOptions::EOption::CtrlClickHyperlink); - if ((bCtrlClickHappened && bCtrlClickSecOption) - || (!bCtrlClickHappened && !bCtrlClickSecOption)) - { - css::uno::Reference<css::system::XSystemShellExecute> exec( - css::system::SystemShellExecute::create( - comphelper::getProcessComponentContext())); - exec->execute(pUrlField->GetURL(), OUString(), - css::system::SystemShellExecuteFlags::DEFAULTS); - } - } - GetEditEnginePtr()->FieldClicked( *pFld ); - } + css::uno::Reference<css::system::XSystemShellExecute> exec( + css::system::SystemShellExecute::create( + comphelper::getProcessComponentContext())); + exec->execute(pUrlField->GetURL(), OUString(), + css::system::SystemShellExecuteFlags::DEFAULTS); } } return true; @@ -657,33 +674,39 @@ void ImpEditEngine::Clear() { InitDoc( false ); - EditPaM aPaM = aEditDoc.GetStartPaM(); + EditPaM aPaM = maEditDoc.GetStartPaM(); EditSelection aSel( aPaM ); - nCurTextHeight = 0; - nCurTextHeightNTP = 0; + mnCurTextHeight = 0; + mnCurTextHeightNTP = 0; ResetUndoManager(); - for (size_t nView = aEditViews.size(); nView; ) + for (size_t nView = maEditViews.size(); nView; ) { - EditView* pView = aEditViews[--nView]; - pView->pImpEditView->SetEditSelection( aSel ); + EditView* pView = maEditViews[--nView]; + pView->getImpl().SetEditSelection( aSel ); } + + // Related: tdf#82115 Fix crash when handling input method events. + // The nodes in mpIMEInfos may be deleted in ImpEditEngine::Clear() which + // causes a crash in the CommandEventId::ExtTextInput and + // CommandEventId::EndExtTextInput event handlers. + mpIMEInfos.reset(); } EditPaM ImpEditEngine::RemoveText() { InitDoc( true ); - EditPaM aStartPaM = aEditDoc.GetStartPaM(); + EditPaM aStartPaM = maEditDoc.GetStartPaM(); EditSelection aEmptySel( aStartPaM, aStartPaM ); - for (EditView* pView : aEditViews) + for (EditView* pView : maEditViews) { - pView->pImpEditView->SetEditSelection( aEmptySel ); + pView->getImpl().SetEditSelection( aEmptySel ); } ResetUndoManager(); - return aEditDoc.GetStartPaM(); + return maEditDoc.GetStartPaM(); } @@ -700,22 +723,23 @@ void ImpEditEngine::SetText(const OUString& rText) if (!rText.isEmpty()) aPaM = ImpInsertText( aEmptySel, rText ); - for (EditView* pView : aEditViews) + for (EditView* pView : maEditViews) { - pView->pImpEditView->SetEditSelection( EditSelection( aPaM, aPaM ) ); + pView->getImpl().SetEditSelection( EditSelection( aPaM, aPaM ) ); // If no text then also no Format&Update // => The text remains. if (rText.isEmpty() && IsUpdateLayout()) { tools::Rectangle aTmpRect( pView->GetOutputArea().TopLeft(), - Size( aPaperSize.Width(), nCurTextHeight ) ); + Size( maPaperSize.Width(), mnCurTextHeight ) ); aTmpRect.Intersection( pView->GetOutputArea() ); pView->InvalidateWindow( aTmpRect ); } } - if (rText.isEmpty()) { // otherwise it must be invalidated later, !bFormatted is enough. - nCurTextHeight = 0; - nCurTextHeightNTP = 0; + if (rText.isEmpty()) // otherwise it must be invalidated later, !bFormatted is enough. + { + mnCurTextHeight = 0; + mnCurTextHeightNTP = 0; } EnableUndo( bUndoCurrentlyEnabled ); OSL_ENSURE( !HasUndoManager() || !GetUndoManager().GetUndoActionCount(), "Undo after SetText?" ); @@ -726,7 +750,7 @@ const SfxItemSet& ImpEditEngine::GetEmptyItemSet() const { if ( !pEmptyItemSet ) { - pEmptyItemSet = std::make_unique<SfxItemSetFixed<EE_ITEMS_START, EE_ITEMS_END>>(const_cast<SfxItemPool&>(aEditDoc.GetItemPool())); + pEmptyItemSet = std::make_unique<SfxItemSetFixed<EE_ITEMS_START, EE_ITEMS_END>>(const_cast<SfxItemPool&>(maEditDoc.GetItemPool())); for ( sal_uInt16 nWhich = EE_ITEMS_START; nWhich <= EE_CHAR_END; nWhich++) { pEmptyItemSet->ClearItem( nWhich ); @@ -738,18 +762,9 @@ const SfxItemSet& ImpEditEngine::GetEmptyItemSet() const // MISC -void ImpEditEngine::CursorMoved( const ContentNode* pPrevNode ) -{ - // Delete empty attributes, but only if paragraph is not empty! - if (pPrevNode->GetCharAttribs().HasEmptyAttribs() && pPrevNode->Len()) - { - const_cast<ContentNode*>(pPrevNode)->GetCharAttribs().DeleteEmptyAttribs(aEditDoc.GetItemPool()); - } -} - void ImpEditEngine::TextModified() { - bFormatted = false; + mbFormatted = false; if ( GetNotifyHdl().IsSet() ) { @@ -763,20 +778,21 @@ void ImpEditEngine::ParaAttribsChanged( ContentNode const * pNode, bool bIgnoreU { assert(pNode && "ParaAttribsChanged: Which one?"); - aEditDoc.SetModified( true ); - bFormatted = false; + maEditDoc.SetModified( true ); + mbFormatted = false; - ParaPortion& rPortion = FindParaPortion( pNode ); - rPortion.MarkSelectionInvalid( 0 ); + ParaPortion* pPortion = FindParaPortion( pNode ); + assert(pPortion); + pPortion->MarkSelectionInvalid( 0 ); - sal_Int32 nPara = aEditDoc.GetPos( pNode ); - if ( bIgnoreUndoCheck || pEditEngine->IsInUndo() ) - pEditEngine->ParaAttribsChanged( nPara ); + sal_Int32 nPara = maEditDoc.GetPos( pNode ); + if (bIgnoreUndoCheck || mpEditEngine->IsInUndo()) + mpEditEngine->ParaAttribsChanged( nPara ); ParaPortion* pNextPortion = GetParaPortions().SafeGetObject( nPara+1 ); // => is formatted again anyway, if Invalid. if ( pNextPortion && !pNextPortion->IsInvalid() ) - CalcHeight( pNextPortion ); + CalcHeight(*pNextPortion); } @@ -788,7 +804,7 @@ EditSelection const & ImpEditEngine::MoveCursor( const KeyEvent& rKeyEvent, Edit // Actually, only necessary for up/down, but whatever. CheckIdleFormatter(); - EditPaM aPaM( pEditView->pImpEditView->GetEditSelection().Max() ); + EditPaM aPaM(pEditView->getImpl().GetEditSelection().Max()); EditPaM aOldPaM( aPaM ); @@ -928,41 +944,41 @@ EditSelection const & ImpEditEngine::MoveCursor( const KeyEvent& rKeyEvent, Edit break; } - if ( aOldPaM != aPaM ) + if ( aOldPaM != aPaM && nullptr != aOldPaM.GetNode() ) { - CursorMoved( aOldPaM.GetNode() ); + aOldPaM.GetNode()->checkAndDeleteEmptyAttribs(); } // May cause, a CreateAnchor or deselection all - aSelEngine.SetCurView( pEditView ); - aSelEngine.CursorPosChanging( bKeyModifySelection, aTranslatedKeyEvent.GetKeyCode().IsMod1() ); - EditPaM aOldEnd( pEditView->pImpEditView->GetEditSelection().Max() ); + maSelEngine.SetCurView(pEditView); + maSelEngine.CursorPosChanging( bKeyModifySelection, aTranslatedKeyEvent.GetKeyCode().IsMod1() ); + EditPaM aOldEnd(pEditView->getImpl().GetEditSelection().Max()); { - EditSelection aNewSelection(pEditView->pImpEditView->GetEditSelection()); + EditSelection aNewSelection(pEditView->getImpl().GetEditSelection()); aNewSelection.Max() = aPaM; - pEditView->pImpEditView->SetEditSelection(aNewSelection); - // const_cast<EditPaM&>(pEditView->pImpEditView->GetEditSelection().Max()) = aPaM; + pEditView->getImpl().SetEditSelection(aNewSelection); + // const_cast<EditPaM&>(pEditView->getImpl().GetEditSelection().Max()) = aPaM; } if ( bKeyModifySelection ) { // Then the selection is expanded ... or the whole selection is painted in case of tiled rendering. - EditSelection aTmpNewSel( comphelper::LibreOfficeKit::isActive() ? pEditView->pImpEditView->GetEditSelection().Min() : aOldEnd, aPaM ); - pEditView->pImpEditView->DrawSelectionXOR( aTmpNewSel ); + EditSelection aTmpNewSel( comphelper::LibreOfficeKit::isActive() ? pEditView->getImpl().GetEditSelection().Min() : aOldEnd, aPaM ); + pEditView->getImpl().DrawSelectionXOR( aTmpNewSel ); } else { - EditSelection aNewSelection(pEditView->pImpEditView->GetEditSelection()); + EditSelection aNewSelection(pEditView->getImpl().GetEditSelection()); aNewSelection.Min() = aPaM; - pEditView->pImpEditView->SetEditSelection(aNewSelection); - // const_cast<EditPaM&>(pEditView->pImpEditView->GetEditSelection().Min()) = aPaM; + pEditView->getImpl().SetEditSelection(aNewSelection); + // const_cast<EditPaM&>(pEditView->getImpl().GetEditSelection().Min()) = aPaM; } - return pEditView->pImpEditView->GetEditSelection(); + return pEditView->getImpl().GetEditSelection(); } -EditPaM ImpEditEngine::CursorVisualStartEnd( EditView const * pEditView, const EditPaM& rPaM, bool bStart ) +EditPaM ImpEditEngine::CursorVisualStartEnd( EditView const * mpEditView, const EditPaM& rPaM, bool bStart ) { EditPaM aPaM( rPaM ); @@ -975,7 +991,7 @@ EditPaM ImpEditEngine::CursorVisualStartEnd( EditView const * pEditView, const E const EditLine& rLine = pParaPortion->GetLines()[nLine]; bool bEmptyLine = rLine.GetStart() == rLine.GetEnd(); - pEditView->pImpEditView->nExtraCursorFlags = GetCursorFlags::NONE; + mpEditView->getImpl().maExtraCursorFlags = CursorFlags(); if ( !bEmptyLine ) { @@ -1001,15 +1017,15 @@ EditPaM ImpEditEngine::CursorVisualStartEnd( EditView const * pEditView, const E if ( bStart ) { - pEditView->pImpEditView->SetCursorBidiLevel( bPortionRTL ? 0 : 1 ); + mpEditView->getImpl().SetCursorBidiLevel( bPortionRTL ? 0 : 1 ); // Maybe we must be *behind* the character - if ( bPortionRTL && pEditView->IsInsertMode() ) + if (bPortionRTL && mpEditView->IsInsertMode()) aPaM.SetIndex( aPaM.GetIndex()+1 ); } else { - pEditView->pImpEditView->SetCursorBidiLevel( bPortionRTL ? 1 : 0 ); - if ( !bPortionRTL && pEditView->IsInsertMode() ) + mpEditView->getImpl().SetCursorBidiLevel( bPortionRTL ? 1 : 0 ); + if ( !bPortionRTL && mpEditView->IsInsertMode() ) aPaM.SetIndex( aPaM.GetIndex()+1 ); } } @@ -1030,7 +1046,7 @@ EditPaM ImpEditEngine::CursorVisualLeftRight( EditView const * pEditView, const const EditLine& rLine = pParaPortion->GetLines()[nLine]; bool bEmptyLine = rLine.GetStart() == rLine.GetEnd(); - pEditView->pImpEditView->nExtraCursorFlags = GetCursorFlags::NONE; + pEditView->getImpl().maExtraCursorFlags = CursorFlags(); bool bParaRTL = IsRightToLeft( nPara ); @@ -1081,12 +1097,12 @@ EditPaM ImpEditEngine::CursorVisualLeftRight( EditView const * pEditView, const if (bVisualToLeft != bool(nRTLLevel % 2)) { aPaM = CursorLeft( aPaM, nCharacterIteratorMode ); - pEditView->pImpEditView->SetCursorBidiLevel( 1 ); + pEditView->getImpl().SetCursorBidiLevel( 1 ); } else { aPaM = CursorRight( aPaM, nCharacterIteratorMode ); - pEditView->pImpEditView->SetCursorBidiLevel( 0 ); + pEditView->getImpl().SetCursorBidiLevel( 0 ); } bDone = true; } @@ -1126,13 +1142,13 @@ EditPaM ImpEditEngine::CursorVisualLeftRight( EditView const * pEditView, const if ( !bGotoEndOfPrevLine && !bGotoStartOfNextLine ) { aPaM.SetIndex( rLine.GetStart() + ubidi_getLogicalIndex( pBidi, nVisPos, &nError ) ); - pEditView->pImpEditView->SetCursorBidiLevel( 0 ); + pEditView->getImpl().SetCursorBidiLevel( 0 ); } } else { bool bWasBehind = false; - bool bBeforePortion = !nPosInLine || pEditView->pImpEditView->GetCursorBidiLevel() == 1; + bool bBeforePortion = !nPosInLine || pEditView->getImpl().GetCursorBidiLevel() == 1; if ( nPosInLine && ( !bBeforePortion ) ) // before the next portion bWasBehind = true; // step one back, otherwise visual will be unusable when rtl portion follows. @@ -1171,7 +1187,7 @@ EditPaM ImpEditEngine::CursorVisualLeftRight( EditView const * pEditView, const else if ( !bVisualToLeft && bRTLPortion && ( bWasBehind || !_rTextPortion.IsRightToLeft() ) ) aPaM.SetIndex( aPaM.GetIndex()+1 ); - pEditView->pImpEditView->SetCursorBidiLevel( _nPortionStart ); + pEditView->getImpl().SetCursorBidiLevel( _nPortionStart ); } } @@ -1252,24 +1268,25 @@ EditPaM ImpEditEngine::CursorUp( const EditPaM& rPaM, EditView const * pView ) { assert(pView && "No View - No Cursor Movement!"); - const ParaPortion& rPPortion = FindParaPortion( rPaM.GetNode() ); - sal_Int32 nLine = rPPortion.GetLineNumber( rPaM.GetIndex() ); - const EditLine& rLine = rPPortion.GetLines()[nLine]; + const ParaPortion* pPPortion = FindParaPortion( rPaM.GetNode() ); + assert(pPPortion); + sal_Int32 nLine = pPPortion->GetLineNumber( rPaM.GetIndex() ); + const EditLine& rLine = pPPortion->GetLines()[nLine]; tools::Long nX; - if ( pView->pImpEditView->nTravelXPos == TRAVEL_X_DONTKNOW ) + if ( pView->getImpl().mnTravelXPos == TRAVEL_X_DONTKNOW ) { - nX = GetXPos( &rPPortion, &rLine, rPaM.GetIndex() ); - pView->pImpEditView->nTravelXPos = nX+nOnePixelInRef; + nX = GetXPos(*pPPortion, rLine, rPaM.GetIndex()); + pView->getImpl().mnTravelXPos = nX + mnOnePixelInRef; } else - nX = pView->pImpEditView->nTravelXPos; + nX = pView->getImpl().mnTravelXPos; EditPaM aNewPaM( rPaM ); if ( nLine ) // same paragraph { - const EditLine& rPrevLine = rPPortion.GetLines()[nLine-1]; - aNewPaM.SetIndex( GetChar( &rPPortion, &rPrevLine, nX ) ); + const EditLine& rPrevLine = pPPortion->GetLines()[nLine-1]; + aNewPaM.SetIndex(GetChar(*pPPortion, rPrevLine, nX)); // If a previous automatically wrapped line, and one has to be exactly // at the end of this line, the cursor lands on the current line at the // beginning. See Problem: Last character of an automatically wrapped @@ -1279,12 +1296,12 @@ EditPaM ImpEditEngine::CursorUp( const EditPaM& rPaM, EditView const * pView ) } else // previous paragraph { - const ParaPortion* pPrevPortion = GetPrevVisPortion( &rPPortion ); + const ParaPortion* pPrevPortion = GetPrevVisPortion( pPPortion ); if ( pPrevPortion ) { const EditLine& rLine2 = pPrevPortion->GetLines()[pPrevPortion->GetLines().Count()-1]; aNewPaM.SetNode( pPrevPortion->GetNode() ); - aNewPaM.SetIndex( GetChar( pPrevPortion, &rLine2, nX+nOnePixelInRef ) ); + aNewPaM.SetIndex(GetChar(*pPrevPortion, rLine2, nX + mnOnePixelInRef)); } } @@ -1293,40 +1310,41 @@ EditPaM ImpEditEngine::CursorUp( const EditPaM& rPaM, EditView const * pView ) EditPaM ImpEditEngine::CursorDown( const EditPaM& rPaM, EditView const * pView ) { - OSL_ENSURE( pView, "No View - No Cursor Movement!" ); + assert(pView); - const ParaPortion& rPPortion = FindParaPortion( rPaM.GetNode() ); - sal_Int32 nLine = rPPortion.GetLineNumber( rPaM.GetIndex() ); + const ParaPortion* pPPortion = FindParaPortion( rPaM.GetNode() ); + assert(pPPortion); + sal_Int32 nLine = pPPortion->GetLineNumber( rPaM.GetIndex() ); tools::Long nX; - if ( pView->pImpEditView->nTravelXPos == TRAVEL_X_DONTKNOW ) + if ( pView->getImpl().mnTravelXPos == TRAVEL_X_DONTKNOW ) { - const EditLine& rLine = rPPortion.GetLines()[nLine]; - nX = GetXPos( &rPPortion, &rLine, rPaM.GetIndex() ); - pView->pImpEditView->nTravelXPos = nX+nOnePixelInRef; + const EditLine& rLine = pPPortion->GetLines()[nLine]; + nX = GetXPos(*pPPortion, rLine, rPaM.GetIndex()); + pView->getImpl().mnTravelXPos = nX + mnOnePixelInRef; } else - nX = pView->pImpEditView->nTravelXPos; + nX = pView->getImpl().mnTravelXPos; EditPaM aNewPaM( rPaM ); - if ( nLine < rPPortion.GetLines().Count()-1 ) + if ( nLine < pPPortion->GetLines().Count()-1 ) { - const EditLine& rNextLine = rPPortion.GetLines()[nLine+1]; - aNewPaM.SetIndex( GetChar( &rPPortion, &rNextLine, nX ) ); + const EditLine& rNextLine = pPPortion->GetLines()[nLine+1]; + aNewPaM.SetIndex(GetChar(*pPPortion, rNextLine, nX)); // Special treatment, see CursorUp ... - if ( ( aNewPaM.GetIndex() == rNextLine.GetEnd() ) && ( aNewPaM.GetIndex() > rNextLine.GetStart() ) && ( aNewPaM.GetIndex() < rPPortion.GetNode()->Len() ) ) + if ( ( aNewPaM.GetIndex() == rNextLine.GetEnd() ) && ( aNewPaM.GetIndex() > rNextLine.GetStart() ) && ( aNewPaM.GetIndex() < pPPortion->GetNode()->Len() ) ) aNewPaM = CursorLeft( aNewPaM ); } else // next paragraph { - const ParaPortion* pNextPortion = GetNextVisPortion( &rPPortion ); + const ParaPortion* pNextPortion = GetNextVisPortion( pPPortion ); if ( pNextPortion ) { const EditLine& rLine = pNextPortion->GetLines()[0]; aNewPaM.SetNode( pNextPortion->GetNode() ); // Never at the very end when several lines, because then a line // below the cursor appears. - aNewPaM.SetIndex( GetChar( pNextPortion, &rLine, nX+nOnePixelInRef ) ); + aNewPaM.SetIndex(GetChar(*pNextPortion, rLine, nX + mnOnePixelInRef)); if ( ( aNewPaM.GetIndex() == rLine.GetEnd() ) && ( aNewPaM.GetIndex() > rLine.GetStart() ) && ( pNextPortion->GetLines().Count() > 1 ) ) aNewPaM = CursorLeft( aNewPaM ); } @@ -1337,9 +1355,10 @@ EditPaM ImpEditEngine::CursorDown( const EditPaM& rPaM, EditView const * pView ) EditPaM ImpEditEngine::CursorStartOfLine( const EditPaM& rPaM ) { - const ParaPortion& rCurPortion = FindParaPortion( rPaM.GetNode() ); - sal_Int32 nLine = rCurPortion.GetLineNumber( rPaM.GetIndex() ); - const EditLine& rLine = rCurPortion.GetLines()[nLine]; + const ParaPortion* pCurPortion = FindParaPortion( rPaM.GetNode() ); + assert(pCurPortion); + sal_Int32 nLine = pCurPortion->GetLineNumber( rPaM.GetIndex() ); + const EditLine& rLine = pCurPortion->GetLines()[nLine]; EditPaM aNewPaM( rPaM ); aNewPaM.SetIndex( rLine.GetStart() ); @@ -1348,9 +1367,10 @@ EditPaM ImpEditEngine::CursorStartOfLine( const EditPaM& rPaM ) EditPaM ImpEditEngine::CursorEndOfLine( const EditPaM& rPaM ) { - const ParaPortion& rCurPortion = FindParaPortion( rPaM.GetNode() ); - sal_Int32 nLine = rCurPortion.GetLineNumber( rPaM.GetIndex() ); - const EditLine& rLine = rCurPortion.GetLines()[nLine]; + const ParaPortion* pCurPortion = FindParaPortion( rPaM.GetNode() ); + assert(pCurPortion); + sal_Int32 nLine = pCurPortion->GetLineNumber( rPaM.GetIndex() ); + const EditLine& rLine = pCurPortion->GetLines()[nLine]; EditPaM aNewPaM( rPaM ); aNewPaM.SetIndex( rLine.GetEnd() ); @@ -1390,14 +1410,14 @@ EditPaM ImpEditEngine::CursorEndOfParagraph( const EditPaM& rPaM ) EditPaM ImpEditEngine::CursorStartOfDoc() { - EditPaM aPaM( aEditDoc.GetObject( 0 ), 0 ); + EditPaM aPaM( maEditDoc.GetObject( 0 ), 0 ); return aPaM; } EditPaM ImpEditEngine::CursorEndOfDoc() { - ContentNode* pLastNode = aEditDoc.GetObject( aEditDoc.Count()-1 ); - ParaPortion* pLastPortion = GetParaPortions().SafeGetObject( aEditDoc.Count()-1 ); + ContentNode* pLastNode = maEditDoc.GetObject( maEditDoc.Count()-1 ); + ParaPortion* pLastPortion = GetParaPortions().SafeGetObject( maEditDoc.Count()-1 ); OSL_ENSURE( pLastNode && pLastPortion, "CursorEndOfDoc: Node or Portion not found" ); if (!(pLastNode && pLastPortion)) return EditPaM(); @@ -1407,7 +1427,7 @@ EditPaM ImpEditEngine::CursorEndOfDoc() pLastNode = GetPrevVisNode( pLastPortion->GetNode() ); OSL_ENSURE( pLastNode, "No visible paragraph?" ); if ( !pLastNode ) - pLastNode = aEditDoc.GetObject( aEditDoc.Count()-1 ); + pLastNode = maEditDoc.GetObject( maEditDoc.Count()-1 ); } EditPaM aPaM( pLastNode, pLastNode->Len() ); @@ -1419,7 +1439,7 @@ EditPaM ImpEditEngine::PageUp( const EditPaM& rPaM, EditView const * pView ) tools::Rectangle aRect = PaMtoEditCursor( rPaM ); Point aTopLeft = aRect.TopLeft(); aTopLeft.AdjustY( -(pView->GetVisArea().GetHeight() *9/10) ); - aTopLeft.AdjustX(nOnePixelInRef ); + aTopLeft.AdjustX(mnOnePixelInRef); if ( aTopLeft.Y() < 0 ) { aTopLeft.setY( 0 ); @@ -1432,7 +1452,7 @@ EditPaM ImpEditEngine::PageDown( const EditPaM& rPaM, EditView const * pView ) tools::Rectangle aRect = PaMtoEditCursor( rPaM ); Point aBottomRight = aRect.BottomRight(); aBottomRight.AdjustY(pView->GetVisArea().GetHeight() *9/10 ); - aBottomRight.AdjustX(nOnePixelInRef ); + aBottomRight.AdjustX(mnOnePixelInRef); tools::Long nHeight = GetTextHeight(); if ( aBottomRight.Y() > nHeight ) { @@ -1448,8 +1468,8 @@ EditPaM ImpEditEngine::WordLeft( const EditPaM& rPaM ) if ( nCurrentPos == 0 ) { // Previous paragraph... - sal_Int32 nCurPara = aEditDoc.GetPos( aNewPaM.GetNode() ); - ContentNode* pPrevNode = aEditDoc.GetObject( --nCurPara ); + sal_Int32 nCurPara = maEditDoc.GetPos( aNewPaM.GetNode() ); + ContentNode* pPrevNode = maEditDoc.GetObject( --nCurPara ); if ( pPrevNode ) { aNewPaM.SetNode( pPrevNode ); @@ -1498,8 +1518,8 @@ EditPaM ImpEditEngine::WordRight( const EditPaM& rPaM, sal_Int16 nWordType ) if ( aNewPaM.GetIndex() >= nMax ) { // Next paragraph ... - sal_Int32 nCurPara = aEditDoc.GetPos( aNewPaM.GetNode() ); - ContentNode* pNextNode = aEditDoc.GetObject( ++nCurPara ); + sal_Int32 nCurPara = maEditDoc.GetPos( aNewPaM.GetNode() ); + ContentNode* pNextNode = maEditDoc.GetObject( ++nCurPara ); if ( pNextNode ) { aNewPaM.SetNode( pNextNode ); @@ -1521,8 +1541,11 @@ EditPaM ImpEditEngine::StartOfWord( const EditPaM& rPaM ) lang::Locale aLocale( GetLocale( aTmpPaM ) ); uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() ); + // tdf#135761 - since this function is only used when a selection is deleted at the left, + // change the search preference of the word boundary from forward to backward. + // For further details of a deletion of a selection check ImpEditEngine::DeleteLeftOrRight. i18n::Boundary aBoundary = _xBI->getWordBoundary( - rPaM.GetNode()->GetString(), rPaM.GetIndex(), aLocale, css::i18n::WordType::ANYWORD_IGNOREWHITESPACES, true); + rPaM.GetNode()->GetString(), rPaM.GetIndex(), aLocale, css::i18n::WordType::ANYWORD_IGNOREWHITESPACES, false); aNewPaM.SetIndex( aBoundary.startPos ); return aNewPaM; @@ -1547,7 +1570,7 @@ EditPaM ImpEditEngine::EndOfWord( const EditPaM& rPaM ) return aNewPaM; } -EditSelection ImpEditEngine::SelectWord( const EditSelection& rCurSel, sal_Int16 nWordType, bool bAcceptStartOfWord ) +EditSelection ImpEditEngine::SelectWord( const EditSelection& rCurSel, sal_Int16 nWordType, bool bAcceptStartOfWord, bool bAcceptEndOfWord ) { EditSelection aNewSel( rCurSel ); EditPaM aPaM( rCurSel.Max() ); @@ -1569,7 +1592,7 @@ EditSelection ImpEditEngine::SelectWord( const EditSelection& rCurSel, sal_Int16 aPaM.GetNode()->GetString(), aPaM.GetIndex(), aLocale, nWordType, true); // don't select when cursor at end of word - if ( ( aBoundary.endPos > aPaM.GetIndex() ) && + if ( ( aBoundary.endPos > aPaM.GetIndex() || ( bAcceptEndOfWord && aBoundary.endPos == aPaM.GetIndex() ) ) && ( ( aBoundary.startPos < aPaM.GetIndex() ) || ( bAcceptStartOfWord && ( aBoundary.startPos == aPaM.GetIndex() ) ) ) ) { aNewSel.Min().SetIndex( aBoundary.startPos ); @@ -1605,15 +1628,13 @@ EditSelection ImpEditEngine::SelectSentence( const EditSelection& rCurSel ) bool ImpEditEngine::IsInputSequenceCheckingRequired( sal_Unicode nChar, const EditSelection& rCurSel ) const { uno::Reference < i18n::XBreakIterator > _xBI( ImplGetBreakIterator() ); - if (!pCTLOptions) - pCTLOptions.reset( new SvtCTLOptions ); // get the index that really is first const sal_Int32 nFirstPos = std::min(rCurSel.Min().GetIndex(), rCurSel.Max().GetIndex()); bool bIsSequenceChecking = - pCTLOptions->IsCTLFontEnabled() && - pCTLOptions->IsCTLSequenceChecking() && + SvtCTLOptions::IsCTLFontEnabled() && + SvtCTLOptions::IsCTLSequenceChecking() && nFirstPos != 0 && /* first char needs not to be checked */ _xBI.is() && i18n::ScriptType::COMPLEX == _xBI->getScriptType( OUString( nChar ), 0 ); @@ -1640,7 +1661,7 @@ void ImpEditEngine::InitScriptTypes( sal_Int32 nPara ) if (!pParaPortion) return; - ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos; + ScriptTypePosInfos& rTypes = pParaPortion->getScriptTypePosInfos(); rTypes.clear(); ContentNode* pNode = pParaPortion->GetNode(); @@ -1706,14 +1727,19 @@ void ImpEditEngine::InitScriptTypes( sal_Int32 nPara ) } else { - if ( _xBI->getScriptType( aText, nPos - 1 ) == i18n::ScriptType::WEAK ) + auto nPrevPos = nPos; + auto nPrevChar = aText.iterateCodePoints(&nPrevPos, -1); + if (_xBI->getScriptType(aText, nPrevPos) == i18n::ScriptType::WEAK) { - switch ( u_charType(aText.iterateCodePoints(&nPos, 0) ) ) { - case U_NON_SPACING_MARK: - case U_ENCLOSING_MARK: - case U_COMBINING_SPACING_MARK: - --nPos; - rTypes.back().nEndPos--; + auto nChar = aText.iterateCodePoints(&nPos, 0); + auto nType = unicode::getUnicodeType(nChar); + if (nType == css::i18n::UnicodeType::NON_SPACING_MARK || + nType == css::i18n::UnicodeType::ENCLOSING_MARK || + nType == css::i18n::UnicodeType::COMBINING_SPACING_MARK || + (nPrevChar == 0x202F /* NNBSP, tdf#112594 */ && + u_getIntPropertyValue(nChar, UCHAR_SCRIPT) == USCRIPT_MONGOLIAN)) + { + rTypes.back().nEndPos = nPos = nPrevPos; break; } } @@ -1727,11 +1753,11 @@ void ImpEditEngine::InitScriptTypes( sal_Int32 nPara ) rTypes[0].nScriptType = ( rTypes.size() > 1 ) ? rTypes[1].nScriptType : SvtLanguageOptions::GetI18NScriptTypeOfLanguage( GetDefaultLanguage() ); // create writing direction information: - if ( pParaPortion->aWritingDirectionInfos.empty() ) + WritingDirectionInfos& rDirInfos = pParaPortion->getWritingDirectionInfos(); + if (rDirInfos.empty()) InitWritingDirections( nPara ); // i89825: Use CTL font for numbers embedded into an RTL run: - WritingDirectionInfos& rDirInfos = pParaPortion->aWritingDirectionInfos; for (const WritingDirectionInfo & rDirInfo : rDirInfos) { const sal_Int32 nStart = rDirInfo.nStartPos; @@ -1806,10 +1832,10 @@ sal_uInt16 ImpEditEngine::GetI18NScriptType( const EditPaM& rPaM, sal_Int32* pEn const ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara ); if (pParaPortion) { - if ( pParaPortion->aScriptInfos.empty() ) - const_cast<ImpEditEngine*>(this)->InitScriptTypes( nPara ); + const ScriptTypePosInfos& rTypes = pParaPortion->getScriptTypePosInfos(); - const ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos; + if (rTypes.empty()) + const_cast<ImpEditEngine*>(this)->InitScriptTypes( nPara ); const sal_Int32 nPos = rPaM.GetIndex(); ScriptTypePosInfos::const_iterator itr = std::find_if(rTypes.begin(), rTypes.end(), FindByPos(nPos)); @@ -1827,7 +1853,7 @@ sal_uInt16 ImpEditEngine::GetI18NScriptType( const EditPaM& rPaM, sal_Int32* pEn SvtScriptType ImpEditEngine::GetItemScriptType( const EditSelection& rSel ) const { EditSelection aSel( rSel ); - aSel.Adjust( aEditDoc ); + aSel.Adjust( maEditDoc ); SvtScriptType nScriptType = SvtScriptType::NONE; @@ -1840,10 +1866,10 @@ SvtScriptType ImpEditEngine::GetItemScriptType( const EditSelection& rSel ) cons if (!pParaPortion) continue; - if ( pParaPortion->aScriptInfos.empty() ) - const_cast<ImpEditEngine*>(this)->InitScriptTypes( nPara ); + ScriptTypePosInfos const& rTypes = pParaPortion->getScriptTypePosInfos(); - const ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos; + if (rTypes.empty()) + const_cast<ImpEditEngine*>(this)->InitScriptTypes( nPara ); // find all the scripts of this range sal_Int32 nS = ( nPara == nStartPara ) ? aSel.Min().GetIndex() : 0; @@ -1886,10 +1912,11 @@ bool ImpEditEngine::IsScriptChange( const EditPaM& rPaM ) const const ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara ); if (pParaPortion) { - if ( pParaPortion->aScriptInfos.empty() ) + ScriptTypePosInfos const& rTypes = pParaPortion->getScriptTypePosInfos(); + + if (rTypes.empty()) const_cast<ImpEditEngine*>(this)->InitScriptTypes( nPara ); - const ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos; const sal_Int32 nPos = rPaM.GetIndex(); for (const ScriptTypePosInfo & rType : rTypes) { @@ -1911,10 +1938,11 @@ bool ImpEditEngine::HasScriptType( sal_Int32 nPara, sal_uInt16 nType ) const const ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara ); if (pParaPortion) { - if ( pParaPortion->aScriptInfos.empty() ) + const ScriptTypePosInfos& rTypes = pParaPortion->getScriptTypePosInfos(); + + if (rTypes.empty()) const_cast<ImpEditEngine*>(this)->InitScriptTypes( nPara ); - const ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos; for ( size_t n = rTypes.size(); n && !bTypeFound; ) { if ( rTypes[--n].nScriptType == nType ) @@ -1930,10 +1958,10 @@ void ImpEditEngine::InitWritingDirections( sal_Int32 nPara ) if (!pParaPortion) return; - WritingDirectionInfos& rInfos = pParaPortion->aWritingDirectionInfos; + WritingDirectionInfos& rInfos = pParaPortion->getWritingDirectionInfos(); rInfos.clear(); - if (pParaPortion->GetNode()->Len()) + if (pParaPortion->GetNode()->Len() && !mbFuzzing) { const OUString aText = pParaPortion->GetNode()->GetString(); @@ -2030,16 +2058,16 @@ sal_uInt8 ImpEditEngine::GetRightToLeft( sal_Int32 nPara, sal_Int32 nPos, sal_In { sal_uInt8 nRightToLeft = 0; - ContentNode* pNode = aEditDoc.GetObject( nPara ); + ContentNode* pNode = maEditDoc.GetObject( nPara ); if ( pNode && pNode->Len() ) { ParaPortion* pParaPortion = GetParaPortions().SafeGetObject( nPara ); if (pParaPortion) { - if ( pParaPortion->aWritingDirectionInfos.empty() ) + WritingDirectionInfos& rDirInfos = pParaPortion->getWritingDirectionInfos(); + if (rDirInfos.empty()) InitWritingDirections( nPara ); - WritingDirectionInfos& rDirInfos = pParaPortion->aWritingDirectionInfos; for (const WritingDirectionInfo & rDirInfo : rDirInfos) { if ( ( rDirInfo.nStartPos <= nPos ) && ( rDirInfo.nEndPos >= nPos ) ) @@ -2061,7 +2089,7 @@ SvxAdjust ImpEditEngine::GetJustification( sal_Int32 nPara ) const { SvxAdjust eJustification = SvxAdjust::Left; - if ( !aStatus.IsOutliner() ) + if (!maStatus.IsOutliner()) { eJustification = GetParaAttrib( nPara, EE_PARA_JUST ).GetAdjust(); @@ -2110,15 +2138,15 @@ void ImpEditEngine::ImpRemoveChars( const EditPaM& rPaM, sal_Int32 nChars ) break; // for } } - InsertUndo(std::make_unique<EditUndoRemoveChars>(pEditEngine, CreateEPaM(rPaM), aStr)); + InsertUndo(std::make_unique<EditUndoRemoveChars>(mpEditEngine, CreateEPaM(rPaM), aStr)); } - aEditDoc.RemoveChars( rPaM, nChars ); + maEditDoc.RemoveChars( rPaM, nChars ); } EditSelection ImpEditEngine::ImpMoveParagraphs( Range aOldPositions, sal_Int32 nNewPos ) { - aOldPositions.Justify(); + aOldPositions.Normalize(); bool bValidAction = ( static_cast<tools::Long>(nNewPos) < aOldPositions.Min() ) || ( static_cast<tools::Long>(nNewPos) > aOldPositions.Max() ); OSL_ENSURE( bValidAction, "Move in itself?" ); OSL_ENSURE( aOldPositions.Max() <= static_cast<tools::Long>(GetParaPortions().Count()), "totally over it: MoveParagraphs" ); @@ -2127,7 +2155,7 @@ EditSelection ImpEditEngine::ImpMoveParagraphs( Range aOldPositions, sal_Int32 n if ( !bValidAction ) { - aSelection = aEditDoc.GetStartPaM(); + aSelection = maEditDoc.GetStartPaM(); return aSelection; } @@ -2142,68 +2170,83 @@ EditSelection ImpEditEngine::ImpMoveParagraphs( Range aOldPositions, sal_Int32 n ParaPortion* pRecalc3 = nullptr; ParaPortion* pRecalc4 = nullptr; - if ( nNewPos == 0 ) // Move to Start + if (nNewPos == 0) // Move to Start { - pRecalc1 = &GetParaPortions()[0]; - pRecalc2 = &GetParaPortions()[aOldPositions.Min()]; + if (GetParaPortions().exists(0)) + pRecalc1 = &GetParaPortions().getRef(0); + if (GetParaPortions().exists(aOldPositions.Min())) + pRecalc2 = &GetParaPortions().getRef(aOldPositions.Min()); } - else if ( nNewPos == nParaCount ) + else if (nNewPos == nParaCount) { - pRecalc1 = &GetParaPortions()[nParaCount-1]; - pRecalc2 = &GetParaPortions()[aOldPositions.Max()]; + if (GetParaPortions().exists(nParaCount - 1)) + pRecalc1 = &GetParaPortions().getRef(nParaCount - 1); + if (GetParaPortions().exists(aOldPositions.Max())) + pRecalc2 = &GetParaPortions().getRef(aOldPositions.Max()); } - if ( aOldPositions.Min() == 0 ) // Move from Start + if (aOldPositions.Min() == 0) // Move from Start { - pRecalc3 = &GetParaPortions()[0]; - pRecalc4 = &GetParaPortions()[aOldPositions.Max()+1]; + if (GetParaPortions().exists(0)) + pRecalc3 = &GetParaPortions().getRef(0); + if (GetParaPortions().exists(aOldPositions.Max() + 1)) + pRecalc4 = &GetParaPortions().getRef(aOldPositions.Max() + 1); } - else if ( aOldPositions.Max() == (nParaCount-1) ) + else if (aOldPositions.Max() == nParaCount - 1) { - pRecalc3 = &GetParaPortions()[aOldPositions.Max()]; - pRecalc4 = &GetParaPortions()[aOldPositions.Min()-1]; + if (GetParaPortions().exists(aOldPositions.Max())) + pRecalc3 = &GetParaPortions().getRef(aOldPositions.Max()); + if (GetParaPortions().exists(aOldPositions.Min() - 1)) + pRecalc4 = &GetParaPortions().getRef(aOldPositions.Min() - 1); } MoveParagraphsInfo aMoveParagraphsInfo( aOldPositions.Min(), aOldPositions.Max(), nNewPos ); - aBeginMovingParagraphsHdl.Call( aMoveParagraphsInfo ); + maBeginMovingParagraphsHdl.Call( aMoveParagraphsInfo ); if ( IsUndoEnabled() && !IsInUndo()) - InsertUndo(std::make_unique<EditUndoMoveParagraphs>(pEditEngine, aOldPositions, nNewPos)); + InsertUndo(std::make_unique<EditUndoMoveParagraphs>(mpEditEngine, aOldPositions, nNewPos)); // do not lose sight of the Position ! ParaPortion* pDestPortion = GetParaPortions().SafeGetObject( nNewPos ); - ParaPortionList aTmpPortionList; + // Temporary containers used for moving the paragraph portions and content nodes to a new location + std::vector<std::unique_ptr<ParaPortion>> aParagraphPortionVector; + std::vector<std::unique_ptr<ContentNode>> aContentNodeVector; + + // Take the paragraph portions and content nodes out of its containers for (tools::Long i = aOldPositions.Min(); i <= aOldPositions.Max(); i++ ) { - // always aOldPositions.Min(), since Remove(). - ParaPortion aTmpPortion = GetParaPortions().Remove(aOldPositions.Min()); - aEditDoc.Release( aOldPositions.Min() ); - aTmpPortionList.Append(std::move(aTmpPortion)); + // always aOldPositions.Min() as the index, since we remove and the elements from the containers and the + // other elements shift to the left. + std::unique_ptr<ParaPortion> pPortion = GetParaPortions().Release(aOldPositions.Min()); + aParagraphPortionVector.push_back(std::move(pPortion)); + + std::unique_ptr<ContentNode> pContentNode = maEditDoc.Release(aOldPositions.Min()); + aContentNodeVector.push_back(std::move(pContentNode)); } + // Determine the new location for paragraphs sal_Int32 nRealNewPos = pDestPortion ? GetParaPortions().GetPos( pDestPortion ) : GetParaPortions().Count(); - OSL_ENSURE( nRealNewPos != EE_PARA_NOT_FOUND, "ImpMoveParagraphs: Invalid Position!" ); + assert( nRealNewPos != EE_PARA_NOT_FOUND && "ImpMoveParagraphs: Invalid Position!" ); + // Add the paragraph portions and content nodes to a new position sal_Int32 i = 0; - while( aTmpPortionList.Count() > 0 ) + for (auto& pPortion : aParagraphPortionVector) { - ParaPortion aTmpPortion = aTmpPortionList.Remove(0); - if ( i == 0 ) - aSelection.Min().SetNode( aTmpPortion.GetNode() ); + if (i == 0) + aSelection.Min().SetNode(pPortion->GetNode()); + aSelection.Max().SetNode(pPortion->GetNode()); + aSelection.Max().SetIndex(pPortion->GetNode()->Len()); - aSelection.Max().SetNode( aTmpPortion.GetNode() ); - aSelection.Max().SetIndex( aTmpPortion.GetNode()->Len() ); + maEditDoc.Insert(nRealNewPos + i, std::move(aContentNodeVector[i])); + GetParaPortions().Insert(nRealNewPos + i, std::move(pPortion)); - ContentNode* pN = aTmpPortion.GetNode(); - aEditDoc.Insert(nRealNewPos+i, pN); - - GetParaPortions().Insert(nRealNewPos+i, std::move(aTmpPortion)); ++i; } - aEndMovingParagraphsHdl.Call( aMoveParagraphsInfo ); + // Signal end of paragraph moving + maEndMovingParagraphsHdl.Call( aMoveParagraphsInfo ); if ( GetNotifyHdl().IsSet() ) { @@ -2214,19 +2257,19 @@ EditSelection ImpEditEngine::ImpMoveParagraphs( Range aOldPositions, sal_Int32 n GetNotifyHdl().Call( aNotify ); } - aEditDoc.SetModified( true ); + maEditDoc.SetModified( true ); - if ( pRecalc1 ) - CalcHeight( pRecalc1 ); - if ( pRecalc2 ) - CalcHeight( pRecalc2 ); - if ( pRecalc3 ) - CalcHeight( pRecalc3 ); - if ( pRecalc4 ) - CalcHeight( pRecalc4 ); + if (pRecalc1) + CalcHeight(*pRecalc1); + if (pRecalc2) + CalcHeight(*pRecalc2); + if (pRecalc3) + CalcHeight(*pRecalc3); + if (pRecalc4) + CalcHeight(*pRecalc4); #if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG - ParaPortionList::DbgCheck(GetParaPortions(), aEditDoc); + ParaPortionList::DbgCheck(GetParaPortions(), maEditDoc); #endif return aSelection; } @@ -2235,28 +2278,28 @@ EditSelection ImpEditEngine::ImpMoveParagraphs( Range aOldPositions, sal_Int32 n EditPaM ImpEditEngine::ImpConnectParagraphs( ContentNode* pLeft, ContentNode* pRight, bool bBackward ) { OSL_ENSURE( pLeft != pRight, "Join together the same paragraph ?" ); - OSL_ENSURE( aEditDoc.GetPos( pLeft ) != EE_PARA_NOT_FOUND, "Inserted node not found (1)" ); - OSL_ENSURE( aEditDoc.GetPos( pRight ) != EE_PARA_NOT_FOUND, "Inserted node not found (2)" ); + OSL_ENSURE( maEditDoc.GetPos( pLeft ) != EE_PARA_NOT_FOUND, "Inserted node not found (1)" ); + OSL_ENSURE( maEditDoc.GetPos( pRight ) != EE_PARA_NOT_FOUND, "Inserted node not found (2)" ); // #i120020# it is possible that left and right are *not* in the desired order (left/right) // so correct it. This correction is needed, else an invalid SfxLinkUndoAction will be // created from ConnectParagraphs below. Assert this situation, it should be corrected by the // caller. - if(aEditDoc.GetPos( pLeft ) > aEditDoc.GetPos( pRight )) + if (maEditDoc.GetPos( pLeft ) > maEditDoc.GetPos( pRight )) { OSL_ENSURE(false, "ImpConnectParagraphs with wrong order of pLeft/pRight nodes (!)"); std::swap(pLeft, pRight); } - sal_Int32 nParagraphTobeDeleted = aEditDoc.GetPos( pRight ); - aDeletedNodes.push_back(std::make_unique<DeletedNodeInfo>( pRight, nParagraphTobeDeleted )); + sal_Int32 nParagraphTobeDeleted = maEditDoc.GetPos( pRight ); + maDeletedNodes.push_back(std::make_unique<DeletedNodeInfo>( pRight, nParagraphTobeDeleted )); - GetEditEnginePtr()->ParagraphConnected( aEditDoc.GetPos( pLeft ), aEditDoc.GetPos( pRight ) ); + GetEditEnginePtr()->ParagraphConnected( maEditDoc.GetPos( pLeft ), maEditDoc.GetPos( pRight ) ); if ( IsUndoEnabled() && !IsInUndo() ) { - InsertUndo( std::make_unique<EditUndoConnectParas>(pEditEngine, - aEditDoc.GetPos( pLeft ), pLeft->Len(), + InsertUndo( std::make_unique<EditUndoConnectParas>(mpEditEngine, + maEditDoc.GetPos( pLeft ), pLeft->Len(), pLeft->GetContentAttribs().GetItems(), pRight->GetContentAttribs().GetItems(), pLeft->GetStyleSheet(), pRight->GetStyleSheet(), bBackward ) ); } @@ -2273,7 +2316,8 @@ EditPaM ImpEditEngine::ImpConnectParagraphs( ContentNode* pLeft, ContentNode* pR ParaAttribsChanged( pLeft, true ); // First search for Portions since pRight is gone after ConnectParagraphs. - ParaPortion& rLeftPortion = FindParaPortion( pLeft ); + ParaPortion* pLeftPortion = FindParaPortion( pLeft ); + assert(pLeftPortion); if ( GetStatus().DoOnlineSpelling() ) { @@ -2297,10 +2341,10 @@ EditPaM ImpEditEngine::ImpConnectParagraphs( ContentNode* pLeft, ContentNode* pR if ( IsCallParaInsertedOrDeleted() ) GetEditEnginePtr()->ParagraphDeleted( nParagraphTobeDeleted ); - EditPaM aPaM = aEditDoc.ConnectParagraphs( pLeft, pRight ); + EditPaM aPaM = maEditDoc.ConnectParagraphs( pLeft, pRight ); GetParaPortions().Remove( nParagraphTobeDeleted ); - rLeftPortion.MarkSelectionInvalid( aPaM.GetIndex() ); + pLeftPortion->MarkSelectionInvalid( aPaM.GetIndex() ); // the right node is deleted by EditDoc:ConnectParagraphs(). if ( GetTextRanger() ) @@ -2310,9 +2354,9 @@ EditPaM ImpEditEngine::ImpConnectParagraphs( ContentNode* pLeft, ContentNode* pR // the change of the total text height too late... for ( sal_Int32 n = nParagraphTobeDeleted; n < GetParaPortions().Count(); n++ ) { - ParaPortion& rPP = GetParaPortions()[n]; - rPP.MarkSelectionInvalid( 0 ); - rPP.GetLines().Reset(); + ParaPortion& rParaPortion = GetParaPortions().getRef(n); + rParaPortion.MarkSelectionInvalid(0); + rParaPortion.GetLines().Reset(); } } @@ -2323,7 +2367,7 @@ EditPaM ImpEditEngine::ImpConnectParagraphs( ContentNode* pLeft, ContentNode* pR EditPaM ImpEditEngine::DeleteLeftOrRight( const EditSelection& rSel, sal_uInt8 nMode, DeleteMode nDelMode ) { - OSL_ENSURE( !rSel.DbgIsBuggy( aEditDoc ), "Index out of range in DeleteLeftOrRight" ); + OSL_ENSURE( !rSel.DbgIsBuggy( maEditDoc ), "Index out of range in DeleteLeftOrRight" ); if ( rSel.HasRange() ) // only then Delete Selection return ImpDeleteSelection( rSel ); @@ -2336,17 +2380,15 @@ EditPaM ImpEditEngine::DeleteLeftOrRight( const EditSelection& rSel, sal_uInt8 n if ( nDelMode == DeleteMode::Simple ) { sal_uInt16 nCharMode = i18n::CharacterIteratorMode::SKIPCHARACTER; - // Check if we are deleting a CJK ideograph variance sequence (IVS). + // If we are deleting a variation selector, we want to delete the + // whole sequence (cell). sal_Int32 nIndex = aCurPos.GetIndex(); if (nIndex > 0) { const OUString& rString = aCurPos.GetNode()->GetString(); sal_Int32 nCode = rString.iterateCodePoints(&nIndex, -1); - if (unicode::isIVSSelector(nCode) && nIndex > 0 && - unicode::isCJKIVSCharacter(rString.iterateCodePoints(&nIndex, -1))) - { + if (unicode::isVariationSelector(nCode)) nCharMode = i18n::CharacterIteratorMode::SKIPCELL; - } } aDelStart = CursorLeft(aCurPos, nCharMode); } @@ -2420,18 +2462,20 @@ EditPaM ImpEditEngine::ImpDeleteSelection(const EditSelection& rCurSel) return rCurSel.Min(); EditSelection aCurSel(rCurSel); - aCurSel.Adjust( aEditDoc ); + aCurSel.Adjust( maEditDoc ); EditPaM aStartPaM(aCurSel.Min()); EditPaM aEndPaM(aCurSel.Max()); - CursorMoved( aStartPaM.GetNode() ); // only so that newly set Attributes disappear... - CursorMoved( aEndPaM.GetNode() ); // only so that newly set Attributes disappear... + if( nullptr != aStartPaM.GetNode() ) + aStartPaM.GetNode()->checkAndDeleteEmptyAttribs(); // only so that newly set Attributes disappear... + if( nullptr != aEndPaM.GetNode() ) + aEndPaM.GetNode()->checkAndDeleteEmptyAttribs(); // only so that newly set Attributes disappear... OSL_ENSURE( aStartPaM.GetIndex() <= aStartPaM.GetNode()->Len(), "Index out of range in ImpDeleteSelection" ); OSL_ENSURE( aEndPaM.GetIndex() <= aEndPaM.GetNode()->Len(), "Index out of range in ImpDeleteSelection" ); - sal_Int32 nStartNode = aEditDoc.GetPos( aStartPaM.GetNode() ); - sal_Int32 nEndNode = aEditDoc.GetPos( aEndPaM.GetNode() ); + sal_Int32 nStartNode = maEditDoc.GetPos( aStartPaM.GetNode() ); + sal_Int32 nEndNode = maEditDoc.GetPos( aEndPaM.GetNode() ); OSL_ENSURE( nEndNode != EE_PARA_NOT_FOUND, "Start > End ?!" ); OSL_ENSURE( nStartNode <= nEndNode, "Start > End ?!" ); @@ -2447,23 +2491,26 @@ EditPaM ImpEditEngine::ImpDeleteSelection(const EditSelection& rCurSel) { // The Rest of the StartNodes... ImpRemoveChars( aStartPaM, aStartPaM.GetNode()->Len() - aStartPaM.GetIndex() ); - ParaPortion& rPortion = FindParaPortion( aStartPaM.GetNode() ); - rPortion.MarkSelectionInvalid( aStartPaM.GetIndex() ); + ParaPortion* pPortion = FindParaPortion( aStartPaM.GetNode() ); + assert(pPortion); + pPortion->MarkSelectionInvalid( aStartPaM.GetIndex() ); // The beginning of the EndNodes... const sal_Int32 nChars = aEndPaM.GetIndex(); aEndPaM.SetIndex( 0 ); ImpRemoveChars( aEndPaM, nChars ); - ParaPortion& rPortion2 = FindParaPortion( aEndPaM.GetNode() ); - rPortion2.MarkSelectionInvalid( 0 ); + pPortion = FindParaPortion( aEndPaM.GetNode() ); + assert(pPortion); + pPortion->MarkSelectionInvalid( 0 ); // Join together... aStartPaM = ImpConnectParagraphs( aStartPaM.GetNode(), aEndPaM.GetNode() ); } else { ImpRemoveChars( aStartPaM, aEndPaM.GetIndex() - aStartPaM.GetIndex() ); - ParaPortion& rPortion = FindParaPortion( aStartPaM.GetNode() ); - rPortion.MarkInvalid( aEndPaM.GetIndex(), aStartPaM.GetIndex() - aEndPaM.GetIndex() ); + ParaPortion* pPortion = FindParaPortion( aStartPaM.GetNode() ); + assert(pPortion); + pPortion->MarkInvalid( aEndPaM.GetIndex(), aStartPaM.GetIndex() - aEndPaM.GetIndex() ); } UpdateSelections(); @@ -2473,15 +2520,15 @@ EditPaM ImpEditEngine::ImpDeleteSelection(const EditSelection& rCurSel) void ImpEditEngine::ImpRemoveParagraph( sal_Int32 nPara ) { - ContentNode* pNode = aEditDoc.GetObject( nPara ); - ContentNode* pNextNode = aEditDoc.GetObject( nPara+1 ); + assert(maEditDoc.GetObject(nPara)); - OSL_ENSURE( pNode, "Blind Node in ImpRemoveParagraph" ); + ContentNode* pNextNode = maEditDoc.GetObject( nPara+1 ); - aDeletedNodes.push_back(std::make_unique<DeletedNodeInfo>( pNode, nPara )); + std::unique_ptr<ContentNode> pNode = maEditDoc.Release(nPara); + maDeletedNodes.push_back(std::make_unique<DeletedNodeInfo>(pNode.get(), nPara)); // The node is managed by the undo and possibly destroyed! - aEditDoc.Release( nPara ); + GetParaPortions().Remove( nPara ); if ( IsCallParaInsertedOrDeleted() ) @@ -2495,14 +2542,15 @@ void ImpEditEngine::ImpRemoveParagraph( sal_Int32 nPara ) if ( pNextNode ) ParaAttribsChanged( pNextNode ); - if ( IsUndoEnabled() && !IsInUndo() ) - InsertUndo(std::make_unique<EditUndoDelContent>(pEditEngine, pNode, nPara)); + if (IsUndoEnabled() && !IsInUndo()) + { + InsertUndo(std::make_unique<EditUndoDelContent>(mpEditEngine, std::move(pNode), nPara)); + } else { - aEditDoc.RemoveItemsFromPool(*pNode); if ( pNode->GetStyleSheet() ) - EndListening( *pNode->GetStyleSheet() ); - delete pNode; + EndListening(*pNode->GetStyleSheet()); + pNode.reset(); } } @@ -2563,7 +2611,7 @@ EditPaM ImpEditEngine::AutoCorrect( const EditSelection& rCurSel, sal_Unicode c, ContentNode* pNode = aSel.Max().GetNode(); const sal_Int32 nIndex = aSel.Max().GetIndex(); - EdtAutoCorrDoc aAuto(pEditEngine, pNode, nIndex, c); + EdtAutoCorrDoc aAuto(mpEditEngine, pNode, nIndex, c); // FIXME: this _must_ be called with reference to the actual node text! OUString const& rNodeString(pNode->GetString()); pAutoCorrect->DoAutoCorrect( @@ -2603,7 +2651,7 @@ EditPaM ImpEditEngine::InsertTextUserInput( const EditSelection& rCurSel, // If selected, then do not also overwrite a character! EditSelection aTmpSel( aPaM ); aTmpSel.Max().SetIndex( aTmpSel.Max().GetIndex()+1 ); - OSL_ENSURE( !aTmpSel.DbgIsBuggy( aEditDoc ), "Overwrite: Wrong selection! "); + OSL_ENSURE( !aTmpSel.DbgIsBuggy( maEditDoc ), "Overwrite: Wrong selection! "); ImpDeleteSelection( aTmpSel ); } @@ -2612,20 +2660,18 @@ EditPaM ImpEditEngine::InsertTextUserInput( const EditSelection& rCurSel, if (IsInputSequenceCheckingRequired( c, rCurSel )) { uno::Reference < i18n::XExtendedInputSequenceChecker > _xISC( ImplGetInputSequenceChecker() ); - if (!pCTLOptions) - pCTLOptions.reset( new SvtCTLOptions ); if (_xISC) { const sal_Int32 nTmpPos = aPaM.GetIndex(); - sal_Int16 nCheckMode = pCTLOptions->IsCTLSequenceCheckingRestricted() ? + sal_Int16 nCheckMode = SvtCTLOptions::IsCTLSequenceCheckingRestricted() ? i18n::InputSequenceCheckMode::STRICT : i18n::InputSequenceCheckMode::BASIC; // the text that needs to be checked is only the one // before the current cursor position const OUString aOldText( aPaM.GetNode()->Copy(0, nTmpPos) ); OUString aNewText( aOldText ); - if (pCTLOptions->IsCTLSequenceCheckingTypeAndReplace()) + if (SvtCTLOptions::IsCTLSequenceCheckingTypeAndReplace()) { _xISC->correctInputSequence(aNewText, nTmpPos - 1, c, nCheckMode); @@ -2662,14 +2708,15 @@ EditPaM ImpEditEngine::InsertTextUserInput( const EditSelection& rCurSel, if ( IsUndoEnabled() && !IsInUndo() ) { - std::unique_ptr<EditUndoInsertChars> pNewUndo(new EditUndoInsertChars(pEditEngine, CreateEPaM(aPaM), OUString(c))); + std::unique_ptr<EditUndoInsertChars> pNewUndo(new EditUndoInsertChars(mpEditEngine, CreateEPaM(aPaM), OUString(c))); bool bTryMerge = !bDoOverwrite && ( c != ' ' ); InsertUndo( std::move(pNewUndo), bTryMerge ); } - aEditDoc.InsertText( aPaM, OUString(c) ); - ParaPortion& rPortion = FindParaPortion( aPaM.GetNode() ); - rPortion.MarkInvalid( aPaM.GetIndex(), 1 ); + maEditDoc.InsertText( aPaM, OUStringChar(c) ); + ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() ); + assert(pPortion); + pPortion->MarkInvalid( aPaM.GetIndex(), 1 ); aPaM.SetIndex( aPaM.GetIndex()+1 ); // does not do EditDoc-Method anymore } @@ -2702,7 +2749,7 @@ EditPaM ImpEditEngine::ImpInsertText(const EditSelection& aCurSel, const OUStrin aCurWord = SelectWord( aCurPaM, i18n::WordType::DICTIONARY_WORD ); OUString aText(convertLineEnd(rStr, LINEEND_LF)); - if (utl::ConfigManager::IsFuzzing()) //tab expansion performance in editeng is appalling + if (mbFuzzing) //tab expansion performance in editeng is appalling aText = aText.replaceAll("\t","-"); SfxVoidItem aTabItem( EE_FEATURE_TAB ); @@ -2713,7 +2760,8 @@ EditPaM ImpEditEngine::ImpInsertText(const EditSelection& aCurSel, const OUStrin sal_Int32 nStart = 0; while ( nStart < aText.getLength() ) { - sal_Int32 nEnd = aText.indexOf( LINE_SEP, nStart ); + sal_Int32 nEnd = !maStatus.IsSingleLine() ? + aText.indexOf( LINE_SEP, nStart ) : -1; if ( nEnd == -1 ) nEnd = aText.getLength(); // not dereference! @@ -2726,14 +2774,64 @@ EditPaM ImpEditEngine::ImpInsertText(const EditSelection& aCurSel, const OUStrin if (nChars > MAXCHARSINPARA) { sal_Int32 nMaxNewChars = std::max<sal_Int32>(0, MAXCHARSINPARA - nExistingChars); - nEnd -= ( aLine.getLength() - nMaxNewChars ); // Then the characters end up in the next paragraph. - aLine = aLine.copy( 0, nMaxNewChars ); // Delete the Rest... + // Wherever we break, it may be wrong. However, try to find the + // previous non-alnum/non-letter character. Note this is only + // in the to be appended data, otherwise already existing + // characters would have to be moved and PaM to be updated. + // Restrict to 2*42, if not found by then assume other data or + // language-script uses only letters or idiographs. + sal_Int32 nPos = nMaxNewChars; + while (nPos-- > 0 && (nMaxNewChars - nPos) <= 84) + { + auto nNextPos = nPos; + const auto c = aLine.iterateCodePoints(&nNextPos); + switch (unicode::getUnicodeType(c)) + { + case css::i18n::UnicodeType::UPPERCASE_LETTER: + case css::i18n::UnicodeType::LOWERCASE_LETTER: + case css::i18n::UnicodeType::TITLECASE_LETTER: + case css::i18n::UnicodeType::MODIFIER_LETTER: + case css::i18n::UnicodeType::OTHER_LETTER: + case css::i18n::UnicodeType::DECIMAL_DIGIT_NUMBER: + case css::i18n::UnicodeType::LETTER_NUMBER: + case css::i18n::UnicodeType::OTHER_NUMBER: + case css::i18n::UnicodeType::CURRENCY_SYMBOL: + break; + default: + { + // Ignore NO-BREAK spaces, NBSP, NNBSP, ZWNBSP. + if (c == 0x00A0 || c == 0x202F || c == 0xFEFF) + break; + const auto n = aLine.iterateCodePoints(&nNextPos, 0); + if (c == '-' && nNextPos < nMaxNewChars) + { + // Keep HYPHEN-MINUS with a number to the right. + const sal_Int16 t = unicode::getUnicodeType(n); + if ( t == css::i18n::UnicodeType::DECIMAL_DIGIT_NUMBER || + t == css::i18n::UnicodeType::LETTER_NUMBER || + t == css::i18n::UnicodeType::OTHER_NUMBER) + nMaxNewChars = nPos; // line break before + else + nMaxNewChars = nNextPos; // line break after + } + else + { + nMaxNewChars = nNextPos; // line break after + } + nPos = 0; // will break loop + } + } + } + // Remaining characters end up in the next paragraph. Note that + // new nStart will be nEnd+1 below so decrement by one more. + nEnd -= (aLine.getLength() - nMaxNewChars + 1); + aLine = aLine.copy( 0, nMaxNewChars ); // Delete the Rest... } if ( IsUndoEnabled() && !IsInUndo() ) - InsertUndo(std::make_unique<EditUndoInsertChars>(pEditEngine, CreateEPaM(aPaM), aLine)); + InsertUndo(std::make_unique<EditUndoInsertChars>(mpEditEngine, CreateEPaM(aPaM), aLine)); // Tabs ? if ( aLine.indexOf( '\t' ) == -1 ) - aPaM = aEditDoc.InsertText( aPaM, aLine ); + aPaM = maEditDoc.InsertText( aPaM, aLine ); else { sal_Int32 nStart2 = 0; @@ -2744,15 +2842,16 @@ EditPaM ImpEditEngine::ImpInsertText(const EditSelection& aCurSel, const OUStrin nEnd2 = aLine.getLength(); // not dereference! if ( nEnd2 > nStart2 ) - aPaM = aEditDoc.InsertText( aPaM, aLine.copy( nStart2, nEnd2-nStart2 ) ); + aPaM = maEditDoc.InsertText( aPaM, aLine.subView( nStart2, nEnd2-nStart2 ) ); if ( nEnd2 < aLine.getLength() ) { - aPaM = aEditDoc.InsertFeature( aPaM, aTabItem ); + aPaM = maEditDoc.InsertFeature( aPaM, aTabItem ); } nStart2 = nEnd2+1; } } - ParaPortion& rPortion = FindParaPortion( aPaM.GetNode() ); + ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() ); + assert(pPortion); if ( GetStatus().DoOnlineSpelling() ) { @@ -2761,10 +2860,10 @@ EditPaM ImpEditEngine::ImpInsertText(const EditSelection& aCurSel, const OUStrin if (pWrongs && !pWrongs->empty()) pWrongs->ClearWrongs( aCurWord.Min().GetIndex(), aPaM.GetIndex(), aPaM.GetNode() ); // ... and mark both words as 'to be checked again' - rPortion.MarkInvalid( aCurWord.Min().GetIndex(), aLine.getLength() ); + pPortion->MarkInvalid( aCurWord.Min().GetIndex(), aLine.getLength() ); } else - rPortion.MarkInvalid( aCurPaM.GetIndex(), aLine.getLength() ); + pPortion->MarkInvalid( aCurPaM.GetIndex(), aLine.getLength() ); } if ( nEnd < aText.getLength() ) aPaM = ImpInsertParaBreak( aPaM ); @@ -2787,9 +2886,9 @@ EditPaM ImpEditEngine::ImpFastInsertText( EditPaM aPaM, const OUString& rStr ) if ( ( aPaM.GetNode()->Len() + rStr.getLength() ) < MAXCHARSINPARA ) { if ( IsUndoEnabled() && !IsInUndo() ) - InsertUndo(std::make_unique<EditUndoInsertChars>(pEditEngine, CreateEPaM(aPaM), rStr)); + InsertUndo(std::make_unique<EditUndoInsertChars>(mpEditEngine, CreateEPaM(aPaM), rStr)); - aPaM = aEditDoc.InsertText( aPaM, rStr ); + aPaM = maEditDoc.InsertText( aPaM, rStr ); TextModified(); } else @@ -2812,12 +2911,13 @@ EditPaM ImpEditEngine::ImpInsertFeature(const EditSelection& rCurSel, const SfxP return aPaM; if ( IsUndoEnabled() && !IsInUndo() ) - InsertUndo(std::make_unique<EditUndoInsertFeature>(pEditEngine, CreateEPaM(aPaM), rItem)); - aPaM = aEditDoc.InsertFeature( aPaM, rItem ); + InsertUndo(std::make_unique<EditUndoInsertFeature>(mpEditEngine, CreateEPaM(aPaM), rItem)); + aPaM = maEditDoc.InsertFeature( aPaM, rItem ); UpdateFields(); - ParaPortion& rPortion = FindParaPortion( aPaM.GetNode() ); - rPortion.MarkInvalid( aPaM.GetIndex()-1, 1 ); + ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() ); + assert(pPortion); + pPortion->MarkInvalid( aPaM.GetIndex()-1, 1 ); TextModified(); @@ -2837,7 +2937,7 @@ EditPaM ImpEditEngine::ImpInsertParaBreak( const EditSelection& rCurSel ) EditPaM ImpEditEngine::ImpInsertParaBreak( EditPaM& rPaM, bool bKeepEndingAttribs ) { - if ( aEditDoc.Count() >= EE_PARA_MAX_COUNT ) + if ( maEditDoc.Count() >= EE_PARA_MAX_COUNT ) { SAL_WARN( "editeng", "ImpEditEngine::ImpInsertParaBreak - can't process more than " << EE_PARA_MAX_COUNT << " paragraphs!"); @@ -2845,9 +2945,11 @@ EditPaM ImpEditEngine::ImpInsertParaBreak( EditPaM& rPaM, bool bKeepEndingAttrib } if ( IsUndoEnabled() && !IsInUndo() ) - InsertUndo(std::make_unique<EditUndoSplitPara>(pEditEngine, aEditDoc.GetPos(rPaM.GetNode()), rPaM.GetIndex())); + InsertUndo(std::make_unique<EditUndoSplitPara>(mpEditEngine, maEditDoc.GetPos(rPaM.GetNode()), rPaM.GetIndex())); - EditPaM aPaM( aEditDoc.InsertParaBreak( rPaM, bKeepEndingAttribs ) ); + EditPaM aPaM( maEditDoc.InsertParaBreak( rPaM, bKeepEndingAttribs ) ); + if (auto pStyle = aPaM.GetNode()->GetStyleSheet()) + StartListening(*pStyle, DuplicateHandling::Allow); if ( GetStatus().DoOnlineSpelling() ) { @@ -2879,18 +2981,22 @@ EditPaM ImpEditEngine::ImpInsertParaBreak( EditPaM& rPaM, bool bKeepEndingAttrib pRWrongs->SetInvalidRange(0, 1); // Only test the first word } - ParaPortion& rPortion = FindParaPortion( rPaM.GetNode() ); - rPortion.MarkInvalid( rPaM.GetIndex(), 0 ); + ParaPortion* pPortion = FindParaPortion( rPaM.GetNode() ); + assert(pPortion); + pPortion->MarkInvalid( rPaM.GetIndex(), 0 ); // Optimization: Do not place unnecessarily many getPos to Listen! // Here, as in undo, but also in all other methods. - sal_Int32 nPos = GetParaPortions().GetPos( &rPortion ); - ParaPortion& rNewPortion = GetParaPortions().Insert(nPos+1, ParaPortion(aPaM.GetNode())); - ParaAttribsChanged( rNewPortion.GetNode() ); + sal_Int32 nPos = GetParaPortions().GetPos( pPortion ); + ParaPortion* pNewPortion = new ParaPortion( aPaM.GetNode() ); + GetParaPortions().Insert(nPos+1, std::unique_ptr<ParaPortion>(pNewPortion)); + ParaAttribsChanged( pNewPortion->GetNode() ); if ( IsCallParaInsertedOrDeleted() ) GetEditEnginePtr()->ParagraphInserted( nPos+1 ); - CursorMoved( rPaM.GetNode() ); // if empty Attributes have emerged. + if( nullptr != rPaM.GetNode() ) + rPaM.GetNode()->checkAndDeleteEmptyAttribs(); // if empty Attributes have emerged. + TextModified(); return aPaM; } @@ -2901,23 +3007,23 @@ EditPaM ImpEditEngine::ImpFastInsertParagraph( sal_Int32 nPara ) { if ( nPara ) { - OSL_ENSURE( aEditDoc.GetObject( nPara-1 ), "FastInsertParagraph: Prev does not exist" ); - InsertUndo(std::make_unique<EditUndoSplitPara>(pEditEngine, nPara-1, aEditDoc.GetObject( nPara-1 )->Len())); + assert(maEditDoc.GetObject(nPara - 1)); + InsertUndo(std::make_unique<EditUndoSplitPara>(mpEditEngine, nPara-1, maEditDoc.GetObject(nPara - 1)->Len())); } else - InsertUndo(std::make_unique<EditUndoSplitPara>(pEditEngine, 0, 0)); + InsertUndo(std::make_unique<EditUndoSplitPara>(mpEditEngine, 0, 0)); } - ContentNode* pNode = new ContentNode( aEditDoc.GetItemPool() ); + ContentNode* pNode = new ContentNode( maEditDoc.GetItemPool() ); // If flat mode, then later no Font is set: - pNode->GetCharAttribs().GetDefFont() = aEditDoc.GetDefFont(); + pNode->GetCharAttribs().GetDefFont() = maEditDoc.GetDefFont(); if ( GetStatus().DoOnlineSpelling() ) pNode->CreateWrongList(); - aEditDoc.Insert(nPara, pNode); + maEditDoc.Insert(nPara, std::unique_ptr<ContentNode>(pNode)); - GetParaPortions().Insert(nPara, ParaPortion( pNode )); + GetParaPortions().Insert(nPara, std::make_unique<ParaPortion>( pNode )); if ( IsCallParaInsertedOrDeleted() ) GetEditEnginePtr()->ParagraphInserted( nPara ); @@ -2927,9 +3033,9 @@ EditPaM ImpEditEngine::ImpFastInsertParagraph( sal_Int32 nPara ) EditPaM ImpEditEngine::InsertParaBreak(const EditSelection& rCurSel) { EditPaM aPaM(ImpInsertParaBreak(rCurSel)); - if ( aStatus.DoAutoIndenting() ) + if ( maStatus.DoAutoIndenting() ) { - sal_Int32 nPara = aEditDoc.GetPos( aPaM.GetNode() ); + sal_Int32 nPara = maEditDoc.GetPos( aPaM.GetNode() ); OSL_ENSURE( nPara > 0, "AutoIndenting: Error!" ); const OUString aPrevParaText( GetEditDoc().GetParaAsString( nPara-1 ) ); sal_Int32 n = 0; @@ -2966,7 +3072,7 @@ bool ImpEditEngine::UpdateFields() { bool bChangesInPara = false; ContentNode* pNode = GetEditDoc().GetObject( nPara ); - OSL_ENSURE( pNode, "NULL-Pointer in Doc" ); + assert(pNode); CharAttribList::AttribsType& rAttribs = pNode->GetCharAttribs().GetAttribs(); for (std::unique_ptr<EditCharAttrib> & rAttrib : rAttribs) { @@ -2977,10 +3083,10 @@ bool ImpEditEngine::UpdateFields() EditCharAttribField aCurrent(rField); rField.Reset(); - if (!aStatus.MarkNonUrlFields() && !aStatus.MarkUrlFields()) + if (!maStatus.MarkNonUrlFields() && !maStatus.MarkUrlFields()) ; // nothing marked - else if (aStatus.MarkNonUrlFields() && aStatus.MarkUrlFields()) - rField.GetFieldColor() = GetColorConfig().GetColorValue( svtools::WRITERFIELDSHADINGS ).nColor; + else if (maStatus.MarkNonUrlFields() && maStatus.MarkUrlFields()) + rField.GetFieldColor() = GetColorConfig().GetColorValue(svtools::WRITERFIELDSHADINGS).nColor; else { bool bURL = false; @@ -2989,14 +3095,14 @@ bool ImpEditEngine::UpdateFields() if (const SvxFieldData* pFieldData = pFieldItem->GetField()) bURL = (dynamic_cast<const SvxURLField* >(pFieldData) != nullptr); } - if ((bURL && aStatus.MarkUrlFields()) || (!bURL && aStatus.MarkNonUrlFields())) + if ((bURL && maStatus.MarkUrlFields()) || (!bURL && maStatus.MarkNonUrlFields())) rField.GetFieldColor() = GetColorConfig().GetColorValue( svtools::WRITERFIELDSHADINGS ).nColor; } const OUString aFldValue = GetEditEnginePtr()->CalcFieldValue( static_cast<const SvxFieldItem&>(*rField.GetItem()), - nPara, rField.GetStart(), rField.GetTextColor(), rField.GetFieldColor()); + nPara, rField.GetStart(), rField.GetTextColor(), rField.GetFieldColor(), rField.GetFldLineStyle() ); rField.SetFieldValue(aFldValue); if (rField != aCurrent) @@ -3009,7 +3115,8 @@ bool ImpEditEngine::UpdateFields() if ( bChangesInPara ) { // If possible be more precise when invalidate. - ParaPortion& rPortion = GetParaPortions()[nPara]; + assert(GetParaPortions().exists(nPara)); + ParaPortion& rPortion = GetParaPortions().getRef(nPara); rPortion.MarkSelectionInvalid( 0 ); } } @@ -3025,45 +3132,43 @@ EditPaM ImpEditEngine::InsertLineBreak(const EditSelection& aCurSel) // Helper functions -tools::Rectangle ImpEditEngine::GetEditCursor(const ParaPortion* pPortion, const EditLine* pLine, - sal_Int32 nIndex, GetCursorFlags nFlags) +tools::Rectangle ImpEditEngine::GetEditCursor(ParaPortion const& rPortion, EditLine const& rLine, + sal_Int32 nIndex, CursorFlags aFlags) { - assert(pPortion && pLine); // nIndex might be not in the line // Search within the line... tools::Long nX; - if ((nIndex == pLine->GetStart()) && (nFlags & GetCursorFlags::StartOfLine)) + if (nIndex == rLine.GetStart() && aFlags.bStartOfLine) { - Range aXRange = GetLineXPosStartEnd(pPortion, pLine); - nX = !IsRightToLeft(GetEditDoc().GetPos(pPortion->GetNode())) ? aXRange.Min() + Range aXRange = GetLineXPosStartEnd(rPortion, rLine); + nX = !IsRightToLeft(GetEditDoc().GetPos(rPortion.GetNode())) ? aXRange.Min() : aXRange.Max(); } - else if ((nIndex == pLine->GetEnd()) && (nFlags & GetCursorFlags::EndOfLine)) + else if (nIndex == rLine.GetEnd() && aFlags.bEndOfLine) { - Range aXRange = GetLineXPosStartEnd(pPortion, pLine); - nX = !IsRightToLeft(GetEditDoc().GetPos(pPortion->GetNode())) ? aXRange.Max() + Range aXRange = GetLineXPosStartEnd(rPortion, rLine); + nX = !IsRightToLeft(GetEditDoc().GetPos(rPortion.GetNode())) ? aXRange.Max() : aXRange.Min(); } else { - nX = GetXPos(pPortion, pLine, nIndex, bool(nFlags & GetCursorFlags::PreferPortionStart)); + nX = GetXPos(rPortion, rLine, nIndex, aFlags.bPreferPortionStart); } tools::Rectangle aEditCursor; aEditCursor.SetLeft(nX); aEditCursor.SetRight(nX); - aEditCursor.SetBottom(pLine->GetHeight() - 1); - if (nFlags & GetCursorFlags::TextOnly) - aEditCursor.SetTop(aEditCursor.Bottom() - pLine->GetTxtHeight() + 1); + aEditCursor.SetBottom(rLine.GetHeight() - 1); + if (aFlags.bTextOnly) + aEditCursor.SetTop(aEditCursor.Bottom() - rLine.GetTxtHeight() + 1); else - aEditCursor.SetTop(aEditCursor.Bottom() - - std::min(pLine->GetTxtHeight(), pLine->GetHeight()) + 1); + aEditCursor.SetTop(aEditCursor.Bottom() - std::min(rLine.GetTxtHeight(), rLine.GetHeight()) + 1); return aEditCursor; } -tools::Rectangle ImpEditEngine::PaMtoEditCursor( EditPaM aPaM, GetCursorFlags nFlags ) +tools::Rectangle ImpEditEngine::PaMtoEditCursor( EditPaM aPaM, CursorFlags aFlags) { assert( IsUpdateLayout() && "Must not be reached when Update=FALSE: PaMtoEditCursor" ); @@ -3073,8 +3178,8 @@ tools::Rectangle ImpEditEngine::PaMtoEditCursor( EditPaM aPaM, GetCursorFlags nF const EditLine* pLastLine = nullptr; tools::Rectangle aLineArea; - auto FindPortionLineAndArea - = [&, bEOL(bool(nFlags & GetCursorFlags::EndOfLine))](const LineAreaInfo& rInfo) { + auto FindPortionLineAndArea = [&, bEOL(aFlags.bEndOfLine)](const LineAreaInfo& rInfo) + { if (!rInfo.pLine) // start of ParaPortion { ContentNode* pNode = rInfo.rPortion.GetNode(); @@ -3094,9 +3199,9 @@ tools::Rectangle ImpEditEngine::PaMtoEditCursor( EditPaM aPaM, GetCursorFlags nF }; IterateLineAreas(FindPortionLineAndArea, IterFlag::none); - if (pLastLine) + if (pLastLine && pPortion) { - aEditCursor = GetEditCursor(pPortion, pLastLine, nIndex, nFlags); + aEditCursor = GetEditCursor(*pPortion, *pLastLine, nIndex, aFlags); aEditCursor.Move(getTopLeftDocOffset(aLineArea)); } else @@ -3110,11 +3215,11 @@ void ImpEditEngine::IterateLineAreas(const IterateLinesAreasFunc& f, IterFlag eO const Point aOrigin(0, 0); Point aLineStart(aOrigin); const tools::Long nVertLineSpacing = CalcVertLineSpacing(aLineStart); - const tools::Long nColumnWidth = GetColumnWidth(aPaperSize); + const tools::Long nColumnWidth = GetColumnWidth(maPaperSize); sal_Int16 nColumn = 0; for (sal_Int32 n = 0, nPortions = GetParaPortions().Count(); n < nPortions; ++n) { - ParaPortion& rPortion = GetParaPortions()[n]; + ParaPortion& rPortion = GetParaPortions().getRef(n); bool bSkipThis = true; if (rPortion.IsVisible()) { @@ -3123,7 +3228,7 @@ void ImpEditEngine::IterateLineAreas(const IterateLinesAreasFunc& f, IterFlag eO return; LineAreaInfo aInfo{ - rPortion, // rPortion + rPortion, nullptr, // pLine 0, // nHeightNeededToNotWrap { aLineStart, Size{ nColumnWidth, rPortion.GetFirstLineOffset() } }, // aArea @@ -3137,12 +3242,12 @@ void ImpEditEngine::IterateLineAreas(const IterateLinesAreasFunc& f, IterFlag eO bSkipThis = eResult == CallbackResult::SkipThisPortion; sal_uInt16 nSBL = 0; - if (!aStatus.IsOutliner()) + if (!maStatus.IsOutliner()) { const SvxLineSpacingItem& rLSItem = rPortion.GetNode()->GetContentAttribs().GetItem(EE_PARA_SBL); nSBL = (rLSItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Fix) - ? GetYValue(rLSItem.GetInterLineSpace()) + ? scaleYSpacingValue(rLSItem.GetInterLineSpace()) : 0; } @@ -3156,7 +3261,7 @@ void ImpEditEngine::IterateLineAreas(const IterateLinesAreasFunc& f, IterFlag eO MoveToNextLine(aLineStart, nLineHeight, nColumn, aOrigin, &aInfo.nHeightNeededToNotWrap); const bool bInclILS = eOptions & IterFlag::inclILS; - if (bInclILS && (nLine != nLines - 1) && !aStatus.IsOutliner()) + if (bInclILS && (nLine != nLines - 1) && !maStatus.IsOutliner()) { adjustYDirectionAware(aLineStart, nSBL); nLineHeight += nSBL; @@ -3172,21 +3277,20 @@ void ImpEditEngine::IterateLineAreas(const IterateLinesAreasFunc& f, IterFlag eO aInfo.nColumn = nColumn; aInfo.pLine = &rLine; aInfo.nLine = nLine; - aInfo.aArea = tools::Rectangle::Justify(aLineStart, aOtherCorner); + aInfo.aArea = tools::Rectangle::Normalize(aLineStart, aOtherCorner); eResult = f(aInfo); if (eResult == CallbackResult::Stop) return; bSkipThis = eResult == CallbackResult::SkipThisPortion; } - if (!bInclILS && (nLine != nLines - 1) && !aStatus.IsOutliner()) + if (!bInclILS && (nLine != nLines - 1) && !maStatus.IsOutliner()) adjustYDirectionAware(aLineStart, nSBL); } - if (!aStatus.IsOutliner()) + if (!maStatus.IsOutliner()) { - const SvxULSpaceItem& rULItem - = rPortion.GetNode()->GetContentAttribs().GetItem(EE_PARA_ULSPACE); - tools::Long nUL = GetYValue(rULItem.GetLower()); + const SvxULSpaceItem& rULItem = rPortion.GetNode()->GetContentAttribs().GetItem(EE_PARA_ULSPACE); + tools::Long nUL = scaleYSpacingValue(rULItem.GetLower()); adjustYDirectionAware(aLineStart, nUL); } } @@ -3199,7 +3303,7 @@ ImpEditEngine::GetPortionAndLine(Point aDocPos) { // First find the column from the point sal_Int32 nClickColumn = 0; - for (tools::Long nColumnStart = 0, nColumnWidth = GetColumnWidth(aPaperSize);; + for (tools::Long nColumnStart = 0, nColumnWidth = GetColumnWidth(maPaperSize);; nColumnStart += mnColumnSpacing + nColumnWidth, ++nClickColumn) { if (aDocPos.X() <= nColumnStart + nColumnWidth + mnColumnSpacing / 2) @@ -3238,8 +3342,9 @@ EditPaM ImpEditEngine::GetPaM( Point aDocPos, bool bSmart ) if (const auto& [pPortion, pLine, nLineStartX] = GetPortionAndLine(aDocPos); pPortion) { - sal_Int32 nCurIndex - = GetChar(pPortion, pLine, aDocPos.X() - nLineStartX, bSmart); + assert(pLine); + assert(pPortion); + sal_Int32 nCurIndex = GetChar(*pPortion, *pLine, aDocPos.X() - nLineStartX, bSmart); EditPaM aPaM(pPortion->GetNode(), nCurIndex); if (nCurIndex && (nCurIndex == pLine->GetEnd()) @@ -3257,7 +3362,9 @@ bool ImpEditEngine::IsTextPos(const Point& rDocPos, sal_uInt16 nBorder) { if (const auto& [pPortion, pLine, nLineStartX] = GetPortionAndLine(rDocPos); pPortion) { - Range aLineXPosStartEnd = GetLineXPosStartEnd(pPortion, pLine); + assert(pLine); + assert(pPortion); + Range aLineXPosStartEnd = GetLineXPosStartEnd(*pPortion, *pLine); if ((rDocPos.X() >= nLineStartX + aLineXPosStartEnd.Min() - nBorder) && (rDocPos.X() <= nLineStartX + aLineXPosStartEnd.Max() + nBorder)) return true; @@ -3269,7 +3376,7 @@ sal_uInt32 ImpEditEngine::GetTextHeight() const { assert( IsUpdateLayout() && "Should not be used for Update=FALSE: GetTextHeight" ); OSL_ENSURE( IsFormatted() || IsFormatting(), "GetTextHeight: Not formatted" ); - return nCurTextHeight; + return mnCurTextHeight; } sal_uInt32 ImpEditEngine::CalcTextWidth( bool bIgnoreExtraSpace ) @@ -3303,38 +3410,39 @@ sal_uInt32 ImpEditEngine::CalcParaWidth( sal_Int32 nPara, bool bIgnoreExtraSpace // Over all the paragraphs ... - ParaPortion& rPortion = GetParaPortions()[nPara]; - if ( rPortion.IsVisible() ) + OSL_ENSURE(GetParaPortions().exists(nPara), "CalcParaWidth: Out of range"); + ParaPortion* pPortion = GetParaPortions().SafeGetObject(nPara); + if ( pPortion && pPortion->IsVisible() ) { - const SvxLRSpaceItem& rLRItem = GetLRSpaceItem( rPortion.GetNode() ); - sal_Int32 nSpaceBeforeAndMinLabelWidth = GetSpaceBeforeAndMinLabelWidth( rPortion.GetNode() ); + const SvxLRSpaceItem& rLRItem = GetLRSpaceItem( pPortion->GetNode() ); + sal_Int32 nSpaceBeforeAndMinLabelWidth = GetSpaceBeforeAndMinLabelWidth( pPortion->GetNode() ); // On the lines of the paragraph ... - sal_Int32 nLines = rPortion.GetLines().Count(); + sal_Int32 nLines = pPortion->GetLines().Count(); for ( sal_Int32 nLine = 0; nLine < nLines; nLine++ ) { - EditLine& rLine = rPortion.GetLines()[nLine]; + EditLine const& rLine = pPortion->GetLines()[nLine]; // nCurWidth = pLine->GetStartPosX(); // For Center- or Right- alignment it depends on the paper // width, here not preferred. I general, it is best not leave it // to StartPosX, also the right indents have to be taken into // account! - tools::Long nCurWidth = GetXValue( rLRItem.GetTextLeft() + nSpaceBeforeAndMinLabelWidth ); + tools::Long nCurWidth = scaleXSpacingValue(rLRItem.GetTextLeft() + nSpaceBeforeAndMinLabelWidth); if ( nLine == 0 ) { - tools::Long nFI = GetXValue( rLRItem.GetTextFirstLineOffset() ); + tools::Long nFI = scaleXSpacingValue(rLRItem.GetTextFirstLineOffset()); nCurWidth -= nFI; - if ( rPortion.GetBulletX() > nCurWidth ) + if ( pPortion->GetBulletX() > nCurWidth ) { nCurWidth += nFI; // LI? - if ( rPortion.GetBulletX() > nCurWidth ) - nCurWidth = rPortion.GetBulletX(); + if ( pPortion->GetBulletX() > nCurWidth ) + nCurWidth = pPortion->GetBulletX(); } } - nCurWidth += GetXValue( rLRItem.GetRight() ); - nCurWidth += CalcLineWidth( &rPortion, &rLine, bIgnoreExtraSpace ); + nCurWidth += scaleXSpacingValue(rLRItem.GetRight()); + nCurWidth += CalcLineWidth(*pPortion, rLine, bIgnoreExtraSpace); if ( nCurWidth > nMaxWidth ) { nMaxWidth = nCurWidth; @@ -3346,9 +3454,9 @@ sal_uInt32 ImpEditEngine::CalcParaWidth( sal_Int32 nPara, bool bIgnoreExtraSpace return static_cast<sal_uInt32>(nMaxWidth); } -sal_uInt32 ImpEditEngine::CalcLineWidth( ParaPortion* pPortion, EditLine* pLine, bool bIgnoreExtraSpace ) +sal_uInt32 ImpEditEngine::CalcLineWidth(ParaPortion const& rPortion, EditLine const& rLine, bool bIgnoreExtraSpace) { - sal_Int32 nPara = GetEditDoc().GetPos( pPortion->GetNode() ); + sal_Int32 nPara = GetEditDoc().GetPos(rPortion.GetNode()); // #114278# Saving both layout mode and language (since I'm // potentially changing both) @@ -3360,10 +3468,10 @@ sal_uInt32 ImpEditEngine::CalcLineWidth( ParaPortion* pPortion, EditLine* pLine, // Calculation of the width without the Indents ... sal_uInt32 nWidth = 0; - sal_Int32 nPos = pLine->GetStart(); - for ( sal_Int32 nTP = pLine->GetStartPortion(); nTP <= pLine->GetEndPortion(); nTP++ ) + sal_Int32 nPos = rLine.GetStart(); + for ( sal_Int32 nTP = rLine.GetStartPortion(); nTP <= rLine.GetEndPortion(); nTP++ ) { - const TextPortion& rTextPortion = pPortion->GetTextPortions()[nTP]; + const TextPortion& rTextPortion = rPortion.GetTextPortions()[nTP]; switch ( rTextPortion.GetKind() ) { case PortionKind::FIELD: @@ -3381,11 +3489,12 @@ sal_uInt32 ImpEditEngine::CalcLineWidth( ParaPortion* pPortion, EditLine* pLine, } else { - SvxFont aTmpFont( pPortion->GetNode()->GetCharAttribs().GetDefFont() ); - SeekCursor( pPortion->GetNode(), nPos+1, aTmpFont ); + SvxFont aTmpFont(rPortion.GetNode()->GetCharAttribs().GetDefFont()); + SeekCursor(rPortion.GetNode(), nPos + 1, aTmpFont); aTmpFont.SetPhysFont(*GetRefDevice()); ImplInitDigitMode(*GetRefDevice(), aTmpFont.GetLanguage()); - nWidth += aTmpFont.QuickGetTextSize( GetRefDevice(), pPortion->GetNode()->GetString(), nPos, rTextPortion.GetLen() ).Width(); + nWidth += aTmpFont.QuickGetTextSize( GetRefDevice(), + rPortion.GetNode()->GetString(), nPos, rTextPortion.GetLen(), nullptr ).Width(); } } break; @@ -3403,7 +3512,7 @@ sal_uInt32 ImpEditEngine::GetTextHeightNTP() const { assert( IsUpdateLayout() && "Should not be used for Update=FALSE: GetTextHeight" ); DBG_ASSERT( IsFormatted() || IsFormatting(), "GetTextHeight: Not formatted" ); - return nCurTextHeightNTP; + return mnCurTextHeightNTP; } tools::Long ImpEditEngine::Calc1ColumnTextHeight(tools::Long* pHeightNTP) @@ -3412,10 +3521,9 @@ tools::Long ImpEditEngine::Calc1ColumnTextHeight(tools::Long* pHeightNTP) if (pHeightNTP) *pHeightNTP = 0; // Pretend that we have ~infinite height to get total height - comphelper::ValueRestorationGuard aGuard(nCurTextHeight, - std::numeric_limits<tools::Long>::max()); + comphelper::ValueRestorationGuard aGuard(mnCurTextHeight, std::numeric_limits<tools::Long>::max()); - auto FindLastLineBottom = [&](const LineAreaInfo& rInfo) { + IterateLinesAreasFunc FindLastLineBottom = [&](const LineAreaInfo& rInfo) { if (rInfo.pLine) { // bottom coordinate does not belong to area, so no need to do +1 @@ -3444,7 +3552,7 @@ tools::Long ImpEditEngine::CalcTextHeight(tools::Long* pHeightNTP) tools::Long nCurrentTextHeight; // This does the necessary column balancing for the case when the text does not fit min height. - // When the height of column (taken from nCurTextHeight) is too small, the last column will + // When the height of column (taken from mnCurTextHeight) is too small, the last column will // overflow, so the resulting height of the text will exceed the set column height. Increasing // the column height step by step by the minimal value that allows one of columns to accommodate // one line more, we finally get to the point where all the text fits. At each iteration, the @@ -3515,7 +3623,7 @@ tools::Long ImpEditEngine::CalcTextHeight(tools::Long* pHeightNTP) } return CallbackResult::Continue; }; - comphelper::ValueRestorationGuard aGuard(nCurTextHeight, nTentativeColHeight); + comphelper::ValueRestorationGuard aGuard(mnCurTextHeight, nTentativeColHeight); IterateLineAreas(GetHeightAndWantedIncrease, IterFlag::none); } while (nCurrentTextHeight > nTentativeColHeight && nWantedIncrease > 0 && nWantedIncrease != std::numeric_limits<tools::Long>::max()); @@ -3524,8 +3632,8 @@ tools::Long ImpEditEngine::CalcTextHeight(tools::Long* pHeightNTP) sal_Int32 ImpEditEngine::GetLineCount( sal_Int32 nParagraph ) const { - OSL_ENSURE( 0 <= nParagraph && nParagraph < GetParaPortions().Count(), "GetLineCount: Out of range" ); - const ParaPortion* pPPortion = GetParaPortions().SafeGetObject( nParagraph ); + OSL_ENSURE(GetParaPortions().exists(nParagraph), "GetLineCount: Out of range"); + const ParaPortion* pPPortion = GetParaPortions().SafeGetObject(nParagraph); OSL_ENSURE( pPPortion, "Paragraph not found: GetLineCount" ); if ( pPPortion ) return pPPortion->GetLines().Count(); @@ -3535,9 +3643,9 @@ sal_Int32 ImpEditEngine::GetLineCount( sal_Int32 nParagraph ) const sal_Int32 ImpEditEngine::GetLineLen( sal_Int32 nParagraph, sal_Int32 nLine ) const { - OSL_ENSURE( 0 <= nParagraph && nParagraph < GetParaPortions().Count(), "GetLineLen: Out of range" ); - const ParaPortion* pPPortion = GetParaPortions().SafeGetObject( nParagraph ); - OSL_ENSURE( pPPortion, "Paragraph not found: GetLineLen" ); + OSL_ENSURE(GetParaPortions().exists(nParagraph), "GetLineLen: Out of range"); + const ParaPortion* pPPortion = GetParaPortions().SafeGetObject(nParagraph); + OSL_ENSURE(pPPortion, "Paragraph not found: GetLineLen"); if ( pPPortion && ( nLine < pPPortion->GetLines().Count() ) ) { const EditLine& rLine = pPPortion->GetLines()[nLine]; @@ -3549,7 +3657,7 @@ sal_Int32 ImpEditEngine::GetLineLen( sal_Int32 nParagraph, sal_Int32 nLine ) con void ImpEditEngine::GetLineBoundaries( /*out*/sal_Int32 &rStart, /*out*/sal_Int32 &rEnd, sal_Int32 nParagraph, sal_Int32 nLine ) const { - OSL_ENSURE( 0 <= nParagraph && nParagraph < GetParaPortions().Count(), "GetLineCount: Out of range" ); + OSL_ENSURE(GetParaPortions().exists(nParagraph), "GetLineCount: Out of range"); const ParaPortion* pPPortion = GetParaPortions().SafeGetObject( nParagraph ); OSL_ENSURE( pPPortion, "Paragraph not found: GetLineBoundaries" ); rStart = rEnd = -1; // default values in case of error @@ -3590,7 +3698,7 @@ sal_Int32 ImpEditEngine::GetLineNumberAtIndex( sal_Int32 nPara, sal_Int32 nIndex sal_uInt16 ImpEditEngine::GetLineHeight( sal_Int32 nParagraph, sal_Int32 nLine ) { - OSL_ENSURE( 0 <= nParagraph && nParagraph < GetParaPortions().Count(), "GetLineCount: Out of range" ); + OSL_ENSURE(GetParaPortions().exists(nParagraph), "GetLineCount: Out of range"); ParaPortion* pPPortion = GetParaPortions().SafeGetObject( nParagraph ); OSL_ENSURE( pPPortion, "Paragraph not found: GetLineHeight" ); if ( pPPortion && ( nLine < pPPortion->GetLines().Count() ) ) @@ -3602,11 +3710,11 @@ sal_uInt16 ImpEditEngine::GetLineHeight( sal_Int32 nParagraph, sal_Int32 nLine ) return 0xFFFF; } -sal_uInt32 ImpEditEngine::GetParaHeight( sal_Int32 nParagraph ) +sal_uInt32 ImpEditEngine::GetParaHeight(sal_Int32 nParagraph) const { sal_uInt32 nHeight = 0; - ParaPortion* pPPortion = GetParaPortions().SafeGetObject( nParagraph ); + ParaPortion const* pPPortion = GetParaPortions().SafeGetObject( nParagraph ); OSL_ENSURE( pPPortion, "Paragraph not found: GetParaHeight" ); if ( pPPortion ) @@ -3619,11 +3727,11 @@ void ImpEditEngine::UpdateSelections() { // Check whether one of the selections is at a deleted node... // If the node is valid, the index has yet to be examined! - for (EditView* pView : aEditViews) + for (EditView* pView : maEditViews) { - EditSelection aCurSel( pView->pImpEditView->GetEditSelection() ); + EditSelection aCurSel( pView->getImpl().GetEditSelection() ); bool bChanged = false; - for (const std::unique_ptr<DeletedNodeInfo> & aDeletedNode : aDeletedNodes) + for (const std::unique_ptr<DeletedNodeInfo> & aDeletedNode : maDeletedNodes) { const DeletedNodeInfo& rInf = *aDeletedNode; if ( ( aCurSel.Min().GetNode() == rInf.GetNode() ) || @@ -3632,26 +3740,27 @@ void ImpEditEngine::UpdateSelections() // Use ParaPortions, as now also hidden paragraphs have to be // taken into account! sal_Int32 nPara = rInf.GetPosition(); - if (!GetParaPortions().SafeGetObject(nPara)) // Last paragraph + if (!GetParaPortions().exists(nPara)) // Last paragraph { - nPara = GetParaPortions().Count()-1; + nPara = GetParaPortions().lastIndex(); } + assert(GetParaPortions().exists(nPara) && "Empty Document in UpdateSelections ?"); // Do not end up from a hidden paragraph: - sal_Int32 nCurPara = nPara; - sal_Int32 nLastPara = GetParaPortions().Count()-1; - while ( nPara <= nLastPara && !GetParaPortions()[nPara].IsVisible() ) + sal_Int32 nCurrentPara = nPara; + sal_Int32 nLastParaIndex = GetParaPortions().lastIndex(); + while (nPara <= nLastParaIndex && !GetParaPortions().getRef(nPara).IsVisible()) nPara++; - if ( nPara > nLastPara ) // then also backwards ... + if (nPara > nLastParaIndex) // then also backwards ... { - nPara = nCurPara; - while ( nPara && !GetParaPortions()[nPara].IsVisible() ) + nPara = nCurrentPara; + while ( nPara && !GetParaPortions().getRef(nPara).IsVisible() ) nPara--; } - OSL_ENSURE( GetParaPortions()[nPara].IsVisible(), "No visible paragraph found: UpdateSelections" ); + OSL_ENSURE(GetParaPortions().getRef(nPara).IsVisible(), "No visible paragraph found: UpdateSelections" ); - ParaPortion& rParaPortion = GetParaPortions()[nPara]; - EditSelection aTmpSelection( EditPaM( rParaPortion.GetNode(), 0 ) ); - pView->pImpEditView->SetEditSelection( aTmpSelection ); + ParaPortion& rParaPortion = GetParaPortions().getRef(nPara); + EditSelection aTmpSelection(EditPaM(rParaPortion.GetNode(), 0)); + pView->getImpl().SetEditSelection( aTmpSelection ); bChanged=true; break; // for loop } @@ -3662,16 +3771,16 @@ void ImpEditEngine::UpdateSelections() if ( aCurSel.Min().GetIndex() > aCurSel.Min().GetNode()->Len() ) { aCurSel.Min().SetIndex( aCurSel.Min().GetNode()->Len() ); - pView->pImpEditView->SetEditSelection( aCurSel ); + pView->getImpl().SetEditSelection( aCurSel ); } if ( aCurSel.Max().GetIndex() > aCurSel.Max().GetNode()->Len() ) { aCurSel.Max().SetIndex( aCurSel.Max().GetNode()->Len() ); - pView->pImpEditView->SetEditSelection( aCurSel ); + pView->getImpl().SetEditSelection( aCurSel ); } } } - aDeletedNodes.clear(); + maDeletedNodes.clear(); } EditSelection ImpEditEngine::ConvertSelection( @@ -3680,11 +3789,11 @@ EditSelection ImpEditEngine::ConvertSelection( EditSelection aNewSelection; // Start... - ContentNode* pNode = aEditDoc.GetObject( nStartPara ); + ContentNode* pNode = maEditDoc.GetObject( nStartPara ); sal_Int32 nIndex = nStartPos; if ( !pNode ) { - pNode = aEditDoc[ aEditDoc.Count()-1 ]; + pNode = maEditDoc.GetObject(maEditDoc.Count() - 1); nIndex = pNode->Len(); } else if ( nIndex > pNode->Len() ) @@ -3694,11 +3803,11 @@ EditSelection ImpEditEngine::ConvertSelection( aNewSelection.Min().SetIndex( nIndex ); // End... - pNode = aEditDoc.GetObject( nEndPara ); + pNode = maEditDoc.GetObject( nEndPara ); nIndex = nEndPos; if ( !pNode ) { - pNode = aEditDoc[ aEditDoc.Count()-1 ]; + pNode = maEditDoc.GetObject(maEditDoc.Count() - 1); nIndex = pNode->Len(); } else if ( nIndex > pNode->Len() ) @@ -3715,16 +3824,16 @@ void ImpEditEngine::SetActiveView( EditView* pView ) // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // Actually, now bHasVisSel and HideSelection would be necessary !!! - if ( pView == pActiveView ) + if (pView == mpActiveView) return; - if ( pActiveView && pActiveView->HasSelection() ) - pActiveView->pImpEditView->DrawSelectionXOR(); + if (mpActiveView && mpActiveView->HasSelection()) + mpActiveView->getImpl().DrawSelectionXOR(); - pActiveView = pView; + mpActiveView = pView; - if ( pActiveView && pActiveView->HasSelection() ) - pActiveView->pImpEditView->DrawSelectionXOR(); + if (mpActiveView && mpActiveView->HasSelection()) + mpActiveView->getImpl().DrawSelectionXOR(); // NN: Quick fix for #78668#: // When editing of a cell in Calc is ended, the edit engine is not deleted, @@ -3787,7 +3896,7 @@ uno::Reference< datatransfer::XTransferable > ImpEditEngine::CreateTransferable( return pDataObj; } -EditSelection ImpEditEngine::PasteText( uno::Reference< datatransfer::XTransferable > const & rxDataObj, const OUString& rBaseURL, const EditPaM& rPaM, bool bUseSpecial ) +EditSelection ImpEditEngine::PasteText( uno::Reference< datatransfer::XTransferable > const & rxDataObj, const OUString& rBaseURL, const EditPaM& rPaM, bool bUseSpecial, SotClipboardFormatId format) { EditSelection aNewSelection( rPaM ); @@ -3801,7 +3910,7 @@ EditSelection ImpEditEngine::PasteText( uno::Reference< datatransfer::XTransfera { // XML SotExchange::GetFormatDataFlavor( SotClipboardFormatId::EDITENGINE_ODF_TEXT_FLAT, aFlavor ); - if ( rxDataObj->isDataFlavorSupported( aFlavor ) ) + if ( rxDataObj->isDataFlavorSupported( aFlavor ) && (SotClipboardFormatId::NONE == format || SotClipboardFormatId::EDITENGINE_ODF_TEXT_FLAT == format)) { try { @@ -3829,7 +3938,7 @@ EditSelection ImpEditEngine::PasteText( uno::Reference< datatransfer::XTransfera SotExchange::GetFormatDataFlavor( SotClipboardFormatId::RICHTEXT, aFlavorRichtext ); bool bRtfSupported = rxDataObj->isDataFlavorSupported( aFlavor ); bool bRichtextSupported = rxDataObj->isDataFlavorSupported( aFlavorRichtext ); - if ( bRtfSupported || bRichtextSupported ) + if ( (bRtfSupported || bRichtextSupported) && (SotClipboardFormatId::NONE == format || SotClipboardFormatId::RICHTEXT == format || SotClipboardFormatId::RTF == format)) { if(bRichtextSupported) { @@ -3851,6 +3960,55 @@ EditSelection ImpEditEngine::PasteText( uno::Reference< datatransfer::XTransfera } } } + if (!bDone) { + // HTML_SIMPLE + SotExchange::GetFormatDataFlavor(SotClipboardFormatId::HTML_SIMPLE, aFlavor); + bool bHtmlSupported = rxDataObj->isDataFlavorSupported(aFlavor); + if (bHtmlSupported && (SotClipboardFormatId::NONE == format || SotClipboardFormatId::HTML_SIMPLE == format)) { + MSE40HTMLClipFormatObj aMSE40HTMLClipFormatObj; + try + { + uno::Any aData = rxDataObj->getTransferData(aFlavor); + uno::Sequence< sal_Int8 > aSeq; + aData >>= aSeq; + { + SvMemoryStream aHtmlStream(aSeq.getArray(), aSeq.getLength(), StreamMode::READ); + SvStream* pHtmlStream = aMSE40HTMLClipFormatObj.IsValid(aHtmlStream); + if (pHtmlStream != nullptr) { + aNewSelection = Read(*pHtmlStream, rBaseURL, EETextFormat::Html, rPaM); + } + } + bDone = true; + } + catch (const css::uno::Exception&) + { + } + } + } + + if (!bDone) + { + // HTML + SotExchange::GetFormatDataFlavor(SotClipboardFormatId::HTML, aFlavor); + bool bHtmlSupported = rxDataObj->isDataFlavorSupported(aFlavor); + if (bHtmlSupported + && (format == SotClipboardFormatId::NONE || format == SotClipboardFormatId::HTML)) + { + try + { + uno::Any aData = rxDataObj->getTransferData(aFlavor); + uno::Sequence<sal_Int8> aSeq; + aData >>= aSeq; + SvMemoryStream aHtmlStream(aSeq.getArray(), aSeq.getLength(), StreamMode::READ); + aNewSelection = Read(aHtmlStream, rBaseURL, EETextFormat::Html, rPaM); + bDone = true; + } + catch (const css::uno::Exception&) + { + TOOLS_WARN_EXCEPTION("editeng", "HTML paste failed"); + } + } + } } if ( !bDone ) { @@ -3874,20 +4032,17 @@ EditSelection ImpEditEngine::PasteText( uno::Reference< datatransfer::XTransfera return aNewSelection; } -sal_Int32 ImpEditEngine::GetChar( - const ParaPortion* pParaPortion, const EditLine* pLine, tools::Long nXPos, bool bSmart) +sal_Int32 ImpEditEngine::GetChar(ParaPortion const& rParaPortion, EditLine const& rLine, tools::Long nXPos, bool bSmart) { - OSL_ENSURE( pLine, "No line received: GetChar" ); - sal_Int32 nChar = -1; - sal_Int32 nCurIndex = pLine->GetStart(); + sal_Int32 nCurIndex = rLine.GetStart(); // Search best matching portion with GetPortionXOffset() - for ( sal_Int32 i = pLine->GetStartPortion(); i <= pLine->GetEndPortion(); i++ ) + for ( sal_Int32 i = rLine.GetStartPortion(); i <= rLine.GetEndPortion(); i++ ) { - const TextPortion& rPortion = pParaPortion->GetTextPortions()[i]; - tools::Long nXLeft = GetPortionXOffset( pParaPortion, pLine, i ); + const TextPortion& rPortion = rParaPortion.GetTextPortions()[i]; + tools::Long nXLeft = GetPortionXOffset(rParaPortion, rLine, i); tools::Long nXRight = nXLeft + rPortion.GetSize().Width(); if ( ( nXLeft <= nXPos ) && ( nXRight >= nXPos ) ) { @@ -3911,7 +4066,7 @@ sal_Int32 ImpEditEngine::GetChar( { sal_Int32 nMax = rPortion.GetLen(); sal_Int32 nOffset = -1; - sal_Int32 nTmpCurIndex = nChar - pLine->GetStart(); + sal_Int32 nTmpCurIndex = nChar - rLine.GetStart(); tools::Long nXInPortion = nXPos - nXLeft; if ( rPortion.IsRightToLeft() ) @@ -3920,25 +4075,26 @@ sal_Int32 ImpEditEngine::GetChar( // Search in Array... for ( sal_Int32 x = 0; x < nMax; x++ ) { - tools::Long nTmpPosMax = pLine->GetCharPosArray()[nTmpCurIndex+x]; + tools::Long nTmpPosMax = rLine.GetCharPosArray()[nTmpCurIndex+x]; if ( nTmpPosMax > nXInPortion ) { // Check whether this or the previous... - tools::Long nTmpPosMin = x ? pLine->GetCharPosArray()[nTmpCurIndex+x-1] : 0; + tools::Long nTmpPosMin = x ? rLine.GetCharPosArray()[nTmpCurIndex+x-1] : 0; tools::Long nDiffLeft = nXInPortion - nTmpPosMin; tools::Long nDiffRight = nTmpPosMax - nXInPortion; OSL_ENSURE( nDiffLeft >= 0, "DiffLeft negative" ); OSL_ENSURE( nDiffRight >= 0, "DiffRight negative" ); - nOffset = ( bSmart && ( nDiffRight < nDiffLeft ) ) ? x+1 : x; - // I18N: If there are character position with the length of 0, - // they belong to the same character, we can not use this position as an index. - // Skip all 0-positions, cheaper than using XBreakIterator: - if ( nOffset < nMax ) + + if (bSmart && nDiffRight < nDiffLeft) { - const tools::Long nX = pLine->GetCharPosArray()[nOffset]; - while ( ( (nOffset+1) < nMax ) && ( pLine->GetCharPosArray()[nOffset+1] == nX ) ) - nOffset++; + // I18N: If there are character position with the length of 0, + // they belong to the same character, we can not use this position as an index. + // Skip all 0-positions, cheaper than using XBreakIterator: + tools::Long nX = rLine.GetCharPosArray()[nTmpCurIndex + x]; + while(x < nMax && rLine.GetCharPosArray()[nTmpCurIndex + x] == nX) + ++x; } + nOffset = x; break; } } @@ -3954,9 +4110,9 @@ sal_Int32 ImpEditEngine::GetChar( nChar = nChar + nOffset; // Check if index is within a cell: - if ( nChar && ( nChar < pParaPortion->GetNode()->Len() ) ) + if ( nChar && ( nChar < rParaPortion.GetNode()->Len() ) ) { - EditPaM aPaM( pParaPortion->GetNode(), nChar+1 ); + EditPaM aPaM( rParaPortion.GetNode(), nChar+1 ); sal_uInt16 nScriptType = GetI18NScriptType( aPaM ); if ( nScriptType == i18n::ScriptType::COMPLEX ) { @@ -3964,9 +4120,9 @@ sal_Int32 ImpEditEngine::GetChar( sal_Int32 nCount = 1; lang::Locale aLocale = GetLocale( aPaM ); sal_Int32 nRight = _xBI->nextCharacters( - pParaPortion->GetNode()->GetString(), nChar, aLocale, css::i18n::CharacterIteratorMode::SKIPCELL, nCount, nCount ); + rParaPortion.GetNode()->GetString(), nChar, aLocale, css::i18n::CharacterIteratorMode::SKIPCELL, nCount, nCount ); sal_Int32 nLeft = _xBI->previousCharacters( - pParaPortion->GetNode()->GetString(), nRight, aLocale, css::i18n::CharacterIteratorMode::SKIPCELL, nCount, nCount ); + rParaPortion.GetNode()->GetString(), nRight, aLocale, css::i18n::CharacterIteratorMode::SKIPCELL, nCount, nCount ); if ( ( nLeft != nChar ) && ( nRight != nChar ) ) { nChar = ( std::abs( nRight - nChar ) < std::abs( nLeft - nChar ) ) ? nRight : nLeft; @@ -3974,7 +4130,7 @@ sal_Int32 ImpEditEngine::GetChar( } else { - OUString aStr(pParaPortion->GetNode()->GetString()); + OUString aStr(rParaPortion.GetNode()->GetString()); // tdf#102625: don't select middle of a pair of surrogates with mouse cursor if (rtl::isSurrogate(aStr[nChar])) --nChar; @@ -3988,40 +4144,38 @@ sal_Int32 ImpEditEngine::GetChar( if ( nChar == -1 ) { - nChar = ( nXPos <= pLine->GetStartPosX() ) ? pLine->GetStart() : pLine->GetEnd(); + nChar = ( nXPos <= rLine.GetStartPosX() ) ? rLine.GetStart() : rLine.GetEnd(); } return nChar; } -Range ImpEditEngine::GetLineXPosStartEnd( const ParaPortion* pParaPortion, const EditLine* pLine ) const +Range ImpEditEngine::GetLineXPosStartEnd(ParaPortion const& rParaPortion, EditLine const& rLine) const { Range aLineXPosStartEnd; - sal_Int32 nPara = GetEditDoc().GetPos( pParaPortion->GetNode() ); + sal_Int32 nPara = GetEditDoc().GetPos(rParaPortion.GetNode()); if ( !IsRightToLeft( nPara ) ) { - aLineXPosStartEnd.Min() = pLine->GetStartPosX(); - aLineXPosStartEnd.Max() = pLine->GetStartPosX() + pLine->GetTextWidth(); + aLineXPosStartEnd.Min() = rLine.GetStartPosX(); + aLineXPosStartEnd.Max() = rLine.GetStartPosX() + rLine.GetTextWidth(); } else { - aLineXPosStartEnd.Min() = GetPaperSize().Width() - ( pLine->GetStartPosX() + pLine->GetTextWidth() ); - aLineXPosStartEnd.Max() = GetPaperSize().Width() - pLine->GetStartPosX(); + aLineXPosStartEnd.Min() = GetPaperSize().Width() - (rLine.GetStartPosX() + rLine.GetTextWidth()); + aLineXPosStartEnd.Max() = GetPaperSize().Width() - rLine.GetStartPosX(); } - return aLineXPosStartEnd; } -tools::Long ImpEditEngine::GetPortionXOffset( - const ParaPortion* pParaPortion, const EditLine* pLine, sal_Int32 nTextPortion) const +tools::Long ImpEditEngine::GetPortionXOffset(ParaPortion const& rParaPortion, EditLine const& rLine, sal_Int32 nTextPortion) const { - tools::Long nX = pLine->GetStartPosX(); + tools::Long nX = rLine.GetStartPosX(); - for ( sal_Int32 i = pLine->GetStartPortion(); i < nTextPortion; i++ ) + for ( sal_Int32 i = rLine.GetStartPortion(); i < nTextPortion; i++ ) { - const TextPortion& rPortion = pParaPortion->GetTextPortions()[i]; + const TextPortion& rPortion = rParaPortion.GetTextPortions()[i]; switch ( rPortion.GetKind() ) { case PortionKind::FIELD: @@ -4036,19 +4190,19 @@ tools::Long ImpEditEngine::GetPortionXOffset( } } - sal_Int32 nPara = GetEditDoc().GetPos( pParaPortion->GetNode() ); + sal_Int32 nPara = GetEditDoc().GetPos(rParaPortion.GetNode()); bool bR2LPara = IsRightToLeft( nPara ); - const TextPortion& rDestPortion = pParaPortion->GetTextPortions()[nTextPortion]; + const TextPortion& rDestPortion = rParaPortion.GetTextPortions()[nTextPortion]; if ( rDestPortion.GetKind() != PortionKind::TAB ) { if ( !bR2LPara && rDestPortion.GetRightToLeftLevel() ) { // Portions behind must be added, visual before this portion sal_Int32 nTmpPortion = nTextPortion+1; - while ( nTmpPortion <= pLine->GetEndPortion() ) + while ( nTmpPortion <= rLine.GetEndPortion() ) { - const TextPortion& rNextTextPortion = pParaPortion->GetTextPortions()[nTmpPortion]; + const TextPortion& rNextTextPortion = rParaPortion.GetTextPortions()[nTmpPortion]; if ( rNextTextPortion.GetRightToLeftLevel() && ( rNextTextPortion.GetKind() != PortionKind::TAB ) ) nX += rNextTextPortion.GetSize().Width(); else @@ -4057,10 +4211,10 @@ tools::Long ImpEditEngine::GetPortionXOffset( } // Portions before must be removed, visual behind this portion nTmpPortion = nTextPortion; - while ( nTmpPortion > pLine->GetStartPortion() ) + while ( nTmpPortion > rLine.GetStartPortion() ) { --nTmpPortion; - const TextPortion& rPrevTextPortion = pParaPortion->GetTextPortions()[nTmpPortion]; + const TextPortion& rPrevTextPortion = rParaPortion.GetTextPortions()[nTmpPortion]; if ( rPrevTextPortion.GetRightToLeftLevel() && ( rPrevTextPortion.GetKind() != PortionKind::TAB ) ) nX -= rPrevTextPortion.GetSize().Width(); else @@ -4071,9 +4225,9 @@ tools::Long ImpEditEngine::GetPortionXOffset( { // Portions behind must be removed, visual behind this portion sal_Int32 nTmpPortion = nTextPortion+1; - while ( nTmpPortion <= pLine->GetEndPortion() ) + while ( nTmpPortion <= rLine.GetEndPortion() ) { - const TextPortion& rNextTextPortion = pParaPortion->GetTextPortions()[nTmpPortion]; + const TextPortion& rNextTextPortion = rParaPortion.GetTextPortions()[nTmpPortion]; if ( !rNextTextPortion.IsRightToLeft() && ( rNextTextPortion.GetKind() != PortionKind::TAB ) ) nX += rNextTextPortion.GetSize().Width(); else @@ -4082,10 +4236,10 @@ tools::Long ImpEditEngine::GetPortionXOffset( } // Portions before must be added, visual before this portion nTmpPortion = nTextPortion; - while ( nTmpPortion > pLine->GetStartPortion() ) + while ( nTmpPortion > rLine.GetStartPortion() ) { --nTmpPortion; - const TextPortion& rPrevTextPortion = pParaPortion->GetTextPortions()[nTmpPortion]; + const TextPortion& rPrevTextPortion = rParaPortion.GetTextPortions()[nTmpPortion]; if ( !rPrevTextPortion.IsRightToLeft() && ( rPrevTextPortion.GetKind() != PortionKind::TAB ) ) nX -= rPrevTextPortion.GetSize().Width(); else @@ -4105,33 +4259,31 @@ tools::Long ImpEditEngine::GetPortionXOffset( return nX; } -tools::Long ImpEditEngine::GetXPos( - const ParaPortion* pParaPortion, const EditLine* pLine, sal_Int32 nIndex, bool bPreferPortionStart) const +tools::Long ImpEditEngine::GetXPos(ParaPortion const& rParaPortion, EditLine const& rLine, sal_Int32 nIndex, bool bPreferPortionStart) const { - OSL_ENSURE( pLine, "No line received: GetXPos" ); - OSL_ENSURE( ( nIndex >= pLine->GetStart() ) && ( nIndex <= pLine->GetEnd() ) , "GetXPos has to be called properly!" ); + OSL_ENSURE( ( nIndex >= rLine.GetStart() ) && ( nIndex <= rLine.GetEnd() ) , "GetXPos has to be called properly!" ); bool bDoPreferPortionStart = bPreferPortionStart; // Assure that the portion belongs to this line: - if ( nIndex == pLine->GetStart() ) + if ( nIndex == rLine.GetStart() ) bDoPreferPortionStart = true; - else if ( nIndex == pLine->GetEnd() ) + else if ( nIndex == rLine.GetEnd() ) bDoPreferPortionStart = false; sal_Int32 nTextPortionStart = 0; - sal_Int32 nTextPortion = pParaPortion->GetTextPortions().FindPortion( nIndex, nTextPortionStart, bDoPreferPortionStart ); + sal_Int32 nTextPortion = rParaPortion.GetTextPortions().FindPortion( nIndex, nTextPortionStart, bDoPreferPortionStart ); - OSL_ENSURE( ( nTextPortion >= pLine->GetStartPortion() ) && ( nTextPortion <= pLine->GetEndPortion() ), "GetXPos: Portion not in current line! " ); + OSL_ENSURE( ( nTextPortion >= rLine.GetStartPortion() ) && ( nTextPortion <= rLine.GetEndPortion() ), "GetXPos: Portion not in current line! " ); - const TextPortion& rPortion = pParaPortion->GetTextPortions()[nTextPortion]; + const TextPortion& rPortion = rParaPortion.GetTextPortions()[nTextPortion]; - tools::Long nX = GetPortionXOffset( pParaPortion, pLine, nTextPortion ); + tools::Long nX = GetPortionXOffset(rParaPortion, rLine, nTextPortion); // calc text width, portion size may include CJK/CTL spacing... // But the array might not be init yet, if using text ranger this method is called within CreateLines()... tools::Long nPortionTextWidth = rPortion.GetSize().Width(); if ( ( rPortion.GetKind() == PortionKind::TEXT ) && rPortion.GetLen() && !GetTextRanger() ) - nPortionTextWidth = pLine->GetCharPosArray()[nTextPortionStart + rPortion.GetLen() - 1 - pLine->GetStart()]; + nPortionTextWidth = rLine.GetCharPosArray()[nTextPortionStart + rPortion.GetLen() - 1 - rLine.GetStart()]; if ( nTextPortionStart != nIndex ) { @@ -4141,18 +4293,18 @@ tools::Long ImpEditEngine::GetXPos( // End of Portion if ( rPortion.GetKind() == PortionKind::TAB ) { - if ( nTextPortion+1 < pParaPortion->GetTextPortions().Count() ) + if ( nTextPortion+1 < rParaPortion.GetTextPortions().Count() ) { - const TextPortion& rNextPortion = pParaPortion->GetTextPortions()[nTextPortion+1]; + const TextPortion& rNextPortion = rParaPortion.GetTextPortions()[nTextPortion+1]; if ( rNextPortion.GetKind() != PortionKind::TAB ) { if ( !bPreferPortionStart ) - nX = GetXPos( pParaPortion, pLine, nIndex, true ); - else if ( !IsRightToLeft( GetEditDoc().GetPos( pParaPortion->GetNode() ) ) ) + nX = GetXPos(rParaPortion, rLine, nIndex, true ); + else if ( !IsRightToLeft( GetEditDoc().GetPos(rParaPortion.GetNode()) ) ) nX += nPortionTextWidth; } } - else if ( !IsRightToLeft( GetEditDoc().GetPos( pParaPortion->GetNode() ) ) ) + else if ( !IsRightToLeft( GetEditDoc().GetPos(rParaPortion.GetNode()) ) ) { nX += nPortionTextWidth; } @@ -4164,20 +4316,20 @@ tools::Long ImpEditEngine::GetXPos( } else if ( rPortion.GetKind() == PortionKind::TEXT ) { - OSL_ENSURE( nIndex != pLine->GetStart(), "Strange behavior in new GetXPos()" ); - OSL_ENSURE( pLine && !pLine->GetCharPosArray().empty(), "svx::ImpEditEngine::GetXPos(), portion in an empty line?" ); + OSL_ENSURE( nIndex != rLine.GetStart(), "Strange behavior in new GetXPos()" ); + OSL_ENSURE( !rLine.GetCharPosArray().empty(), "svx::ImpEditEngine::GetXPos(), portion in an empty line?" ); - if( !pLine->GetCharPosArray().empty() ) + if( !rLine.GetCharPosArray().empty() ) { - sal_Int32 nPos = nIndex - 1 - pLine->GetStart(); - if (nPos < 0 || nPos >= static_cast<sal_Int32>(pLine->GetCharPosArray().size())) + sal_Int32 nPos = nIndex - 1 - rLine.GetStart(); + if (nPos < 0 || o3tl::make_unsigned(nPos) >= rLine.GetCharPosArray().size()) { - nPos = pLine->GetCharPosArray().size()-1; + nPos = rLine.GetCharPosArray().size()-1; OSL_FAIL("svx::ImpEditEngine::GetXPos(), index out of range!"); } // old code restored see #i112788 (which leaves #i74188 unfixed again) - tools::Long nPosInPortion = pLine->GetCharPosArray()[nPos]; + tools::Long nPosInPortion = rLine.GetCharPosArray()[nPos]; if ( !rPortion.IsRightToLeft() ) { @@ -4193,17 +4345,17 @@ tools::Long ImpEditEngine::GetXPos( nX += rPortion.GetExtraInfos()->nPortionOffsetX; if ( rPortion.GetExtraInfos()->nAsianCompressionTypes & AsianCompressionFlags::PunctuationRight ) { - AsianCompressionFlags nType = GetCharTypeForCompression( pParaPortion->GetNode()->GetChar( nIndex ) ); - if ( nType == AsianCompressionFlags::PunctuationRight && !pLine->GetCharPosArray().empty() ) + AsianCompressionFlags nType = GetCharTypeForCompression(rParaPortion.GetNode()->GetChar(nIndex)); + if ( nType == AsianCompressionFlags::PunctuationRight && !rLine.GetCharPosArray().empty() ) { sal_Int32 n = nIndex - nTextPortionStart; - const sal_Int32* pDXArray = pLine->GetCharPosArray().data()+( nTextPortionStart-pLine->GetStart() ); + const sal_Int32* pDXArray = rLine.GetCharPosArray().data() + (nTextPortionStart - rLine.GetStart()); sal_Int32 nCharWidth = ( ( (n+1) < rPortion.GetLen() ) ? pDXArray[n] : rPortion.GetSize().Width() ) - ( n ? pDXArray[n-1] : 0 ); if ( (n+1) < rPortion.GetLen() ) { // smaller, when char behind is AsianCompressionFlags::PunctuationRight also - nType = GetCharTypeForCompression( pParaPortion->GetNode()->GetChar( nIndex+1 ) ); + nType = GetCharTypeForCompression(rParaPortion.GetNode()->GetChar(nIndex + 1)); if ( nType == AsianCompressionFlags::PunctuationRight ) { sal_Int32 nNextCharWidth = ( ( (n+2) < rPortion.GetLen() ) ? pDXArray[n+1] : rPortion.GetSize().Width() ) @@ -4225,7 +4377,7 @@ tools::Long ImpEditEngine::GetXPos( } } } - else // if ( nIndex == pLine->GetStart() ) + else // if ( nIndex == rLine.GetStart() ) { if ( rPortion.IsRightToLeft() ) { @@ -4236,48 +4388,66 @@ tools::Long ImpEditEngine::GetXPos( return nX; } -void ImpEditEngine::CalcHeight( ParaPortion* pPortion ) +/** Is true if paragraph is in the empty cluster of paragraphs at the end */ +bool ImpEditEngine::isInEmptyClusterAtTheEnd(ParaPortion& rPortion) +{ + sal_Int32 nPortion = GetParaPortions().GetPos(&rPortion); + + auto& rParagraphs = GetParaPortions(); + if (rParagraphs.Count() <= 0) + return false; + + sal_Int32 nCurrent = rParagraphs.lastIndex(); + while (nCurrent > 0 && rParagraphs.getRef(nCurrent).IsEmpty()) + { + if (nCurrent == nPortion) + return true; + nCurrent--; + } + return false; +} + +void ImpEditEngine::CalcHeight(ParaPortion& rPortion) { - pPortion->nHeight = 0; - pPortion->nFirstLineOffset = 0; + rPortion.mnHeight = 0; + rPortion.mnFirstLineOffset = 0; - if ( !pPortion->IsVisible() ) + if (!rPortion.IsVisible() || isInEmptyClusterAtTheEnd(rPortion)) return; - OSL_ENSURE( pPortion->GetLines().Count(), "Paragraph with no lines in ParaPortion::CalcHeight" ); - for (sal_Int32 nLine = 0; nLine < pPortion->GetLines().Count(); ++nLine) - pPortion->nHeight += pPortion->GetLines()[nLine].GetHeight(); + OSL_ENSURE(rPortion.GetLines().Count(), "Paragraph with no lines in ParaPortion::CalcHeight"); + for (sal_Int32 nLine = 0; nLine < rPortion.GetLines().Count(); ++nLine) + rPortion.mnHeight += rPortion.GetLines()[nLine].GetHeight(); - if ( aStatus.IsOutliner() ) + if (maStatus.IsOutliner()) return; - const SvxULSpaceItem& rULItem = pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE ); - const SvxLineSpacingItem& rLSItem = pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL ); - sal_Int32 nSBL = ( rLSItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Fix ) ? GetYValue( rLSItem.GetInterLineSpace() ) : 0; + const SvxULSpaceItem& rULItem = rPortion.GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE ); + const SvxLineSpacingItem& rLSItem = rPortion.GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL ); + sal_Int32 nSBL = ( rLSItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Fix ) ? scaleYSpacingValue(rLSItem.GetInterLineSpace()) : 0; if ( nSBL ) { - if ( pPortion->GetLines().Count() > 1 ) - pPortion->nHeight += ( pPortion->GetLines().Count() - 1 ) * nSBL; - if ( aStatus.ULSpaceSummation() ) - pPortion->nHeight += nSBL; + if (rPortion.GetLines().Count() > 1) + rPortion.mnHeight += (rPortion.GetLines().Count() - 1) * nSBL; + if (maStatus.ULSpaceSummation()) + rPortion.mnHeight += nSBL; } - sal_Int32 nPortion = GetParaPortions().GetPos( pPortion ); + sal_Int32 nPortion = GetParaPortions().GetPos(&rPortion); if ( nPortion ) { - sal_uInt16 nUpper = GetYValue( rULItem.GetUpper() ); - pPortion->nHeight += nUpper; - pPortion->nFirstLineOffset = nUpper; + sal_uInt16 nUpper = scaleYSpacingValue(rULItem.GetUpper()); + rPortion.mnHeight += nUpper; + rPortion.mnFirstLineOffset = nUpper; } - if ( nPortion != (GetParaPortions().Count()-1) ) + if (nPortion != GetParaPortions().lastIndex()) { - pPortion->nHeight += GetYValue( rULItem.GetLower() ); // not in the last + rPortion.mnHeight += scaleYSpacingValue(rULItem.GetLower()); // not in the last } - - if ( !nPortion || aStatus.ULSpaceSummation() ) + if ( !nPortion || maStatus.ULSpaceSummation() ) return; ParaPortion* pPrev = GetParaPortions().SafeGetObject( nPortion-1 ); @@ -4293,30 +4463,29 @@ void ImpEditEngine::CalcHeight( ParaPortion* pPortion ) // Only Writer3: Do not add up, but minimum distance. // check if distance by LineSpacing > Upper: - sal_uInt16 nExtraSpace = GetYValue( lcl_CalcExtraSpace( rLSItem ) ); - if ( nExtraSpace > pPortion->nFirstLineOffset ) + sal_uInt16 nExtraSpace = scaleYSpacingValue(lcl_CalcExtraSpace(rLSItem)); + if (nExtraSpace > rPortion.mnFirstLineOffset) { // Paragraph becomes 'bigger': - pPortion->nHeight += ( nExtraSpace - pPortion->nFirstLineOffset ); - pPortion->nFirstLineOffset = nExtraSpace; + rPortion.mnHeight += (nExtraSpace - rPortion.mnFirstLineOffset); + rPortion.mnFirstLineOffset = nExtraSpace; } // Determine nFirstLineOffset now f(pNode) => now f(pNode, pPrev): - sal_uInt16 nPrevLower = GetYValue( rPrevULItem.GetLower() ); + sal_uInt16 nPrevLower = scaleYSpacingValue(rPrevULItem.GetLower()); // This PrevLower is still in the height of PrevPortion ... - if ( nPrevLower > pPortion->nFirstLineOffset ) + if (nPrevLower > rPortion.mnFirstLineOffset) { // Paragraph is 'small': - pPortion->nHeight -= pPortion->nFirstLineOffset; - pPortion->nFirstLineOffset = 0; + rPortion.mnHeight -= rPortion.mnFirstLineOffset; + rPortion.mnFirstLineOffset = 0; } else if ( nPrevLower ) { // Paragraph becomes 'somewhat smaller': - pPortion->nHeight -= nPrevLower; - pPortion->nFirstLineOffset = - pPortion->nFirstLineOffset - nPrevLower; + rPortion.mnHeight -= nPrevLower; + rPortion.mnFirstLineOffset = rPortion.mnFirstLineOffset - nPrevLower; } // I find it not so good, but Writer3 feature: // Check if distance by LineSpacing > Lower: this value is not @@ -4324,39 +4493,39 @@ void ImpEditEngine::CalcHeight( ParaPortion* pPortion ) if ( pPrev->IsInvalid() ) return; - nExtraSpace = GetYValue( lcl_CalcExtraSpace( rPrevLSItem ) ); + nExtraSpace = scaleYSpacingValue(lcl_CalcExtraSpace(rPrevLSItem)); if ( nExtraSpace > nPrevLower ) { sal_uInt16 nMoreLower = nExtraSpace - nPrevLower; // Paragraph becomes 'bigger', 'grows' downwards: - if ( nMoreLower > pPortion->nFirstLineOffset ) + if ( nMoreLower > rPortion.mnFirstLineOffset ) { - pPortion->nHeight += ( nMoreLower - pPortion->nFirstLineOffset ); - pPortion->nFirstLineOffset = nMoreLower; + rPortion.mnHeight += (nMoreLower - rPortion.mnFirstLineOffset); + rPortion.mnFirstLineOffset = nMoreLower; } } } void ImpEditEngine::SetValidPaperSize( const Size& rNewSz ) { - aPaperSize = rNewSz; + maPaperSize = rNewSz; - tools::Long nMinWidth = aStatus.AutoPageWidth() ? aMinAutoPaperSize.Width() : 0; - tools::Long nMaxWidth = aStatus.AutoPageWidth() ? aMaxAutoPaperSize.Width() : 0x7FFFFFFF; - tools::Long nMinHeight = aStatus.AutoPageHeight() ? aMinAutoPaperSize.Height() : 0; - tools::Long nMaxHeight = aStatus.AutoPageHeight() ? aMaxAutoPaperSize.Height() : 0x7FFFFFFF; + tools::Long nMinWidth = maStatus.AutoPageWidth() ? maMinAutoPaperSize.Width() : 0; + tools::Long nMaxWidth = maStatus.AutoPageWidth() ? maMaxAutoPaperSize.Width() : 0x7FFFFFFF; + tools::Long nMinHeight = maStatus.AutoPageHeight() ? maMinAutoPaperSize.Height() : 0; + tools::Long nMaxHeight = maStatus.AutoPageHeight() ? maMaxAutoPaperSize.Height() : 0x7FFFFFFF; // Minimum/Maximum width: - if ( aPaperSize.Width() < nMinWidth ) - aPaperSize.setWidth( nMinWidth ); - else if ( aPaperSize.Width() > nMaxWidth ) - aPaperSize.setWidth( nMaxWidth ); + if ( maPaperSize.Width() < nMinWidth ) + maPaperSize.setWidth( nMinWidth ); + else if ( maPaperSize.Width() > nMaxWidth ) + maPaperSize.setWidth( nMaxWidth ); // Minimum/Maximum height: - if ( aPaperSize.Height() < nMinHeight ) - aPaperSize.setHeight( nMinHeight ); - else if ( aPaperSize.Height() > nMaxHeight ) - aPaperSize.setHeight( nMaxHeight ); + if ( maPaperSize.Height() < nMinHeight ) + maPaperSize.setHeight( nMinHeight ); + else if ( maPaperSize.Height() > nMaxHeight ) + maPaperSize.setHeight( nMaxHeight ); } std::shared_ptr<SvxForbiddenCharactersTable> const & ImpEditEngine::GetForbiddenCharsTable() @@ -4373,10 +4542,7 @@ bool ImpEditEngine::IsVisualCursorTravelingEnabled() { bool bVisualCursorTravaling = false; - if( !pCTLOptions ) - pCTLOptions.reset( new SvtCTLOptions ); - - if ( pCTLOptions->IsCTLFontEnabled() && ( pCTLOptions->GetCTLCursorMovement() == SvtCTLOptions::MOVEMENT_VISUAL ) ) + if ( SvtCTLOptions::IsCTLFontEnabled() && ( SvtCTLOptions::GetCTLCursorMovement() == SvtCTLOptions::MOVEMENT_VISUAL ) ) { bVisualCursorTravaling = true; } @@ -4393,7 +4559,7 @@ bool ImpEditEngine::DoVisualCursorTraveling() IMPL_LINK_NOARG(ImpEditEngine, DocModified, LinkParamNone*, void) { - aModifyHdl.Call( nullptr /*GetEditEnginePtr()*/ ); // NULL, because also used for Outliner + maModifyHdl.Call( nullptr /*GetEditEnginePtr()*/ ); // NULL, because also used for Outliner } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/impedit3.cxx b/editeng/source/editeng/impedit3.cxx index c28e1eab7b00..c0a8b1fc734c 100644 --- a/editeng/source/editeng/impedit3.cxx +++ b/editeng/source/editeng/impedit3.cxx @@ -24,6 +24,7 @@ #include <vcl/settings.hxx> #include <vcl/window.hxx> +#include <editeng/outliner.hxx> #include <editeng/tstpitem.hxx> #include <editeng/lspcitem.hxx> #include <editeng/flditem.hxx> @@ -41,18 +42,24 @@ #include <editeng/wghtitem.hxx> #include <editeng/postitem.hxx> #include <editeng/langitem.hxx> +#include <editeng/frmdiritem.hxx> #include <editeng/scriptspaceitem.hxx> #include <editeng/charscaleitem.hxx> #include <editeng/numitem.hxx> +#include <outleeng.hxx> +#include <TextPortion.hxx> #include <svtools/colorcfg.hxx> #include <svl/ctloptions.hxx> #include <svl/asiancfg.hxx> +#include <svx/compatflags.hxx> +#include <sfx2/viewsh.hxx> + #include <editeng/hngpnctitem.hxx> #include <editeng/forbiddencharacterstable.hxx> -#include <unotools/configmgr.hxx> +#include <comphelper/configuration.hxx> #include <math.h> #include <vcl/metric.hxx> @@ -63,23 +70,27 @@ #include <i18nlangtag/mslangid.hxx> #include <comphelper/processfactory.hxx> +#include <comphelper/lok.hxx> #include <rtl/ustrbuf.hxx> #include <sal/log.hxx> #include <o3tl/safeint.hxx> #include <o3tl/sorted_vector.hxx> #include <osl/diagnose.h> #include <comphelper/string.hxx> +#include <cstddef> #include <memory> #include <set> #include <vcl/outdev/ScopedStates.hxx> +#include <unicode/uchar.h> + using namespace ::com::sun::star; using namespace ::com::sun::star::uno; using namespace ::com::sun::star::beans; using namespace ::com::sun::star::linguistic2; -constexpr OUStringLiteral CH_HYPH = u"-"; +constexpr OUString CH_HYPH = u"-"_ustr; constexpr tools::Long WRONG_SHOW_MIN = 5; @@ -105,42 +116,22 @@ struct TabInfo } -Point Rotate( const Point& rPoint, Degree10 nOrientation, const Point& rOrigin ) -{ - double nRealOrientation = toRadians(nOrientation); - double nCos = cos( nRealOrientation ); - double nSin = sin( nRealOrientation ); - - Point aRotatedPos; - Point aTranslatedPos( rPoint ); - - // Translation - aTranslatedPos -= rOrigin; - - // Rotation... - aRotatedPos.setX( static_cast<tools::Long>( nCos*aTranslatedPos.X() + nSin*aTranslatedPos.Y() ) ); - aRotatedPos.setY( static_cast<tools::Long>(- ( nSin*aTranslatedPos.X() - nCos*aTranslatedPos.Y() )) ); - aTranslatedPos = aRotatedPos; - - // Translation... - aTranslatedPos += rOrigin; - return aTranslatedPos; -} - AsianCompressionFlags GetCharTypeForCompression( sal_Unicode cChar ) { switch ( cChar ) { case 0x3008: case 0x300A: case 0x300C: case 0x300E: case 0x3010: case 0x3014: case 0x3016: case 0x3018: - case 0x301A: case 0x301D: + case 0x301A: case 0x301D: case 0xFF09: case 0xFF3D: + case 0xFF5D: { return AsianCompressionFlags::PunctuationRight; } case 0x3001: case 0x3002: case 0x3009: case 0x300B: case 0x300D: case 0x300F: case 0x3011: case 0x3015: case 0x3017: case 0x3019: case 0x301B: case 0x301E: - case 0x301F: + case 0x301F: case 0xFF08: case 0xFF0C: case 0xFF0E: + case 0xFF1A: case 0xFF1B: case 0xFF3B: case 0xFF5B: { return AsianCompressionFlags::PunctuationLeft; } @@ -156,7 +147,7 @@ static void lcl_DrawRedLines( OutputDevice& rOutDev, const Point& rPoint, size_t nIndex, size_t nMaxEnd, - o3tl::span<const sal_Int32> pDXArray, + std::span<const sal_Int32> pDXArray, WrongList const * pWrongs, Degree10 nOrientation, const Point& rOrigin, @@ -220,8 +211,8 @@ static void lcl_DrawRedLines( OutputDevice& rOutDev, if (nOrientation) { - aPoint1 = Rotate(aPoint1, nOrientation, rOrigin); - aPoint2 = Rotate(aPoint2, nOrientation, rOrigin); + rOrigin.RotateAround(aPoint1, nOrientation); + rOrigin.RotateAround(aPoint2, nOrientation); } { @@ -237,35 +228,83 @@ static void lcl_DrawRedLines( OutputDevice& rOutDev, } } -static Point lcl_ImplCalcRotatedPos( Point rPos, Point rOrigin, double nSin, double nCos ) +// For Kashidas from sw/source/core/text/porlay.cxx + +#define IS_JOINING_GROUP(c, g) ( u_getIntPropertyValue( (c), UCHAR_JOINING_GROUP ) == U_JG_##g ) +#define isAinChar(c) IS_JOINING_GROUP((c), AIN) +#define isAlefChar(c) IS_JOINING_GROUP((c), ALEF) +#define isDalChar(c) IS_JOINING_GROUP((c), DAL) +#define isFehChar(c) (IS_JOINING_GROUP((c), FEH) || IS_JOINING_GROUP((c), AFRICAN_FEH)) +#define isGafChar(c) IS_JOINING_GROUP((c), GAF) +#define isHehChar(c) IS_JOINING_GROUP((c), HEH) +#define isKafChar(c) IS_JOINING_GROUP((c), KAF) +#define isLamChar(c) IS_JOINING_GROUP((c), LAM) +#define isQafChar(c) (IS_JOINING_GROUP((c), QAF) || IS_JOINING_GROUP((c), AFRICAN_QAF)) +#define isRehChar(c) IS_JOINING_GROUP((c), REH) +#define isTahChar(c) IS_JOINING_GROUP((c), TAH) +#define isTehMarbutaChar(c) IS_JOINING_GROUP((c), TEH_MARBUTA) +#define isWawChar(c) IS_JOINING_GROUP((c), WAW) +#define isSeenOrSadChar(c) (IS_JOINING_GROUP((c), SAD) || IS_JOINING_GROUP((c), SEEN)) + +// Beh and characters that behave like Beh in medial form. +static bool isBehChar(sal_Unicode cCh) +{ + bool bRet = false; + switch (u_getIntPropertyValue(cCh, UCHAR_JOINING_GROUP)) + { + case U_JG_BEH: + case U_JG_NOON: + case U_JG_AFRICAN_NOON: + case U_JG_NYA: + case U_JG_YEH: + case U_JG_FARSI_YEH: + case U_JG_BURUSHASKI_YEH_BARREE: + bRet = true; + break; + default: + bRet = false; + break; + } + + return bRet; +} + +// Yeh and characters that behave like Yeh in final form. +static bool isYehChar(sal_Unicode cCh) +{ + bool bRet = false; + switch (u_getIntPropertyValue(cCh, UCHAR_JOINING_GROUP)) + { + case U_JG_YEH: + case U_JG_FARSI_YEH: + case U_JG_YEH_BARREE: + case U_JG_BURUSHASKI_YEH_BARREE: + case U_JG_YEH_WITH_TAIL: + bRet = true; + break; + default: + bRet = false; + break; + } + + return bRet; +} + +static bool isTransparentChar ( sal_Unicode cCh ) { - Point aRotatedPos; - // Translation... - Point aTranslatedPos( rPos); - aTranslatedPos -= rOrigin; - - aRotatedPos.setX( static_cast<tools::Long>( nCos*aTranslatedPos.X() + nSin*aTranslatedPos.Y() ) ); - aRotatedPos.setY( static_cast<tools::Long>(- ( nSin*aTranslatedPos.X() - nCos*aTranslatedPos.Y() )) ); - aTranslatedPos = aRotatedPos; - // Translation... - aTranslatedPos += rOrigin; - - return aTranslatedPos; + return u_getIntPropertyValue( cCh, UCHAR_JOINING_TYPE ) == U_JT_TRANSPARENT; } -static bool lcl_IsLigature( sal_Unicode cCh, sal_Unicode cNextCh ) // For Kashidas from sw/source/core/text/porlay.txt +static bool lcl_IsLigature( sal_Unicode cCh, sal_Unicode cNextCh ) { // Lam + Alef - return ( 0x644 == cCh && 0x627 == cNextCh ) || - // Beh + Reh - ( 0x628 == cCh && 0x631 == cNextCh ); + return ( isLamChar ( cCh ) && isAlefChar ( cNextCh )); } -static bool lcl_ConnectToPrev( sal_Unicode cCh, sal_Unicode cPrevCh ) // For Kashidas from sw/source/core/text/porlay.txt +static bool lcl_ConnectToPrev( sal_Unicode cCh, sal_Unicode cPrevCh ) { - // Alef, Dal, Thal, Reh, Zain, and Waw do not connect to the left - bool bRet = 0x627 != cPrevCh && 0x62F != cPrevCh && 0x630 != cPrevCh && - 0x631 != cPrevCh && 0x632 != cPrevCh && 0x648 != cPrevCh; + const int32_t nJoiningType = u_getIntPropertyValue( cPrevCh, UCHAR_JOINING_TYPE ); + bool bRet = nJoiningType != U_JT_RIGHT_JOINING && nJoiningType != U_JT_NON_JOINING; // check for ligatures cPrevChar + cChar if ( bRet ) @@ -278,23 +317,23 @@ static bool lcl_ConnectToPrev( sal_Unicode cCh, sal_Unicode cPrevCh ) // For Ka void ImpEditEngine::UpdateViews( EditView* pCurView ) { - if ( !IsUpdateLayout() || IsFormatting() || aInvalidRect.IsEmpty() ) + if ( !IsUpdateLayout() || IsFormatting() || maInvalidRect.IsEmpty() ) return; DBG_ASSERT( IsFormatted(), "UpdateViews: Doc not formatted!" ); - for (EditView* pView : aEditViews) + for (EditView* pView : maEditViews) { pView->HideCursor(); - tools::Rectangle aClipRect( aInvalidRect ); + tools::Rectangle aClipRect(maInvalidRect); tools::Rectangle aVisArea( pView->GetVisArea() ); aClipRect.Intersection( aVisArea ); if ( !aClipRect.IsEmpty() ) { // convert to window coordinates... - aClipRect = pView->pImpEditView->GetWindowPos( aClipRect ); + aClipRect = pView->getImpl().GetWindowPos( aClipRect ); // moved to one executing method to allow finer control pView->InvalidateWindow(aClipRect); @@ -305,11 +344,11 @@ void ImpEditEngine::UpdateViews( EditView* pCurView ) if ( pCurView ) { - bool bGotoCursor = pCurView->pImpEditView->DoAutoScroll(); + bool bGotoCursor = pCurView->getImpl().DoAutoScroll(); pCurView->ShowCursor( bGotoCursor ); } - aInvalidRect = tools::Rectangle(); + maInvalidRect = tools::Rectangle(); CallStatusHdl(); } @@ -318,18 +357,18 @@ IMPL_LINK_NOARG(ImpEditEngine, OnlineSpellHdl, Timer *, void) if ( !Application::AnyInput( VclInputFlags::KEYBOARD ) && IsUpdateLayout() && IsFormatted() ) DoOnlineSpelling(); else - aOnlineSpellTimer.Start(); + maOnlineSpellTimer.Start(); } IMPL_LINK_NOARG(ImpEditEngine, IdleFormatHdl, Timer *, void) { - aIdleFormatter.ResetRestarts(); + maIdleFormatter.ResetRestarts(); // #i97146# check if that view is still available // else probably the idle format timer fired while we're already // downing - EditView* pView = aIdleFormatter.GetView(); - for (EditView* aEditView : aEditViews) + EditView* pView = maIdleFormatter.GetView(); + for (EditView* aEditView : maEditViews) { if( aEditView == pView ) { @@ -341,7 +380,7 @@ IMPL_LINK_NOARG(ImpEditEngine, IdleFormatHdl, Timer *, void) void ImpEditEngine::CheckIdleFormatter() { - aIdleFormatter.ForceTimeout(); + maIdleFormatter.ForceTimeout(); // If not idle, but still not formatted: if ( !IsFormatted() ) FormatDoc(); @@ -355,186 +394,218 @@ bool ImpEditEngine::IsPageOverflow( ) const void ImpEditEngine::FormatFullDoc() { - for ( sal_Int32 nPortion = 0; nPortion < GetParaPortions().Count(); nPortion++ ) - GetParaPortions()[nPortion].MarkSelectionInvalid( 0 ); + GetParaPortions().MarkAllSelectionsInvalid(0); FormatDoc(); } -void ImpEditEngine::FormatDoc() +tools::Long ImpEditEngine::FormatParagraphs(o3tl::sorted_vector<sal_Int32>& aRepaintParagraphList) { - if (!IsUpdateLayout() || IsFormatting()) - return; - - bIsFormatting = true; - - // Then I can also start the spell-timer... - if ( GetStatus().DoOnlineSpelling() ) - StartOnlineSpellTimer(); - + sal_Int32 nParaCount = GetParaPortions().Count(); tools::Long nY = 0; bool bGrow = false; - // Here already, so that not always in CreateLines... - bool bMapChanged = ImpCheckRefMapMode(); - std::set<sal_Int32> aRepaintParas; - - for ( sal_Int32 nPara = 0; nPara < GetParaPortions().Count(); nPara++ ) + for (sal_Int32 nParagraph = 0; nParagraph < nParaCount; nParagraph++) { - ParaPortion& rParaPortion = GetParaPortions()[nPara]; - if ( rParaPortion.MustRepaint() || ( rParaPortion.IsInvalid() && rParaPortion.IsVisible() ) ) + ParaPortion& rParaPortion = GetParaPortions().getRef(nParagraph); + if (rParaPortion.MustRepaint() || (rParaPortion.IsInvalid() && rParaPortion.IsVisible())) { // No formatting should be necessary for MustRepaint()! - if ( !rParaPortion.IsInvalid() || CreateLines( nPara, nY ) ) + if (CreateLines(nParagraph, nY)) { - if ( !bGrow && GetTextRanger() ) + if (!bGrow && GetTextRanger()) { // For a change in height all below must be reformatted... - for ( sal_Int32 n = nPara+1; n < GetParaPortions().Count(); n++ ) + for (sal_Int32 n = nParagraph + 1; n < nParaCount; n++) { - ParaPortion& rPP = GetParaPortions()[n]; - rPP.MarkSelectionInvalid( 0 ); - rPP.GetLines().Reset(); + ParaPortion& rParaPortionToInvalidate = GetParaPortions().getRef(n); + rParaPortionToInvalidate.MarkSelectionInvalid(0); + rParaPortionToInvalidate.GetLines().Reset(); } } bGrow = true; - if ( IsCallParaInsertedOrDeleted() ) + if (IsCallParaInsertedOrDeleted()) { - GetEditEnginePtr()->ParagraphHeightChanged( nPara ); + GetEditEnginePtr()->ParagraphHeightChanged(nParagraph); - for (EditView* pView : aEditViews) + for (EditView* pView : maEditViews) { - ImpEditView* pImpView = pView->pImpEditView.get(); - pImpView->ScrollStateChange(); + pView->getImpl().ScrollStateChange(); } } - rParaPortion.SetMustRepaint( false ); + rParaPortion.SetMustRepaint(false); } - aRepaintParas.insert(nPara); + aRepaintParagraphList.insert(nParagraph); } nY += rParaPortion.GetHeight(); } + return nY; +} - aInvalidRect = tools::Rectangle(); // make empty +namespace +{ +constexpr std::array<ScalingParameters, 13> constScaleLevels = +{ + ScalingParameters{ 1.000, 1.000, 1.0, 0.9 }, + ScalingParameters{ 0.925, 0.925, 1.0, 0.9 }, + ScalingParameters{ 0.925, 0.925, 1.0, 0.8 }, + ScalingParameters{ 0.850, 0.850, 1.0, 0.9 }, + ScalingParameters{ 0.850, 0.850, 1.0, 0.8 }, + ScalingParameters{ 0.775, 0.775, 1.0, 0.8 }, + ScalingParameters{ 0.700, 0.700, 1.0, 0.8 }, + ScalingParameters{ 0.625, 0.625, 1.0, 0.8 }, + ScalingParameters{ 0.550, 0.550, 1.0, 0.8 }, + ScalingParameters{ 0.475, 0.475, 1.0, 0.8 }, + ScalingParameters{ 0.400, 0.400, 1.0, 0.8 }, + ScalingParameters{ 0.325, 0.325, 1.0, 0.8 }, + ScalingParameters{ 0.250, 0.250, 1.0, 0.8 }, +}; + +} // end anonymous ns + +void ImpEditEngine::ScaleContentToFitWindow(o3tl::sorted_vector<sal_Int32>& aRepaintParagraphList) +{ + if (!maCustomScalingParameters.areValuesDefault()) + maScalingParameters = maCustomScalingParameters; + + tools::Long nHeight = FormatParagraphs(aRepaintParagraphList); + bool bOverflow = nHeight > (maMaxAutoPaperSize.Height() * mnColumns); + + size_t nCurrentScaleLevel = 0; + while (bOverflow && nCurrentScaleLevel < constScaleLevels.size()) + { + // Clean-up and reset paragraphs + aRepaintParagraphList.clear(); + for (auto& pParaPortionToInvalidate : GetParaPortions()) + { + pParaPortionToInvalidate->GetLines().Reset(); + pParaPortionToInvalidate->MarkSelectionInvalid(0); + pParaPortionToInvalidate->SetMustRepaint(true); + } + + // Get new scaling parameters + maScalingParameters = constScaleLevels[nCurrentScaleLevel]; + + // Try again with different scaling factor + nHeight = FormatParagraphs(aRepaintParagraphList); + bOverflow = nHeight > (maMaxAutoPaperSize.Height() * mnColumns); + + // Increase scale level + nCurrentScaleLevel++; + } +} + +void ImpEditEngine::FormatDoc() +{ + if (!IsUpdateLayout() || IsFormatting()) + return; + + mbIsFormatting = true; + + // Then I can also start the spell-timer... + if (GetStatus().DoOnlineSpelling()) + StartOnlineSpellTimer(); + + // Reserve, as it should match the current number of paragraphs + o3tl::sorted_vector<sal_Int32> aRepaintParagraphList; + aRepaintParagraphList.reserve(GetParaPortions().Count()); + + if (maStatus.DoStretch()) + ScaleContentToFitWindow(aRepaintParagraphList); + else + FormatParagraphs(aRepaintParagraphList); + + maInvalidRect = tools::Rectangle(); // make empty // One can also get into the formatting through UpdateMode ON=>OFF=>ON... // enable optimization first after Vobis delivery... { tools::Long nNewHeightNTP; tools::Long nNewHeight = CalcTextHeight(&nNewHeightNTP); - tools::Long nDiff = nNewHeight - nCurTextHeight; + tools::Long nDiff = nNewHeight - mnCurTextHeight; if ( nDiff ) - aStatus.GetStatusWord() |= !IsEffectivelyVertical() ? EditStatusFlags::TextHeightChanged : EditStatusFlags::TEXTWIDTHCHANGED; + { + maInvalidRect.Union(tools::Rectangle::Normalize( + { 0, nNewHeight }, { getWidthDirectionAware(maPaperSize), mnCurTextHeight })); + maStatus.GetStatusWord() |= !IsEffectivelyVertical() ? EditStatusFlags::TextHeightChanged : EditStatusFlags::TEXTWIDTHCHANGED; + } - nCurTextHeight = nNewHeight; - nCurTextHeightNTP = nNewHeightNTP; + mnCurTextHeight = nNewHeight; + mnCurTextHeightNTP = nNewHeightNTP; - if ( aStatus.AutoPageSize() ) + if ( maStatus.AutoPageSize() ) CheckAutoPageSize(); else if ( nDiff ) { - for (EditView* pView : aEditViews) + for (EditView* pView : maEditViews) { - ImpEditView* pImpView = pView->pImpEditView.get(); - if ( pImpView->DoAutoHeight() ) + ImpEditView& rImpView = pView->getImpl(); + if (rImpView.DoAutoHeight()) { - Size aSz( pImpView->GetOutputArea().GetWidth(), nCurTextHeight ); - if ( aSz.Height() > aMaxAutoPaperSize.Height() ) - aSz.setHeight( aMaxAutoPaperSize.Height() ); - else if ( aSz.Height() < aMinAutoPaperSize.Height() ) - aSz.setHeight( aMinAutoPaperSize.Height() ); - pImpView->ResetOutputArea( tools::Rectangle( - pImpView->GetOutputArea().TopLeft(), aSz ) ); + Size aSz(rImpView.GetOutputArea().GetWidth(), mnCurTextHeight); + if ( aSz.Height() > maMaxAutoPaperSize.Height() ) + aSz.setHeight( maMaxAutoPaperSize.Height() ); + else if ( aSz.Height() < maMinAutoPaperSize.Height() ) + aSz.setHeight( maMinAutoPaperSize.Height() ); + rImpView.ResetOutputArea( tools::Rectangle(rImpView.GetOutputArea().TopLeft(), aSz)); } } } - if (nDiff) - aInvalidRect.Union(tools::Rectangle::Justify( - { 0, nNewHeight }, { getWidthDirectionAware(aPaperSize), nCurTextHeight })); - - if (!aRepaintParas.empty()) + if (!aRepaintParagraphList.empty()) { auto CombineRepaintParasAreas = [&](const LineAreaInfo& rInfo) { - if (aRepaintParas.count(rInfo.nPortion)) - aInvalidRect.Union(rInfo.aArea); + if (aRepaintParagraphList.count(rInfo.nPortion)) + maInvalidRect.Union(rInfo.aArea); return CallbackResult::Continue; }; IterateLineAreas(CombineRepaintParasAreas, IterFlag::inclILS); } } - bIsFormatting = false; - bFormatted = true; - - if ( bMapChanged ) - GetRefDevice()->Pop(); + mbIsFormatting = false; + mbFormatted = true; CallStatusHdl(); // If Modified... } -bool ImpEditEngine::ImpCheckRefMapMode() -{ - bool bChange = false; - - if ( aStatus.DoFormat100() ) - { - MapMode aMapMode( GetRefDevice()->GetMapMode() ); - if ( aMapMode.GetScaleX().GetNumerator() != aMapMode.GetScaleX().GetDenominator() ) - bChange = true; - else if ( aMapMode.GetScaleY().GetNumerator() != aMapMode.GetScaleY().GetDenominator() ) - bChange = true; - - if ( bChange ) - { - Fraction Scale1( 1, 1 ); - aMapMode.SetScaleX( Scale1 ); - aMapMode.SetScaleY( Scale1 ); - GetRefDevice()->Push(); - GetRefDevice()->SetMapMode( aMapMode ); - } - } - - return bChange; -} - void ImpEditEngine::CheckAutoPageSize() { Size aPrevPaperSize( GetPaperSize() ); if ( GetStatus().AutoPageWidth() ) - aPaperSize.setWidth( !IsEffectivelyVertical() ? CalcTextWidth( true ) : GetTextHeight() ); + maPaperSize.setWidth( !IsEffectivelyVertical() ? CalcTextWidth( true ) : GetTextHeight() ); if ( GetStatus().AutoPageHeight() ) - aPaperSize.setHeight( !IsEffectivelyVertical() ? GetTextHeight() : CalcTextWidth( true ) ); + maPaperSize.setHeight( !IsEffectivelyVertical() ? GetTextHeight() : CalcTextWidth( true ) ); - SetValidPaperSize( aPaperSize ); // consider Min, Max + SetValidPaperSize( maPaperSize ); // consider Min, Max - if ( aPaperSize == aPrevPaperSize ) + if ( maPaperSize == aPrevPaperSize ) return; - if ( ( !IsEffectivelyVertical() && ( aPaperSize.Width() != aPrevPaperSize.Width() ) ) - || ( IsEffectivelyVertical() && ( aPaperSize.Height() != aPrevPaperSize.Height() ) ) ) + if ( ( !IsEffectivelyVertical() && ( maPaperSize.Width() != aPrevPaperSize.Width() ) ) + || ( IsEffectivelyVertical() && ( maPaperSize.Height() != aPrevPaperSize.Height() ) ) ) { // If ahead is centered / right or tabs... - aStatus.GetStatusWord() |= !IsEffectivelyVertical() ? EditStatusFlags::TEXTWIDTHCHANGED : EditStatusFlags::TextHeightChanged; + maStatus.GetStatusWord() |= !IsEffectivelyVertical() ? EditStatusFlags::TEXTWIDTHCHANGED : EditStatusFlags::TextHeightChanged; for ( sal_Int32 nPara = 0; nPara < GetParaPortions().Count(); nPara++ ) { // Only paragraphs which are not aligned to the left need to be // reformatted, the height can not be changed here anymore. - ParaPortion& rParaPortion = GetParaPortions()[nPara]; + ParaPortion& rParaPortion = GetParaPortions().getRef(nPara); SvxAdjust eJustification = GetJustification( nPara ); if ( eJustification != SvxAdjust::Left ) { - rParaPortion.MarkSelectionInvalid( 0 ); + rParaPortion.MarkSelectionInvalid(0); CreateLines( nPara, 0 ); // 0: For AutoPageSize no TextRange! } } } - Size aInvSize = aPaperSize; - if ( aPaperSize.Width() < aPrevPaperSize.Width() ) + Size aInvSize = maPaperSize; + if ( maPaperSize.Width() < aPrevPaperSize.Width() ) aInvSize.setWidth( aPrevPaperSize.Width() ); - if ( aPaperSize.Height() < aPrevPaperSize.Height() ) + if ( maPaperSize.Height() < aPrevPaperSize.Height() ) aInvSize.setHeight( aPrevPaperSize.Height() ); Size aSz( aInvSize ); @@ -543,18 +614,18 @@ void ImpEditEngine::CheckAutoPageSize() aSz.setWidth( aInvSize.Height() ); aSz.setHeight( aInvSize.Width() ); } - aInvalidRect = tools::Rectangle( Point(), aSz ); + maInvalidRect = tools::Rectangle( Point(), aSz ); - for (EditView* pView : aEditViews) + for (EditView* pView : maEditViews) { - pView->pImpEditView->RecalcOutputArea(); + pView->getImpl().RecalcOutputArea(); } } void ImpEditEngine::CheckPageOverflow() { - SAL_INFO("editeng.chaining", "[CONTROL_STATUS] AutoPageSize is " << (( aStatus.GetControlWord() & EEControlBits::AUTOPAGESIZE ) ? "ON" : "OFF") ); + SAL_INFO("editeng.chaining", "[CONTROL_STATUS] AutoPageSize is " << (( maStatus.GetControlWord() & EEControlBits::AUTOPAGESIZE ) ? "ON" : "OFF") ); tools::Long nBoxHeight = GetMaxAutoPaperSize().Height(); SAL_INFO("editeng.chaining", "[OVERFLOW-CHECK] Current MaxAutoPaperHeight is " << nBoxHeight); @@ -572,12 +643,12 @@ void ImpEditEngine::CheckPageOverflow() { // which paragraph is the first to cause higher size of the box? ImplUpdateOverflowingParaNum( nBoxHeight); // XXX: currently only for horizontal text - //aStatus.SetPageOverflow(true); + //maStatus.SetPageOverflow(true); mbNeedsChainingHandling = true; } else { // No overflow if within box boundaries - //aStatus.SetPageOverflow(false); + //maStatus.SetPageOverflow(false); mbNeedsChainingHandling = false; } @@ -585,7 +656,8 @@ void ImpEditEngine::CheckPageOverflow() static sal_Int32 ImplCalculateFontIndependentLineSpacing( const sal_Int32 nFontHeight ) { - return ( nFontHeight * 12 ) / 10; // + 20% + constexpr const double f120Percent = 12.0 / 10.0; + return basegfx::fround(nFontHeight * f120Percent); // + 20% } tools::Long ImpEditEngine::GetColumnWidth(const Size& rPaperSize) const @@ -595,46 +667,82 @@ tools::Long ImpEditEngine::GetColumnWidth(const Size& rPaperSize) const return (nWidth - mnColumnSpacing * (mnColumns - 1)) / mnColumns; } +bool ImpEditEngine::createLinesForEmptyParagraph(ParaPortion& rParaPortion) +{ + // fast special treatment... + if (rParaPortion.GetTextPortions().Count()) + rParaPortion.GetTextPortions().Reset(); + if (rParaPortion.GetLines().Count()) + rParaPortion.GetLines().Reset(); + + CreateAndInsertEmptyLine(rParaPortion); + return FinishCreateLines(rParaPortion); +} + +tools::Long ImpEditEngine::calculateMaxLineWidth(tools::Long nStartX, SvxLRSpaceItem const& rLRItem) +{ + const bool bAutoSize = IsEffectivelyVertical() ? maStatus.AutoPageHeight() : maStatus.AutoPageWidth(); + tools::Long nMaxLineWidth = GetColumnWidth(bAutoSize ? maMaxAutoPaperSize : maPaperSize); + + nMaxLineWidth -= scaleXSpacingValue(rLRItem.GetRight()); + nMaxLineWidth -= nStartX; + + // If PaperSize == long_max, one cannot take away any negative + // first line indent. (Overflow) + if (nMaxLineWidth < 0 && nStartX < 0) + nMaxLineWidth = GetColumnWidth(maPaperSize) - scaleXSpacingValue(rLRItem.GetRight()); + + // If still less than 0, it may be just the right edge. + if (nMaxLineWidth <= 0) + nMaxLineWidth = 1; + + return nMaxLineWidth; +} + bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) { - ParaPortion& rParaPortion = GetParaPortions()[nPara]; + assert(GetParaPortions().exists(nPara) && "Portion paragraph index is not valid"); + ParaPortion& rParaPortion = GetParaPortions().getRef(nPara); // sal_Bool: Changes in the height of paragraph Yes / No - sal_True/sal_False - assert( rParaPortion.GetNode() && "Portion without Node in CreateLines" ); + assert(rParaPortion.GetNode() && "Portion without Node in CreateLines" ); DBG_ASSERT( rParaPortion.IsVisible(), "Invisible paragraphs not formatted!" ); DBG_ASSERT( rParaPortion.IsInvalid(), "CreateLines: Portion not invalid!" ); - bool bProcessingEmptyLine = ( rParaPortion.GetNode()->Len() == 0 ); - bool bEmptyNodeWithPolygon = ( rParaPortion.GetNode()->Len() == 0 ) && GetTextRanger(); + bool bProcessingEmptyLine = rParaPortion.GetNode()->Len() == 0 ; + bool bEmptyNodeWithPolygon = rParaPortion.GetNode()->Len() == 0 && GetTextRanger(); // Fast special treatment for empty paragraphs... - - if ( ( rParaPortion.GetNode()->Len() == 0 ) && !GetTextRanger() ) + bool bEmptyParagraph = rParaPortion.GetNode()->Len() == 0 && !GetTextRanger(); + if (bEmptyParagraph) + return createLinesForEmptyParagraph(rParaPortion); + + sal_Int64 nCurrentPosY = nStartPosY; + // If we're allowed to skip parts outside and this cannot possibly fit in the given height, + // bail out to avoid possibly formatting a lot of text that will not be used. For the first + // paragraph still format at least a bit. + if( mbSkipOutsideFormat && nPara != 0 + && !maStatus.AutoPageHeight() && maPaperSize.Height() < nCurrentPosY ) { - // fast special treatment... - if ( rParaPortion.GetTextPortions().Count() ) - rParaPortion.GetTextPortions().Reset(); - if ( rParaPortion.GetLines().Count() ) - rParaPortion.GetLines().Reset(); - CreateAndInsertEmptyLine( &rParaPortion ); - return FinishCreateLines( &rParaPortion ); + return false; } + //If the paragraph SvxFrameDirection is Stacked, use STACKED + const SvxFrameDirectionItem* pFrameDirItem = &GetParaAttrib(nPara, EE_PARA_WRITINGDIR); + bool bStacked = pFrameDirItem->GetValue() == SvxFrameDirection::Stacked; + if (bStacked) + maStatus.TurnOnFlags(EEControlBits::STACKED); + else + maStatus.TurnOffFlags(EEControlBits::STACKED); // Initialization... - - // Always format for 100%: - bool bMapChanged = ImpCheckRefMapMode(); - - if ( rParaPortion.GetLines().Count() == 0 ) + if (rParaPortion.GetLines().Count() == 0) { - EditLine* pL = new EditLine; - rParaPortion.GetLines().Append(pL); + rParaPortion.GetLines().Append(std::make_unique<EditLine>()); } - // Get Paragraph attributes... ContentNode* const pNode = rParaPortion.GetNode(); @@ -655,27 +763,28 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) const sal_Int32 nInvalidEnd = nInvalidStart + std::abs( nInvalidDiff ); bool bQuickFormat = false; - if ( !bEmptyNodeWithPolygon && !HasScriptType( nPara, i18n::ScriptType::COMPLEX ) ) + + // Determine if quick format should be used + if (!bEmptyNodeWithPolygon && !HasScriptType(nPara, i18n::ScriptType::COMPLEX)) { - if ( ( rParaPortion.IsSimpleInvalid() ) && ( nInvalidDiff > 0 ) && - ( pNode->GetString().indexOf( CH_FEATURE, nInvalidStart ) > nInvalidEnd ) ) + if (rParaPortion.IsSimpleInvalid() && + rParaPortion.GetInvalidDiff() > 0 && + pNode->GetString().indexOf(CH_FEATURE, nInvalidStart) > nInvalidEnd) { bQuickFormat = true; } - else if ( ( rParaPortion.IsSimpleInvalid() ) && ( nInvalidDiff < 0 ) ) + else if (rParaPortion.IsSimpleInvalid() && nInvalidDiff < 0) { // check if delete over the portion boundaries was done... sal_Int32 nStart = nInvalidStart; // DOUBLE !!!!!!!!!!!!!!! sal_Int32 nEnd = nStart - nInvalidDiff; // negative bQuickFormat = true; sal_Int32 nPos = 0; - sal_Int32 nPortions = rParaPortion.GetTextPortions().Count(); - for ( sal_Int32 nTP = 0; nTP < nPortions; nTP++ ) + for (auto const& pTextPortion : rParaPortion.GetTextPortions()) { // There must be no start / end in the deleted area. - const TextPortion& rTP = rParaPortion.GetTextPortions()[ nTP ]; - nPos = nPos + rTP.GetLen(); - if ( ( nPos > nStart ) && ( nPos < nEnd ) ) + nPos = nPos + pTextPortion->GetLen(); + if (nPos > nStart && nPos < nEnd) { bQuickFormat = false; break; @@ -691,7 +800,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) sal_Int32 nRealInvalidStart = nInvalidStart; - if ( bEmptyNodeWithPolygon ) + if (bEmptyNodeWithPolygon) { TextPortion* pDummyPortion = new TextPortion( 0 ); rParaPortion.GetTextPortions().Reset(); @@ -700,14 +809,13 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) else if ( bQuickFormat ) { // faster Method: - RecalcTextPortion( &rParaPortion, nInvalidStart, nInvalidDiff ); + RecalcTextPortion(rParaPortion, nInvalidStart, nInvalidDiff); } else // nRealInvalidStart can be before InvalidStart, since Portions were deleted... { - CreateTextPortions( &rParaPortion, nRealInvalidStart ); + CreateTextPortions(rParaPortion, nRealInvalidStart); } - // Search for line with InvalidPos, start one line before // Flag the line => do not remove it ! @@ -725,35 +833,38 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) } // Begin one line before... // If it is typed at the end, the line in front cannot change. - if ( nLine && ( !rParaPortion.IsSimpleInvalid() || ( nInvalidEnd < pNode->Len() ) || ( nInvalidDiff <= 0 ) ) ) + if (nLine && (!rParaPortion.IsSimpleInvalid() || + (nInvalidEnd < pNode->Len()) || + (nInvalidDiff <= 0))) + { nLine--; + } - EditLine* pLine = &rParaPortion.GetLines()[nLine]; + tools::Rectangle aBulletArea{Point(), Point()}; - static const tools::Rectangle aZeroArea { Point(), Point() }; - tools::Rectangle aBulletArea( aZeroArea ); - if ( !nLine ) + if (!nLine) { - aBulletArea = GetEditEnginePtr()->GetBulletArea( GetParaPortions().GetPos( &rParaPortion ) ); + aBulletArea = GetEditEnginePtr()->GetBulletArea(GetParaPortions().GetPos(&rParaPortion)); if ( !aBulletArea.IsWidthEmpty() && aBulletArea.Right() > 0 ) - rParaPortion.SetBulletX( static_cast<sal_Int32>(GetXValue( aBulletArea.Right() )) ); + rParaPortion.SetBulletX(sal_Int32(scaleXSpacingValue(aBulletArea.Right()))); else rParaPortion.SetBulletX( 0 ); // if Bullet is set incorrectly } - // Reformat all lines from here... + int nStartNextLineAfterMultiLineField = 0; + sal_Int32 nDelFromLine = -1; bool bLineBreak = false; + EditLine* pLine = &rParaPortion.GetLines()[nLine]; sal_Int32 nIndex = pLine->GetStart(); EditLine aSaveLine( *pLine ); - SvxFont aTmpFont( pNode->GetCharAttribs().GetDefFont() ); - ImplInitLayoutMode(*GetRefDevice(), nPara, nIndex); + SvxFont aTmpFont( pNode->GetCharAttribs().GetDefFont() ); - std::vector<sal_Int32> aBuf( pNode->Len() ); + KernArray aCharPositionArray; bool bSameLineAgain = false; // For TextRanger, if the height changes. TabInfo aCurrentTab; @@ -763,39 +874,33 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) while ( ( nIndex < pNode->Len() ) || bForceOneRun ) { + assert(pLine); + bForceOneRun = false; + bool bFieldStartNextLine = false; bool bEOL = false; bool bEOC = false; sal_Int32 nPortionStart = 0; sal_Int32 nPortionEnd = 0; - tools::Long nStartX = GetXValue( rLRItem.GetTextLeft() + nSpaceBeforeAndMinLabelWidth ); + tools::Long nStartX = scaleXSpacingValue(rLRItem.GetTextLeft() + nSpaceBeforeAndMinLabelWidth); + // Multiline hyperlink may need to know if the next line is bigger. + tools::Long nStartXNextLine = nStartX; if ( nIndex == 0 ) { - tools::Long nFI = GetXValue( rLRItem.GetTextFirstLineOffset() ); + tools::Long nFI = scaleXSpacingValue(rLRItem.GetTextFirstLineOffset()); nStartX += nFI; - if ( !nLine && ( rParaPortion.GetBulletX() > nStartX ) ) + if (!nLine && rParaPortion.GetBulletX() > nStartX) { - nStartX = rParaPortion.GetBulletX(); + nStartX = rParaPortion.GetBulletX(); } } - const bool bAutoSize = IsEffectivelyVertical() ? aStatus.AutoPageHeight() : aStatus.AutoPageWidth(); - tools::Long nMaxLineWidth = GetColumnWidth(bAutoSize ? aMaxAutoPaperSize : aPaperSize); - - nMaxLineWidth -= GetXValue( rLRItem.GetRight() ); - nMaxLineWidth -= nStartX; - - // If PaperSize == long_max, one cannot take away any negative - // first line indent. (Overflow) - if ( ( nMaxLineWidth < 0 ) && ( nStartX < 0 ) ) - nMaxLineWidth = GetColumnWidth(aPaperSize) - GetXValue(rLRItem.GetRight()); - - // If still less than 0, it may be just the right edge. - if ( nMaxLineWidth <= 0 ) - nMaxLineWidth = 1; + nStartX += nStartNextLineAfterMultiLineField; + nStartNextLineAfterMultiLineField = 0; + tools::Long nMaxLineWidth = calculateMaxLineWidth(nStartX, rLRItem); // Problem: // Since formatting starts a line _before_ the invalid position, @@ -818,7 +923,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) { GetTextRanger()->SetVertical( IsEffectivelyVertical() ); - tools::Long nTextY = nStartPosY + GetEditCursor( &rParaPortion, pLine, pLine->GetStart(), GetCursorFlags::NONE ).Top(); + tools::Long nTextY = nStartPosY + GetEditCursor(rParaPortion, *pLine, pLine->GetStart(), CursorFlags()).Top(); if ( !bSameLineAgain ) { SeekCursor( pNode, nTmpPos+1, aTmpFont ); @@ -871,7 +976,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) } nXWidth = nMaxRangeWidth; if ( nXWidth ) - nMaxLineWidth = nXWidth - nStartX - GetXValue( rLRItem.GetRight() ); + nMaxLineWidth = nXWidth - nStartX - scaleXSpacingValue(rLRItem.GetRight()); else { // Try further down in the polygon. @@ -929,10 +1034,10 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) nTmpWidth -= rPrev.GetSize().Width(); nTmpPos = nTmpPos - rPrev.GetLen(); rPrev.SetLen(rPrev.GetLen() + nTmpLen); - rPrev.GetSize().setWidth( -1 ); + rPrev.setWidth(-1); } - assert( nTmpPortion < rParaPortion.GetTextPortions().Count() && "No more Portions left!" ); + assert(nTmpPortion < rParaPortion.GetTextPortions().Count() && "No more Portions left!"); pPortion = &rParaPortion.GetTextPortions()[nTmpPortion]; } @@ -961,14 +1066,15 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) tools::Long nOldTmpWidth = nTmpWidth; // Search for Tab-Pos... - tools::Long nCurPos = nTmpWidth+nStartX; + tools::Long nCurPos = nTmpWidth + nStartX; // consider scaling - if ( aStatus.DoStretch() && ( nStretchX != 100 ) ) - nCurPos = nCurPos*100/std::max(static_cast<sal_Int32>(nStretchX), static_cast<sal_Int32>(1)); + double fFontScalingX = maScalingParameters.fFontX; + if (maStatus.DoStretch() && (fFontScalingX != 1.0)) + nCurPos = basegfx::fround<tools::Long>(double(nCurPos) / std::max(fFontScalingX, 0.01)); - short nAllSpaceBeforeText = static_cast< short >(rLRItem.GetTextLeft()/* + rLRItem.GetTextLeft()*/ + nSpaceBeforeAndMinLabelWidth); - aCurrentTab.aTabStop = pNode->GetContentAttribs().FindTabStop( nCurPos - nAllSpaceBeforeText /*rLRItem.GetTextLeft()*/, aEditDoc.GetDefTab() ); - aCurrentTab.nTabPos = GetXValue( static_cast<tools::Long>( aCurrentTab.aTabStop.GetTabPos() + nAllSpaceBeforeText /*rLRItem.GetTextLeft()*/ ) ); + short nAllSpaceBeforeText = short(rLRItem.GetTextLeft()); + aCurrentTab.aTabStop = pNode->GetContentAttribs().FindTabStop( nCurPos - nAllSpaceBeforeText , maEditDoc.GetDefTab() ); + aCurrentTab.nTabPos = tools::Long(aCurrentTab.aTabStop.GetTabPos() + nAllSpaceBeforeText); aCurrentTab.bValid = false; // Switch direction in R2L para... @@ -990,25 +1096,28 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) aCurrentTab.nTabPortion = nTmpPortion; } + if (nMaxLineWidth < aCurrentTab.nTabPos && nTmpWidth != nMaxLineWidth - 1) + aCurrentTab.nTabPos = nMaxLineWidth - 1; + pPortion->SetKind(PortionKind::TAB); pPortion->SetExtraValue( aCurrentTab.aTabStop.GetFill() ); - pPortion->GetSize().setWidth( aCurrentTab.nTabPos - (nTmpWidth+nStartX) ); + pPortion->setWidth( aCurrentTab.nTabPos - (nTmpWidth+nStartX) ); // Height needed... SeekCursor( pNode, nTmpPos+1, aTmpFont ); - pPortion->GetSize().setHeight( aTmpFont.QuickGetTextSize( GetRefDevice(), OUString(), 0, 0 ).Height() ); + pPortion->setHeight( GetRefDevice()->GetTextHeight() ); DBG_ASSERT( pPortion->GetSize().Width() >= 0, "Tab incorrectly calculated!" ); nTmpWidth = aCurrentTab.nTabPos-nStartX; // If this is the first token on the line, - // and nTmpWidth > aPaperSize.Width, => infinite loop! + // and nTmpWidth > maPaperSize.Width, => infinite loop! if ( ( nTmpWidth >= nXWidth ) && ( nTmpPortion == pLine->GetStartPortion() ) ) { // What now? // make the tab fitting - pPortion->GetSize().setWidth( nXWidth-nOldTmpWidth ); + pPortion->setWidth( nXWidth-nOldTmpWidth ); nTmpWidth = nXWidth-1; bEOL = true; bBrokenLine = true; @@ -1022,7 +1131,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) case EE_FEATURE_LINEBR: { assert( pPortion ); - pPortion->GetSize().setWidth( 0 ); + pPortion->setWidth(0); bEOL = true; bLineBreak = true; pPortion->SetKind( PortionKind::LINEBREAK ); @@ -1040,11 +1149,12 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) OUString aFieldValue = static_cast<const EditCharAttribField*>(pNextFeature)->GetFieldValue(); // get size, but also DXArray to allow length information in line breaking below - std::vector<sal_Int32> aTmpDXArray; - pPortion->GetSize() = aTmpFont.QuickGetTextSize(GetRefDevice(), aFieldValue, 0, aFieldValue.getLength(), &aTmpDXArray); + KernArray aTmpDXArray; + pPortion->SetSize(aTmpFont.QuickGetTextSize(GetRefDevice(), + aFieldValue, 0, aFieldValue.getLength(), &aTmpDXArray)); // So no scrolling for oversized fields - if ( pPortion->GetSize().Width() > nXWidth ) + if (pPortion->GetSize().Width() > nXWidth - nTmpWidth) { // create ExtraPortionInfo on-demand, flush lineBreaksList ExtraPortionInfo *pExtraInfo = pPortion->GetExtraInfos(); @@ -1076,6 +1186,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) nDone)); sal_Int32 nLastCellBreak(0); sal_Int32 nLineStartX(0); + nLineStartX = -nTmpWidth; // always add 1st line break (safe, we already know we are larger than nXWidth) pExtraInfo->lineBreaksList.push_back(0); @@ -1093,6 +1204,22 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) if(0 != a) { pExtraInfo->lineBreaksList.push_back(a); + // the following lines may be different sized + if (nStartX > nStartXNextLine) + { + nXWidth += nStartX - nStartXNextLine; + pLine->SetNextLinePosXDiff(nStartX + - nStartXNextLine); + nStartXNextLine = nStartX; + } + } + else + { + //even the 1. char does not fit.. + //this means the field should start on next line + //except if the actual line is a full line already + if (nLineStartX < 0 || nStartX > nStartXNextLine) + bFieldStartNextLine = true; } // moveLineStart forward in X @@ -1110,6 +1237,17 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) nDone); } } + //next Line should start here... after this field end + if (!bFieldStartNextLine) + nStartNextLineAfterMultiLineField + = aTmpDXArray[nTextLength - 1] - nLineStartX; + else if (pExtraInfo) + { + // if the 1. character does not fit, + // but there is pExtraInfo, then delete it + pPortion->SetExtraInfos(nullptr); + pExtraInfo = nullptr; + } } nTmpWidth += pPortion->GetSize().Width(); EditLine::CharPosArrayType& rArray = pLine->GetCharPosArray(); @@ -1117,7 +1255,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) rArray.insert(rArray.begin()+nPos, pPortion->GetSize().Width()); pPortion->SetKind(PortionKind::FIELD); // If this is the first token on the line, - // and nTmpWidth > aPaperSize.Width, => infinite loop! + // and nTmpWidth > maPaperSize.Width, => infinite loop! if ( ( nTmpWidth >= nXWidth ) && ( nTmpPortion == pLine->GetStartPortion() ) ) { nTmpWidth = nXWidth-1; @@ -1145,28 +1283,31 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) if (bContinueLastPortion) { - Size aSize( aTmpFont.QuickGetTextSize( GetRefDevice(), - rParaPortion.GetNode()->GetString(), nTmpPos, nPortionLen, &aBuf )); - pPortion->GetSize().AdjustWidth(aSize.Width() ); + Size aSize = aTmpFont.QuickGetTextSize( GetRefDevice(), rParaPortion.GetNode()->GetString(), nTmpPos, nPortionLen, &aCharPositionArray, bStacked); + pPortion->adjustSize(aSize.Width(), 0); if (pPortion->GetSize().Height() < aSize.Height()) - pPortion->GetSize().setHeight( aSize.Height() ); + pPortion->setHeight(aSize.Height()); } else { - pPortion->GetSize() = aTmpFont.QuickGetTextSize( GetRefDevice(), - rParaPortion.GetNode()->GetString(), nTmpPos, nPortionLen, &aBuf ); + Size aSize = aTmpFont.QuickGetTextSize(GetRefDevice(), rParaPortion.GetNode()->GetString(), nTmpPos, nPortionLen, &aCharPositionArray, bStacked); + pPortion->SetSize(aSize); } // #i9050# Do Kerning also behind portions... if ( ( aTmpFont.GetFixKerning() > 0 ) && ( ( nTmpPos + nPortionLen ) < pNode->Len() ) ) - pPortion->GetSize().AdjustWidth(aTmpFont.GetFixKerning() ); + pPortion->adjustSize(aTmpFont.GetFixKerning(), 0); if ( IsFixedCellHeight() ) - pPortion->GetSize().setHeight( ImplCalculateFontIndependentLineSpacing( aTmpFont.GetFontHeight() ) ); + { + pPortion->setHeight( ImplCalculateFontIndependentLineSpacing( aTmpFont.GetFontHeight() ) ); + } // The array is generally flattened at the beginning // => Always simply quick inserts. size_t nPos = nTmpPos - pLine->GetStart(); EditLine::CharPosArrayType& rArray = pLine->GetCharPosArray(); - rArray.insert( rArray.begin() + nPos, aBuf.data(), aBuf.data() + nPortionLen); + assert(aCharPositionArray.get_factor() == 1); + std::vector<sal_Int32>& rKernArray = aCharPositionArray.get_subunit_array(); + rArray.insert( rArray.begin() + nPos, rKernArray.data(), rKernArray.data() + nPortionLen); // And now check for Compression: if ( !bContinueLastPortion && nPortionLen && GetAsianCompressionMode() != CharCompressType::NONE ) @@ -1190,9 +1331,9 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) // No spacing within L2R/R2L nesting if ( bAllow ) { - tools::Long nExtraSpace = pPortion->GetSize().Height()/5; - nExtraSpace = GetXValue( nExtraSpace ); - pPortion->GetSize().AdjustWidth(nExtraSpace ); + tools::Long nExtraSpace = pPortion->GetSize().Height() / 5; + nExtraSpace = scaleXSpacingValue(nExtraSpace); + pPortion->adjustSize(nExtraSpace, 0); nTmpWidth += nExtraSpace; } } @@ -1203,12 +1344,13 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) tools::Long nWidthAfterTab = 0; for ( sal_Int32 n = aCurrentTab.nTabPortion+1; n <= nTmpPortion; n++ ) { - const TextPortion& rTP = rParaPortion.GetTextPortions()[n]; - nWidthAfterTab += rTP.GetSize().Width(); + const TextPortion& rTextPortion = rParaPortion.GetTextPortions()[n]; + nWidthAfterTab += rTextPortion.GetSize().Width(); } tools::Long nW = nWidthAfterTab; // Length before tab position if ( aCurrentTab.aTabStop.GetAdjustment() == SvxTabAdjust::Right ) { + // Do nothing } else if ( aCurrentTab.aTabStop.GetAdjustment() == SvxTabAdjust::Center ) { @@ -1216,13 +1358,16 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) } else if ( aCurrentTab.aTabStop.GetAdjustment() == SvxTabAdjust::Decimal ) { - OUString aText = GetSelected( EditSelection( EditPaM( rParaPortion.GetNode(), nTmpPos ), - EditPaM( rParaPortion.GetNode(), nTmpPos + nPortionLen ) ) ); + EditPaM aSelectionStart(rParaPortion.GetNode(), nTmpPos); + EditPaM aSelectionEnd(rParaPortion.GetNode(), nTmpPos + nPortionLen); + EditSelection aSelection(aSelectionStart, aSelectionEnd); + OUString aText = GetSelected(aSelection); + sal_Int32 nDecPos = aText.indexOf( aCurrentTab.aTabStop.GetDecimal() ); if ( nDecPos != -1 ) { nW -= rParaPortion.GetTextPortions()[nTmpPortion].GetSize().Width(); - nW += aTmpFont.QuickGetTextSize( GetRefDevice(), rParaPortion.GetNode()->GetString(), nTmpPos, nDecPos ).Width(); + nW += aTmpFont.QuickGetTextSize(GetRefDevice(), rParaPortion.GetNode()->GetString(), nTmpPos, nDecPos, nullptr).Width(); aCurrentTab.bValid = false; } } @@ -1237,14 +1382,14 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) aCurrentTab.bValid = false; } TextPortion& rTabPortion = rParaPortion.GetTextPortions()[aCurrentTab.nTabPortion]; - rTabPortion.GetSize().setWidth( aCurrentTab.nTabPos - aCurrentTab.nStartPosX - nW - nStartX ); + rTabPortion.setWidth( aCurrentTab.nTabPos - aCurrentTab.nStartPosX - nW - nStartX ); nTmpWidth = aCurrentTab.nStartPosX + rTabPortion.GetSize().Width() + nWidthAfterTab; } nTmpPos = nTmpPos + nPortionLen; nPortionEnd = nTmpPos; nTmpPortion++; - if ( aStatus.OneCharPerLine() ) + if (maStatus.OneCharPerLine()) bEOL = true; } @@ -1256,7 +1401,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) // this was possibly a portion too far: bool bFixedEnd = false; - if ( aStatus.OneCharPerLine() ) + if (maStatus.OneCharPerLine()) { // State before Portion (apart from nTmpWidth): nTmpPos -= pPortion ? nPortionLen : 0; @@ -1275,7 +1420,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) { DBG_ASSERT( pPortion->GetKind() == PortionKind::TEXT, "Len>1, but no TextPortion?" ); nTmpWidth -= pPortion->GetSize().Width(); - sal_Int32 nP = SplitTextPortion( &rParaPortion, nTmpPos, pLine ); + sal_Int32 nP = SplitTextPortion(rParaPortion, nTmpPos, pLine); nTmpWidth += rParaPortion.GetTextPortions()[nP].GetSize().Width(); } } @@ -1316,30 +1461,47 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) bEOL = true; bEOC = true; pLine->SetEnd( nPortionEnd ); - assert( rParaPortion.GetTextPortions().Count() && "No TextPortions?" ); - pLine->SetEndPortion( rParaPortion.GetTextPortions().Count() - 1 ); + assert(rParaPortion.GetTextPortions().Count() && "No TextPortions?"); + pLine->SetEndPortion(rParaPortion.GetTextPortions().Count() - 1); } - if ( aStatus.OneCharPerLine() ) + if (maStatus.OneCharPerLine()) { pLine->SetEnd( nPortionEnd ); pLine->SetEndPortion( nTmpPortion-1 ); } else if ( bFixedEnd ) { - pLine->SetEnd( nPortionStart ); - pLine->SetEndPortion( nTmpPortion-1 ); + if (bFieldStartNextLine) + { + pLine->SetEnd(nPortionStart); + pLine->SetEndPortion(nTmpPortion - 1); + } + else + { + pLine->SetEnd(nPortionStart + 1); + pLine->SetEndPortion(nTmpPortion); + } } else if ( bLineBreak || bBrokenLine ) { - pLine->SetEnd( nPortionStart+1 ); - pLine->SetEndPortion( nTmpPortion-1 ); + if (bFieldStartNextLine) + { + pLine->SetEnd(nPortionStart); + pLine->SetEndPortion(nTmpPortion - 2); + } + else + { + pLine->SetEnd(nPortionStart + 1); + pLine->SetEndPortion(nTmpPortion - 1); + } bEOC = false; // was set above, maybe change the sequence of the if's? } else if ( !bEOL && !bContinueLastPortion ) { DBG_ASSERT( pPortion && ((nPortionEnd-nPortionStart) == pPortion->GetLen()), "However, another portion?!" ); - tools::Long nRemainingWidth = nMaxLineWidth - nTmpWidth; + tools::Long nRemainingWidth = !maStatus.IsSingleLine() ? + nMaxLineWidth - nTmpWidth : pLine->GetCharPosArray()[pLine->GetCharPosArray().size() - 1] + 1; bool bCanHyphenate = ( aTmpFont.GetCharSet() != RTL_TEXTENCODING_SYMBOL ); if ( bCompressedChars && pPortion && ( pPortion->GetLen() > 1 ) && pPortion->GetExtraInfos() && pPortion->GetExtraInfos()->bCompressed ) { @@ -1349,8 +1511,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) pNode, pPortion, nPortionStart, pDXArray, 10000, true); } if( pPortion ) - ImpBreakLine( &rParaPortion, pLine, pPortion, nPortionStart, - nRemainingWidth, bCanHyphenate && bHyphenatePara ); + ImpBreakLine(rParaPortion, *pLine, pPortion, nPortionStart, nRemainingWidth, bCanHyphenate && bHyphenatePara); } @@ -1358,18 +1519,18 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) // CalcTextSize should be replaced by a continuous registering! - Size aTextSize = pLine->CalcTextSize( rParaPortion ); + Size aTextSize = pLine->CalcTextSize(rParaPortion); if ( aTextSize.Height() == 0 ) { SeekCursor( pNode, pLine->GetStart()+1, aTmpFont ); - aTmpFont.SetPhysFont(*pRefDev); - ImplInitDigitMode(*pRefDev, aTmpFont.GetLanguage()); + aTmpFont.SetPhysFont(*mpRefDev); + ImplInitDigitMode(*mpRefDev, aTmpFont.GetLanguage()); if ( IsFixedCellHeight() ) aTextSize.setHeight( ImplCalculateFontIndependentLineSpacing( aTmpFont.GetFontHeight() ) ); else - aTextSize.setHeight( aTmpFont.GetPhysTxtSize( pRefDev ).Height() ); + aTextSize.setHeight( aTmpFont.GetPhysTxtSize(mpRefDev).Height() ); pLine->SetHeight( static_cast<sal_uInt16>(aTextSize.Height()) ); } @@ -1403,12 +1564,13 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) bSameLineAgain = true; } - - if ( !bSameLineAgain && !aStatus.IsOutliner() ) + if (!bSameLineAgain && !maStatus.IsOutliner()) { if ( rLSItem.GetLineSpaceRule() == SvxLineSpaceRule::Min ) { - sal_uInt16 nMinHeight = GetYValue( rLSItem.GetLineHeight() ); + double fMinHeight = scaleYSpacingValue(rLSItem.GetLineHeight()); + sal_uInt16 nMinHeight = basegfx::fround(fMinHeight); + sal_uInt16 nTxtHeight = pLine->GetHeight(); if ( nTxtHeight < nMinHeight ) { @@ -1420,7 +1582,9 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) } else if ( rLSItem.GetLineSpaceRule() == SvxLineSpaceRule::Fix ) { - sal_uInt16 nFixHeight = GetYValue( rLSItem.GetLineHeight() ); + double fFixHeight = scaleYSpacingValue(rLSItem.GetLineHeight()); + sal_uInt16 nFixHeight = basegfx::fround(fFixHeight); + sal_uInt16 nTxtHeight = pLine->GetHeight(); pLine->SetMaxAscent( static_cast<sal_uInt16>(pLine->GetMaxAscent() + ( nFixHeight - nTxtHeight ) ) ); pLine->SetHeight( nFixHeight, nTxtHeight ); @@ -1429,40 +1593,61 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) { // There are documents with PropLineSpace 0, why? // (cmc: re above question :-) such documents can be seen by importing a .ppt - if ( rLSItem.GetPropLineSpace() && ( rLSItem.GetPropLineSpace() < 100 ) ) + sal_uInt16 nPropLineSpace = rLSItem.GetPropLineSpace(); + double fProportionalScale = double(nPropLineSpace) / 100.0; + constexpr const double f80Percent = 8.0 / 10.0; + double fSpacingFactor = maScalingParameters.fSpacingY; + if (nPropLineSpace && nPropLineSpace < 100) { // Adapted code from sw/source/core/text/itrform2.cxx - sal_uInt16 nPropLineSpace = rLSItem.GetPropLineSpace(); sal_uInt16 nAscent = pLine->GetMaxAscent(); - sal_uInt16 nNewAscent = pLine->GetTxtHeight() * nPropLineSpace / 100 * 4 / 5; // 80% - if ( !nAscent || nAscent > nNewAscent ) - { - pLine->SetMaxAscent( nNewAscent ); - } - sal_uInt16 nHeight = pLine->GetHeight() * nPropLineSpace / 100; - pLine->SetHeight( nHeight, pLine->GetTxtHeight() ); + sal_uInt16 nNewAscent = basegfx::fround(pLine->GetTxtHeight() * fSpacingFactor * fProportionalScale * f80Percent); + if (!nAscent || nAscent > nNewAscent) + pLine->SetMaxAscent(nNewAscent); + sal_uInt16 nHeight = basegfx::fround(pLine->GetHeight() * fProportionalScale * fSpacingFactor); + + pLine->SetHeight(nHeight, pLine->GetTxtHeight()); } - else if ( rLSItem.GetPropLineSpace() && ( rLSItem.GetPropLineSpace() != 100 ) ) + else if (nPropLineSpace && nPropLineSpace != 100) { sal_uInt16 nTxtHeight = pLine->GetHeight(); - sal_Int32 nPropTextHeight = nTxtHeight * rLSItem.GetPropLineSpace() / 100; + sal_Int32 nPropTextHeight = nTxtHeight * fProportionalScale * fSpacingFactor; // The Ascent has to be adjusted for the difference: tools::Long nDiff = pLine->GetHeight() - nPropTextHeight; pLine->SetMaxAscent( static_cast<sal_uInt16>( pLine->GetMaxAscent() - nDiff ) ); pLine->SetHeight( static_cast<sal_uInt16>( nPropTextHeight ), nTxtHeight ); } } + else if (rLSItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Off) + { + if (maScalingParameters.fSpacingY < 1.0) + { + double fSpacingFactor = maScalingParameters.fSpacingY; + sal_uInt16 nPropLineSpace = basegfx::fround(100.0 * fSpacingFactor); + if (nPropLineSpace && nPropLineSpace < 100) + { + // Adapted code from sw/source/core/text/itrform2.cxx + sal_uInt16 nAscent = pLine->GetMaxAscent(); + sal_uInt16 nNewAscent = basegfx::fround(pLine->GetTxtHeight() * fSpacingFactor); + if (!nAscent || nAscent > nNewAscent) + pLine->SetMaxAscent(nNewAscent); + sal_uInt16 nHeight = basegfx::fround(pLine->GetHeight() * fSpacingFactor); + + pLine->SetHeight(nHeight, pLine->GetTxtHeight()); + } + + } + } } - if ( ( !IsEffectivelyVertical() && aStatus.AutoPageWidth() ) || - ( IsEffectivelyVertical() && aStatus.AutoPageHeight() ) ) + if ( ( !IsEffectivelyVertical() && maStatus.AutoPageWidth() ) || + ( IsEffectivelyVertical() && maStatus.AutoPageHeight() ) ) { // If the row fits within the current paper width, then this width // has to be used for the Alignment. If it does not fit or if it // will change the paper width, it will be formatted again for // Justification! = LEFT anyway. - tools::Long nMaxLineWidthFix = GetColumnWidth(aPaperSize) - - GetXValue( rLRItem.GetRight() ) - nStartX; + tools::Long nMaxLineWidthFix = GetColumnWidth(maPaperSize) - scaleXSpacingValue(rLRItem.GetRight()) - nStartX; if ( aTextSize.Width() < nMaxLineWidthFix ) nMaxLineWidth = nMaxLineWidthFix; } @@ -1472,8 +1657,8 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) tools::Long nRemainingWidth = nMaxLineWidth - aTextSize.Width(); if ( nRemainingWidth > 0 ) { - ImplExpandCompressedPortions( pLine, &rParaPortion, nRemainingWidth ); - aTextSize = pLine->CalcTextSize( rParaPortion ); + ImplExpandCompressedPortions(*pLine, rParaPortion, nRemainingWidth); + aTextSize = pLine->CalcTextSize(rParaPortion); } } @@ -1485,8 +1670,11 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) TextPortion& rTP = rParaPortion.GetTextPortions()[pLine->GetEndPortion()]; sal_Int32 nPosInArray = pLine->GetEnd()-1-pLine->GetStart(); tools::Long nNewValue = ( nPosInArray ? pLine->GetCharPosArray()[ nPosInArray-1 ] : 0 ) + n; - pLine->GetCharPosArray()[ nPosInArray ] = nNewValue; - rTP.GetSize().AdjustWidth(n ); + if (o3tl::make_unsigned(nPosInArray) < pLine->GetCharPosArray().size()) + { + pLine->GetCharPosArray()[ nPosInArray ] = nNewValue; + } + rTP.adjustSize(n, 0); } pLine->SetTextWidth( aTextSize.Width() ); @@ -1514,7 +1702,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) tools::Long nRemainingSpace = nMaxLineWidth - aTextSize.Width(); pLine->SetStartPosX( nStartX ); if ( nRemainingSpace > 0 && (!bEOC || bDistLastLine) ) - ImpAdjustBlocks( &rParaPortion, pLine, nRemainingSpace ); + ImpAdjustBlocks(rParaPortion, *pLine, nRemainingSpace); } break; default: @@ -1548,7 +1736,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) } // for <0 think over ! - if ( rParaPortion.IsSimpleInvalid() ) + if (rParaPortion.IsSimpleInvalid()) { // Change through simple Text changes... // Do not cancel formatting since Portions possibly have to be split @@ -1601,6 +1789,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) // as nEnd points to the last character! sal_Int32 nEndPortion = pLine->GetEndPortion(); + nCurrentPosY += pLine->GetHeight(); // Next line or maybe a new line... pLine = nullptr; @@ -1611,12 +1800,22 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) nDelFromLine = nLine; break; } + // Stop processing if allowed and this is outside of the paper size height. + // Format at least two lines though, in case something detects whether + // the text has been wrapped or something similar. + if( mbSkipOutsideFormat && nLine > 2 + && !maStatus.AutoPageHeight() && maPaperSize.Height() < nCurrentPosY ) + { + if ( pLine && ( nIndex >= pNode->Len()) ) + nDelFromLine = nLine; + break; + } if ( !pLine ) { if ( nIndex < pNode->Len() ) { pLine = new EditLine; - rParaPortion.GetLines().Insert(++nLine, pLine); + rParaPortion.GetLines().Insert(++nLine, std::unique_ptr<EditLine>(pLine)); } else if ( nIndex && bLineBreak && GetTextRanger() ) { @@ -1625,7 +1824,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) TextPortion* pDummyPortion = new TextPortion( 0 ); rParaPortion.GetTextPortions().Append(pDummyPortion); pLine = new EditLine; - rParaPortion.GetLines().Insert(++nLine, pLine); + rParaPortion.GetLines().Insert(++nLine, std::unique_ptr<EditLine>(pLine)); bForceOneRun = true; bProcessingEmptyLine = true; } @@ -1644,66 +1843,63 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) if ( nDelFromLine >= 0 ) rParaPortion.GetLines().DeleteFromLine( nDelFromLine ); - DBG_ASSERT( rParaPortion.GetLines().Count(), "No line after CreateLines!" ); + DBG_ASSERT(rParaPortion.GetLines().Count(), "No line after CreateLines!"); if ( bLineBreak ) - CreateAndInsertEmptyLine( &rParaPortion ); - - bool bHeightChanged = FinishCreateLines( &rParaPortion ); + CreateAndInsertEmptyLine(rParaPortion); - if ( bMapChanged ) - GetRefDevice()->Pop(); + bool bHeightChanged = FinishCreateLines(rParaPortion); GetRefDevice()->Pop(); return bHeightChanged; } -void ImpEditEngine::CreateAndInsertEmptyLine( ParaPortion* pParaPortion ) +void ImpEditEngine::CreateAndInsertEmptyLine(ParaPortion& rParaPortion) { DBG_ASSERT( !GetTextRanger(), "Don't use CreateAndInsertEmptyLine with a polygon!" ); EditLine* pTmpLine = new EditLine; - pTmpLine->SetStart( pParaPortion->GetNode()->Len() ); - pTmpLine->SetEnd( pParaPortion->GetNode()->Len() ); - pParaPortion->GetLines().Append(pTmpLine); + pTmpLine->SetStart(rParaPortion.GetNode()->Len()); + pTmpLine->SetEnd(rParaPortion.GetNode()->Len()); + rParaPortion.GetLines().Append(std::unique_ptr<EditLine>(pTmpLine)); - bool bLineBreak = pParaPortion->GetNode()->Len() > 0; + bool bLineBreak = rParaPortion.GetNode()->Len() > 0; sal_Int32 nSpaceBefore = 0; - sal_Int32 nSpaceBeforeAndMinLabelWidth = GetSpaceBeforeAndMinLabelWidth( pParaPortion->GetNode(), &nSpaceBefore ); - const SvxLRSpaceItem& rLRItem = GetLRSpaceItem( pParaPortion->GetNode() ); - const SvxLineSpacingItem& rLSItem = pParaPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL ); - tools::Long nStartX = GetXValue( rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset() + nSpaceBefore ); + sal_Int32 nSpaceBeforeAndMinLabelWidth = GetSpaceBeforeAndMinLabelWidth(rParaPortion.GetNode(), &nSpaceBefore); + const SvxLRSpaceItem& rLRItem = GetLRSpaceItem(rParaPortion.GetNode()); + const SvxLineSpacingItem& rLSItem = rParaPortion.GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL ); + tools::Long nStartX = scaleXSpacingValue(rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset() + nSpaceBefore); tools::Rectangle aBulletArea { Point(), Point() }; if ( bLineBreak ) { - nStartX = GetXValue( rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset() + nSpaceBeforeAndMinLabelWidth ); + nStartX = scaleXSpacingValue(rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset() + nSpaceBeforeAndMinLabelWidth); } else { - aBulletArea = GetEditEnginePtr()->GetBulletArea( GetParaPortions().GetPos( pParaPortion ) ); + aBulletArea = GetEditEnginePtr()->GetBulletArea( GetParaPortions().GetPos(&rParaPortion)); if ( !aBulletArea.IsEmpty() && aBulletArea.Right() > 0 ) - pParaPortion->SetBulletX( static_cast<sal_Int32>(GetXValue( aBulletArea.Right() )) ); + rParaPortion.SetBulletX(sal_Int32(scaleXSpacingValue(aBulletArea.Right()))); else - pParaPortion->SetBulletX( 0 ); // If Bullet set incorrectly. - if ( pParaPortion->GetBulletX() > nStartX ) + rParaPortion.SetBulletX( 0 ); // If Bullet set incorrectly. + if (rParaPortion.GetBulletX() > nStartX) { - nStartX = GetXValue( rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset() + nSpaceBeforeAndMinLabelWidth ); - if ( pParaPortion->GetBulletX() > nStartX ) - nStartX = pParaPortion->GetBulletX(); + nStartX = scaleXSpacingValue(rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset() + nSpaceBeforeAndMinLabelWidth); + if (rParaPortion.GetBulletX() > nStartX) + nStartX = rParaPortion.GetBulletX(); } } SvxFont aTmpFont; - SeekCursor( pParaPortion->GetNode(), bLineBreak ? pParaPortion->GetNode()->Len() : 0, aTmpFont ); - aTmpFont.SetPhysFont(*pRefDev); + SeekCursor(rParaPortion.GetNode(), bLineBreak ? rParaPortion.GetNode()->Len() : 0, aTmpFont ); + aTmpFont.SetPhysFont(*mpRefDev); TextPortion* pDummyPortion = new TextPortion( 0 ); - pDummyPortion->GetSize() = aTmpFont.GetPhysTxtSize( pRefDev ); + pDummyPortion->SetSize(aTmpFont.GetPhysTxtSize(mpRefDev)); if ( IsFixedCellHeight() ) - pDummyPortion->GetSize().setHeight( ImplCalculateFontIndependentLineSpacing( aTmpFont.GetFontHeight() ) ); - pParaPortion->GetTextPortions().Append(pDummyPortion); + pDummyPortion->setHeight( ImplCalculateFontIndependentLineSpacing( aTmpFont.GetFontHeight() ) ); + rParaPortion.GetTextPortions().Append(pDummyPortion); FormatterFontMetric aFormatterMetrics; RecalcFormatterFontMetrics( aFormatterMetrics, aTmpFont ); pTmpLine->SetMaxAscent( aFormatterMetrics.nMaxAscent ); @@ -1712,12 +1908,12 @@ void ImpEditEngine::CreateAndInsertEmptyLine( ParaPortion* pParaPortion ) if ( nLineHeight > pTmpLine->GetHeight() ) pTmpLine->SetHeight( nLineHeight ); - if ( !aStatus.IsOutliner() ) + if (!maStatus.IsOutliner()) { - sal_Int32 nPara = GetParaPortions().GetPos( pParaPortion ); + sal_Int32 nPara = GetParaPortions().GetPos(&rParaPortion); SvxAdjust eJustification = GetJustification( nPara ); - tools::Long nMaxLineWidth = GetColumnWidth(aPaperSize); - nMaxLineWidth -= GetXValue( rLRItem.GetRight() ); + tools::Long nMaxLineWidth = GetColumnWidth(maPaperSize); + nMaxLineWidth -= scaleXSpacingValue(rLRItem.GetRight()); if ( nMaxLineWidth < 0 ) nMaxLineWidth = 1; if ( eJustification == SvxAdjust::Center ) @@ -1728,7 +1924,7 @@ void ImpEditEngine::CreateAndInsertEmptyLine( ParaPortion* pParaPortion ) pTmpLine->SetStartPosX( nStartX ); - if ( !aStatus.IsOutliner() ) + if (!maStatus.IsOutliner()) { if ( rLSItem.GetLineSpaceRule() == SvxLineSpaceRule::Min ) { @@ -1752,7 +1948,7 @@ void ImpEditEngine::CreateAndInsertEmptyLine( ParaPortion* pParaPortion ) } else if ( rLSItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop ) { - sal_Int32 nPara = GetParaPortions().GetPos( pParaPortion ); + sal_Int32 nPara = GetParaPortions().GetPos(&rParaPortion); if ( nPara || pTmpLine->GetStartPortion() ) // Not the very first line { // There are documents with PropLineSpace 0, why? @@ -1789,37 +1985,37 @@ void ImpEditEngine::CreateAndInsertEmptyLine( ParaPortion* pParaPortion ) { // -2: The new one is already inserted. #ifdef DBG_UTIL - EditLine& rLastLine = pParaPortion->GetLines()[pParaPortion->GetLines().Count()-2]; - DBG_ASSERT( rLastLine.GetEnd() == pParaPortion->GetNode()->Len(), "different anyway?" ); + EditLine& rLastLine = rParaPortion.GetLines()[rParaPortion.GetLines().Count()-2]; + DBG_ASSERT( rLastLine.GetEnd() == rParaPortion.GetNode()->Len(), "different anyway?" ); #endif - sal_Int32 nPos = pParaPortion->GetTextPortions().Count() - 1 ; + sal_Int32 nPos = rParaPortion.GetTextPortions().Count() - 1 ; pTmpLine->SetStartPortion( nPos ); pTmpLine->SetEndPortion( nPos ); } } -bool ImpEditEngine::FinishCreateLines( ParaPortion* pParaPortion ) +bool ImpEditEngine::FinishCreateLines(ParaPortion& rParaPortion) { // CalcCharPositions( pParaPortion ); - pParaPortion->SetValid(); - tools::Long nOldHeight = pParaPortion->GetHeight(); - CalcHeight( pParaPortion ); + rParaPortion.SetValid(); + tools::Long nOldHeight = rParaPortion.GetHeight(); + CalcHeight(rParaPortion); - DBG_ASSERT( pParaPortion->GetTextPortions().Count(), "FinishCreateLines: No Text-Portion?" ); - bool bRet = ( pParaPortion->GetHeight() != nOldHeight ); + DBG_ASSERT(rParaPortion.GetTextPortions().Count(), "FinishCreateLines: No Text-Portion?"); + bool bRet = rParaPortion.GetHeight() != nOldHeight; return bRet; } -void ImpEditEngine::ImpBreakLine( ParaPortion* pParaPortion, EditLine* pLine, TextPortion const * pPortion, sal_Int32 nPortionStart, tools::Long nRemainingWidth, bool bCanHyphenate ) +void ImpEditEngine::ImpBreakLine(ParaPortion& rParaPortion, EditLine& rLine, TextPortion const * pPortion, sal_Int32 nPortionStart, tools::Long nRemainingWidth, bool bCanHyphenate) { - ContentNode* const pNode = pParaPortion->GetNode(); + ContentNode* const pNode = rParaPortion.GetNode(); - sal_Int32 nBreakInLine = nPortionStart - pLine->GetStart(); + sal_Int32 nBreakInLine = nPortionStart - rLine.GetStart(); sal_Int32 nMax = nBreakInLine + pPortion->GetLen(); - while ( ( nBreakInLine < nMax ) && ( pLine->GetCharPosArray()[nBreakInLine] < nRemainingWidth ) ) + while ( ( nBreakInLine < nMax ) && ( rLine.GetCharPosArray()[nBreakInLine] < nRemainingWidth ) ) nBreakInLine++; - sal_Int32 nMaxBreakPos = nBreakInLine + pLine->GetStart(); + sal_Int32 nMaxBreakPos = nBreakInLine + rLine.GetStart(); sal_Int32 nBreakPos = SAL_MAX_INT32; bool bCompressBlank = false; @@ -1831,7 +2027,7 @@ void ImpEditEngine::ImpBreakLine( ParaPortion* pParaPortion, EditLine* pLine, Te bool bAltFullRight = false; sal_uInt32 nAltDelChar = 0; - if ( ( nMaxBreakPos < ( nMax + pLine->GetStart() ) ) && ( pNode->GetChar( nMaxBreakPos ) == ' ' ) ) + if ( ( nMaxBreakPos < ( nMax + rLine.GetStart() ) ) && ( pNode->GetChar( nMaxBreakPos ) == ' ' ) ) { // Break behind the blank, blank will be compressed... nBreakPos = nMaxBreakPos + 1; @@ -1839,7 +2035,7 @@ void ImpEditEngine::ImpBreakLine( ParaPortion* pParaPortion, EditLine* pLine, Te } else { - sal_Int32 nMinBreakPos = pLine->GetStart(); + sal_Int32 nMinBreakPos = rLine.GetStart(); const CharAttribList::AttribsType& rAttrs = pNode->GetCharAttribs().GetAttribs(); for (size_t nAttr = rAttrs.size(); nAttr; ) { @@ -1877,9 +2073,20 @@ void ImpEditEngine::ImpBreakLine( ParaPortion* pParaPortion, EditLine* pLine, Te aUserOptions.allowPunctuationOutsideMargin = bAllowPunctuationOutsideMargin; aUserOptions.allowHyphenateEnglish = false; - i18n::LineBreakResults aLBR = _xBI->getLineBreak( - pNode->GetString(), nMaxBreakPos, aLocale, nMinBreakPos, aHyphOptions, aUserOptions ); - nBreakPos = aLBR.breakIndex; + if (!maStatus.IsSingleLine()) + { + i18n::LineBreakResults aLBR = _xBI->getLineBreak( + pNode->GetString(), nMaxBreakPos, aLocale, nMinBreakPos, aHyphOptions, aUserOptions ); + nBreakPos = aLBR.breakIndex; + + // show soft hyphen + if ( nBreakPos && CH_SOFTHYPHEN == pNode->GetString()[ sal_Int32(nBreakPos) - 1 ] ) + bHyphenated = true; + } + else + { + nBreakPos = nMaxBreakPos; + } // BUG in I18N - under special condition (break behind field, #87327#) breakIndex is < nMinBreakPos if ( nBreakPos < nMinBreakPos ) @@ -1906,7 +2113,7 @@ void ImpEditEngine::ImpBreakLine( ParaPortion* pParaPortion, EditLine* pLine, Te } bHangingPunctuation = nBreakPos > nMaxBreakPos; - pLine->SetHangingPunctuation( bHangingPunctuation ); + rLine.SetHangingPunctuation( bHangingPunctuation ); // Whether a separator or not, push the word after the separator through // hyphenation... NMaxBreakPos is the last character that fits into @@ -1928,14 +2135,14 @@ void ImpEditEngine::ImpBreakLine( ParaPortion* pParaPortion, EditLine* pLine, Te const OUString aWord = pNode->GetString().copy(nWordStart, nWordLen); sal_Int32 nMinTrail = nWordEnd-nMaxBreakPos+1; //+1: Before the dickey letter Reference< XHyphenatedWord > xHyphWord; - if (xHyphenator.is()) - xHyphWord = xHyphenator->hyphenate( aWord, aLocale, aWord.getLength() - nMinTrail, Sequence< PropertyValue >() ); + if (mxHyphenator.is()) + xHyphWord = mxHyphenator->hyphenate( aWord, aLocale, aWord.getLength() - nMinTrail, Sequence< PropertyValue >() ); if (xHyphWord.is()) { bool bAlternate = xHyphWord->isAlternativeSpelling(); sal_Int32 _nWordLen = 1 + xHyphWord->getHyphenPos(); - if ( ( _nWordLen >= 2 ) && ( (nWordStart+_nWordLen) >= (pLine->GetStart() + 2 ) ) ) + if ( ( _nWordLen >= 2 ) && ( (nWordStart+_nWordLen) >= (rLine.GetStart() + 2 ) ) ) { if ( !bAlternate ) { @@ -1946,8 +2153,8 @@ void ImpEditEngine::ImpBreakLine( ParaPortion* pParaPortion, EditLine* pLine, Te { // TODO: handle all alternative hyphenations (see hyphen-1.2.8/tests/unicode.*) OUString aAlt( xHyphWord->getHyphenatedWord() ); - OUString aAltLeft(aAlt.copy(0, _nWordLen)); - OUString aAltRight(aAlt.copy(_nWordLen)); + std::u16string_view aAltLeft(aAlt.subView(0, _nWordLen)); + std::u16string_view aAltRight(aAlt.subView(_nWordLen)); bAltFullLeft = aWord.startsWith(aAltLeft); bAltFullRight = aWord.endsWith(aAltRight); nAltDelChar = aWord.getLength() - aAlt.getLength() + static_cast<int>(!bAltFullLeft) + static_cast<int>(!bAltFullRight); @@ -2006,39 +2213,42 @@ void ImpEditEngine::ImpBreakLine( ParaPortion* pParaPortion, EditLine* pLine, Te } } - if ( nBreakPos <= pLine->GetStart() ) + if ( nBreakPos <= rLine.GetStart() ) { // No separator in line => Chop! nBreakPos = nMaxBreakPos; // I18N nextCharacters ! - if ( nBreakPos <= pLine->GetStart() ) - nBreakPos = pLine->GetStart() + 1; // Otherwise infinite loop! + if ( nBreakPos <= rLine.GetStart() ) + nBreakPos = rLine.GetStart() + 1; // Otherwise infinite loop! } } // the dickey portion is the end portion - pLine->SetEnd( nBreakPos ); + rLine.SetEnd( nBreakPos ); - sal_Int32 nEndPortion = SplitTextPortion( pParaPortion, nBreakPos, pLine ); + sal_Int32 nEndPortion = SplitTextPortion(rParaPortion, nBreakPos, &rLine); if ( !bCompressBlank && !bHangingPunctuation ) { // When justification is not SvxAdjust::Left, it's important to compress // the trailing space even if there is enough room for the space... // Don't check for SvxAdjust::Left, doesn't matter to compress in this case too... - assert( nBreakPos > pLine->GetStart() && "ImpBreakLines - BreakPos not expected!" ); + assert( nBreakPos > rLine.GetStart() && "ImpBreakLines - BreakPos not expected!" ); if ( pNode->GetChar( nBreakPos-1 ) == ' ' ) bCompressBlank = true; } if ( bCompressBlank || bHangingPunctuation ) { - TextPortion& rTP = pParaPortion->GetTextPortions()[nEndPortion]; + TextPortion& rTP = rParaPortion.GetTextPortions()[nEndPortion]; DBG_ASSERT( rTP.GetKind() == PortionKind::TEXT, "BlankRubber: No TextPortion!" ); - DBG_ASSERT( nBreakPos > pLine->GetStart(), "SplitTextPortion at the beginning of the line?" ); - sal_Int32 nPosInArray = nBreakPos - 1 - pLine->GetStart(); - rTP.GetSize().setWidth( ( nPosInArray && ( rTP.GetLen() > 1 ) ) ? pLine->GetCharPosArray()[ nPosInArray-1 ] : 0 ); - pLine->GetCharPosArray()[ nPosInArray ] = rTP.GetSize().Width(); + DBG_ASSERT( nBreakPos > rLine.GetStart(), "SplitTextPortion at the beginning of the line?" ); + sal_Int32 nPosInArray = nBreakPos - 1 - rLine.GetStart(); + rTP.setWidth( ( nPosInArray && ( rTP.GetLen() > 1 ) ) ? rLine.GetCharPosArray()[ nPosInArray-1 ] : 0 ); + if (o3tl::make_unsigned(nPosInArray) < rLine.GetCharPosArray().size()) + { + rLine.GetCharPosArray()[ nPosInArray ] = rTP.GetSize().Width(); + } } else if ( bHyphenated ) { @@ -2047,51 +2257,55 @@ void ImpEditEngine::ImpBreakLine( ParaPortion* pParaPortion, EditLine* pLine, Te pHyphPortion->SetKind( PortionKind::HYPHENATOR ); if ( (cAlternateReplChar || cAlternateExtraChar) && bAltFullRight ) // alternation after the break doesn't supported { - TextPortion& rPrev = pParaPortion->GetTextPortions()[nEndPortion]; + TextPortion& rPrev = rParaPortion.GetTextPortions()[nEndPortion]; DBG_ASSERT( rPrev.GetLen(), "Hyphenate: Prev portion?!" ); rPrev.SetLen( rPrev.GetLen() - nAltDelChar ); pHyphPortion->SetLen( nAltDelChar ); if (cAlternateReplChar && !bAltFullLeft) pHyphPortion->SetExtraValue( cAlternateReplChar ); // Correct width of the portion above: - rPrev.GetSize().setWidth( - pLine->GetCharPosArray()[ nBreakPos-1 - pLine->GetStart() - nAltDelChar ] ); + rPrev.setWidth( + rLine.GetCharPosArray()[ nBreakPos-1 - rLine.GetStart() - nAltDelChar ] ); } // Determine the width of the Hyph-Portion: SvxFont aFont; - SeekCursor( pParaPortion->GetNode(), nBreakPos, aFont ); + SeekCursor(rParaPortion.GetNode(), nBreakPos, aFont); aFont.SetPhysFont(*GetRefDevice()); - pHyphPortion->GetSize().setHeight( GetRefDevice()->GetTextHeight() ); - pHyphPortion->GetSize().setWidth( GetRefDevice()->GetTextWidth( CH_HYPH ) ); + pHyphPortion->SetSize(Size(GetRefDevice()->GetTextWidth(CH_HYPH), GetRefDevice()->GetTextHeight())); - pParaPortion->GetTextPortions().Insert(++nEndPortion, pHyphPortion); + rParaPortion.GetTextPortions().Insert(++nEndPortion, pHyphPortion); } - pLine->SetEndPortion( nEndPortion ); + rLine.SetEndPortion( nEndPortion ); } -void ImpEditEngine::ImpAdjustBlocks( ParaPortion* pParaPortion, EditLine* pLine, tools::Long nRemainingSpace ) +void ImpEditEngine::ImpAdjustBlocks(ParaPortion& rParaPortion, EditLine& rLine, tools::Long nRemainingSpace ) { DBG_ASSERT( nRemainingSpace > 0, "AdjustBlocks: Somewhat too little..." ); - assert( pLine && "AdjustBlocks: Line ?!" ); - if ( ( nRemainingSpace < 0 ) || pLine->IsEmpty() ) + + if ( ( nRemainingSpace < 0 ) || rLine.IsEmpty() ) return ; - const sal_Int32 nFirstChar = pLine->GetStart(); - const sal_Int32 nLastChar = pLine->GetEnd() -1; // Last points behind - ContentNode* pNode = pParaPortion->GetNode(); + const sal_Int32 nFirstChar = rLine.GetStart(); + const sal_Int32 nLastChar = rLine.GetEnd() -1; // Last points behind + ContentNode* pNode = rParaPortion.GetNode(); DBG_ASSERT( nLastChar < pNode->Len(), "AdjustBlocks: Out of range!" ); // Search blanks or Kashidas... std::vector<sal_Int32> aPositions; + + // Kashidas ? + ImpFindKashidas( pNode, nFirstChar, nLastChar, aPositions ); + auto nKashidas = aPositions.size(); + sal_uInt16 nLastScript = i18n::ScriptType::LATIN; for ( sal_Int32 nChar = nFirstChar; nChar <= nLastChar; nChar++ ) { EditPaM aPaM( pNode, nChar+1 ); - LanguageType eLang = GetLanguage(aPaM); + LanguageType eLang = GetLanguage(aPaM).nLang; sal_uInt16 nScript = GetI18NScriptType(aPaM); - if ( MsLangId::getPrimaryLanguage( eLang) == LANGUAGE_ARABIC_PRIMARY_ONLY ) - // Arabic script is handled later. + // Arabic script is handled above, but if no Kashida positions are found, use blanks. + if (MsLangId::getPrimaryLanguage(eLang) == LANGUAGE_ARABIC_PRIMARY_ONLY && nKashidas) continue; if ( pNode->GetChar(nChar) == ' ' ) @@ -2117,9 +2331,6 @@ void ImpEditEngine::ImpAdjustBlocks( ParaPortion* pParaPortion, EditLine* pLine, nLastScript = nScript; } - // Kashidas ? - ImpFindKashidas( pNode, nFirstChar, nLastChar, aPositions ); - if ( aPositions.empty() ) return; @@ -2127,26 +2338,26 @@ void ImpEditEngine::ImpAdjustBlocks( ParaPortion* pParaPortion, EditLine* pLine, // The width must be distributed to the blockers in front... // But not if it is the only one. if ( ( pNode->GetChar( nLastChar ) == ' ' ) && ( aPositions.size() > 1 ) && - ( MsLangId::getPrimaryLanguage( GetLanguage( EditPaM( pNode, nLastChar ) ) ) != LANGUAGE_ARABIC_PRIMARY_ONLY ) ) + ( MsLangId::getPrimaryLanguage( GetLanguage( EditPaM( pNode, nLastChar ) ).nLang ) != LANGUAGE_ARABIC_PRIMARY_ONLY ) ) { aPositions.pop_back(); sal_Int32 nPortionStart, nPortion; - nPortion = pParaPortion->GetTextPortions().FindPortion( nLastChar+1, nPortionStart ); - TextPortion& rLastPortion = pParaPortion->GetTextPortions()[ nPortion ]; - tools::Long nRealWidth = pLine->GetCharPosArray()[nLastChar-nFirstChar]; + nPortion = rParaPortion.GetTextPortions().FindPortion( nLastChar+1, nPortionStart ); + TextPortion& rLastPortion = rParaPortion.GetTextPortions()[ nPortion ]; + tools::Long nRealWidth = rLine.GetCharPosArray()[nLastChar-nFirstChar]; tools::Long nBlankWidth = nRealWidth; if ( nLastChar > nPortionStart ) - nBlankWidth -= pLine->GetCharPosArray()[nLastChar-nFirstChar-1]; + nBlankWidth -= rLine.GetCharPosArray()[nLastChar-nFirstChar-1]; // Possibly the blank has already been deducted in ImpBreakLine: if ( nRealWidth == rLastPortion.GetSize().Width() ) { // For the last character the portion must stop behind the blank // => Simplify correction: DBG_ASSERT( ( nPortionStart + rLastPortion.GetLen() ) == ( nLastChar+1 ), "Blank actually not at the end of the portion!?"); - rLastPortion.GetSize().AdjustWidth( -nBlankWidth ); + rLastPortion.adjustSize(-nBlankWidth, 0); nRemainingSpace += nBlankWidth; } - pLine->GetCharPosArray()[nLastChar-nFirstChar] -= nBlankWidth; + rLine.GetCharPosArray()[nLastChar-nFirstChar] -= nBlankWidth; } size_t nGaps = aPositions.size(); @@ -2156,6 +2367,19 @@ void ImpEditEngine::ImpAdjustBlocks( ParaPortion* pParaPortion, EditLine* pLine, DBG_ASSERT( nSomeExtraSpace < static_cast<tools::Long>(nGaps), "AdjustBlocks: ExtraSpace too large" ); DBG_ASSERT( nSomeExtraSpace >= 0, "AdjustBlocks: ExtraSpace < 0 " ); + // Mark Kashida positions, so that VCL knows where to insert Kashida and + // where to only expand the width. + if (nKashidas) + { + rLine.GetKashidaArray().resize(rLine.GetCharPosArray().size(), false); + for (size_t i = 0; i < nKashidas; i++) + { + auto nChar = aPositions[i]; + if ( nChar < nLastChar ) + rLine.GetKashidaArray()[nChar-nFirstChar] = 1 /*sal_True*/; + } + } + // Correct the positions in the Array and the portion widths: // Last character won't be considered... for (auto const& nChar : aPositions) @@ -2163,22 +2387,23 @@ void ImpEditEngine::ImpAdjustBlocks( ParaPortion* pParaPortion, EditLine* pLine, if ( nChar < nLastChar ) { sal_Int32 nPortionStart, nPortion; - nPortion = pParaPortion->GetTextPortions().FindPortion( nChar, nPortionStart, true ); - TextPortion& rLastPortion = pParaPortion->GetTextPortions()[ nPortion ]; + nPortion = rParaPortion.GetTextPortions().FindPortion( nChar, nPortionStart, true ); + TextPortion& rLastPortion = rParaPortion.GetTextPortions()[ nPortion ]; // The width of the portion: - rLastPortion.GetSize().AdjustWidth(nMore4Everyone ); - if ( nSomeExtraSpace ) - rLastPortion.GetSize().AdjustWidth( 1 ); + rLastPortion.adjustSize(nMore4Everyone, 0); + if (nSomeExtraSpace) + { + rLastPortion.adjustSize(1, 0); + } // Correct positions in array - // Even for kashidas just change positions, VCL will then draw the kashida automatically sal_Int32 nPortionEnd = nPortionStart + rLastPortion.GetLen(); for ( sal_Int32 _n = nChar; _n < nPortionEnd; _n++ ) { - pLine->GetCharPosArray()[_n-nFirstChar] += nMore4Everyone; + rLine.GetCharPosArray()[_n-nFirstChar] += nMore4Everyone; if ( nSomeExtraSpace ) - pLine->GetCharPosArray()[_n-nFirstChar]++; + rLine.GetCharPosArray()[_n-nFirstChar]++; } if ( nSomeExtraSpace ) @@ -2187,11 +2412,18 @@ void ImpEditEngine::ImpAdjustBlocks( ParaPortion* pParaPortion, EditLine* pLine, } // Now the text width contains the extra width... - pLine->SetTextWidth( pLine->GetTextWidth() + nRemainingSpace ); + rLine.SetTextWidth(rLine.GetTextWidth() + nRemainingSpace); } +// For Kashidas from sw/source/core/text/porlay.cxx void ImpEditEngine::ImpFindKashidas( ContentNode* pNode, sal_Int32 nStart, sal_Int32 nEnd, std::vector<sal_Int32>& rArray ) { + // Kashida glyph looks suspicious, skip Kashida justification + if (GetRefDevice()->GetMinKashida() <= 0) + return; + + std::vector<sal_Int32> aKashidaArray; + // the search has to be performed on a per word base EditSelection aWordSel( EditPaM( pNode, nStart ) ); @@ -2210,12 +2442,20 @@ void ImpEditEngine::ImpFindKashidas( ContentNode* pNode, sal_Int32 nStart, sal_I // restore selection for proper iteration at the end of the function aWordSel.Max().SetIndex( nSavPos ); - sal_Int32 nIdx = 0; + sal_Int32 nIdx = 0, nPrevIdx = 0; sal_Int32 nKashidaPos = -1; - sal_Unicode cCh; - sal_Unicode cPrevCh = 0; + sal_Unicode cCh, cPrevCh = 0; + + int nPriorityLevel = 7; // 0..6 = level found + // 7 not found - while ( nIdx < aWord.getLength() ) + sal_Int32 nWordLen = aWord.getLength(); + + // ignore trailing vowel chars + while( nWordLen && isTransparentChar( aWord[ nWordLen - 1 ] )) + --nWordLen; + + while ( nIdx < nWordLen ) { cCh = aWord[ nIdx ]; @@ -2224,104 +2464,163 @@ void ImpEditEngine::ImpFindKashidas( ContentNode* pNode, sal_Int32 nStart, sal_I if ( 0x640 == cCh ) { nKashidaPos = aWordSel.Min().GetIndex() + nIdx; - break; + nPriorityLevel = 0; } // 2. Priority: // after a Seen or Sad - if ( nIdx + 1 < aWord.getLength() && - ( 0x633 == cCh || 0x635 == cCh ) ) + if (nPriorityLevel >= 1 && nIdx < nWordLen - 1) { - nKashidaPos = aWordSel.Min().GetIndex() + nIdx; - break; + if( isSeenOrSadChar( cCh ) + && (aWord[ nIdx+1 ] != 0x200C) ) // #i98410#: prevent ZWNJ expansion + { + nKashidaPos = aWordSel.Min().GetIndex() + nIdx; + nPriorityLevel = 1; + } } // 3. Priority: - // before final form of the Marbuta, Hah, Dal - // 4. Priority: - // before final form of Alef, Lam or Kaf - if ( nIdx && nIdx + 1 == aWord.getLength() && - ( 0x629 == cCh || 0x62D == cCh || 0x62F == cCh || - 0x627 == cCh || 0x644 == cCh || 0x643 == cCh ) ) + // before final form of Teh Marbuta, Heh, Dal + if ( nPriorityLevel >= 2 && nIdx > 0 ) { - DBG_ASSERT( 0 != cPrevCh, "No previous character" ); + if ( isTehMarbutaChar ( cCh ) || // Teh Marbuta (right joining) + isDalChar ( cCh ) || // Dal (right joining) final form may appear in the middle of word + ( isHehChar ( cCh ) && nIdx == nWordLen - 1)) // Heh (dual joining) only at end of word + { - // check if character is connectable to previous character, - if ( lcl_ConnectToPrev( cCh, cPrevCh ) ) + SAL_WARN_IF( 0 == cPrevCh, "editeng", "No previous character" ); + // check if character is connectable to previous character, + if ( lcl_ConnectToPrev( cCh, cPrevCh ) ) + { + nKashidaPos = aWordSel.Min().GetIndex() + nPrevIdx; + nPriorityLevel = 2; + } + } + } + + // 4. Priority: + // before final form of Alef, Tah, Lam, Kaf or Gaf + if ( nPriorityLevel >= 3 && nIdx > 0 ) + { + if ( isAlefChar ( cCh ) || // Alef (right joining) final form may appear in the middle of word + (( isLamChar ( cCh ) || // Lam, + isTahChar ( cCh ) || // Tah, + isKafChar ( cCh ) || // Kaf (all dual joining) + isGafChar ( cCh ) ) + && nIdx == nWordLen - 1)) // only at end of word { - nKashidaPos = aWordSel.Min().GetIndex() + nIdx - 1; - break; + SAL_WARN_IF( 0 == cPrevCh, "editeng", "No previous character" ); + // check if character is connectable to previous character, + if ( lcl_ConnectToPrev( cCh, cPrevCh ) ) + { + nKashidaPos = aWordSel.Min().GetIndex() + nPrevIdx; + nPriorityLevel = 3; + } } } // 5. Priority: - // before media Bah - if ( nIdx && nIdx + 1 < aWord.getLength() && 0x628 == cCh ) + // before medial Beh-like + if ( nPriorityLevel >= 4 && nIdx > 0 && nIdx < nWordLen - 1 ) { - DBG_ASSERT( 0 != cPrevCh, "No previous character" ); - - // check if next character is Reh, Yeh or Alef Maksura - sal_Unicode cNextCh = aWord[ nIdx + 1 ]; + if ( isBehChar ( cCh ) ) + { + // check if next character is Reh or Yeh-like + sal_Unicode cNextCh = aWord[ nIdx + 1 ]; + if ( isRehChar ( cNextCh ) || isYehChar ( cNextCh )) + { + SAL_WARN_IF( 0 == cPrevCh, "editeng", "No previous character" ); + // check if character is connectable to previous character, + if ( lcl_ConnectToPrev( cCh, cPrevCh ) ) + { + nKashidaPos = aWordSel.Min().GetIndex() + nPrevIdx; + nPriorityLevel = 4; + } + } + } + } - if ( 0x631 == cNextCh || 0x64A == cNextCh || - 0x649 == cNextCh ) + // 6. Priority: + // before the final form of Waw, Ain, Qaf and Feh + if ( nPriorityLevel >= 5 && nIdx > 0 ) + { + if ( isWawChar ( cCh ) || // Wav (right joining) + // final form may appear in the middle of word + (( isAinChar ( cCh ) || // Ain (dual joining) + isQafChar ( cCh ) || // Qaf (dual joining) + isFehChar ( cCh ) ) // Feh (dual joining) + && nIdx == nWordLen - 1)) // only at end of word { + SAL_WARN_IF( 0 == cPrevCh, "editeng", "No previous character" ); // check if character is connectable to previous character, if ( lcl_ConnectToPrev( cCh, cPrevCh ) ) - nKashidaPos = aWordSel.Min().GetIndex() + nIdx - 1; + { + nKashidaPos = aWordSel.Min().GetIndex() + nPrevIdx; + nPriorityLevel = 5; + } } } - // 6. Priority: // other connecting possibilities - if ( nIdx && nIdx + 1 == aWord.getLength() && - 0x60C <= cCh && 0x6FE >= cCh ) + if ( nPriorityLevel >= 6 && nIdx > 0 ) { - DBG_ASSERT( 0 != cPrevCh, "No previous character" ); - - // check if character is connectable to previous character, - if ( lcl_ConnectToPrev( cCh, cPrevCh ) ) + // Reh, Zain + if ( isRehChar ( cCh ) ) { - // only choose this position if we did not find - // a better one: - if ( nKashidaPos<0 ) - nKashidaPos = aWordSel.Min().GetIndex() + nIdx - 1; - break; + SAL_WARN_IF( 0 == cPrevCh, "editeng", "No previous character" ); + // check if character is connectable to previous character, + if ( lcl_ConnectToPrev( cCh, cPrevCh ) ) + { + nKashidaPos = aWordSel.Min().GetIndex() + nPrevIdx; + nPriorityLevel = 6; + } } } - // Do not consider Fathatan, Dammatan, Kasratan, Fatha, - // Damma, Kasra, Shadda and Sukun when checking if - // a character can be connected to previous character. - if ( cCh < 0x64B || cCh > 0x652 ) + // Do not consider vowel marks when checking if a character + // can be connected to previous character. + if ( !isTransparentChar ( cCh) ) + { cPrevCh = cCh; + nPrevIdx = nIdx; + } ++nIdx; } // end of current word if ( nKashidaPos>=0 ) - rArray.push_back( nKashidaPos ); + aKashidaArray.push_back( nKashidaPos ); aWordSel = WordRight( aWordSel.Max(), css::i18n::WordType::DICTIONARY_WORD ); aWordSel = SelectWord( aWordSel, css::i18n::WordType::DICTIONARY_WORD ); } + + // Validate + std::vector<sal_Int32> aDropped(aKashidaArray.size()); + auto nOldLayout = GetRefDevice()->GetLayoutMode(); + GetRefDevice()->SetLayoutMode(nOldLayout | vcl::text::ComplexTextLayoutFlags::BiDiRtl); + GetRefDevice()->ValidateKashidas(pNode->GetString(), nStart, nEnd - nStart, + aKashidaArray.size(), aKashidaArray.data(), aDropped.data()); + GetRefDevice()->SetLayoutMode(nOldLayout); + + for (auto const& pos : aKashidaArray) + if (std::find(aDropped.begin(), aDropped.end(), pos) == aDropped.end()) + rArray.push_back(pos); } -sal_Int32 ImpEditEngine::SplitTextPortion( ParaPortion* pPortion, sal_Int32 nPos, EditLine* pCurLine ) +sal_Int32 ImpEditEngine::SplitTextPortion(ParaPortion& rParaPortion, sal_Int32 nPos, EditLine* pCurLine) { // The portion at nPos is split, if there is not a transition at nPos anyway if ( nPos == 0 ) return 0; - assert( pPortion && "SplitTextPortion: Which ?" ); - sal_Int32 nSplitPortion; sal_Int32 nTmpPos = 0; TextPortion* pTextPortion = nullptr; - sal_Int32 nPortions = pPortion->GetTextPortions().Count(); + sal_Int32 nPortions = rParaPortion.GetTextPortions().Count(); for ( nSplitPortion = 0; nSplitPortion < nPortions; nSplitPortion++ ) { - TextPortion& rTP = pPortion->GetTextPortions()[nSplitPortion]; + TextPortion& rTP = rParaPortion.GetTextPortions()[nSplitPortion]; nTmpPos = nTmpPos + rTP.GetLen(); if ( nTmpPos >= nPos ) { @@ -2344,44 +2643,45 @@ sal_Int32 ImpEditEngine::SplitTextPortion( ParaPortion* pPortion, sal_Int32 nPos sal_Int32 nOverlapp = nTmpPos - nPos; pTextPortion->SetLen( pTextPortion->GetLen() - nOverlapp ); TextPortion* pNewPortion = new TextPortion( nOverlapp ); - pPortion->GetTextPortions().Insert(nSplitPortion+1, pNewPortion); + rParaPortion.GetTextPortions().Insert(nSplitPortion+1, pNewPortion); // Set sizes if ( pCurLine ) { // No new GetTextSize, instead use values from the Array: assert( nPos > pCurLine->GetStart() && "SplitTextPortion at the beginning of the line?" ); - pTextPortion->GetSize().setWidth( pCurLine->GetCharPosArray()[ nPos-pCurLine->GetStart()-1 ] ); + pTextPortion->setWidth(pCurLine->GetCharPosArray()[nPos - pCurLine->GetStart() - 1]); if ( pTextPortion->GetExtraInfos() && pTextPortion->GetExtraInfos()->bCompressed ) { // We need the original size from the portion - sal_Int32 nTxtPortionStart = pPortion->GetTextPortions().GetStartPos( nSplitPortion ); - SvxFont aTmpFont( pPortion->GetNode()->GetCharAttribs().GetDefFont() ); - SeekCursor( pPortion->GetNode(), nTxtPortionStart+1, aTmpFont ); + sal_Int32 nTxtPortionStart = rParaPortion.GetTextPortions().GetStartPos( nSplitPortion ); + SvxFont aTmpFont = rParaPortion.GetNode()->GetCharAttribs().GetDefFont(); + SeekCursor(rParaPortion.GetNode(), nTxtPortionStart + 1, aTmpFont); aTmpFont.SetPhysFont(*GetRefDevice()); GetRefDevice()->Push( vcl::PushFlags::TEXTLANGUAGE ); ImplInitDigitMode(*GetRefDevice(), aTmpFont.GetLanguage()); - Size aSz = aTmpFont.QuickGetTextSize( GetRefDevice(), pPortion->GetNode()->GetString(), nTxtPortionStart, pTextPortion->GetLen() ); + Size aSz = aTmpFont.QuickGetTextSize( GetRefDevice(), rParaPortion.GetNode()->GetString(), + nTxtPortionStart, pTextPortion->GetLen(), nullptr ); GetRefDevice()->Pop(); pTextPortion->GetExtraInfos()->nOrgWidth = aSz.Width(); } } else - pTextPortion->GetSize().setWidth( -1 ); + pTextPortion->setWidth(-1); return nSplitPortion; } -void ImpEditEngine::CreateTextPortions( ParaPortion* pParaPortion, sal_Int32& rStart ) +void ImpEditEngine::CreateTextPortions(ParaPortion& rParaPortion, sal_Int32& rStart) { sal_Int32 nStartPos = rStart; - ContentNode* pNode = pParaPortion->GetNode(); + ContentNode* pNode = rParaPortion.GetNode(); DBG_ASSERT( pNode->Len(), "CreateTextPortions should not be used for empty paragraphs!" ); o3tl::sorted_vector< sal_Int32 > aPositions; aPositions.insert( 0 ); - for (sal_uInt16 nAttr = 0;; ++nAttr) + for (std::size_t nAttr = 0;; ++nAttr) { // Insert Start and End into the Array... // The Insert method does not allow for duplicate values... @@ -2393,15 +2693,13 @@ void ImpEditEngine::CreateTextPortions( ParaPortion* pParaPortion, sal_Int32& rS } aPositions.insert( pNode->Len() ); - if ( pParaPortion->aScriptInfos.empty() ) - InitScriptTypes( GetParaPortions().GetPos( pParaPortion ) ); + if (rParaPortion.getScriptTypePosInfos().empty()) + InitScriptTypes(GetParaPortions().GetPos(&rParaPortion)); - const ScriptTypePosInfos& rTypes = pParaPortion->aScriptInfos; - for (const ScriptTypePosInfo& rType : rTypes) + for (const ScriptTypePosInfo& rType : rParaPortion.getScriptTypePosInfos()) aPositions.insert( rType.nStartPos ); - const WritingDirectionInfos& rWritingDirections = pParaPortion->aWritingDirectionInfos; - for (const WritingDirectionInfo & rWritingDirection : rWritingDirections) + for (const WritingDirectionInfo& rWritingDirection : rParaPortion.getWritingDirectionInfos()) aPositions.insert( rWritingDirection.nStartPos ); if ( mpIMEInfos && mpIMEInfos->nLen && mpIMEInfos->pAttribs && ( mpIMEInfos->aPos.GetNode() == pNode ) ) @@ -2424,9 +2722,9 @@ void ImpEditEngine::CreateTextPortions( ParaPortion* pParaPortion, sal_Int32& rS sal_Int32 nPortionStart = 0; sal_Int32 nInvPortion = 0; sal_Int32 nP; - for ( nP = 0; nP < pParaPortion->GetTextPortions().Count(); nP++ ) + for ( nP = 0; nP < rParaPortion.GetTextPortions().Count(); nP++ ) { - const TextPortion& rTmpPortion = pParaPortion->GetTextPortions()[nP]; + const TextPortion& rTmpPortion = rParaPortion.GetTextPortions()[nP]; nPortionStart = nPortionStart + rTmpPortion.GetLen(); if ( nPortionStart >= nStartPos ) { @@ -2436,16 +2734,16 @@ void ImpEditEngine::CreateTextPortions( ParaPortion* pParaPortion, sal_Int32& rS break; } } - DBG_ASSERT( nP < pParaPortion->GetTextPortions().Count() || !pParaPortion->GetTextPortions().Count(), "Nothing to delete: CreateTextPortions" ); - if ( nInvPortion && ( nPortionStart+pParaPortion->GetTextPortions()[nInvPortion].GetLen() > nStartPos ) ) + DBG_ASSERT( nP < rParaPortion.GetTextPortions().Count() || !rParaPortion.GetTextPortions().Count(), "Nothing to delete: CreateTextPortions" ); + if ( nInvPortion && ( nPortionStart + rParaPortion.GetTextPortions()[nInvPortion].GetLen() > nStartPos ) ) { // prefer one in front... // But only if it was in the middle of the portion of, otherwise it // might be the only one in the row in front! nInvPortion--; - nPortionStart = nPortionStart - pParaPortion->GetTextPortions()[nInvPortion].GetLen(); + nPortionStart = nPortionStart - rParaPortion.GetTextPortions()[nInvPortion].GetLen(); } - pParaPortion->GetTextPortions().DeleteFromPortion( nInvPortion ); + rParaPortion.GetTextPortions().DeleteFromPortion( nInvPortion ); // A portion may also have been formed by a line break: aPositions.insert( nPortionStart ); @@ -2458,21 +2756,21 @@ void ImpEditEngine::CreateTextPortions( ParaPortion* pParaPortion, sal_Int32& rS while ( i != aPositions.end() ) { TextPortion* pNew = new TextPortion( (*i++) - *nInvPos++ ); - pParaPortion->GetTextPortions().Append(pNew); + rParaPortion.GetTextPortions().Append(pNew); } - DBG_ASSERT( pParaPortion->GetTextPortions().Count(), "No Portions?!" ); + DBG_ASSERT(rParaPortion.GetTextPortions().Count(), "No Portions?!"); #if OSL_DEBUG_LEVEL > 0 - OSL_ENSURE( ParaPortion::DbgCheckTextPortions(*pParaPortion), "Portion is broken?" ); + OSL_ENSURE( ParaPortion::DbgCheckTextPortions(rParaPortion), "Portion is broken?" ); #endif } -void ImpEditEngine::RecalcTextPortion( ParaPortion* pParaPortion, sal_Int32 nStartPos, sal_Int32 nNewChars ) +void ImpEditEngine::RecalcTextPortion(ParaPortion& rParaPortion, sal_Int32 nStartPos, sal_Int32 nNewChars) { - DBG_ASSERT( pParaPortion->GetTextPortions().Count(), "No Portions!" ); + DBG_ASSERT(rParaPortion.GetTextPortions().Count(), "No Portions!"); DBG_ASSERT( nNewChars, "RecalcTextPortion with Diff == 0" ); - ContentNode* const pNode = pParaPortion->GetNode(); + ContentNode* const pNode = rParaPortion.GetNode(); if ( nNewChars > 0 ) { // If an Attribute begins/ends at nStartPos, then a new portion starts @@ -2481,31 +2779,30 @@ void ImpEditEngine::RecalcTextPortion( ParaPortion* pParaPortion, sal_Int32 nSta { sal_Int32 nNewPortionPos = 0; if ( nStartPos ) - nNewPortionPos = SplitTextPortion( pParaPortion, nStartPos ) + 1; + nNewPortionPos = SplitTextPortion(rParaPortion, nStartPos) + 1; // A blank portion may be here, if the paragraph was empty, // or if a line was created by a hard line break. - if ( ( nNewPortionPos < pParaPortion->GetTextPortions().Count() ) && - !pParaPortion->GetTextPortions()[nNewPortionPos].GetLen() ) + if ( ( nNewPortionPos < rParaPortion.GetTextPortions().Count() ) && + !rParaPortion.GetTextPortions()[nNewPortionPos].GetLen() ) { - TextPortion& rTP = pParaPortion->GetTextPortions()[nNewPortionPos]; + TextPortion& rTP = rParaPortion.GetTextPortions()[nNewPortionPos]; DBG_ASSERT( rTP.GetKind() == PortionKind::TEXT, "the empty portion was no TextPortion!" ); rTP.SetLen( rTP.GetLen() + nNewChars ); } else { TextPortion* pNewPortion = new TextPortion( nNewChars ); - pParaPortion->GetTextPortions().Insert(nNewPortionPos, pNewPortion); + rParaPortion.GetTextPortions().Insert(nNewPortionPos, pNewPortion); } } else { sal_Int32 nPortionStart; - const sal_Int32 nTP = pParaPortion->GetTextPortions(). - FindPortion( nStartPos, nPortionStart ); - TextPortion& rTP = pParaPortion->GetTextPortions()[ nTP ]; + const sal_Int32 nTP = rParaPortion.GetTextPortions().FindPortion( nStartPos, nPortionStart ); + TextPortion& rTP = rParaPortion.GetTextPortions()[ nTP ]; rTP.SetLen( rTP.GetLen() + nNewChars ); - rTP.GetSize().setWidth( -1 ); + rTP.setWidth(-1); } } else @@ -2520,11 +2817,11 @@ void ImpEditEngine::RecalcTextPortion( ParaPortion* pParaPortion, sal_Int32 nSta sal_Int32 nPortion = 0; sal_Int32 nPos = 0; sal_Int32 nEnd = nStartPos-nNewChars; - sal_Int32 nPortions = pParaPortion->GetTextPortions().Count(); + sal_Int32 nPortions = rParaPortion.GetTextPortions().Count(); TextPortion* pTP = nullptr; for ( nPortion = 0; nPortion < nPortions; nPortion++ ) { - pTP = &pParaPortion->GetTextPortions()[ nPortion ]; + pTP = &rParaPortion.GetTextPortions()[ nPortion ]; if ( ( nPos+pTP->GetLen() ) > nStartPos ) { DBG_ASSERT( nPos <= nStartPos, "Wrong Start!" ); @@ -2538,14 +2835,14 @@ void ImpEditEngine::RecalcTextPortion( ParaPortion* pParaPortion, sal_Int32 nSta { // Remove portion; PortionKind nType = pTP->GetKind(); - pParaPortion->GetTextPortions().Remove( nPortion ); + rParaPortion.GetTextPortions().Remove( nPortion ); if ( nType == PortionKind::LINEBREAK ) { - TextPortion& rNext = pParaPortion->GetTextPortions()[ nPortion ]; + TextPortion& rNext = rParaPortion.GetTextPortions()[ nPortion ]; if ( !rNext.GetLen() ) { // Remove dummy portion - pParaPortion->GetTextPortions().Remove( nPortion ); + rParaPortion.GetTextPortions().Remove( nPortion ); } } } @@ -2555,48 +2852,47 @@ void ImpEditEngine::RecalcTextPortion( ParaPortion* pParaPortion, sal_Int32 nSta pTP->SetLen( pTP->GetLen() + nNewChars ); } - sal_Int32 nPortionCount = pParaPortion->GetTextPortions().Count(); + sal_Int32 nPortionCount = rParaPortion.GetTextPortions().Count(); assert( nPortionCount ); if (nPortionCount) { // No HYPHENATOR portion is allowed to get stuck right at the end... sal_Int32 nLastPortion = nPortionCount - 1; - pTP = &pParaPortion->GetTextPortions()[nLastPortion]; + pTP = &rParaPortion.GetTextPortions()[nLastPortion]; if ( pTP->GetKind() == PortionKind::HYPHENATOR ) { // Discard portion; if possible, correct the ones before, // if the Hyphenator portion has swallowed one character... if ( nLastPortion && pTP->GetLen() ) { - TextPortion& rPrev = pParaPortion->GetTextPortions()[nLastPortion - 1]; + TextPortion& rPrev = rParaPortion.GetTextPortions()[nLastPortion - 1]; DBG_ASSERT( rPrev.GetKind() == PortionKind::TEXT, "Portion?!" ); rPrev.SetLen( rPrev.GetLen() + pTP->GetLen() ); - rPrev.GetSize().setWidth( -1 ); + rPrev.setWidth(-1); } - pParaPortion->GetTextPortions().Remove( nLastPortion ); + rParaPortion.GetTextPortions().Remove( nLastPortion ); } } } #if OSL_DEBUG_LEVEL > 0 - OSL_ENSURE( ParaPortion::DbgCheckTextPortions(*pParaPortion), "Portions are broken?" ); + OSL_ENSURE( ParaPortion::DbgCheckTextPortions(rParaPortion), "Portions are broken?" ); #endif } void ImpEditEngine::SetTextRanger( std::unique_ptr<TextRanger> pRanger ) { - pTextRanger = std::move(pRanger); + mpTextRanger = std::move(pRanger); - for ( sal_Int32 nPara = 0; nPara < GetParaPortions().Count(); nPara++ ) + for (auto& pParaPortion : GetParaPortions()) { - ParaPortion& rParaPortion = GetParaPortions()[nPara]; - rParaPortion.MarkSelectionInvalid( 0 ); - rParaPortion.GetLines().Reset(); + pParaPortion->MarkSelectionInvalid( 0 ); + pParaPortion->GetLines().Reset(); } FormatFullDoc(); UpdateViews( GetActiveView() ); if ( IsUpdateLayout() && GetActiveView() ) - pActiveView->ShowCursor(false, false); + mpActiveView->ShowCursor(false, false); } void ImpEditEngine::SetVertical( bool bVertical) @@ -2604,7 +2900,7 @@ void ImpEditEngine::SetVertical( bool bVertical) if ( IsEffectivelyVertical() != bVertical) { GetEditDoc().SetVertical(bVertical); - bool bUseCharAttribs = bool(aStatus.GetControlWord() & EEControlBits::USECHARATTRIBS); + bool bUseCharAttribs = bool(maStatus.GetControlWord() & EEControlBits::USECHARATTRIBS); GetEditDoc().CreateDefFont( bUseCharAttribs ); if ( IsFormatted() ) { @@ -2619,7 +2915,7 @@ void ImpEditEngine::SetRotation(TextRotation nRotation) if (GetEditDoc().GetRotation() == nRotation) return; // not modified GetEditDoc().SetRotation(nRotation); - bool bUseCharAttribs = bool(aStatus.GetControlWord() & EEControlBits::USECHARATTRIBS); + bool bUseCharAttribs = bool(maStatus.GetControlWord() & EEControlBits::USECHARATTRIBS); GetEditDoc().CreateDefFont( bUseCharAttribs ); if ( IsFormatted() ) { @@ -2630,8 +2926,14 @@ void ImpEditEngine::SetRotation(TextRotation nRotation) void ImpEditEngine::SetTextColumns(sal_Int16 nColumns, sal_Int32 nSpacing) { + assert(nColumns >= 1); if (mnColumns != nColumns || mnColumnSpacing != nSpacing) { + if (nColumns == 0) + { + SAL_WARN("editeng", "bad nColumns value, ignoring"); + nColumns = 1; + } mnColumns = nColumns; mnColumnSpacing = nSpacing; if (IsFormatted()) @@ -2712,7 +3014,7 @@ void ImpEditEngine::SeekCursor( ContentNode* pNode, sal_Int32 nPos, SvxFont& rFo /* * Scan through char attributes of pNode */ - if ( aStatus.UseCharAttribs() ) + if (maStatus.UseCharAttribs()) { CharAttribList::AttribsType& rAttribs = pNode->GetCharAttribs().GetAttribs(); size_t nAttr = 0; @@ -2734,7 +3036,11 @@ void ImpEditEngine::SeekCursor( ContentNode* pNode, sal_Int32 nPos, SvxFont& rFo // #i1550# hard color attrib should win over text color from field if ( pAttrib->Which() == EE_FEATURE_FIELD ) { - EditCharAttrib* pColorAttr = pNode->GetCharAttribs().FindAttrib( EE_CHAR_COLOR, nPos ); + // These Attribs positions come from PaMs, so their interval is right-open and left-closed + // when SeekCursor is called, nPos is incremented by 1. I do not know why... + // probably designed to be a nEndPos, and like in a PaM, it is the position after the actual character. + sal_Int32 nPosActual = nPos > 0 ? nPos - 1 : 0; + EditCharAttrib* pColorAttr = pNode->GetCharAttribs().FindAttribRightOpen( EE_CHAR_COLOR, nPosActual ); if ( pColorAttr ) pColorAttr->SetFont( rFont, pOut ); } @@ -2756,12 +3062,12 @@ void ImpEditEngine::SeekCursor( ContentNode* pNode, sal_Int32 nPos, SvxFont& rFo if ( (rFont.GetKerning() != FontKerning::NONE) && IsKernAsianPunctuation() && ( nScriptTypeI18N == i18n::ScriptType::ASIAN ) ) rFont.SetKerning( rFont.GetKerning() | FontKerning::Asian ); - if ( aStatus.DoNotUseColors() ) + if (maStatus.DoNotUseColors()) { rFont.SetColor( /* rColorItem.GetValue() */ COL_BLACK ); } - if ( aStatus.DoStretch() || ( nRelWidth != 100 ) ) + if (maStatus.DoStretch() || ( nRelWidth != 100 )) { // For the current Output device, because otherwise if RefDev=Printer its looks // ugly on the screen! @@ -2780,24 +3086,29 @@ void ImpEditEngine::SeekCursor( ContentNode* pNode, sal_Int32 nPos, SvxFont& rFo Size aRealSz( aMetric.GetFontSize() ); rFont.SetPropr( 100 ); - if ( aStatus.DoStretch() ) + if (maStatus.DoStretch()) { - if ( nStretchY != 100 ) + if (maScalingParameters.fFontY != 1.0) { - aRealSz.setHeight( aRealSz.Height() * nStretchY ); - aRealSz.setHeight( aRealSz.Height() / 100 ); + double fHeightRounded = roundToNearestPt(aRealSz.Height()); + double fNewHeight = fHeightRounded * maScalingParameters.fFontY; + fNewHeight = roundToNearestPt(fNewHeight); + aRealSz.setHeight(basegfx::fround<tools::Long>(fNewHeight)); } - if ( nStretchX != 100 ) + if (maScalingParameters.fFontX != 1.0) { - if ( nStretchX == nStretchY && - nRelWidth == 100 ) + auto fFontX = maScalingParameters.fFontX; + auto fFontY = maScalingParameters.fFontY; + if (fFontX == fFontY && nRelWidth == 100 ) { aRealSz.setWidth( 0 ); } else { - aRealSz.setWidth( aRealSz.Width() * nStretchX ); - aRealSz.setWidth( aRealSz.Width() / 100 ); + double fWidthRounded = roundToNearestPt(aRealSz.Width()); + double fNewWidth = fWidthRounded * fFontX; + fNewWidth = roundToNearestPt(fNewWidth); + aRealSz.setWidth(basegfx::fround<tools::Long>(fNewWidth)); // Also the Kerning: (long due to handle Interim results) tools::Long nKerning = rFont.GetFixKerning(); @@ -2812,17 +3123,15 @@ void ImpEditEngine::SeekCursor( ContentNode* pNode, sal_Int32 nPos, SvxFont& rFo >0 >100 > (Proportional) <0 >100 < (The amount, thus disproportional) */ - if ( ( nKerning < 0 ) && ( nStretchX > 100 ) ) + if (nKerning < 0 && fFontX > 1.0) { // disproportional - nKerning *= 100; - nKerning /= nStretchX; + nKerning = basegfx::fround(nKerning / fFontX); } else if ( nKerning ) { // Proportional - nKerning *= nStretchX; - nKerning /= 100; + nKerning = basegfx::fround(nKerning * fFontX); } rFont.SetFixKerning( static_cast<short>(nKerning) ); } @@ -2864,6 +3173,8 @@ void ImpEditEngine::SeekCursor( ContentNode* pNode, sal_Int32 nPos, SvxFont& rFo ExtTextInputAttr nAttr = mpIMEInfos->pAttribs[ nPos - mpIMEInfos->aPos.GetIndex() - 1 ]; if ( nAttr & ExtTextInputAttr::Underline ) rFont.SetUnderline( LINESTYLE_SINGLE ); + else if ( nAttr & ExtTextInputAttr::DoubleUnderline ) + rFont.SetUnderline( LINESTYLE_DOUBLE ); else if ( nAttr & ExtTextInputAttr::BoldUnderline ) rFont.SetUnderline( LINESTYLE_BOLD ); else if ( nAttr & ExtTextInputAttr::DottedUnderline ) @@ -2897,11 +3208,11 @@ void ImpEditEngine::RecalcFormatterFontMetrics( FormatterFontMetric& rCurMetrics if ( nPropr != 100 ) { rFont.SetPropr( 100 ); - rFont.SetPhysFont(*pRefDev); + rFont.SetPhysFont(*mpRefDev); } sal_uInt16 nAscent, nDescent; - FontMetric aMetric( pRefDev->GetFontMetric() ); + FontMetric aMetric(mpRefDev->GetFontMetric()); nAscent = static_cast<sal_uInt16>(aMetric.GetAscent()); if ( IsAddExtLeading() ) nAscent = sal::static_int_cast< sal_uInt16 >( @@ -2917,10 +3228,10 @@ void ImpEditEngine::RecalcFormatterFontMetrics( FormatterFontMetric& rCurMetrics { sal_uInt16 nIntLeading = ( aMetric.GetInternalLeading() > 0 ) ? static_cast<sal_uInt16>(aMetric.GetInternalLeading()) : 0; // Fonts without leading cause problems - if ( ( nIntLeading == 0 ) && ( pRefDev->GetOutDevType() == OUTDEV_PRINTER ) ) + if ( ( nIntLeading == 0 ) && (mpRefDev->GetOutDevType() == OUTDEV_PRINTER)) { // Lets see what Leading one gets on the screen - VclPtr<VirtualDevice> pVDev = GetVirtualDevice( pRefDev->GetMapMode(), pRefDev->GetDrawMode() ); + VclPtr<VirtualDevice> pVDev = GetVirtualDevice(mpRefDev->GetMapMode(), mpRefDev->GetDrawMode()); rFont.SetPhysFont(*pVDev); aMetric = pVDev->GetFontMetric(); @@ -3057,13 +3368,13 @@ Point ImpEditEngine::MoveToNextLine( // Move the point by the requested distance in Y direction adjustYDirectionAware(rMovePos, nLineHeight); // Check if the resulting position has moved beyond the limits, and more columns left. - // The limits are defined by a rectangle starting from aOrigin with width of aPaperSize - // and height of nCurTextHeight + // The limits are defined by a rectangle starting from aOrigin with width of maPaperSize + // and height of mnCurTextHeight Point aOtherCorner = aOrigin; - adjustXDirectionAware(aOtherCorner, getWidthDirectionAware(aPaperSize)); - adjustYDirectionAware(aOtherCorner, nCurTextHeight); + adjustXDirectionAware(aOtherCorner, getWidthDirectionAware(maPaperSize)); + adjustYDirectionAware(aOtherCorner, mnCurTextHeight); tools::Long nNeeded - = getYOverflowDirectionAware(rMovePos, tools::Rectangle::Justify(aOrigin, aOtherCorner)); + = getYOverflowDirectionAware(rMovePos, tools::Rectangle::Normalize(aOrigin, aOtherCorner)); if (pnHeightNeededToNotWrap) *pnHeightNeededToNotWrap = nNeeded; if (nNeeded && rColumn < mnColumns) @@ -3078,7 +3389,7 @@ Point ImpEditEngine::MoveToNextLine( // Move the point by the requested distance in Y direction adjustYDirectionAware(rMovePos, nLineHeight); // Move the point by the column+spacing distance in X direction - adjustXDirectionAware(rMovePos, GetColumnWidth(aPaperSize) + mnColumnSpacing); + adjustXDirectionAware(rMovePos, GetColumnWidth(maPaperSize) + mnColumnSpacing); } } @@ -3086,7 +3397,6 @@ Point ImpEditEngine::MoveToNextLine( } // TODO: use IterateLineAreas in ImpEditEngine::Paint, to avoid algorithm duplication - void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Point aStartPos, bool bStripOnly, Degree10 nOrientation ) { if ( !IsUpdateLayout() && !bStripOnly ) @@ -3099,7 +3409,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po tools::Long nFirstVisYPos = - rOutDev.GetMapMode().GetOrigin().Y(); DBG_ASSERT( GetParaPortions().Count(), "No ParaPortion?!" ); - SvxFont aTmpFont( GetParaPortions()[0].GetNode()->GetCharAttribs().GetDefFont() ); + SvxFont aTmpFont = GetParaPortions().getRef(0).GetNode()->GetCharAttribs().GetDefFont(); vcl::PDFExtOutDevData* const pPDFExtOutDevData = dynamic_cast< vcl::PDFExtOutDevData* >( rOutDev.GetExtOutDevData() ); // In the case of rotated text is aStartPos considered TopLeft because @@ -3107,13 +3417,6 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po // un-scrolled. // The rectangle is infinite. const Point aOrigin( aStartPos ); - double nCos = 0.0, nSin = 0.0; - if ( nOrientation ) - { - double nRealOrientation = toRadians(nOrientation); - nCos = cos( nRealOrientation ); - nSin = sin( nRealOrientation ); - } // #110496# Added some more optional metafile comments. This // change: factored out some duplicated code. @@ -3126,19 +3429,19 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po // Over all the paragraphs... - for ( sal_Int32 n = 0; n < GetParaPortions().Count(); n++ ) + for (sal_Int32 nParaPortion = 0; nParaPortion < GetParaPortions().Count(); nParaPortion++) { - const ParaPortion& rPortion = GetParaPortions()[n]; + ParaPortion const& rParaPortion = GetParaPortions().getRef(nParaPortion); // if when typing idle formatting, asynchronous Paint. // Invisible Portions may be invalid. - if ( rPortion.IsVisible() && rPortion.IsInvalid() ) + if (rParaPortion.IsVisible() && rParaPortion.IsInvalid()) return; if ( pPDFExtOutDevData ) - pPDFExtOutDevData->BeginStructureElement( vcl::PDFWriter::Paragraph ); + pPDFExtOutDevData->WrapBeginStructureElement(vcl::PDFWriter::Paragraph); - const tools::Long nParaHeight = rPortion.GetHeight(); - if ( rPortion.IsVisible() && ( + const tools::Long nParaHeight = rParaPortion.GetHeight(); + if (rParaPortion.IsVisible() && ( ( !IsEffectivelyVertical() && ( ( aStartPos.Y() + nParaHeight ) > aClipRect.Top() ) ) || ( IsEffectivelyVertical() && IsTopToBottom() && ( ( aStartPos.X() - nParaHeight ) < aClipRect.Right() ) ) || ( IsEffectivelyVertical() && !IsTopToBottom() && ( ( aStartPos.X() + nParaHeight ) > aClipRect.Left() ) ) ) ) @@ -3148,22 +3451,21 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po // Over the lines of the paragraph... - const sal_Int32 nLines = rPortion.GetLines().Count(); + const sal_Int32 nLines = rParaPortion.GetLines().Count(); const sal_Int32 nLastLine = nLines-1; bool bEndOfParagraphWritten(false); - adjustYDirectionAware(aStartPos, rPortion.GetFirstLineOffset()); + adjustYDirectionAware(aStartPos, rParaPortion.GetFirstLineOffset()); - const SvxLineSpacingItem& rLSItem = rPortion.GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL ); + const SvxLineSpacingItem& rLSItem = rParaPortion.GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL ); sal_uInt16 nSBL = ( rLSItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Fix ) - ? GetYValue( rLSItem.GetInterLineSpace() ) : 0; + ? scaleYSpacingValue(rLSItem.GetInterLineSpace()) : 0; bool bPaintBullet (false); for ( sal_Int32 nLine = 0; nLine < nLines; nLine++ ) { - const EditLine* const pLine = &rPortion.GetLines()[nLine]; - assert( pLine && "NULL-Pointer in the line iterator in UpdateViews" ); + EditLine* pLine = &GetParaPortions().getRef(nParaPortion).GetLines()[nLine]; sal_Int32 nIndex = pLine->GetStart(); tools::Long nLineHeight = pLine->GetHeight(); if (nLine != nLastLine) @@ -3187,10 +3489,10 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po { Point aLineStart(aStartPos); adjustYDirectionAware(aLineStart, -nLineHeight); - GetEditEnginePtr()->PaintingFirstLine(n, aLineStart, aOrigin, nOrientation, rOutDev); + GetEditEnginePtr()->PaintingFirstLine(nParaPortion, aLineStart, aOrigin, nOrientation, rOutDev); // Remember whether a bullet was painted. - const SfxBoolItem& rBulletState = pEditEngine->GetParaAttrib(n, EE_PARA_BULLETSTATE); + const SfxBoolItem& rBulletState = mpEditEngine->GetParaAttrib(nParaPortion, EE_PARA_BULLETSTATE); bPaintBullet = rBulletState.GetValue(); } @@ -3199,15 +3501,24 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po bool bParsingFields = false; std::vector< sal_Int32 >::iterator itSubLines; + tools::Long nFirstPortionXOffset = 0; for ( sal_Int32 nPortion = pLine->GetStartPortion(); nPortion <= pLine->GetEndPortion(); nPortion++ ) { - DBG_ASSERT( rPortion.GetTextPortions().Count(), "Line without Textportion in Paint!" ); - const TextPortion& rTextPortion = rPortion.GetTextPortions()[nPortion]; + DBG_ASSERT(rParaPortion.GetTextPortions().Count(), "Line without Textportion in Paint!"); + const TextPortion& rTextPortion = rParaPortion.GetTextPortions()[nPortion]; - const tools::Long nPortionXOffset = GetPortionXOffset( &rPortion, pLine, nPortion ); + const tools::Long nPortionXOffset = GetPortionXOffset(rParaPortion, *pLine, nPortion); setXDirectionAwareFrom(aTmpPos, aStartPos); - adjustXDirectionAware(aTmpPos, nPortionXOffset); + + if (nPortion == pLine->GetStartPortion()) + nFirstPortionXOffset = nPortionXOffset; + + if (!bParsingFields) + adjustXDirectionAware(aTmpPos, nPortionXOffset); + else + adjustXDirectionAware(aTmpPos, nFirstPortionXOffset); + if (isXOverflowDirectionAware(aTmpPos, aClipRect)) break; // No further output in line necessary @@ -3217,7 +3528,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po case PortionKind::FIELD: case PortionKind::HYPHENATOR: { - SeekCursor( rPortion.GetNode(), nIndex+1, aTmpFont, &rOutDev ); + SeekCursor(rParaPortion.GetNode(), nIndex + 1, aTmpFont, &rOutDev); bool bDrawFrame = false; @@ -3243,7 +3554,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po aTmpFont.SetFillColor( COL_LIGHTGRAY ); aTmpFont.SetTransparent( sal_False ); } - else if ( GetI18NScriptType( EditPaM( rPortion.GetNode(), nIndex+1 ) ) == i18n::ScriptType::COMPLEX ) + else if (GetI18NScriptType(EditPaM(rParaPortion.GetNode(), nIndex + 1)) == i18n::ScriptType::COMPLEX) { aTmpFont.SetFillColor( COL_LIGHTCYAN ); aTmpFont.SetTransparent( sal_False ); @@ -3254,30 +3565,37 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po // #114278# Saving both layout mode and language (since I'm // potentially changing both) rOutDev.Push( vcl::PushFlags::TEXTLAYOUTMODE|vcl::PushFlags::TEXTLANGUAGE ); - ImplInitLayoutMode(rOutDev, n, nIndex); + ImplInitLayoutMode(rOutDev, nParaPortion, nIndex); ImplInitDigitMode(rOutDev, aTmpFont.GetLanguage()); OUString aText; sal_Int32 nTextStart = 0; sal_Int32 nTextLen = 0; - o3tl::span<const sal_Int32> pDXArray; - std::vector<sal_Int32> aTmpDXArray; + std::span<const sal_Int32> pDXArray; + std::span<const sal_Bool> pKashidaArray; + KernArray aTmpDXArray; if ( rTextPortion.GetKind() == PortionKind::TEXT ) { - aText = rPortion.GetNode()->GetString(); + aText = rParaPortion.GetNode()->GetString(); nTextStart = nIndex; nTextLen = rTextPortion.GetLen(); - pDXArray = o3tl::span(pLine->GetCharPosArray().data() + (nIndex - pLine->GetStart()), + pDXArray = std::span(pLine->GetCharPosArray().data() + (nIndex - pLine->GetStart()), pLine->GetCharPosArray().size() - (nIndex - pLine->GetStart())); + if (!pLine->GetKashidaArray().empty()) + { + pKashidaArray = std::span(pLine->GetKashidaArray().data() + (nIndex - pLine->GetStart()), + pLine->GetKashidaArray().size() - (nIndex - pLine->GetStart())); + } + // Paint control characters (#i55716#) /* XXX: Given that there's special handling * only for some specific characters * (U+200B ZERO WIDTH SPACE and U+2060 WORD * JOINER) it is assumed to be not relevant * for MarkUrlFields(). */ - if ( aStatus.MarkNonUrlFields() ) + if (maStatus.MarkNonUrlFields()) { sal_Int32 nTmpIdx; const sal_Int32 nTmpEnd = nTextStart + rTextPortion.GetLen(); @@ -3290,7 +3608,8 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po if ( 0x200B == cChar || 0x2060 == cChar ) { - tools::Long nHalfBlankWidth = aTmpFont.QuickGetTextSize( &rOutDev, " ", 0, 1 ).Width() / 2; + tools::Long nHalfBlankWidth = aTmpFont.QuickGetTextSize( &rOutDev, + " ", 0, 1, nullptr ).Width() / 2; const tools::Long nAdvanceX = ( nTmpIdx == nTmpEnd ? rTextPortion.GetSize().Width() : @@ -3326,13 +3645,14 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po aTmpFont.SetPropr( 25 ); aTmpFont.SetPhysFont(rOutDev); - const Size aSlashSize = aTmpFont.QuickGetTextSize( &rOutDev, aSlash, 0, 1 ); + const Size aSlashSize = aTmpFont.QuickGetTextSize( &rOutDev, + aSlash, 0, 1, nullptr ); Point aSlashPos( aTmpPos ); const tools::Long nAddX = nHalfBlankWidth - aSlashSize.Width() / 2; setXDirectionAwareFrom(aSlashPos, aTopLeftRectPos); adjustXDirectionAware(aSlashPos, nAddX); - aTmpFont.QuickDrawText( &rOutDev, aSlashPos, aSlash, 0, 1 ); + aTmpFont.QuickDrawText( &rOutDev, aSlashPos, aSlash, 0, 1, {} ); aTmpFont.SetEscapement( nOldEscapement ); aTmpFont.SetPropr( nOldPropr ); @@ -3344,22 +3664,19 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po } else if ( rTextPortion.GetKind() == PortionKind::FIELD ) { - const EditCharAttrib* pAttr = rPortion.GetNode()->GetCharAttribs().FindFeature(nIndex); + const EditCharAttrib* pAttr = rParaPortion.GetNode()->GetCharAttribs().FindFeature(nIndex); assert( pAttr && "Field not found"); DBG_ASSERT( dynamic_cast< const SvxFieldItem* >( pAttr->GetItem() ) != nullptr, "Field of the wrong type! "); aText = static_cast<const EditCharAttribField*>(pAttr)->GetFieldValue(); nTextStart = 0; nTextLen = aText.getLength(); ExtraPortionInfo *pExtraInfo = rTextPortion.GetExtraInfos(); - // Do not split the Fields into different lines while editing - // With EditView on Overlay bStripOnly is now set for stripping to - // primitives. To stay compatible in EditMode use pActiveView to detect - // when we are in EditMode. For whatever reason URLs are drawn as single - // line in edit mode, originally clipped against edit area (which is no - // longer done in Overlay mode and allows to *read* the URL). - // It would be difficult to change this due to needed adaptations in - // EditEngine (look for lineBreaksList creation) - if( nullptr == pActiveView && bStripOnly && !bParsingFields && pExtraInfo && !pExtraInfo->lineBreaksList.empty() ) + //For historical reasons URLs was drawn as single line in edit mode + //but now we changed it, so it wraps similar as simple text. + //It is not perfect, it still use lineBreaksList, so it won’t seek + //word ends to wrap text there, but it would be difficult to change + //this due to needed adaptations in EditEngine + if (bStripOnly && !bParsingFields && pExtraInfo && !pExtraInfo->lineBreaksList.empty()) { bParsingFields = true; itSubLines = pExtraInfo->lineBreaksList.begin(); @@ -3376,6 +3693,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po aTmpPos += MoveToNextLine(aStartPos, nMaxAscent, nColumn, aOrigin); + adjustXDirectionAware(aTmpPos, -pLine->GetNextLinePosXDiff()); } std::vector< sal_Int32 >::iterator curIt = itSubLines; ++itSubLines; @@ -3389,12 +3707,43 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po nTextStart = *curIt; nTextLen = nTextLen - nTextStart; bParsingFields = false; + + if (nLine + 1 < nLines) + { + // tdf#148966 don't paint the line break following a + // multiline field based on a compat flag + OutlinerEditEng* pOutlEditEng{ dynamic_cast<OutlinerEditEng*>(mpEditEngine)}; + int nStartNextLine = rParaPortion.GetLines()[nLine + 1].GetStartPortion(); + const TextPortion& rNextTextPortion = rParaPortion.GetTextPortions()[nStartNextLine]; + if (pOutlEditEng + && pOutlEditEng->GetCompatFlag(SdrCompatibilityFlag::IgnoreBreakAfterMultilineField) + .value_or(false)) + { + if (rNextTextPortion.GetKind() == PortionKind::LINEBREAK) + ++nLine; //ignore the following linebreak + } + else if (mpActiveView && rNextTextPortion.GetKind() == PortionKind::LINEBREAK) + { + // if we are at edit mode, the compat flag does not work + // here we choose to work if compat flag is true, + // this is better for newer documents + nLine++; + } + if (rNextTextPortion.GetKind() != PortionKind::LINEBREAK) + { + nLine++; + pLine = &GetParaPortions().getRef(nParaPortion).GetLines()[nLine]; + } + } } } aTmpFont.SetPhysFont(*GetRefDevice()); - aTmpFont.QuickGetTextSize( GetRefDevice(), aText, nTextStart, nTextLen, &aTmpDXArray ); - pDXArray = aTmpDXArray; + aTmpFont.QuickGetTextSize( GetRefDevice(), aText, nTextStart, nTextLen, + &aTmpDXArray ); + assert(aTmpDXArray.get_factor() == 1); + std::vector<sal_Int32>& rKernArray = aTmpDXArray.get_subunit_array(); + pDXArray = rKernArray; // add a meta file comment if we record to a metafile if( bMetafileValid ) @@ -3419,8 +3768,11 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po // crash when accessing 0 pointer in pDXArray aTmpFont.SetPhysFont(*GetRefDevice()); - aTmpFont.QuickGetTextSize( GetRefDevice(), aText, 0, aText.getLength(), &aTmpDXArray ); - pDXArray = aTmpDXArray; + aTmpFont.QuickGetTextSize( GetRefDevice(), aText, 0, aText.getLength(), + &aTmpDXArray ); + assert(aTmpDXArray.get_factor() == 1); + std::vector<sal_Int32>& rKernArray = aTmpDXArray.get_subunit_array(); + pDXArray = rKernArray; } tools::Long nTxtWidth = rTextPortion.GetSize().Width(); @@ -3438,7 +3790,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po if(GetStatus().DoOnlineSpelling() && rTextPortion.GetLen()) { - WrongList* pWrongs = rPortion.GetNode()->GetWrongList(); + WrongList* pWrongs = rParaPortion.GetNode()->GetWrongList(); if(pWrongs && !pWrongs->empty()) { @@ -3485,7 +3837,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po if(PortionKind::FIELD == rTextPortion.GetKind()) { - const EditCharAttrib* pAttr = rPortion.GetNode()->GetCharAttribs().FindFeature(nIndex); + const EditCharAttrib* pAttr = rParaPortion.GetNode()->GetCharAttribs().FindFeature(nIndex); const SvxFieldItem* pFieldItem = dynamic_cast<const SvxFieldItem*>(pAttr->GetItem()); if(pFieldItem) @@ -3497,7 +3849,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po // support for EOC, EOW, EOS TEXT comments. To support that, // the locale is needed. With the locale and a XBreakIterator it is // possible to re-create the text marking info on primitive level - const lang::Locale aLocale(GetLocale(EditPaM(rPortion.GetNode(), nIndex + 1))); + const lang::Locale aLocale(GetLocale(EditPaM(rParaPortion.GetNode(), nIndex + 1))); // create EOL and EOP bools const bool bEndOfLine(nPortion == pLine->GetEndPortion()); @@ -3516,8 +3868,8 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po ImplCalcDigitLang(aTmpFont.GetLanguage())); // StripPortions() data callback - GetEditEnginePtr()->DrawingText( aOutPos, aText, nTextStart, nTextLen, pDXArray, - aTmpFont, n, rTextPortion.GetRightToLeftLevel(), + GetEditEnginePtr()->DrawingText( aOutPos, aText, nTextStart, nTextLen, pDXArray, pKashidaArray, + aTmpFont, nParaPortion, rTextPortion.GetRightToLeftLevel(), !aWrongSpellVector.empty() ? &aWrongSpellVector : nullptr, pFieldData, bEndOfLine, bEndOfParagraph, // support for EOL/EOP TEXT comments @@ -3545,7 +3897,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po aTmpFont.SetEscapement( 0 ); } - aOutPos = lcl_ImplCalcRotatedPos( aOutPos, aOrigin, nSin, nCos ); + aOrigin.RotateAround(aOutPos, nOrientation); aTmpFont.SetOrientation( aTmpFont.GetOrientation()+nOrientation ); aTmpFont.SetPhysFont(rOutDev); @@ -3564,20 +3916,20 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po // base line of the original font height... // But only if there was something underlined before! bool bSpecialUnderline = false; - EditCharAttrib* pPrev = rPortion.GetNode()->GetCharAttribs().FindAttrib( EE_CHAR_ESCAPEMENT, nIndex ); + EditCharAttrib* pPrev = rParaPortion.GetNode()->GetCharAttribs().FindAttrib( EE_CHAR_ESCAPEMENT, nIndex ); if ( pPrev ) { SvxFont aDummy; // Underscore in front? if ( pPrev->GetStart() ) { - SeekCursor( rPortion.GetNode(), pPrev->GetStart(), aDummy ); + SeekCursor( rParaPortion.GetNode(), pPrev->GetStart(), aDummy ); if ( aDummy.GetUnderline() != LINESTYLE_NONE ) bSpecialUnderline = true; } - if ( !bSpecialUnderline && ( pPrev->GetEnd() < rPortion.GetNode()->Len() ) ) + if ( !bSpecialUnderline && ( pPrev->GetEnd() < rParaPortion.GetNode()->Len() ) ) { - SeekCursor( rPortion.GetNode(), pPrev->GetEnd()+1, aDummy ); + SeekCursor( rParaPortion.GetNode(), pPrev->GetEnd()+1, aDummy ); if ( aDummy.GetUnderline() != LINESTYLE_NONE ) bSpecialUnderline = true; } @@ -3589,11 +3941,14 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po aTmpFont.SetEscapement( 0 ); aTmpFont.SetPropr( 100 ); aTmpFont.SetPhysFont(rOutDev); - OUStringBuffer aBlanks; + OUStringBuffer aBlanks(nTextLen); comphelper::string::padToLength( aBlanks, nTextLen, ' ' ); Point aUnderlinePos( aOutPos ); if ( nOrientation ) - aUnderlinePos = lcl_ImplCalcRotatedPos( aTmpPos, aOrigin, nSin, nCos ); + { + aUnderlinePos = aTmpPos; + aOrigin.RotateAround(aUnderlinePos, nOrientation); + } rOutDev.DrawStretchText( aUnderlinePos, aSz.Width(), aBlanks.makeStringAndClear(), 0, nTextLen ); aTmpFont.SetUnderline( LINESTYLE_NONE ); @@ -3619,47 +3974,63 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po ' ' == aText[nTextStart + nTextLen - 1] ) --nTextLen; + // PDF export: + const SvxFieldData* pFieldData = nullptr; + if (pPDFExtOutDevData) + { + if (rTextPortion.GetKind() == PortionKind::FIELD) + { + const EditCharAttrib* pAttr = rParaPortion.GetNode()->GetCharAttribs().FindFeature(nIndex); + const SvxFieldItem* pFieldItem = dynamic_cast<const SvxFieldItem*>(pAttr->GetItem()); + if (pFieldItem) + { + pFieldData = pFieldItem->GetField(); + auto pUrlField = dynamic_cast<const SvxURLField*>(pFieldData); + if (pUrlField) + if (pPDFExtOutDevData->GetIsExportTaggedPDF()) + pPDFExtOutDevData->WrapBeginStructureElement(vcl::PDFWriter::Link, "Link"); + } + } + } + // output directly - aTmpFont.QuickDrawText( &rOutDev, aRealOutPos, aText, nTextStart, nTextLen, pDXArray ); + aTmpFont.QuickDrawText( &rOutDev, aRealOutPos, aText, nTextStart, nTextLen, pDXArray, pKashidaArray ); if ( bDrawFrame ) { Point aTopLeft( aTmpPos ); aTopLeft.AdjustY( -(pLine->GetMaxAscent()) ); if ( nOrientation ) - aTopLeft = lcl_ImplCalcRotatedPos( aTopLeft, aOrigin, nSin, nCos ); + aOrigin.RotateAround(aTopLeft, nOrientation); tools::Rectangle aRect( aTopLeft, rTextPortion.GetSize() ); rOutDev.DrawRect( aRect ); } // PDF export: - if ( pPDFExtOutDevData ) + if (pPDFExtOutDevData) { - if ( rTextPortion.GetKind() == PortionKind::FIELD ) + if (auto pUrlField = dynamic_cast<const SvxURLField*>(pFieldData)) { - const EditCharAttrib* pAttr = rPortion.GetNode()->GetCharAttribs().FindFeature(nIndex); - const SvxFieldItem* pFieldItem = dynamic_cast<const SvxFieldItem*>(pAttr->GetItem()); - if( pFieldItem ) + Point aTopLeft(aTmpPos); + aTopLeft.AdjustY(-(pLine->GetMaxAscent())); + + tools::Rectangle aRect(aTopLeft, rTextPortion.GetSize()); + vcl::PDFExtOutDevBookmarkEntry aBookmark; + aBookmark.nLinkId = pPDFExtOutDevData->CreateLink(aRect, pUrlField->GetRepresentation()); + aBookmark.aBookmark = pUrlField->GetURL(); + std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFExtOutDevData->GetBookmarks(); + rBookmarks.push_back(aBookmark); + + if (pPDFExtOutDevData->GetIsExportTaggedPDF()) { - const SvxFieldData* pFieldData = pFieldItem->GetField(); - if ( auto pUrlField = dynamic_cast< const SvxURLField* >( pFieldData ) ) - { - Point aTopLeft( aTmpPos ); - aTopLeft.AdjustY( -(pLine->GetMaxAscent()) ); - - tools::Rectangle aRect( aTopLeft, rTextPortion.GetSize() ); - vcl::PDFExtOutDevBookmarkEntry aBookmark; - aBookmark.nLinkId = pPDFExtOutDevData->CreateLink( aRect ); - aBookmark.aBookmark = pUrlField->GetURL(); - std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFExtOutDevData->GetBookmarks(); - rBookmarks.push_back( aBookmark ); - } + pPDFExtOutDevData->SetStructureAttributeNumerical(vcl::PDFWriter::LinkAnnotation, aBookmark.nLinkId); + pPDFExtOutDevData->EndStructureElement(); } } } } - const WrongList* const pWrongList = rPortion.GetNode()->GetWrongList(); + const WrongList* const pWrongList = rParaPortion.GetNode()->GetWrongList(); if ( GetStatus().DoOnlineSpelling() && pWrongList && !pWrongList->empty() && rTextPortion.GetLen() ) { {//#105750# adjust LinePos for superscript or subscript text @@ -3672,7 +4043,10 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po } Color aOldColor( rOutDev.GetLineColor() ); rOutDev.SetLineColor( GetColorConfig().GetColorValue( svtools::SPELL ).nColor ); - lcl_DrawRedLines( rOutDev, aTmpFont.GetFontSize().Height(), aRedLineTmpPos, static_cast<size_t>(nIndex), static_cast<size_t>(nIndex) + rTextPortion.GetLen(), pDXArray, rPortion.GetNode()->GetWrongList(), nOrientation, aOrigin, IsEffectivelyVertical(), rTextPortion.IsRightToLeft() ); + lcl_DrawRedLines(rOutDev, aTmpFont.GetFontSize().Height(), aRedLineTmpPos, + static_cast<size_t>(nIndex), static_cast<size_t>(nIndex) + rTextPortion.GetLen(), + pDXArray, rParaPortion.GetNode()->GetWrongList(), nOrientation, + aOrigin, IsEffectivelyVertical(), rTextPortion.IsRightToLeft()); rOutDev.SetLineColor( aOldColor ); } } @@ -3684,7 +4058,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po // add a meta file comment if we record to a metafile if( bMetafileValid ) { - const EditCharAttrib* pAttr = rPortion.GetNode()->GetCharAttribs().FindFeature(nIndex); + const EditCharAttrib* pAttr = rParaPortion.GetNode()->GetCharAttribs().FindFeature(nIndex); assert( pAttr && "Field not found" ); const SvxFieldItem* pFieldItem = dynamic_cast<const SvxFieldItem*>(pAttr->GetItem()); @@ -3706,12 +4080,12 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po { if ( rTextPortion.GetExtraValue() && ( rTextPortion.GetExtraValue() != ' ' ) ) { - SeekCursor( rPortion.GetNode(), nIndex+1, aTmpFont, &rOutDev ); + SeekCursor(rParaPortion.GetNode(), nIndex+1, aTmpFont, &rOutDev); aTmpFont.SetTransparent( false ); aTmpFont.SetEscapement( 0 ); aTmpFont.SetPhysFont(rOutDev); tools::Long nCharWidth = aTmpFont.QuickGetTextSize( &rOutDev, - OUString(rTextPortion.GetExtraValue()), 0, 1 ).Width(); + OUString(rTextPortion.GetExtraValue()), 0, 1, {} ).Width(); sal_Int32 nChars = 2; if( nCharWidth ) nChars = rTextPortion.GetSize().Width() / nCharWidth; @@ -3720,10 +4094,10 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po else if ( nChars == 2 ) nChars = 3; // looks better - OUStringBuffer aBuf; + OUStringBuffer aBuf(nChars); comphelper::string::padToLength(aBuf, nChars, rTextPortion.GetExtraValue()); OUString aText(aBuf.makeStringAndClear()); - aTmpFont.QuickDrawText( &rOutDev, aTmpPos, aText, 0, aText.getLength() ); + aTmpFont.QuickDrawText( &rOutDev, aTmpPos, aText, 0, aText.getLength(), {} ); rOutDev.DrawStretchText( aTmpPos, rTextPortion.GetSize().Width(), aText ); if ( bStripOnly ) @@ -3739,7 +4113,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po GetEditEnginePtr()->DrawingTab( aTmpPos, rTextPortion.GetSize().Width(), OUString(rTextPortion.GetExtraValue()), - aTmpFont, n, rTextPortion.GetRightToLeftLevel(), + aTmpFont, nParaPortion, rTextPortion.GetRightToLeftLevel(), bEndOfLine, bEndOfParagraph, aOverlineColor, aTextLineColor); } @@ -3756,8 +4130,8 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po const Color aTextLineColor(rOutDev.GetTextLineColor()); GetEditEnginePtr()->DrawingText( - aTmpPos, OUString(), 0, 0, {}, - aTmpFont, n, 0, + aTmpPos, OUString(), 0, 0, {}, {}, + aTmpFont, nParaPortion, 0, nullptr, nullptr, bEndOfLine, bEndOfParagraph, @@ -3777,7 +4151,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po } } - if ( ( nLine != nLastLine ) && !aStatus.IsOutliner() ) + if ((nLine != nLastLine ) && !maStatus.IsOutliner()) { adjustYDirectionAware(aStartPos, nSBL); } @@ -3787,10 +4161,10 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po break; } - if ( !aStatus.IsOutliner() ) + if (!maStatus.IsOutliner()) { - const SvxULSpaceItem& rULItem = rPortion.GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE ); - tools::Long nUL = GetYValue( rULItem.GetLower() ); + const SvxULSpaceItem& rULItem = rParaPortion.GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE ); + tools::Long nUL = scaleYSpacingValue(rULItem.GetLower()); adjustYDirectionAware(aStartPos, nUL); } @@ -3805,8 +4179,8 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po const Color aTextLineColor(rOutDev.GetTextLineColor()); GetEditEnginePtr()->DrawingText( - aTmpPos, OUString(), 0, 0, {}, - aTmpFont, n, 0, + aTmpPos, OUString(), 0, 0, {}, {}, + aTmpFont, nParaPortion, 0, nullptr, nullptr, false, true, // support for EOL/EOP TEXT comments @@ -3882,19 +4256,21 @@ void ImpEditEngine::Paint( ImpEditView* pView, const tools::Rectangle& rRect, Ou pView->DrawSelectionXOR(pView->GetEditSelection(), nullptr, &rTarget); } -void ImpEditEngine::InsertContent( ContentNode* pNode, sal_Int32 nPos ) +void ImpEditEngine::InsertContent(std::unique_ptr<ContentNode> pNode, sal_Int32 nPos ) { DBG_ASSERT( pNode, "NULL-Pointer in InsertContent! " ); DBG_ASSERT( IsInUndo(), "InsertContent only for Undo()!" ); - GetParaPortions().Insert(nPos, ParaPortion( pNode )); - aEditDoc.Insert(nPos, pNode); + + GetParaPortions().Insert(nPos, std::make_unique<ParaPortion>(pNode.get())); + maEditDoc.Insert(nPos, std::move(pNode)); + if ( IsCallParaInsertedOrDeleted() ) GetEditEnginePtr()->ParagraphInserted( nPos ); } EditPaM ImpEditEngine::SplitContent( sal_Int32 nNode, sal_Int32 nSepPos ) { - ContentNode* pNode = aEditDoc.GetObject( nNode ); + ContentNode* pNode = maEditDoc.GetObject( nNode ); DBG_ASSERT( pNode, "Invalid Node in SplitContent" ); DBG_ASSERT( IsInUndo(), "SplitContent only for Undo()!" ); DBG_ASSERT( nSepPos <= pNode->Len(), "Index out of range: SplitContent" ); @@ -3904,8 +4280,8 @@ EditPaM ImpEditEngine::SplitContent( sal_Int32 nNode, sal_Int32 nSepPos ) EditPaM ImpEditEngine::ConnectContents( sal_Int32 nLeftNode, bool bBackward ) { - ContentNode* pLeftNode = aEditDoc.GetObject( nLeftNode ); - ContentNode* pRightNode = aEditDoc.GetObject( nLeftNode+1 ); + ContentNode* pLeftNode = maEditDoc.GetObject( nLeftNode ); + ContentNode* pRightNode = maEditDoc.GetObject( nLeftNode+1 ); DBG_ASSERT( pLeftNode, "Invalid left node in ConnectContents "); DBG_ASSERT( pRightNode, "Invalid right node in ConnectContents "); return ImpConnectParagraphs( pLeftNode, pRightNode, bBackward ); @@ -3913,8 +4289,8 @@ EditPaM ImpEditEngine::ConnectContents( sal_Int32 nLeftNode, bool bBackward ) bool ImpEditEngine::SetUpdateLayout( bool bUp, EditView* pCurView, bool bForceUpdate ) { - const bool bPrevUpdateLayout = bUpdateLayout; - const bool bChanged = (bUpdateLayout != bUp); + const bool bPrevUpdateLayout = mbUpdateLayout; + const bool mbChanged = (mbUpdateLayout != bUp); // When switching from true to false, all selections were visible, // => paint over @@ -3922,8 +4298,8 @@ bool ImpEditEngine::SetUpdateLayout( bool bUp, EditView* pCurView, bool bForceUp // If !bFormatted, e.g. after SetText, then if UpdateMode=true // formatting is not needed immediately, probably because more text is coming. // At latest it is formatted at a Paint/CalcTextWidth. - bUpdateLayout = bUp; - if ( bUpdateLayout && ( bChanged || bForceUpdate ) ) + mbUpdateLayout = bUp; + if ( mbUpdateLayout && ( mbChanged || bForceUpdate ) ) FormatAndLayout( pCurView ); return bPrevUpdateLayout; } @@ -3941,13 +4317,13 @@ void ImpEditEngine::ShowParagraph( sal_Int32 nParagraph, bool bShow ) { // Mark as deleted, so that no selection will end or begin at // this paragraph... - aDeletedNodes.push_back(std::make_unique<DeletedNodeInfo>( pPPortion->GetNode(), nParagraph )); + maDeletedNodes.push_back(std::make_unique<DeletedNodeInfo>( pPPortion->GetNode(), nParagraph )); UpdateSelections(); // The region below will not be invalidated if UpdateMode = sal_False! // If anyway, then save as sal_False before SetVisible ! } - if ( bShow && ( pPPortion->IsInvalid() || !pPPortion->nHeight ) ) + if (bShow && (pPPortion->IsInvalid() || !pPPortion->GetHeight())) { if ( !GetTextRanger() ) { @@ -3957,21 +4333,21 @@ void ImpEditEngine::ShowParagraph( sal_Int32 nParagraph, bool bShow ) } else { - CalcHeight( pPPortion ); + CalcHeight(*pPPortion); } - nCurTextHeight += pPPortion->GetHeight(); + mnCurTextHeight += pPPortion->GetHeight(); } else { - nCurTextHeight = 0x7fffffff; + mnCurTextHeight = 0x7fffffff; } } pPPortion->SetMustRepaint( true ); if ( IsUpdateLayout() && !IsInUndo() && !GetTextRanger() ) { - aInvalidRect = tools::Rectangle( Point( 0, GetParaPortions().GetYOffset( pPPortion ) ), - Point( GetPaperSize().Width(), nCurTextHeight ) ); + maInvalidRect = tools::Rectangle( Point( 0, GetParaPortions().GetYOffset( pPPortion ) ), + Point( GetPaperSize().Width(), mnCurTextHeight ) ); UpdateViews( GetActiveView() ); } } @@ -3981,12 +4357,12 @@ EditSelection ImpEditEngine::MoveParagraphs( Range aOldPositions, sal_Int32 nNew DBG_ASSERT( GetParaPortions().Count() != 0, "No paragraphs found: MoveParagraphs" ); if ( GetParaPortions().Count() == 0 ) return EditSelection(); - aOldPositions.Justify(); + aOldPositions.Normalize(); EditSelection aSel( ImpMoveParagraphs( aOldPositions, nNewPos ) ); - if ( nNewPos >= GetParaPortions().Count() ) - nNewPos = GetParaPortions().Count() - 1; + if (nNewPos >= GetParaPortions().Count()) + nNewPos = GetParaPortions().lastIndex(); // Where the paragraph was inserted it has to be properly redrawn: // Where the paragraph was removed it has to be properly redrawn: @@ -4002,11 +4378,11 @@ EditSelection ImpEditEngine::MoveParagraphs( Range aOldPositions, sal_Int32 nNew ParaPortion* pLowerPortion = GetParaPortions().SafeGetObject( nLastPortion ); if (pUpperPortion && pLowerPortion) { - aInvalidRect = tools::Rectangle(); // make empty - aInvalidRect.SetLeft( 0 ); - aInvalidRect.SetRight(GetColumnWidth(aPaperSize)); - aInvalidRect.SetTop( GetParaPortions().GetYOffset( pUpperPortion ) ); - aInvalidRect.SetBottom( GetParaPortions().GetYOffset( pLowerPortion ) + pLowerPortion->GetHeight() ); + maInvalidRect = tools::Rectangle(); // make empty + maInvalidRect.SetLeft( 0 ); + maInvalidRect.SetRight(GetColumnWidth(maPaperSize)); + maInvalidRect.SetTop( GetParaPortions().GetYOffset( pUpperPortion ) ); + maInvalidRect.SetBottom( GetParaPortions().GetYOffset( pLowerPortion ) + pLowerPortion->GetHeight() ); UpdateViews( pCurView ); } @@ -4024,17 +4400,18 @@ void ImpEditEngine::InvalidateFromParagraph( sal_Int32 nFirstInvPara ) { // The following paragraphs are not invalidated, since ResetHeight() // => size change => all the following are re-issued anyway. - if ( nFirstInvPara != 0 ) + + if (nFirstInvPara != 0) { - ParaPortion& rTmpPortion = GetParaPortions()[nFirstInvPara-1]; - rTmpPortion.MarkInvalid( rTmpPortion.GetNode()->Len(), 0 ); - rTmpPortion.ResetHeight(); + ParaPortion& rPortion = GetParaPortions().getRef(nFirstInvPara - 1); + rPortion.MarkInvalid(rPortion.GetNode()->Len(), 0); + rPortion.ResetHeight(); } else { - ParaPortion& rTmpPortion = GetParaPortions()[0]; - rTmpPortion.MarkSelectionInvalid( 0 ); - rTmpPortion.ResetHeight(); + ParaPortion& rPortion = GetParaPortions().getRef(0); + rPortion.MarkSelectionInvalid(0); + rPortion.ResetHeight(); } } @@ -4045,41 +4422,45 @@ IMPL_LINK_NOARG(ImpEditEngine, StatusTimerHdl, Timer *, void) void ImpEditEngine::CallStatusHdl() { - if ( aStatusHdlLink.IsSet() && bool(aStatus.GetStatusWord()) ) + if (maStatusHdlLink.IsSet() && bool(maStatus.GetStatusWord())) { // The Status has to be reset before the Call, // since other Flags might be set in the handler... - EditStatus aTmpStatus( aStatus ); - aStatus.Clear(); - aStatusHdlLink.Call( aTmpStatus ); - aStatusTimer.Stop(); // If called by hand... + EditStatus aTmpStatus( maStatus ); + maStatus.Clear(); + maStatusHdlLink.Call( aTmpStatus ); + maStatusTimer.Stop(); // If called by hand... } } ContentNode* ImpEditEngine::GetPrevVisNode( ContentNode const * pCurNode ) { - const ParaPortion& rPortion1 = FindParaPortion( pCurNode ); - const ParaPortion* pPortion2 = GetPrevVisPortion( &rPortion1 ); - if ( pPortion2 ) - return pPortion2->GetNode(); + const ParaPortion* pPortion = FindParaPortion( pCurNode ); + DBG_ASSERT( pPortion, "GetPrevVisibleNode: No matching portion!" ); + pPortion = GetPrevVisPortion( pPortion ); + if ( pPortion ) + return pPortion->GetNode(); return nullptr; } ContentNode* ImpEditEngine::GetNextVisNode( ContentNode const * pCurNode ) { - const ParaPortion& rPortion = FindParaPortion( pCurNode ); - const ParaPortion* pPortion = GetNextVisPortion( &rPortion ); + const ParaPortion* pPortion = FindParaPortion( pCurNode ); + DBG_ASSERT( pPortion, "GetNextVisibleNode: No matching portion!" ); + pPortion = GetNextVisPortion( pPortion ); if ( pPortion ) return pPortion->GetNode(); return nullptr; } -const ParaPortion* ImpEditEngine::GetPrevVisPortion( const ParaPortion* pCurPortion ) const +const ParaPortion* ImpEditEngine::GetPrevVisPortion( const ParaPortion* pCurPortion) const { - sal_Int32 nPara = GetParaPortions().GetPos( pCurPortion ); - const ParaPortion* pPortion = nPara ? &GetParaPortions()[--nPara] : nullptr; - while ( pPortion && !pPortion->IsVisible() ) - pPortion = nPara ? &GetParaPortions()[--nPara] : nullptr; + sal_Int32 nPara = GetParaPortions().GetPos(pCurPortion); + DBG_ASSERT(GetParaPortions().exists(nPara) , "Portion not found: GetPrevVisPortion"); + + const ParaPortion* pPortion = nPara ? GetParaPortions().SafeGetObject(--nPara) : nullptr; + while (pPortion && !pPortion->IsVisible()) + pPortion = nPara ? GetParaPortions().SafeGetObject(--nPara) : nullptr; return pPortion; } @@ -4108,17 +4489,17 @@ tools::Long ImpEditEngine::CalcVertLineSpacing(Point& rStartPos) const // All paragraphs must have the block justification set. return 0; - const ParaPortion* pPortion = &rParaPortions[i]; - nTotalOccupiedHeight += pPortion->GetFirstLineOffset(); + ParaPortion const& rPortion = rParaPortions.getRef(i); + nTotalOccupiedHeight += rPortion.GetFirstLineOffset(); - const SvxLineSpacingItem& rLSItem = pPortion->GetNode()->GetContentAttribs().GetItem(EE_PARA_SBL); + const SvxLineSpacingItem& rLSItem = rPortion.GetNode()->GetContentAttribs().GetItem(EE_PARA_SBL); sal_uInt16 nSBL = ( rLSItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Fix ) - ? GetYValue( rLSItem.GetInterLineSpace() ) : 0; + ? scaleYSpacingValue(rLSItem.GetInterLineSpace()) : 0; - const SvxULSpaceItem& rULItem = pPortion->GetNode()->GetContentAttribs().GetItem(EE_PARA_ULSPACE); - tools::Long nUL = GetYValue( rULItem.GetLower() ); + const SvxULSpaceItem& rULItem = rPortion.GetNode()->GetContentAttribs().GetItem(EE_PARA_ULSPACE); + tools::Long nUL = scaleYSpacingValue(rULItem.GetLower()); - const EditLineList& rLines = pPortion->GetLines(); + const EditLineList& rLines = rPortion.GetLines(); sal_Int32 nLineCount = rLines.Count(); nTotalLineCount += nLineCount; for (sal_Int32 j = 0; j < nLineCount; ++j) @@ -4131,7 +4512,7 @@ tools::Long ImpEditEngine::CalcVertLineSpacing(Point& rStartPos) const } } - tools::Long nTotalSpace = getHeightDirectionAware(aPaperSize); + tools::Long nTotalSpace = getHeightDirectionAware(maPaperSize); nTotalSpace -= nTotalOccupiedHeight; if (nTotalSpace <= 0 || nTotalLineCount <= 1) return 0; @@ -4176,17 +4557,19 @@ std::optional<EditSelection> ImpEditEngine::SelectParagraph( sal_Int32 nPara ) void ImpEditEngine::FormatAndLayout( EditView* pCurView, bool bCalledFromUndo ) { - if ( bDowning ) - return ; + if (mbDowning) + return; if ( IsInUndo() ) IdleFormatAndLayout( pCurView ); else { if (bCalledFromUndo) + { // in order to make bullet points that have had their styles changed, redraw themselves - for ( sal_Int32 nPortion = 0; nPortion < GetParaPortions().Count(); nPortion++ ) - GetParaPortions()[nPortion].MarkInvalid( 0, 0 ); + for (auto& pParaPortion : GetParaPortions()) + pParaPortion->MarkInvalid(0, 0); + } FormatDoc(); UpdateViews( pCurView ); } @@ -4197,44 +4580,41 @@ void ImpEditEngine::FormatAndLayout( EditView* pCurView, bool bCalledFromUndo ) void ImpEditEngine::SetFlatMode( bool bFlat ) { - if ( bFlat != aStatus.UseCharAttribs() ) + if ( bFlat != maStatus.UseCharAttribs() ) return; if ( !bFlat ) - aStatus.TurnOnFlags( EEControlBits::USECHARATTRIBS ); + maStatus.TurnOnFlags( EEControlBits::USECHARATTRIBS ); else - aStatus.TurnOffFlags( EEControlBits::USECHARATTRIBS ); + maStatus.TurnOffFlags( EEControlBits::USECHARATTRIBS ); - aEditDoc.CreateDefFont( !bFlat ); + maEditDoc.CreateDefFont( !bFlat ); FormatFullDoc(); UpdateViews(); - if ( pActiveView ) - pActiveView->ShowCursor(); + if (mpActiveView) + mpActiveView->ShowCursor(); } -void ImpEditEngine::SetCharStretching( sal_uInt16 nX, sal_uInt16 nY ) +void ImpEditEngine::setScalingParameters(ScalingParameters const& rScalingParameters) { - bool bChanged; - if ( !IsEffectivelyVertical() ) - { - bChanged = nStretchX!=nX || nStretchY!=nY; - nStretchX = nX; - nStretchY = nY; - } - else + ScalingParameters aNewScalingParameters(rScalingParameters); + + if (IsEffectivelyVertical()) { - bChanged = nStretchX!=nY || nStretchY!=nX; - nStretchX = nY; - nStretchY = nX; + std::swap(aNewScalingParameters.fFontX, aNewScalingParameters.fFontY); + std::swap(aNewScalingParameters.fSpacingX, aNewScalingParameters.fSpacingY); } - if (bChanged && aStatus.DoStretch()) + bool bScalingChanged = maScalingParameters != aNewScalingParameters; + maCustomScalingParameters = maScalingParameters = aNewScalingParameters; + + if (bScalingChanged && maStatus.DoStretch()) { FormatFullDoc(); // (potentially) need everything redrawn - aInvalidRect=tools::Rectangle(0,0,1000000,1000000); - UpdateViews( GetActiveView() ); + maInvalidRect = tools::Rectangle(0, 0, 1000000, 1000000); + UpdateViews(GetActiveView()); } } @@ -4253,7 +4633,7 @@ const SvxNumberFormat* ImpEditEngine::GetNumberFormat( const ContentNode *pNode // object to provide // access to the SvxNumberFormat of the Outliner. // The EditEngine implementation will just return 0. - pRes = pEditEngine->GetNumberFormat( nPara ); + pRes = mpEditEngine->GetNumberFormat( nPara ); } } @@ -4291,23 +4671,21 @@ sal_Int32 ImpEditEngine::GetSpaceBeforeAndMinLabelWidth( const SvxLRSpaceItem& ImpEditEngine::GetLRSpaceItem( ContentNode* pNode ) { - return pNode->GetContentAttribs().GetItem( aStatus.IsOutliner() ? EE_PARA_OUTLLRSPACE : EE_PARA_LRSPACE ); + return pNode->GetContentAttribs().GetItem( maStatus.IsOutliner() ? EE_PARA_OUTLLRSPACE : EE_PARA_LRSPACE ); } // select a representative text language for the digit type according to the // text numeral setting: -LanguageType ImpEditEngine::ImplCalcDigitLang(LanguageType eCurLang) const +LanguageType ImpEditEngine::ImplCalcDigitLang(LanguageType eCurLang) { - if (utl::ConfigManager::IsFuzzing()) + if (comphelper::IsFuzzing()) return LANGUAGE_ENGLISH_US; // #114278# Also setting up digit language from Svt options // (cannot reliably inherit the outdev's setting) - if( !pCTLOptions ) - pCTLOptions.reset( new SvtCTLOptions ); LanguageType eLang = eCurLang; - const SvtCTLOptions::TextNumerals nCTLTextNumerals = pCTLOptions->GetCTLTextNumerals(); + const SvtCTLOptions::TextNumerals nCTLTextNumerals = SvtCTLOptions::GetCTLTextNumerals(); if ( SvtCTLOptions::NUMERALS_HINDI == nCTLTextNumerals ) eLang = LANGUAGE_ARABIC_SAUDI_ARABIA; @@ -4386,35 +4764,49 @@ void ImpEditEngine::ImplInitLayoutMode(OutputDevice& rOutDev, sal_Int32 nPara, s Reference < i18n::XBreakIterator > const & ImpEditEngine::ImplGetBreakIterator() const { - if ( !xBI.is() ) + if (!mxBI.is()) { - Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); - xBI = i18n::BreakIterator::create( xContext ); + uno::Reference<uno::XComponentContext> xContext(::comphelper::getProcessComponentContext()); + mxBI = i18n::BreakIterator::create(xContext); } - return xBI; + return mxBI; } Reference < i18n::XExtendedInputSequenceChecker > const & ImpEditEngine::ImplGetInputSequenceChecker() const { - if ( !xISC.is() ) + if (!mxISC.is()) { - Reference< uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() ); - xISC = i18n::InputSequenceChecker::create( xContext ); + uno::Reference<uno::XComponentContext> xContext(::comphelper::getProcessComponentContext()); + mxISC = i18n::InputSequenceChecker::create(xContext); } - return xISC; + return mxISC; } Color ImpEditEngine::GetAutoColor() const { - Color aColor = GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor; + Color aColor; - if ( GetBackgroundColor() != COL_AUTO ) + if (comphelper::LibreOfficeKit::isActive() && SfxViewShell::Current()) { - if ( GetBackgroundColor().IsDark() && aColor.IsDark() ) + // Get document background color from current view instead + aColor = SfxViewShell::Current()->GetColorConfigColor(svtools::DOCCOLOR); + if (aColor.IsDark()) aColor = COL_WHITE; - else if ( GetBackgroundColor().IsBright() && aColor.IsBright() ) + else aColor = COL_BLACK; } + else + { + aColor = GetColorConfig().GetColorValue(svtools::FONTCOLOR).nColor; + + if ( GetBackgroundColor() != COL_AUTO ) + { + if ( GetBackgroundColor().IsDark() && aColor.IsDark() ) + aColor = COL_WHITE; + else if ( GetBackgroundColor().IsBright() && aColor.IsBright() ) + aColor = COL_BLACK; + } + } return aColor; } @@ -4531,7 +4923,7 @@ bool ImpEditEngine::ImplCalcAsianCompression(ContentNode* pNode, if ( bCompressed && ( n100thPercentFromMax == 10000 ) ) pTextPortion->GetExtraInfos()->nWidthFullCompression = nNewPortionWidth; - pTextPortion->GetSize().setWidth( nNewPortionWidth ); + pTextPortion->setWidth(nNewPortionWidth); if ( pTextPortion->GetExtraInfos() && ( n100thPercentFromMax != 10000 ) ) { @@ -4541,21 +4933,21 @@ bool ImpEditEngine::ImplCalcAsianCompression(ContentNode* pNode, nShrink /= 10000; tools::Long nNewWidth = pTextPortion->GetExtraInfos()->nOrgWidth - nShrink; if ( nNewWidth < pTextPortion->GetSize().Width() ) - pTextPortion->GetSize().setWidth( nNewWidth ); + pTextPortion->setWidth(nNewWidth); } } return bCompressed; } -void ImpEditEngine::ImplExpandCompressedPortions( EditLine* pLine, ParaPortion* pParaPortion, tools::Long nRemainingWidth ) +void ImpEditEngine::ImplExpandCompressedPortions(EditLine& rLine, ParaPortion& rParaPortion, tools::Long nRemainingWidth) { bool bFoundCompressedPortion = false; tools::Long nCompressed = 0; std::vector<TextPortion*> aCompressedPortions; - sal_Int32 nPortion = pLine->GetEndPortion(); - TextPortion* pTP = &pParaPortion->GetTextPortions()[ nPortion ]; + sal_Int32 nPortion = rLine.GetEndPortion(); + TextPortion* pTP = &rParaPortion.GetTextPortions()[ nPortion ]; while ( pTP && ( pTP->GetKind() == PortionKind::TEXT ) ) { if ( pTP->GetExtraInfos() && pTP->GetExtraInfos()->bCompressed ) @@ -4564,7 +4956,7 @@ void ImpEditEngine::ImplExpandCompressedPortions( EditLine* pLine, ParaPortion* nCompressed += pTP->GetExtraInfos()->nOrgWidth - pTP->GetSize().Width(); aCompressedPortions.push_back(pTP); } - pTP = ( nPortion > pLine->GetStartPortion() ) ? &pParaPortion->GetTextPortions()[ --nPortion ] : nullptr; + pTP = ( nPortion > rLine.GetStartPortion() ) ? &rParaPortion.GetTextPortions()[ --nPortion ] : nullptr; } if ( !bFoundCompressedPortion ) @@ -4583,16 +4975,16 @@ void ImpEditEngine::ImplExpandCompressedPortions( EditLine* pLine, ParaPortion* { pTP = pTP2; pTP->GetExtraInfos()->bCompressed = false; - pTP->GetSize().setWidth( pTP->GetExtraInfos()->nOrgWidth ); + pTP->setWidth(pTP->GetExtraInfos()->nOrgWidth); if ( nCompressPercent ) { - sal_Int32 nTxtPortion = pParaPortion->GetTextPortions().GetPos( pTP ); - sal_Int32 nTxtPortionStart = pParaPortion->GetTextPortions().GetStartPos( nTxtPortion ); - DBG_ASSERT( nTxtPortionStart >= pLine->GetStart(), "Portion doesn't belong to the line!!!" ); - sal_Int32* pDXArray = pLine->GetCharPosArray().data() + (nTxtPortionStart - pLine->GetStart()); + sal_Int32 nTxtPortion = rParaPortion.GetTextPortions().GetPos( pTP ); + sal_Int32 nTxtPortionStart = rParaPortion.GetTextPortions().GetStartPos( nTxtPortion ); + DBG_ASSERT( nTxtPortionStart >= rLine.GetStart(), "Portion doesn't belong to the line!!!" ); + sal_Int32* pDXArray = rLine.GetCharPosArray().data() + (nTxtPortionStart - rLine.GetStart()); if ( pTP->GetExtraInfos()->pOrgDXArray ) memcpy( pDXArray, pTP->GetExtraInfos()->pOrgDXArray.get(), (pTP->GetLen()-1)*sizeof(sal_Int32) ); - ImplCalcAsianCompression( pParaPortion->GetNode(), pTP, nTxtPortionStart, pDXArray, static_cast<sal_uInt16>(nCompressPercent), true ); + ImplCalcAsianCompression( rParaPortion.GetNode(), pTP, nTxtPortionStart, pDXArray, static_cast<sal_uInt16>(nCompressPercent), true ); } } } @@ -4602,15 +4994,16 @@ void ImpEditEngine::ImplUpdateOverflowingParaNum(tools::Long nPaperHeight) tools::Long nY = 0; tools::Long nPH; - for ( sal_Int32 nPara = 0; nPara < GetParaPortions().Count(); nPara++ ) { - ParaPortion& rPara = GetParaPortions()[nPara]; - nPH = rPara.GetHeight(); + for (sal_Int32 nPara = 0; nPara < GetParaPortions().Count(); nPara++) + { + ParaPortion& rParaPortion = GetParaPortions().getRef(nPara); + nPH = rParaPortion.GetHeight(); nY += nPH; - if ( nY > nPaperHeight /*nCurTextHeight*/ ) // found first paragraph overflowing + if ( nY > nPaperHeight /*mnCurTextHeight*/ ) // found first paragraph overflowing { mnOverflowingPara = nPara; SAL_INFO("editeng.chaining", "[CHAINING] Setting first overflowing #Para#: " << nPara); - ImplUpdateOverflowingLineNum( nPaperHeight, nPara, nY-nPH); + ImplUpdateOverflowingLineNum( nPaperHeight, nPara, nY - nPH); return; } } @@ -4620,21 +5013,26 @@ void ImpEditEngine::ImplUpdateOverflowingLineNum(tools::Long nPaperHeight, sal_uInt32 nOverflowingPara, tools::Long nHeightBeforeOverflowingPara) { + if (GetParaPortions().exists(nOverflowingPara)) + return; + tools::Long nY = nHeightBeforeOverflowingPara; tools::Long nLH; - ParaPortion& rPara = GetParaPortions()[nOverflowingPara]; + ParaPortion& rParaPortion = GetParaPortions().getRef(nOverflowingPara); // Like UpdateOverflowingParaNum but for each line in the first // overflowing paragraph. - for ( sal_Int32 nLine = 0; nLine < rPara.GetLines().Count(); nLine++ ) { + for (sal_Int32 nLine = 0; nLine < rParaPortion.GetLines().Count(); nLine++) + { // XXX: We must use a reference here because the copy constructor resets the height - EditLine &aLine = rPara.GetLines()[nLine]; + EditLine &aLine = rParaPortion.GetLines()[nLine]; nLH = aLine.GetHeight(); nY += nLH; // Debugging output - if (nLine == 0) { + if (nLine == 0) + { SAL_INFO("editeng.chaining", "[CHAINING] First line has height " << nLH); } diff --git a/editeng/source/editeng/impedit4.cxx b/editeng/source/editeng/impedit4.cxx index e160f3896f37..121259f7e394 100644 --- a/editeng/source/editeng/impedit4.cxx +++ b/editeng/source/editeng/impedit4.cxx @@ -18,11 +18,10 @@ */ -#include <vcl/svapp.hxx> - #include <svl/srchitem.hxx> -#include <editeng/lspcitem.hxx> #include <editeng/adjustitem.hxx> +#include <editeng/cmapitem.hxx> +#include <editeng/lspcitem.hxx> #include <editeng/tstpitem.hxx> #include "eertfpar.hxx" @@ -35,6 +34,7 @@ #include <sal/log.hxx> #include <o3tl/safeint.hxx> #include <osl/diagnose.h> +#include <osl/thread.h> #include <editxml.hxx> @@ -73,6 +73,7 @@ #include <svtools/rtfkeywd.hxx> #include <editeng/edtdlg.hxx> +#include <cstddef> #include <memory> #include <unordered_map> #include <vector> @@ -116,10 +117,6 @@ EditPaM ImpEditEngine::ReadText( SvStream& rInput, EditSelection aSel ) bool bDone = rInput.ReadByteStringLine( aTmpStr, rInput.GetStreamCharSet() ); while ( bDone ) { - if (aTmpStr.getLength() > MAXCHARSINPARA) - { - aTmpStr = aTmpStr.copy(0, MAXCHARSINPARA); - } aPaM = ImpInsertText( EditSelection( aPaM, aPaM ), aTmpStr ); aPaM = ImpInsertParaBreak( aPaM ); bDone = rInput.ReadByteStringLine( aTmpStr, rInput.GetStreamCharSet() ); @@ -144,7 +141,7 @@ EditPaM ImpEditEngine::ReadRTF( SvStream& rInput, EditSelection aSel ) // The SvRTF parser expects the Which-mapping passed on in the pool, not // dependent on a secondary. - SfxItemPool* pPool = &aEditDoc.GetItemPool(); + SfxItemPool* pPool = &maEditDoc.GetItemPool(); while (pPool->GetSecondaryPool() && pPool->GetName() != "EditEngineItemPool") { pPool = pPool->GetSecondaryPool(); @@ -153,7 +150,7 @@ EditPaM ImpEditEngine::ReadRTF( SvStream& rInput, EditSelection aSel ) DBG_ASSERT(pPool && pPool->GetName() == "EditEngineItemPool", "ReadRTF: no EditEnginePool!"); - EditRTFParserRef xPrsr = new EditRTFParser(rInput, aSel, *pPool, pEditEngine); + EditRTFParserRef xPrsr = new EditRTFParser(rInput, aSel, *pPool, mpEditEngine); SvParserState eState = xPrsr->CallParser(); if ( ( eState != SvParserState::Accepted ) && ( !rInput.GetError() ) ) { @@ -169,7 +166,7 @@ EditPaM ImpEditEngine::ReadHTML( SvStream& rInput, const OUString& rBaseURL, Edi aSel = ImpDeleteSelection( aSel ); EditHTMLParserRef xPrsr = new EditHTMLParser( rInput, rBaseURL, pHTTPHeaderAttrs ); - SvParserState eState = xPrsr->CallParser(pEditEngine, aSel.Max()); + SvParserState eState = xPrsr->CallParser(mpEditEngine, aSel.Max()); if ( ( eState != SvParserState::Accepted ) && ( !rInput.GetError() ) ) { rInput.SetError( EE_READWRITE_WRONGFORMAT ); @@ -206,20 +203,20 @@ ErrCode ImpEditEngine::WriteText( SvStream& rOutput, EditSelection aSel ) bool bRange = aSel.HasRange(); if ( bRange ) { - aSel.Adjust( aEditDoc ); - nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() ); - nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() ); + aSel.Adjust( maEditDoc ); + nStartNode = maEditDoc.GetPos( aSel.Min().GetNode() ); + nEndNode = maEditDoc.GetPos( aSel.Max().GetNode() ); } else { nStartNode = 0; - nEndNode = aEditDoc.Count()-1; + nEndNode = maEditDoc.Count()-1; } // iterate over the paragraphs ... for ( sal_Int32 nNode = nStartNode; nNode <= nEndNode; nNode++ ) { - ContentNode* pNode = aEditDoc.GetObject( nNode ); + ContentNode* pNode = maEditDoc.GetObject( nNode ); DBG_ASSERT( pNode, "Node not found: Search&Replace" ); sal_Int32 nStartPos = 0; @@ -252,7 +249,7 @@ bool ImpEditEngine::WriteItemListAsRTF( ItemList& rLst, SvStream& rOutput, sal_I static void lcl_FindValidAttribs( ItemList& rLst, ContentNode* pNode, sal_Int32 nIndex, sal_uInt16 nScriptType ) { - sal_uInt16 nAttr = 0; + std::size_t nAttr = 0; EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr ); while ( pAttr && ( pAttr->GetStart() <= nIndex ) ) { @@ -282,25 +279,25 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) FormatDoc(); sal_Int32 nStartNode, nEndNode; - aSel.Adjust( aEditDoc ); + aSel.Adjust( maEditDoc ); - nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() ); - nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() ); + nStartNode = maEditDoc.GetPos( aSel.Min().GetNode() ); + nEndNode = maEditDoc.GetPos( aSel.Max().GetNode() ); // RTF header ... rOutput.WriteChar( '{' ) ; - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_RTF ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_RTF ); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_ANSI ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_ANSI ); rtl_TextEncoding eDestEnc = RTL_TEXTENCODING_MS_1252; // Generate and write out Font table ... std::vector<std::unique_ptr<SvxFontItem>> aFontTable; // default font must be up front, so DEF font in RTF - aFontTable.emplace_back( new SvxFontItem( aEditDoc.GetItemPool().GetDefaultItem( EE_CHAR_FONTINFO ) ) ); - aFontTable.emplace_back( new SvxFontItem( aEditDoc.GetItemPool().GetDefaultItem( EE_CHAR_FONTINFO_CJK ) ) ); - aFontTable.emplace_back( new SvxFontItem( aEditDoc.GetItemPool().GetDefaultItem( EE_CHAR_FONTINFO_CTL ) ) ); + aFontTable.emplace_back( new SvxFontItem( maEditDoc.GetItemPool().GetUserOrPoolDefaultItem( EE_CHAR_FONTINFO ) ) ); + aFontTable.emplace_back( new SvxFontItem( maEditDoc.GetItemPool().GetUserOrPoolDefaultItem( EE_CHAR_FONTINFO_CJK ) ) ); + aFontTable.emplace_back( new SvxFontItem( maEditDoc.GetItemPool().GetUserOrPoolDefaultItem( EE_CHAR_FONTINFO_CTL ) ) ); for ( sal_uInt16 nScriptType = 0; nScriptType < 3; nScriptType++ ) { sal_uInt16 nWhich = EE_CHAR_FONTINFO; @@ -309,12 +306,14 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) else if ( nScriptType == 2 ) nWhich = EE_CHAR_FONTINFO_CTL; - for (const SfxPoolItem* pItem : aEditDoc.GetItemPool().GetItemSurrogates(nWhich)) + ItemSurrogates aSurrogates; + maEditDoc.GetItemPool().GetItemSurrogates(aSurrogates, nWhich); + for (const SfxPoolItem* pItem : aSurrogates) { SvxFontItem const*const pFontItem = static_cast<const SvxFontItem*>(pItem); bool bAlreadyExist = false; - sal_uLong nTestMax = nScriptType ? aFontTable.size() : 1; - for ( sal_uLong nTest = 0; !bAlreadyExist && ( nTest < nTestMax ); nTest++ ) + size_t nTestMax = nScriptType ? aFontTable.size() : 1; + for ( size_t nTest = 0; !bAlreadyExist && ( nTest < nTestMax ); nTest++ ) { bAlreadyExist = *aFontTable[ nTest ] == *pFontItem; } @@ -325,31 +324,31 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) } rOutput << endl; - rOutput.WriteChar( '{' ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_FONTTBL ); + rOutput.WriteChar( '{' ).WriteOString( OOO_STRING_SVTOOLS_RTF_FONTTBL ); for ( std::vector<SvxFontItem*>::size_type j = 0; j < aFontTable.size(); j++ ) { SvxFontItem* pFontItem = aFontTable[ j ].get(); rOutput.WriteChar( '{' ); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_F ); - rOutput.WriteUInt32AsString( j ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_F ); + rOutput.WriteNumberAsString( j ); switch ( pFontItem->GetFamily() ) { - case FAMILY_DONTKNOW: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_FNIL ); + case FAMILY_DONTKNOW: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_FNIL ); break; - case FAMILY_DECORATIVE: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_FDECOR ); + case FAMILY_DECORATIVE: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_FDECOR ); break; - case FAMILY_MODERN: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_FMODERN ); + case FAMILY_MODERN: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_FMODERN ); break; - case FAMILY_ROMAN: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_FROMAN ); + case FAMILY_ROMAN: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_FROMAN ); break; - case FAMILY_SCRIPT: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_FSCRIPT ); + case FAMILY_SCRIPT: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_FSCRIPT ); break; - case FAMILY_SWISS: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_FSWISS ); + case FAMILY_SWISS: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_FSWISS ); break; default: break; } - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_FPRQ ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_FPRQ ); sal_uInt16 nVal = 0; switch( pFontItem->GetPitch() ) { @@ -358,18 +357,28 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) default: break; } - rOutput.WriteUInt32AsString( nVal ); + rOutput.WriteNumberAsString( nVal ); rtl_TextEncoding eChrSet = pFontItem->GetCharSet(); + // tdf#47679 OpenSymbol is not encoded in Symbol Encoding + // and anyway we always attempt to write as eDestEnc + // of RTL_TEXTENCODING_MS_1252 and pay no attention + // on export what encoding we claim to use for these + // fonts. + if (IsOpenSymbol(pFontItem->GetFamilyName())) + { + SAL_WARN_IF(eChrSet == RTL_TEXTENCODING_SYMBOL, "editeng", "OpenSymbol should not have charset of RTL_TEXTENCODING_SYMBOL in new documents"); + eChrSet = RTL_TEXTENCODING_UTF8; + } DBG_ASSERT( eChrSet != 9, "SystemCharSet?!" ); if( RTL_TEXTENCODING_DONTKNOW == eChrSet ) eChrSet = osl_getThreadTextEncoding(); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_FCHARSET ); - rOutput.WriteUInt32AsString( rtl_getBestWindowsCharsetFromTextEncoding( eChrSet ) ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_FCHARSET ); + rOutput.WriteNumberAsString( rtl_getBestWindowsCharsetFromTextEncoding( eChrSet ) ); rOutput.WriteChar( ' ' ); RTFOutFuncs::Out_String( rOutput, pFontItem->GetFamilyName(), eDestEnc ); - rOutput.WriteCharPtr( ";}" ); + rOutput.WriteOString( ";}" ); } rOutput.WriteChar( '}' ); rOutput << endl; @@ -378,12 +387,14 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) SvxColorList aColorList; // COL_AUTO should be the default color, always put it first aColorList.emplace_back(COL_AUTO); - SvxColorItem const& rDefault(aEditDoc.GetItemPool().GetDefaultItem(EE_CHAR_COLOR)); + SvxColorItem const& rDefault(maEditDoc.GetItemPool().GetUserOrPoolDefaultItem(EE_CHAR_COLOR)); if (rDefault.GetValue() != COL_AUTO) // is the default always AUTO? { aColorList.push_back(rDefault.GetValue()); } - for (const SfxPoolItem* pItem : aEditDoc.GetItemPool().GetItemSurrogates(EE_CHAR_COLOR)) + ItemSurrogates aSurrogates; + maEditDoc.GetItemPool().GetItemSurrogates(aSurrogates, EE_CHAR_COLOR); + for (const SfxPoolItem* pItem : aSurrogates) { auto pColorItem(dynamic_cast<SvxColorItem const*>(pItem)); if (pColorItem && pColorItem->GetValue() != COL_AUTO) // may be null! @@ -392,18 +403,18 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) } } - rOutput.WriteChar( '{' ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_COLORTBL ); + rOutput.WriteChar( '{' ).WriteOString( OOO_STRING_SVTOOLS_RTF_COLORTBL ); for ( SvxColorList::size_type j = 0; j < aColorList.size(); j++ ) { Color const color = aColorList[j]; if (color != COL_AUTO) // auto is represented by "empty" element { - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_RED ); - rOutput.WriteUInt32AsString( color.GetRed() ); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_GREEN ); - rOutput.WriteUInt32AsString( color.GetGreen() ); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_BLUE ); - rOutput.WriteUInt32AsString( color.GetBlue() ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_RED ); + rOutput.WriteNumberAsString( color.GetRed() ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_GREEN ); + rOutput.WriteNumberAsString( color.GetGreen() ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_BLUE ); + rOutput.WriteNumberAsString( color.GetBlue() ); } rOutput.WriteChar( ';' ); } @@ -429,16 +440,16 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) { sal_uInt32 nStyle = 0; - rOutput.WriteChar( '{' ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_STYLESHEET ); + rOutput.WriteChar( '{' ).WriteOString( OOO_STRING_SVTOOLS_RTF_STYLESHEET ); for ( SfxStyleSheetBase* pStyle = aSSSIterator->First(); pStyle; pStyle = aSSSIterator->Next() ) { rOutput << endl; - rOutput.WriteChar( '{' ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_S ); + rOutput.WriteChar( '{' ).WriteOString( OOO_STRING_SVTOOLS_RTF_S ); sal_uInt32 nNumber = nStyle + 1; - rOutput.WriteUInt32AsString( nNumber ); + rOutput.WriteNumberAsString( nNumber ); // Attribute, also from Parent! for ( sal_uInt16 nParAttr = EE_PARA_START; nParAttr <= EE_CHAR_END; nParAttr++ ) @@ -455,9 +466,11 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) { SfxStyleSheet* pParent = static_cast<SfxStyleSheet*>(GetStyleSheetPool()->Find( pStyle->GetParent(), pStyle->GetFamily() )); DBG_ASSERT( pParent, "Parent not found!" ); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_SBASEDON ); - nNumber = aStyleSheetToIdMap.find(pParent)->second; - rOutput.WriteUInt32AsString( nNumber ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_SBASEDON ); + auto iter = aStyleSheetToIdMap.find(pParent); + assert(iter != aStyleSheetToIdMap.end()); + nNumber = iter->second; + rOutput.WriteNumberAsString( nNumber ); } // Next Style... (more) @@ -467,14 +480,16 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) pNext = static_cast<SfxStyleSheet*>(GetStyleSheetPool()->Find( pStyle->GetFollow(), pStyle->GetFamily() )); DBG_ASSERT( pNext, "Next not found!" ); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_SNEXT ); - nNumber = aStyleSheetToIdMap.find(pNext)->second; - rOutput.WriteUInt32AsString( nNumber ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_SNEXT ); + auto iter = aStyleSheetToIdMap.find(pNext); + assert(iter != aStyleSheetToIdMap.end()); + nNumber = iter->second; + rOutput.WriteNumberAsString( nNumber ); // Name of the template... - rOutput.WriteCharPtr( " " ); + rOutput.WriteOString( " " ); RTFOutFuncs::Out_String( rOutput, pStyle->GetName(), eDestEnc ); - rOutput.WriteCharPtr( ";}" ); + rOutput.WriteOString( ";}" ); nStyle++; } rOutput.WriteChar( '}' ); @@ -483,10 +498,10 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) } // Write the pool defaults in advance ... - rOutput.WriteChar( '{' ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_IGNORE ).WriteCharPtr( "\\EditEnginePoolDefaults" ); + rOutput.WriteChar( '{' ).WriteOString( OOO_STRING_SVTOOLS_RTF_IGNORE ).WriteOString( "\\EditEnginePoolDefaults" ); for ( sal_uInt16 nPoolDefItem = EE_PARA_START; nPoolDefItem <= EE_CHAR_END; nPoolDefItem++) { - const SfxPoolItem& rItem = aEditDoc.GetItemPool().GetDefaultItem( nPoolDefItem ); + const SfxPoolItem& rItem = maEditDoc.GetItemPool().GetUserOrPoolDefaultItem( nPoolDefItem ); WriteItemAsRTF( rItem, rOutput, 0, 0, aFontTable, aColorList ); } rOutput.WriteChar( '}' ) << endl; @@ -494,17 +509,17 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) // DefTab: MapMode aTwpMode( MapUnit::MapTwip ); sal_uInt16 nDefTabTwps = static_cast<sal_uInt16>(GetRefDevice()->LogicToLogic( - Point( aEditDoc.GetDefTab(), 0 ), + Point( maEditDoc.GetDefTab(), 0 ), &GetRefMapMode(), &aTwpMode ).X()); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_DEFTAB ); - rOutput.WriteUInt32AsString( nDefTabTwps ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_DEFTAB ); + rOutput.WriteNumberAsString( nDefTabTwps ); rOutput << endl; // iterate over the paragraphs ... rOutput.WriteChar( '{' ) << endl; for ( sal_Int32 nNode = nStartNode; nNode <= nEndNode; nNode++ ) { - ContentNode* pNode = aEditDoc.GetObject( nNode ); + ContentNode* pNode = maEditDoc.GetObject( nNode ); DBG_ASSERT( pNode, "Node not found: Search&Replace" ); // The paragraph attributes in advance ... @@ -514,9 +529,11 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) if ( pNode->GetStyleSheet() ) { // Number of template - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_S ); - sal_uInt32 nNumber = aStyleSheetToIdMap.find(pNode->GetStyleSheet())->second; - rOutput.WriteUInt32AsString( nNumber ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_S ); + auto iter = aStyleSheetToIdMap.find(pNode->GetStyleSheet()); + assert(iter != aStyleSheetToIdMap.end()); + sal_uInt32 nNumber = iter->second; + rOutput.WriteNumberAsString( nNumber ); // All Attribute // Attribute, also from Parent! @@ -545,20 +562,21 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) rOutput.WriteChar( ' ' ); // Separator ItemList aAttribItems; - ParaPortion& rParaPortion = FindParaPortion( pNode ); + ParaPortion* pParaPortion = FindParaPortion( pNode ); + DBG_ASSERT( pParaPortion, "Portion not found: WriteRTF" ); sal_Int32 nIndex = 0; sal_Int32 nStartPos = 0; sal_Int32 nEndPos = pNode->Len(); sal_Int32 nStartPortion = 0; - sal_Int32 nEndPortion = rParaPortion.GetTextPortions().Count() - 1; + sal_Int32 nEndPortion = pParaPortion->GetTextPortions().Count() - 1; bool bFinishPortion = false; sal_Int32 nPortionStart; if ( nNode == nStartNode ) { nStartPos = aSel.Min().GetIndex(); - nStartPortion = rParaPortion.GetTextPortions().FindPortion( nStartPos, nPortionStart ); + nStartPortion = pParaPortion->GetTextPortions().FindPortion( nStartPos, nPortionStart ); if ( nStartPos != 0 ) { aAttribItems.Clear(); @@ -576,14 +594,14 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) if ( nNode == nEndNode ) // can also be == nStart! { nEndPos = aSel.Max().GetIndex(); - nEndPortion = rParaPortion.GetTextPortions().FindPortion( nEndPos, nPortionStart ); + nEndPortion = pParaPortion->GetTextPortions().FindPortion( nEndPos, nPortionStart ); } const EditCharAttrib* pNextFeature = pNode->GetCharAttribs().FindFeature(nIndex); // start at 0, so the index is right ... for ( sal_Int32 n = 0; n <= nEndPortion; n++ ) { - const TextPortion& rTextPortion = rParaPortion.GetTextPortions()[n]; + const TextPortion& rTextPortion = pParaPortion->GetTextPortions()[n]; if ( n < nStartPortion ) { nIndex = nIndex + rTextPortion.GetLen(); @@ -636,12 +654,11 @@ ErrCode ImpEditEngine::WriteRTF( SvStream& rOutput, EditSelection aSel ) nIndex = nIndex + rTextPortion.GetLen(); } - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_PAR ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_PARD ).WriteCharPtr( OOO_STRING_SVTOOLS_RTF_PLAIN ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_PAR ).WriteOString( OOO_STRING_SVTOOLS_RTF_PARD ).WriteOString( OOO_STRING_SVTOOLS_RTF_PLAIN ); rOutput << endl; } // RTF-trailer ... - rOutput.WriteCharPtr( "}}" ); // 1xparentheses paragraphs, 1xparentheses RTF document - rOutput.Flush(); + rOutput.WriteOString( "}}" ); // 1xparentheses paragraphs, 1xparentheses RTF document aFontTable.clear(); @@ -659,9 +676,9 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, { const SvxFrameDirectionItem& rWritingMode = static_cast<const SvxFrameDirectionItem&>(rItem); if ( rWritingMode.GetValue() == SvxFrameDirection::Horizontal_RL_TB ) - rOutput.WriteCharPtr( "\\rtlpar" ); + rOutput.WriteOString( "\\rtlpar" ); else - rOutput.WriteCharPtr( "\\ltrpar" ); + rOutput.WriteOString( "\\ltrpar" ); } break; case EE_PARA_OUTLLEVEL: @@ -669,43 +686,43 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, sal_Int32 nLevel = static_cast<const SfxInt16Item&>(rItem).GetValue(); if( nLevel >= 0 ) { - rOutput.WriteCharPtr( "\\level" ); - rOutput.WriteInt32AsString( nLevel ); + rOutput.WriteOString( "\\level" ); + rOutput.WriteNumberAsString( nLevel ); } } break; case EE_PARA_OUTLLRSPACE: case EE_PARA_LRSPACE: { - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_FI ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_FI ); sal_Int32 nTxtFirst = static_cast<const SvxLRSpaceItem&>(rItem).GetTextFirstLineOffset(); nTxtFirst = LogicToTwips( nTxtFirst ); - rOutput.WriteInt32AsString( nTxtFirst ); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_LI ); + rOutput.WriteNumberAsString( nTxtFirst ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_LI ); sal_uInt32 nTxtLeft = static_cast< sal_uInt32 >(static_cast<const SvxLRSpaceItem&>(rItem).GetTextLeft()); nTxtLeft = static_cast<sal_uInt32>(LogicToTwips( nTxtLeft )); - rOutput.WriteInt32AsString( nTxtLeft ); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_RI ); + rOutput.WriteNumberAsString( nTxtLeft ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_RI ); sal_uInt32 nTxtRight = static_cast<const SvxLRSpaceItem&>(rItem).GetRight(); nTxtRight = LogicToTwips( nTxtRight); - rOutput.WriteUInt32AsString( nTxtRight ); + rOutput.WriteNumberAsString( nTxtRight ); } break; case EE_PARA_ULSPACE: { - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_SB ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_SB ); sal_uInt32 nUpper = static_cast<const SvxULSpaceItem&>(rItem).GetUpper(); nUpper = static_cast<sal_uInt32>(LogicToTwips( nUpper )); - rOutput.WriteUInt32AsString( nUpper ); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_SA ); + rOutput.WriteNumberAsString( nUpper ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_SA ); sal_uInt32 nLower = static_cast<const SvxULSpaceItem&>(rItem).GetLower(); nLower = LogicToTwips( nLower ); - rOutput.WriteUInt32AsString( nLower ); + rOutput.WriteNumberAsString( nLower ); } break; case EE_PARA_SBL: { - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_SL ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_SL ); sal_Int32 nVal = static_cast<const SvxLineSpacingItem&>(rItem).GetLineHeight(); char cMult = '0'; if ( static_cast<const SvxLineSpacingItem&>(rItem).GetInterLineSpaceRule() == SvxInterLineSpaceRule::Prop ) @@ -717,8 +734,8 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, nVal /= 100; cMult = '1'; } - rOutput.WriteInt32AsString( nVal ); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_SLMULT ).WriteChar( cMult ); + rOutput.WriteNumberAsString( nVal ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_SLMULT ).WriteChar( cMult ); } break; case EE_PARA_JUST: @@ -726,11 +743,11 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, SvxAdjust eJustification = static_cast<const SvxAdjustItem&>(rItem).GetAdjust(); switch ( eJustification ) { - case SvxAdjust::Center: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_QC ); + case SvxAdjust::Center: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_QC ); break; - case SvxAdjust::Right: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_QR ); + case SvxAdjust::Right: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_QR ); break; - default: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_QL ); + default: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_QL ); break; } } @@ -741,8 +758,8 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, for ( sal_uInt16 i = 0; i < rTabs.Count(); i++ ) { const SvxTabStop& rTab = rTabs[i]; - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_TX ); - rOutput.WriteInt32AsString( LogicToTwips( rTab.GetTabPos() ) ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_TX ); + rOutput.WriteNumberAsString( LogicToTwips( rTab.GetTabPos() ) ); } } break; @@ -753,8 +770,8 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, static_cast<SvxColorItem const&>(rItem).GetValue()); assert(iter != rColorList.end()); sal_uInt32 const n = iter - rColorList.begin(); - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_CF ); - rOutput.WriteUInt32AsString( n ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_CF ); + rOutput.WriteNumberAsString( n ); } break; case EE_CHAR_FONTINFO: @@ -771,20 +788,20 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, } } - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_F ); - rOutput.WriteUInt32AsString( n ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_F ); + rOutput.WriteNumberAsString( n ); } break; case EE_CHAR_FONTHEIGHT: case EE_CHAR_FONTHEIGHT_CJK: case EE_CHAR_FONTHEIGHT_CTL: { - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_FS ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_FS ); sal_Int32 nHeight = static_cast<const SvxFontHeightItem&>(rItem).GetHeight(); nHeight = LogicToTwips( nHeight ); // Twips => HalfPoints nHeight /= 10; - rOutput.WriteInt32AsString( nHeight ); + rOutput.WriteNumberAsString( nHeight ); } break; case EE_CHAR_WEIGHT: @@ -794,8 +811,8 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, FontWeight e = static_cast<const SvxWeightItem&>(rItem).GetWeight(); switch ( e ) { - case WEIGHT_BOLD: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_B ); break; - default: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_B ).WriteChar( '0' ); break; + case WEIGHT_BOLD: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_B ); break; + default: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_B ).WriteChar( '0' ); break; } } break; @@ -806,10 +823,10 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, FontLineStyle e = static_cast<const SvxUnderlineItem&>(rItem).GetLineStyle(); switch ( e ) { - case LINESTYLE_NONE: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_ULNONE ); break; - case LINESTYLE_SINGLE: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_UL ); break; - case LINESTYLE_DOUBLE: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_ULDB ); break; - case LINESTYLE_DOTTED: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_ULD ); break; + case LINESTYLE_NONE: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_ULNONE ); break; + case LINESTYLE_SINGLE: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_UL ); break; + case LINESTYLE_DOUBLE: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_ULDB ); break; + case LINESTYLE_DOTTED: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_ULD ); break; default: break; } @@ -820,10 +837,10 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, FontLineStyle e = static_cast<const SvxOverlineItem&>(rItem).GetLineStyle(); switch ( e ) { - case LINESTYLE_NONE: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_OLNONE ); break; - case LINESTYLE_SINGLE: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_OL ); break; - case LINESTYLE_DOUBLE: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_OLDB ); break; - case LINESTYLE_DOTTED: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_OLD ); break; + case LINESTYLE_NONE: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_OLNONE ); break; + case LINESTYLE_SINGLE: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_OL ); break; + case LINESTYLE_DOUBLE: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_OLDB ); break; + case LINESTYLE_DOTTED: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_OLD ); break; default: break; } @@ -835,8 +852,8 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, switch ( e ) { case STRIKEOUT_SINGLE: - case STRIKEOUT_DOUBLE: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_STRIKE ); break; - case STRIKEOUT_NONE: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_STRIKE ).WriteChar( '0' ); break; + case STRIKEOUT_DOUBLE: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_STRIKE ); break; + case STRIKEOUT_NONE: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_STRIKE ).WriteChar( '0' ); break; default: break; } @@ -850,8 +867,8 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, switch ( e ) { case ITALIC_OBLIQUE: - case ITALIC_NORMAL: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_I ); break; - case ITALIC_NONE: rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_I ).WriteChar( '0' ); break; + case ITALIC_NORMAL: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_I ); break; + case ITALIC_NONE: rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_I ).WriteChar( '0' ); break; default: break; } @@ -859,7 +876,7 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, break; case EE_CHAR_OUTLINE: { - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_OUTL ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_OUTL ); if ( !static_cast<const SvxContourItem&>(rItem).GetValue() ) rOutput.WriteChar( '0' ); } @@ -868,56 +885,56 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, { FontRelief nRelief = static_cast<const SvxCharReliefItem&>(rItem).GetValue(); if ( nRelief == FontRelief::Embossed ) - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_EMBO ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_EMBO ); if ( nRelief == FontRelief::Engraved ) - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_IMPR ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_IMPR ); } break; case EE_CHAR_EMPHASISMARK: { FontEmphasisMark nMark = static_cast<const SvxEmphasisMarkItem&>(rItem).GetEmphasisMark(); if ( nMark == FontEmphasisMark::NONE ) - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_ACCNONE ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_ACCNONE ); else if ( nMark == (FontEmphasisMark::Accent | FontEmphasisMark::PosAbove) ) - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_ACCCOMMA ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_ACCCOMMA ); else - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_ACCDOT ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_ACCDOT ); } break; case EE_CHAR_SHADOW: { - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_SHAD ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_SHAD ); if ( !static_cast<const SvxShadowedItem&>(rItem).GetValue() ) rOutput.WriteChar( '0' ); } break; case EE_FEATURE_TAB: { - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_TAB ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_TAB ); } break; case EE_FEATURE_LINEBR: { - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_SL ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_LINE ); } break; case EE_CHAR_KERNING: { - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_EXPNDTW ); - rOutput.WriteInt32AsString( LogicToTwips( + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_EXPNDTW ); + rOutput.WriteNumberAsString( LogicToTwips( static_cast<const SvxKerningItem&>(rItem).GetValue() ) ); } break; case EE_CHAR_PAIRKERNING: { - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_KERNING ); - rOutput.WriteUInt32AsString( static_cast<const SvxAutoKernItem&>(rItem).GetValue() ? 1 : 0 ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_KERNING ); + rOutput.WriteNumberAsString( static_cast<const SvxAutoKernItem&>(rItem).GetValue() ? 1 : 0 ); } break; case EE_CHAR_ESCAPEMENT: { SvxFont aFont; - ContentNode* pNode = aEditDoc.GetObject( nPara ); + ContentNode* pNode = maEditDoc.GetObject( nPara ); SeekCursor( pNode, nPos, aFont ); MapMode aPntMode( MapUnit::MapPoint ); tools::Long nFontHeight = GetRefDevice()->LogicToLogic( @@ -948,15 +965,35 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, // SWG: if ( nEsc ) { - rOutput.WriteCharPtr( "{\\*\\updnprop" ).WriteCharPtr( OString::number( - nProp100).getStr() ).WriteChar( '}' ); + rOutput.WriteOString( "{\\*\\updnprop" ).WriteNumberAsString( + nProp100 ).WriteChar( '}' ); } tools::Long nUpDown = nFontHeight * std::abs( nEsc ) / 100; if ( nEsc < 0 ) - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_DN ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_DN ); else if ( nEsc > 0 ) - rOutput.WriteCharPtr( OOO_STRING_SVTOOLS_RTF_UP ); - rOutput.WriteOString( OString::number(nUpDown) ); + rOutput.WriteOString( OOO_STRING_SVTOOLS_RTF_UP ); + rOutput.WriteNumberAsString(nUpDown); + } + break; + case EE_CHAR_CASEMAP: + { + const SvxCaseMapItem& rCaseMap = static_cast<const SvxCaseMapItem&>(rItem); + switch (rCaseMap.GetValue()) + { + case SvxCaseMap::SmallCaps: + rOutput.WriteOString(OOO_STRING_SVTOOLS_RTF_SCAPS); + break; + case SvxCaseMap::Uppercase: + rOutput.WriteOString(OOO_STRING_SVTOOLS_RTF_CAPS); + break; + default: // Something that rtf does not support + rOutput.WriteOString(OOO_STRING_SVTOOLS_RTF_SCAPS); + rOutput.WriteNumberAsString(0); + rOutput.WriteOString(OOO_STRING_SVTOOLS_RTF_CAPS); + rOutput.WriteNumberAsString(0); + break; + } } break; } @@ -965,8 +1002,8 @@ void ImpEditEngine::WriteItemAsRTF( const SfxPoolItem& rItem, SvStream& rOutput, std::unique_ptr<EditTextObject> ImpEditEngine::GetEmptyTextObject() { EditSelection aEmptySel; - aEmptySel.Min() = aEditDoc.GetStartPaM(); - aEmptySel.Max() = aEditDoc.GetStartPaM(); + aEmptySel.Min() = maEditDoc.GetStartPaM(); + aEmptySel.Max() = maEditDoc.GetStartPaM(); return CreateTextObject( aEmptySel ); } @@ -974,15 +1011,15 @@ std::unique_ptr<EditTextObject> ImpEditEngine::GetEmptyTextObject() std::unique_ptr<EditTextObject> ImpEditEngine::CreateTextObject() { EditSelection aCompleteSelection; - aCompleteSelection.Min() = aEditDoc.GetStartPaM(); - aCompleteSelection.Max() = aEditDoc.GetEndPaM(); + aCompleteSelection.Min() = maEditDoc.GetStartPaM(); + aCompleteSelection.Max() = maEditDoc.GetEndPaM(); return CreateTextObject( aCompleteSelection ); } std::unique_ptr<EditTextObject> ImpEditEngine::CreateTextObject(const EditSelection& rSel) { - return CreateTextObject(rSel, GetEditTextObjectPool(), aStatus.AllowBigObjects(), nBigTextObjectStart); + return CreateTextObject(rSel, GetEditTextObjectPool(), maStatus.AllowBigObjects(), mnBigTextObjectStart); } std::unique_ptr<EditTextObject> ImpEditEngine::CreateTextObject( EditSelection aSel, SfxItemPool* pPool, bool bAllowBigObjects, sal_Int32 nBigObjectStart ) @@ -990,9 +1027,9 @@ std::unique_ptr<EditTextObject> ImpEditEngine::CreateTextObject( EditSelection a sal_Int32 nStartNode, nEndNode; sal_Int32 nTextPortions = 0; - aSel.Adjust( aEditDoc ); - nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() ); - nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() ); + aSel.Adjust( maEditDoc ); + nStartNode = maEditDoc.GetPos( aSel.Min().GetNode() ); + nEndNode = maEditDoc.GetPos( aSel.Max().GetNode() ); bool bOnlyFullParagraphs = !( aSel.Min().GetIndex() || ( aSel.Max().GetIndex() < aSel.Max().GetNode()->Len() ) ); @@ -1000,7 +1037,7 @@ std::unique_ptr<EditTextObject> ImpEditEngine::CreateTextObject( EditSelection a // Templates are not saved! // (Only the name and family, template itself must be in App!) - const MapUnit eMapUnit = aEditDoc.GetItemPool().GetMetric(DEF_METRIC); + const MapUnit eMapUnit = maEditDoc.GetItemPool().GetMetric(DEF_METRIC); auto pTxtObj(std::make_unique<EditTextObjectImpl>(pPool, eMapUnit, GetVertical(), GetRotation(), GetItemScriptType(aSel))); @@ -1008,13 +1045,12 @@ std::unique_ptr<EditTextObject> ImpEditEngine::CreateTextObject( EditSelection a sal_Int32 nNode; for ( nNode = nStartNode; nNode <= nEndNode; nNode++ ) { - ContentNode* pNode = aEditDoc.GetObject( nNode ); + ContentNode* pNode = maEditDoc.GetObject( nNode ); DBG_ASSERT( pNode, "Node not found: Search&Replace" ); if ( bOnlyFullParagraphs ) { - const ParaPortion& rParaPortion = GetParaPortions()[nNode]; - nTextPortions += rParaPortion.GetTextPortions().Count(); + nTextPortions += GetParaPortions().getRef(nNode).GetTextPortions().Count(); } sal_Int32 nStartPos = 0; @@ -1045,8 +1081,9 @@ std::unique_ptr<EditTextObject> ImpEditEngine::CreateTextObject( EditSelection a auto& rCAttriblist = pC->GetCharAttribs(); // and the Attribute... - sal_uInt16 nAttr = 0; + std::size_t nAttr = 0; EditCharAttrib* pAttr = GetAttrib( pNode->GetCharAttribs().GetAttribs(), nAttr ); + rCAttriblist.reserve(rCAttriblist.size() + pNode->GetCharAttribs().GetAttribs().size()); while ( pAttr ) { // In a blank paragraph keep the attributes! @@ -1067,9 +1104,7 @@ std::unique_ptr<EditTextObject> ImpEditEngine::CreateTextObject( EditSelection a aX.GetEnd() = nEndPos-nStartPos; } DBG_ASSERT( aX.GetEnd() <= (nEndPos-nStartPos), "CreateTextObject: Attribute too long!" ); - if ( !aX.GetLen() && !bEmptyPara ) - pTxtObj->DestroyAttrib(aX); - else + if ( aX.GetLen() || bEmptyPara ) rCAttriblist.push_back(std::move(aX)); } nAttr++; @@ -1086,11 +1121,13 @@ std::unique_ptr<EditTextObject> ImpEditEngine::CreateTextObject( EditSelection a // sleeper set up when Olli paragraphs not hacked! if ( bAllowBigObjects && bOnlyFullParagraphs && IsFormatted() && IsUpdateLayout() && ( nTextPortions >= nBigObjectStart ) ) { - XParaPortionList* pXList = new XParaPortionList( GetRefDevice(), GetColumnWidth(aPaperSize), nStretchX, nStretchY ); + XParaPortionList* pXList = new XParaPortionList(GetRefDevice(), GetColumnWidth(maPaperSize), + maScalingParameters.fFontX, maScalingParameters.fFontY, + maScalingParameters.fSpacingX, maScalingParameters.fSpacingY); pTxtObj->SetPortionInfo(std::unique_ptr<XParaPortionList>(pXList)); for ( nNode = nStartNode; nNode <= nEndNode; nNode++ ) { - const ParaPortion& rParaPortion = GetParaPortions()[nNode]; + ParaPortion const& rParaPortion = GetParaPortions().getRef(nNode); XParaPortion* pX = new XParaPortion; pXList->push_back(pX); @@ -1112,17 +1149,16 @@ std::unique_ptr<EditTextObject> ImpEditEngine::CreateTextObject( EditSelection a for ( n = 0; n < nCount; n++ ) { const EditLine& rLine = rParaPortion.GetLines()[n]; - EditLine* pNew = rLine.Clone(); - pX->aLines.Append(pNew); + pX->aLines.Append(std::unique_ptr<EditLine>(rLine.Clone())); } #ifdef DBG_UTIL sal_uInt16 nTest; int nTPLen = 0, nTxtLen = 0; - for ( nTest = rParaPortion.GetTextPortions().Count(); nTest; ) + for (nTest = rParaPortion.GetTextPortions().Count(); nTest;) nTPLen += rParaPortion.GetTextPortions()[--nTest].GetLen(); - for ( nTest = rParaPortion.GetLines().Count(); nTest; ) + for (nTest = rParaPortion.GetLines().Count(); nTest; ) nTxtLen += rParaPortion.GetLines()[--nTest].GetLen(); - DBG_ASSERT( ( nTPLen == rParaPortion.GetNode()->Len() ) && ( nTxtLen == rParaPortion.GetNode()->Len() ), "CreateBinTextObject: ParaPortion not completely formatted!" ); + DBG_ASSERT(nTPLen == rParaPortion.GetNode()->Len() && nTxtLen == rParaPortion.GetNode()->Len(), "CreateBinTextObject: ParaPortion not completely formatted!"); #endif } } @@ -1137,7 +1173,7 @@ void ImpEditEngine::SetText( const EditTextObject& rTextObject ) bool _bUndo = IsUndoEnabled(); SetText( OUString() ); - EditPaM aPaM = aEditDoc.GetStartPaM(); + EditPaM aPaM = maEditDoc.GetStartPaM(); SetUpdateLayout( false ); EnableUndo( false ); @@ -1153,7 +1189,7 @@ void ImpEditEngine::SetText( const EditTextObject& rTextObject ) EditSelection ImpEditEngine::InsertText( const EditTextObject& rTextObject, EditSelection aSel ) { - aSel.Adjust( aEditDoc ); + aSel.Adjust( maEditDoc ); if ( aSel.HasRange() ) aSel = ImpDeleteSelection( aSel ); EditSelection aNewSel = InsertTextObject( rTextObject, aSel.Max() ); @@ -1164,16 +1200,18 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject { // Optimize: No getPos undFindParaportion, instead calculate index! EditSelection aSel( aPaM, aPaM ); - DBG_ASSERT( !aSel.DbgIsBuggy( aEditDoc ), "InsertBibTextObject: Selection broken!(1)" ); + DBG_ASSERT( !aSel.DbgIsBuggy( maEditDoc ), "InsertBibTextObject: Selection broken!(1)" ); bool bUsePortionInfo = false; const EditTextObjectImpl& rTextObjectImpl = toImpl(rTextObject); XParaPortionList* pPortionInfo = rTextObjectImpl.GetPortionInfo(); - if ( pPortionInfo && ( static_cast<tools::Long>(pPortionInfo->GetPaperWidth()) == GetColumnWidth(aPaperSize) ) - && ( pPortionInfo->GetRefMapMode() == GetRefDevice()->GetMapMode() ) - && ( pPortionInfo->GetStretchX() == nStretchX ) - && ( pPortionInfo->GetStretchY() == nStretchY ) ) + if (pPortionInfo && ( static_cast<tools::Long>(pPortionInfo->GetPaperWidth()) == GetColumnWidth(maPaperSize)) + && pPortionInfo->GetRefMapMode() == GetRefDevice()->GetMapMode() + && pPortionInfo->getFontScaleX() == maScalingParameters.fFontX + && pPortionInfo->getFontScaleY() == maScalingParameters.fFontY + && pPortionInfo->getSpacingScaleX() == maScalingParameters.fSpacingX + && pPortionInfo->getSpacingScaleY() == maScalingParameters.fSpacingY) { if ( (pPortionInfo->GetRefDevPtr() == GetRefDevice()) || (pPortionInfo->RefDevIsVirtual() && GetRefDevice()->IsVirtual()) ) @@ -1185,7 +1223,7 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject if (rTextObjectImpl.HasMetric()) { eSourceUnit = rTextObjectImpl.GetMetric(); - eDestUnit = aEditDoc.GetItemPool().GetMetric( DEF_METRIC ); + eDestUnit = maEditDoc.GetItemPool().GetMetric( DEF_METRIC ); if ( eSourceUnit != eDestUnit ) bConvertMetricOfItems = true; } @@ -1195,7 +1233,7 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject // number paragraphs and is fearlessly incremented. sal_Int32 nContents = static_cast<sal_Int32>(rTextObjectImpl.GetContents().size()); SAL_WARN_IF( nContents < 0, "editeng", "ImpEditEngine::InsertTextObject - contents overflow " << nContents); - sal_Int32 nPara = aEditDoc.GetPos( aPaM.GetNode() ); + sal_Int32 nPara = maEditDoc.GetPos( aPaM.GetNode() ); for (sal_Int32 n = 0; n < nContents; ++n, ++nPara) { @@ -1205,8 +1243,9 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject aPaM = ImpFastInsertText( aPaM, pC->GetText() ); - ParaPortion& rPortion = FindParaPortion( aPaM.GetNode() ); - rPortion.MarkInvalid( nStartPos, pC->GetText().getLength() ); + ParaPortion* pPortion = FindParaPortion( aPaM.GetNode() ); + DBG_ASSERT( pPortion, "Blind Portion in FastInsertText" ); + pPortion->MarkInvalid( nStartPos, pC->GetText().getLength() ); // Character attributes ... bool bAllreadyHasAttribs = aPaM.GetNode()->GetCharAttribs().Count() != 0; @@ -1230,12 +1269,12 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject DBG_ASSERT( rX.GetEnd() <= aPaM.GetNode()->Len(), "InsertBinTextObject: Attribute too large!" ); EditCharAttrib* pAttr; if ( !bConvertMetricOfItems ) - pAttr = MakeCharAttrib( aEditDoc.GetItemPool(), *(rX.GetItem()), rX.GetStart()+nStartPos, rX.GetEnd()+nStartPos ); + pAttr = MakeCharAttrib( maEditDoc.GetItemPool(), *(rX.GetItem()), rX.GetStart()+nStartPos, rX.GetEnd()+nStartPos ); else { std::unique_ptr<SfxPoolItem> pNew(rX.GetItem()->Clone()); ConvertItem( pNew, eSourceUnit, eDestUnit ); - pAttr = MakeCharAttrib( aEditDoc.GetItemPool(), *pNew, rX.GetStart()+nStartPos, rX.GetEnd()+nStartPos ); + pAttr = MakeCharAttrib( maEditDoc.GetItemPool(), *pNew, rX.GetStart()+nStartPos, rX.GetEnd()+nStartPos ); } DBG_ASSERT( pAttr->GetEnd() <= aPaM.GetNode()->Len(), "InsertBinTextObject: Attribute does not fit! (1)" ); aPaM.GetNode()->GetCharAttribs().InsertAttrib( pAttr ); @@ -1246,7 +1285,7 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject { DBG_ASSERT( rX.GetEnd()+nStartPos <= aPaM.GetNode()->Len(), "InsertBinTextObject: Attribute does not fit! (2)" ); // Tabs and other Features can not be inserted through InsertAttrib: - aEditDoc.InsertAttrib( aPaM.GetNode(), rX.GetStart()+nStartPos, rX.GetEnd()+nStartPos, *rX.GetItem() ); + maEditDoc.InsertAttrib( aPaM.GetNode(), rX.GetStart()+nStartPos, rX.GetEnd()+nStartPos, *rX.GetItem() ); } } } @@ -1254,7 +1293,7 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject UpdateFields(); // Otherwise, quick format => no attributes! - rPortion.MarkSelectionInvalid( nStartPos ); + pPortion->MarkSelectionInvalid( nStartPos ); } #if OSL_DEBUG_LEVEL > 0 && !defined NDEBUG @@ -1274,57 +1313,58 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject SetStyleSheet( nPara, pStyle ); } if ( !bConvertMetricOfItems ) - SetParaAttribs( aEditDoc.GetPos( aPaM.GetNode() ), pC->GetParaAttribs() ); + SetParaAttribs( maEditDoc.GetPos( aPaM.GetNode() ), pC->GetParaAttribs() ); else { SfxItemSet aAttribs( GetEmptyItemSet() ); ConvertAndPutItems( aAttribs, pC->GetParaAttribs(), &eSourceUnit, &eDestUnit ); - SetParaAttribs( aEditDoc.GetPos( aPaM.GetNode() ), aAttribs ); + SetParaAttribs( maEditDoc.GetPos( aPaM.GetNode() ), aAttribs ); } if ( bNewContent && bUsePortionInfo ) { const XParaPortion& rXP = (*pPortionInfo)[n]; - ParaPortion& rParaPortion = GetParaPortions()[ nPara ]; - rParaPortion.nHeight = rXP.nHeight; - rParaPortion.nFirstLineOffset = rXP.nFirstLineOffset; - rParaPortion.bForceRepaint = true; - rParaPortion.SetValid(); // Do not format + ParaPortion* pParaPortion = GetParaPortions().SafeGetObject(nPara); + DBG_ASSERT( pParaPortion, "InsertBinTextObject: ParaPortion?" ); + pParaPortion->mnHeight = rXP.nHeight; + pParaPortion->mnFirstLineOffset = rXP.nFirstLineOffset; + pParaPortion->mbForceRepaint = true; + pParaPortion->SetValid(); // Do not format // The Text Portions - rParaPortion.GetTextPortions().Reset(); + pParaPortion->GetTextPortions().Reset(); sal_uInt16 nCount = rXP.aTextPortions.Count(); for ( sal_uInt16 _n = 0; _n < nCount; _n++ ) { const TextPortion& rTextPortion = rXP.aTextPortions[_n]; TextPortion* pNew = new TextPortion( rTextPortion ); - rParaPortion.GetTextPortions().Append(pNew); + pParaPortion->GetTextPortions().Append(pNew); } // The lines - rParaPortion.GetLines().Reset(); + pParaPortion->GetLines().Reset(); nCount = rXP.aLines.Count(); for ( sal_uInt16 m = 0; m < nCount; m++ ) { const EditLine& rLine = rXP.aLines[m]; EditLine* pNew = rLine.Clone(); pNew->SetInvalid(); // Paint again! - rParaPortion.GetLines().Append(pNew); + pParaPortion->GetLines().Append(std::unique_ptr<EditLine>(pNew)); } #ifdef DBG_UTIL sal_uInt16 nTest; int nTPLen = 0, nTxtLen = 0; - for ( nTest = rParaPortion.GetTextPortions().Count(); nTest; ) - nTPLen += rParaPortion.GetTextPortions()[--nTest].GetLen(); - for ( nTest = rParaPortion.GetLines().Count(); nTest; ) - nTxtLen += rParaPortion.GetLines()[--nTest].GetLen(); - DBG_ASSERT( ( nTPLen == rParaPortion.GetNode()->Len() ) && ( nTxtLen == rParaPortion.GetNode()->Len() ), "InsertTextObject: ParaPortion not completely formatted!" ); + for ( nTest = pParaPortion->GetTextPortions().Count(); nTest; ) + nTPLen += pParaPortion->GetTextPortions()[--nTest].GetLen(); + for ( nTest = pParaPortion->GetLines().Count(); nTest; ) + nTxtLen += pParaPortion->GetLines()[--nTest].GetLen(); + DBG_ASSERT( ( nTPLen == pParaPortion->GetNode()->Len() ) && ( nTxtLen == pParaPortion->GetNode()->Len() ), "InsertTextObject: ParaPortion not completely formatted!" ); #endif } } if ( !bParaAttribs ) // DefFont is not calculated for FastInsertParagraph { - aPaM.GetNode()->GetCharAttribs().GetDefFont() = aEditDoc.GetDefFont(); - if ( aStatus.UseCharAttribs() ) + aPaM.GetNode()->GetCharAttribs().GetDefFont() = maEditDoc.GetDefFont(); + if (maStatus.UseCharAttribs()) aPaM.GetNode()->CreateDefFont(); } @@ -1344,7 +1384,7 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject } aSel.Max() = aPaM; - DBG_ASSERT( !aSel.DbgIsBuggy( aEditDoc ), "InsertBibTextObject: Selection broken!(1)" ); + DBG_ASSERT( !aSel.DbgIsBuggy( maEditDoc ), "InsertBibTextObject: Selection broken!(1)" ); return aSel; } @@ -1380,73 +1420,82 @@ void ImpEditEngine::SetAllMisspellRanges( const std::vector<editeng::MisspellRan } } -LanguageType ImpEditEngine::GetLanguage( const EditPaM& rPaM, sal_Int32* pEndPos ) const +editeng::LanguageSpan ImpEditEngine::GetLanguage( const EditPaM& rPaM, sal_Int32* pEndPos ) const { short nScriptTypeI18N = GetI18NScriptType( rPaM, pEndPos ); // pEndPos will be valid now, pointing to ScriptChange or NodeLen SvtScriptType nScriptType = SvtLanguageOptions::FromI18NToSvtScriptType(nScriptTypeI18N); sal_uInt16 nLangId = GetScriptItemId( EE_CHAR_LANGUAGE, nScriptType ); const SvxLanguageItem* pLangItem = &static_cast<const SvxLanguageItem&>(rPaM.GetNode()->GetContentAttribs().GetItem( nLangId )); const EditCharAttrib* pAttr = rPaM.GetNode()->GetCharAttribs().FindAttrib( nLangId, rPaM.GetIndex() ); + + editeng::LanguageSpan aLang; + if ( pAttr ) + { pLangItem = static_cast<const SvxLanguageItem*>(pAttr->GetItem()); + aLang.nStart = pAttr->GetStart(); + aLang.nEnd = pAttr->GetEnd(); + } if ( pEndPos && pAttr && ( pAttr->GetEnd() < *pEndPos ) ) *pEndPos = pAttr->GetEnd(); - return pLangItem->GetLanguage(); + aLang.nLang = pLangItem->GetLanguage(); + + return aLang; } css::lang::Locale ImpEditEngine::GetLocale( const EditPaM& rPaM ) const { - return LanguageTag( GetLanguage( rPaM ) ).getLocale(); + return LanguageTag( GetLanguage( rPaM ).nLang ).getLocale(); } Reference< XSpellChecker1 > const & ImpEditEngine::GetSpeller() { - if ( !xSpeller.is() ) - xSpeller = LinguMgr::GetSpellChecker(); - return xSpeller; + if (!mxSpeller.is()) + mxSpeller = LinguMgr::GetSpellChecker(); + return mxSpeller; } void ImpEditEngine::CreateSpellInfo( bool bMultipleDocs ) { - if (!pSpellInfo) - pSpellInfo.reset( new SpellInfo ); + if (!mpSpellInfo) + mpSpellInfo.reset(new SpellInfo); else - *pSpellInfo = SpellInfo(); // reset to default values + *mpSpellInfo = SpellInfo(); // reset to default values - pSpellInfo->bMultipleDoc = bMultipleDocs; + mpSpellInfo->bMultipleDoc = bMultipleDocs; // always spell draw objects completely, starting at the top. // (spelling in only a selection or not starting with the top requires // further changes elsewhere to work properly) - pSpellInfo->aSpellStart = EPaM(); - pSpellInfo->aSpellTo = EPaM( EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND ); + mpSpellInfo->aSpellStart = EPaM(); + mpSpellInfo->aSpellTo = EPaM( EE_PARA_NOT_FOUND, EE_INDEX_NOT_FOUND ); } EESpellState ImpEditEngine::Spell(EditView* pEditView, weld::Widget* pDialogParent, bool bMultipleDoc) { - SAL_WARN_IF( !xSpeller.is(), "editeng", "No Spell checker set!" ); + SAL_WARN_IF(!mxSpeller.is(), "editeng", "No Spell checker set!"); - if ( !xSpeller.is() ) + if (!mxSpeller.is()) return EESpellState::NoSpeller; - aOnlineSpellTimer.Stop(); + maOnlineSpellTimer.Stop(); // In MultipleDoc always from the front / rear ... if ( bMultipleDoc ) { - pEditView->pImpEditView->SetEditSelection( aEditDoc.GetStartPaM() ); + pEditView->getImpl().SetEditSelection( maEditDoc.GetStartPaM() ); } - EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() ); + EditSelection aCurSel( pEditView->getImpl().GetEditSelection() ); CreateSpellInfo( bMultipleDoc ); bool bIsStart = false; if ( bMultipleDoc ) bIsStart = true; // Accessible from the front or from behind ... - else if ( CreateEPaM( aEditDoc.GetStartPaM() ) == pSpellInfo->aSpellStart ) + else if ( CreateEPaM( maEditDoc.GetStartPaM() ) == mpSpellInfo->aSpellStart ) bIsStart = true; { @@ -1456,16 +1505,16 @@ EESpellState ImpEditEngine::Spell(EditView* pEditView, weld::Widget* pDialogPare if ( !bMultipleDoc ) { - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); if ( aCurSel.Max().GetIndex() > aCurSel.Max().GetNode()->Len() ) aCurSel.Max().SetIndex( aCurSel.Max().GetNode()->Len() ); aCurSel.Min() = aCurSel.Max(); - pEditView->pImpEditView->SetEditSelection( aCurSel ); - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().SetEditSelection( aCurSel ); + pEditView->getImpl().DrawSelectionXOR(); pEditView->ShowCursor( true, false ); } - EESpellState eState = pSpellInfo->eState; - pSpellInfo.reset(); + EESpellState eState = mpSpellInfo->eState; + mpSpellInfo.reset(); return eState; } @@ -1474,11 +1523,11 @@ bool ImpEditEngine::HasConvertibleTextPortion( LanguageType nSrcLang ) { bool bHasConvTxt = false; - sal_Int32 nParas = pEditEngine->GetParagraphCount(); + sal_Int32 nParas = mpEditEngine->GetParagraphCount(); for (sal_Int32 k = 0; k < nParas; ++k) { std::vector<sal_Int32> aPortions; - pEditEngine->GetPortions( k, aPortions ); + mpEditEngine->GetPortions( k, aPortions ); for ( size_t nPos = 0; nPos < aPortions.size(); ++nPos ) { sal_Int32 nEnd = aPortions[ nPos ]; @@ -1489,8 +1538,8 @@ bool ImpEditEngine::HasConvertibleTextPortion( LanguageType nSrcLang ) // specified position is evaluated. if (nEnd > nStart) // empty para? ++nStart; - LanguageType nLangFound = pEditEngine->GetLanguage( k, nStart ); -#ifdef DEBUG + LanguageType nLangFound = mpEditEngine->GetLanguage( k, nStart ).nLang; +#if OSL_DEBUG_LEVEL >= 2 lang::Locale aLocale( LanguageTag::convertToLocale( nLangFound ) ); #endif bHasConvTxt = (nSrcLang == nLangFound) || @@ -1512,15 +1561,15 @@ void ImpEditEngine::Convert( EditView* pEditView, weld::Widget* pDialogParent, // In MultipleDoc always from the front / rear ... if ( bMultipleDoc ) - pEditView->pImpEditView->SetEditSelection( aEditDoc.GetStartPaM() ); + pEditView->getImpl().SetEditSelection( maEditDoc.GetStartPaM() ); // initialize pConvInfo - EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() ); - aCurSel.Adjust( aEditDoc ); - pConvInfo.reset(new ConvInfo); - pConvInfo->bMultipleDoc = bMultipleDoc; - pConvInfo->aConvStart = CreateEPaM( aCurSel.Min() ); + EditSelection aCurSel( pEditView->getImpl().GetEditSelection() ); + aCurSel.Adjust( maEditDoc ); + mpConvInfo.reset(new ConvInfo); + mpConvInfo->bMultipleDoc = bMultipleDoc; + mpConvInfo->aConvStart = CreateEPaM( aCurSel.Min() ); // if it is not just a selection and we are about to begin // with the current conversion for the very first time @@ -1538,16 +1587,16 @@ void ImpEditEngine::Convert( EditView* pEditView, weld::Widget* pDialogParent, // not work. Thus since chinese conversion is not interactive we start // at the begin of the paragraph to solve the problem, i.e. have the // TextConversion service get those characters together in the same call. - pConvInfo->aConvStart.nIndex = editeng::HangulHanjaConversion::IsChinese( nSrcLang ) + mpConvInfo->aConvStart.nIndex = editeng::HangulHanjaConversion::IsChinese( nSrcLang ) ? 0 : aWordStartPaM.GetIndex(); } - pConvInfo->aConvContinue = pConvInfo->aConvStart; + mpConvInfo->aConvContinue = mpConvInfo->aConvStart; bool bIsStart = false; if ( bMultipleDoc ) bIsStart = true; // Accessible from the front or from behind ... - else if ( CreateEPaM( aEditDoc.GetStartPaM() ) == pConvInfo->aConvStart ) + else if ( CreateEPaM( maEditDoc.GetStartPaM() ) == mpConvInfo->aConvStart ) bIsStart = true; TextConvWrapper aWrp( pDialogParent, @@ -1577,15 +1626,15 @@ void ImpEditEngine::Convert( EditView* pEditView, weld::Widget* pDialogParent, if ( !bMultipleDoc ) { - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); if ( aCurSel.Max().GetIndex() > aCurSel.Max().GetNode()->Len() ) aCurSel.Max().SetIndex( aCurSel.Max().GetNode()->Len() ); aCurSel.Min() = aCurSel.Max(); - pEditView->pImpEditView->SetEditSelection( aCurSel ); - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().SetEditSelection( aCurSel ); + pEditView->getImpl().DrawSelectionXOR(); pEditView->ShowCursor( true, false ); } - pConvInfo.reset(); + mpConvInfo.reset(); } @@ -1594,11 +1643,11 @@ void ImpEditEngine::SetLanguageAndFont( LanguageType nLang, sal_uInt16 nLangWhichId, const vcl::Font *pFont, sal_uInt16 nFontWhichId ) { - ESelection aOldSel = pActiveView->GetSelection(); - pActiveView->SetSelection( rESel ); + ESelection aOldSel = mpActiveView->GetSelection(); + mpActiveView->SetSelection( rESel ); // set new language attribute - SfxItemSet aNewSet( pActiveView->GetEmptyItemSet() ); + SfxItemSet aNewSet(mpActiveView->GetEmptyItemSet()); aNewSet.Put( SvxLanguageItem( nLang, nLangWhichId ) ); // new font to be set? @@ -1616,9 +1665,8 @@ void ImpEditEngine::SetLanguageAndFont( } // apply new attributes - pActiveView->SetAttribs( aNewSet ); - - pActiveView->SetSelection( aOldSel ); + mpActiveView->SetAttribs(aNewSet); + mpActiveView->SetSelection(aOldSel); } @@ -1634,7 +1682,7 @@ void ImpEditEngine::ImpConvert( OUString &rConvTxt, LanguageType &rConvTxtLang, OUString aRes; LanguageType nResLang = LANGUAGE_NONE; - EditPaM aPos( CreateEditPaM( pConvInfo->aConvContinue ) ); + EditPaM aPos(CreateEditPaM(mpConvInfo->aConvContinue)); EditSelection aCurSel( aPos, aPos ); OUString aWord; @@ -1643,9 +1691,9 @@ void ImpEditEngine::ImpConvert( OUString &rConvTxt, LanguageType &rConvTxtLang, { // empty paragraph found that needs to have language and font set? if (bAllowImplicitChangesForNotConvertibleText && - pEditEngine->GetText( pConvInfo->aConvContinue.nPara ).isEmpty()) + mpEditEngine->GetText(mpConvInfo->aConvContinue.nPara).isEmpty()) { - sal_Int32 nPara = pConvInfo->aConvContinue.nPara; + sal_Int32 nPara = mpConvInfo->aConvContinue.nPara; ESelection aESel( nPara, 0, nPara, 0 ); // see comment for below same function call SetLanguageAndFont( aESel, @@ -1654,8 +1702,8 @@ void ImpEditEngine::ImpConvert( OUString &rConvTxt, LanguageType &rConvTxtLang, } - if (pConvInfo->aConvContinue.nPara == pConvInfo->aConvTo.nPara && - pConvInfo->aConvContinue.nIndex >= pConvInfo->aConvTo.nIndex) + if (mpConvInfo->aConvContinue.nPara == mpConvInfo->aConvTo.nPara && + mpConvInfo->aConvContinue.nIndex >= mpConvInfo->aConvTo.nIndex) break; sal_Int32 nAttribStart = -1; @@ -1663,7 +1711,7 @@ void ImpEditEngine::ImpConvert( OUString &rConvTxt, LanguageType &rConvTxtLang, sal_Int32 nCurPos = -1; EPaM aCurStart = CreateEPaM( aCurSel.Min() ); std::vector<sal_Int32> aPortions; - pEditEngine->GetPortions( aCurStart.nPara, aPortions ); + mpEditEngine->GetPortions(aCurStart.nPara, aPortions); for ( size_t nPos = 0; nPos < aPortions.size(); ++nPos ) { const sal_Int32 nEnd = aPortions[ nPos ]; @@ -1674,8 +1722,8 @@ void ImpEditEngine::ImpConvert( OUString &rConvTxt, LanguageType &rConvTxtLang, // thus we usually have to add 1 in order to get the language // of the text right to the cursor position const sal_Int32 nLangIdx = nEnd > nStart ? nStart + 1 : nStart; - LanguageType nLangFound = pEditEngine->GetLanguage( aCurStart.nPara, nLangIdx ); -#ifdef DEBUG + LanguageType nLangFound = mpEditEngine->GetLanguage( aCurStart.nPara, nLangIdx ).nLang; +#if OSL_DEBUG_LEVEL >= 2 lang::Locale aLocale( LanguageTag::convertToLocale( nLangFound ) ); #endif bool bLangOk = (nLangFound == nSrcLang) || @@ -1743,26 +1791,26 @@ void ImpEditEngine::ImpConvert( OUString &rConvTxt, LanguageType &rConvTxtLang, aCurSel.Max().SetIndex( nCurPos ); } - if ( !pConvInfo->bConvToEnd ) + if ( !mpConvInfo->bConvToEnd ) { EPaM aEPaM( CreateEPaM( aCurSel.Min() ) ); - if ( !( aEPaM < pConvInfo->aConvTo ) ) + if ( !( aEPaM < mpConvInfo->aConvTo ) ) break; } // clip selected word to the converted area // (main use when conversion starts/ends **within** a word) - EditPaM aPaM( CreateEditPaM( pConvInfo->aConvStart ) ); - if (pConvInfo->bConvToEnd && + EditPaM aPaM( CreateEditPaM( mpConvInfo->aConvStart ) ); + if (mpConvInfo->bConvToEnd && aCurSel.Min().GetNode() == aPaM.GetNode() && aCurSel.Min().GetIndex() < aPaM.GetIndex()) aCurSel.Min().SetIndex( aPaM.GetIndex() ); - aPaM = CreateEditPaM( pConvInfo->aConvContinue ); + aPaM = CreateEditPaM( mpConvInfo->aConvContinue ); if (aCurSel.Min().GetNode() == aPaM.GetNode() && aCurSel.Min().GetIndex() < aPaM.GetIndex()) aCurSel.Min().SetIndex( aPaM.GetIndex() ); - aPaM = CreateEditPaM( pConvInfo->aConvTo ); - if ((!pConvInfo->bConvToEnd || rConvRange.HasRange())&& + aPaM = CreateEditPaM( mpConvInfo->aConvTo ); + if ((!mpConvInfo->bConvToEnd || rConvRange.HasRange())&& aCurSel.Max().GetNode() == aPaM.GetNode() && aCurSel.Max().GetIndex() > aPaM.GetIndex()) aCurSel.Max().SetIndex( aPaM.GetIndex() ); @@ -1776,12 +1824,12 @@ void ImpEditEngine::ImpConvert( OUString &rConvTxt, LanguageType &rConvTxtLang, if ( aRes.isEmpty() ) aCurSel = WordRight( aCurSel.Min(), css::i18n::WordType::DICTIONARY_WORD ); - pConvInfo->aConvContinue = CreateEPaM( aCurSel.Max() ); + mpConvInfo->aConvContinue = CreateEPaM( aCurSel.Max() ); } - pEditView->pImpEditView->DrawSelectionXOR(); - pEditView->pImpEditView->SetEditSelection( aCurSel ); - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); + pEditView->getImpl().SetEditSelection( aCurSel ); + pEditView->getImpl().DrawSelectionXOR(); pEditView->ShowCursor( true, false ); rConvTxt = aRes; @@ -1792,10 +1840,10 @@ void ImpEditEngine::ImpConvert( OUString &rConvTxt, LanguageType &rConvTxtLang, Reference< XSpellAlternatives > ImpEditEngine::ImpSpell( EditView* pEditView ) { - DBG_ASSERT( xSpeller.is(), "No spell checker set!" ); + DBG_ASSERT(mxSpeller.is(), "No spell checker set!"); - ContentNode* pLastNode = aEditDoc.GetObject( aEditDoc.Count()-1 ); - EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() ); + ContentNode* pLastNode = maEditDoc.GetObject( maEditDoc.Count()-1 ); + EditSelection aCurSel( pEditView->getImpl().GetEditSelection() ); aCurSel.Min() = aCurSel.Max(); Reference< XSpellAlternatives > xSpellAlt; @@ -1805,7 +1853,7 @@ Reference< XSpellAlternatives > ImpEditEngine::ImpSpell( EditView* pEditView ) // Known (most likely) bug: If SpellToCurrent, the current has to be // corrected at each replacement, otherwise it may not fit exactly in // the end ... - if ( pSpellInfo->bSpellToEnd || pSpellInfo->bMultipleDoc ) + if (mpSpellInfo->bSpellToEnd || mpSpellInfo->bMultipleDoc) { if ( aCurSel.Max().GetNode() == pLastNode ) { @@ -1813,10 +1861,10 @@ Reference< XSpellAlternatives > ImpEditEngine::ImpSpell( EditView* pEditView ) break; } } - else if ( !pSpellInfo->bSpellToEnd ) + else if (!mpSpellInfo->bSpellToEnd) { EPaM aEPaM( CreateEPaM( aCurSel.Max() ) ); - if ( !( aEPaM < pSpellInfo->aSpellTo ) ) + if (!(aEPaM < mpSpellInfo->aSpellTo)) break; } @@ -1837,20 +1885,20 @@ Reference< XSpellAlternatives > ImpEditEngine::ImpSpell( EditView* pEditView ) if ( !aWord.isEmpty() ) { - LanguageType eLang = GetLanguage( aCurSel.Max() ); - SvxSpellWrapper::CheckSpellLang( xSpeller, eLang ); - xSpellAlt = xSpeller->spell( aWord, static_cast<sal_uInt16>(eLang), aEmptySeq ); + LanguageType eLang = GetLanguage( aCurSel.Max() ).nLang; + SvxSpellWrapper::CheckSpellLang(mxSpeller, eLang); + xSpellAlt = mxSpeller->spell( aWord, static_cast<sal_uInt16>(eLang), aEmptySeq ); } if ( !xSpellAlt.is() ) aCurSel = WordRight( aCurSel.Min(), css::i18n::WordType::DICTIONARY_WORD ); else - pSpellInfo->eState = EESpellState::ErrorFound; + mpSpellInfo->eState = EESpellState::ErrorFound; } - pEditView->pImpEditView->DrawSelectionXOR(); - pEditView->pImpEditView->SetEditSelection( aCurSel ); - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); + pEditView->getImpl().SetEditSelection( aCurSel ); + pEditView->getImpl().DrawSelectionXOR(); pEditView->ShowCursor( true, false ); return xSpellAlt; } @@ -1886,13 +1934,13 @@ Reference< XSpellAlternatives > ImpEditEngine::ImpFindNextError(EditSelection& r } if ( !aWord.isEmpty() ) - xSpellAlt = xSpeller->spell( aWord, static_cast<sal_uInt16>(GetLanguage( aCurSel.Max() )), aEmptySeq ); + xSpellAlt = mxSpeller->spell( aWord, static_cast<sal_uInt16>(GetLanguage( aCurSel.Max() ).nLang), aEmptySeq ); if ( !xSpellAlt.is() ) aCurSel = WordRight( aCurSel.Min(), css::i18n::WordType::DICTIONARY_WORD ); else { - pSpellInfo->eState = EESpellState::ErrorFound; + mpSpellInfo->eState = EESpellState::ErrorFound; rSelection = aCurSel; } } @@ -1903,18 +1951,18 @@ bool ImpEditEngine::SpellSentence(EditView const & rEditView, svx::SpellPortions& rToFill ) { bool bRet = false; - EditSelection aCurSel( rEditView.pImpEditView->GetEditSelection() ); - if(!pSpellInfo) + EditSelection aCurSel( rEditView.getImpl().GetEditSelection() ); + if (!mpSpellInfo) CreateSpellInfo( true ); - pSpellInfo->aCurSentenceStart = aCurSel.Min(); - DBG_ASSERT( xSpeller.is(), "No spell checker set!" ); - pSpellInfo->aLastSpellPortions.clear(); - pSpellInfo->aLastSpellContentSelections.clear(); + mpSpellInfo->aCurSentenceStart = aCurSel.Min(); + DBG_ASSERT(mxSpeller.is(), "No spell checker set!"); + mpSpellInfo->aLastSpellPortions.clear(); + mpSpellInfo->aLastSpellContentSelections.clear(); rToFill.clear(); //if no selection previously exists the range is extended to the end of the object if (!aCurSel.HasRange()) { - ContentNode* pLastNode = aEditDoc.GetObject( aEditDoc.Count()-1); + ContentNode* pLastNode = maEditDoc.GetObject( maEditDoc.Count()-1); aCurSel.Max() = EditPaM(pLastNode, pLastNode->Len()); } // check for next error in aCurSel and set aCurSel to that one if any was found @@ -1953,7 +2001,7 @@ bool ImpEditEngine::SpellSentence(EditView const & rEditView, while( xAlt.is() ); //set the selection to the end of the current sentence - rEditView.pImpEditView->SetEditSelection(aSentencePaM.Max()); + rEditView.getImpl().SetEditSelection(aSentencePaM.Max()); } return bRet; } @@ -1970,14 +2018,14 @@ void ImpEditEngine::AddPortion( svx::SpellPortion aPortion; aPortion.sText = GetSelected( rSel ); - aPortion.eLanguage = GetLanguage( rSel.Min() ); + aPortion.eLanguage = GetLanguage( rSel.Min() ).nLang; aPortion.xAlternatives = xAlt; aPortion.bIsField = bIsField; rToFill.push_back(aPortion); //save the spelled portions for later use - pSpellInfo->aLastSpellPortions.push_back(aPortion); - pSpellInfo->aLastSpellContentSelections.push_back(rSel); + mpSpellInfo->aLastSpellPortions.push_back(aPortion); + mpSpellInfo->aLastSpellContentSelections.push_back(rSel); } // Adds one or more portions of text to the SpellPortions depending on language changes @@ -2004,8 +2052,8 @@ void ImpEditEngine::AddPortionIterated( //iterate over the text to find changes in language //set the mark equal to the point EditPaM aCursor(aStart); - rEditView.pImpEditView->SetEditSelection( aCursor ); - LanguageType eStartLanguage = GetLanguage( aCursor ); + rEditView.getImpl().SetEditSelection( aCursor ); + LanguageType eStartLanguage = GetLanguage( aCursor ).nLang; //search for a field attribute at the beginning - only the end position //of this field is kept to end a portion at that position const EditCharAttrib* pFieldAttr = aCursor.GetNode()->GetCharAttribs(). @@ -2031,7 +2079,7 @@ void ImpEditEngine::AddPortionIterated( if (bIsField) nEndField = _pFieldAttr->GetEnd(); - LanguageType eCurLanguage = GetLanguage( aCursor ); + LanguageType eCurLanguage = GetLanguage( aCursor ).nLang; if(eCurLanguage != eStartLanguage || bIsField || bIsEndField) { eStartLanguage = eCurLanguage; @@ -2056,27 +2104,27 @@ void ImpEditEngine::ApplyChangedSentence(EditView const & rEditView, // Note: rNewPortions.size() == 0 is valid and happens when the whole // sentence got removed in the dialog - DBG_ASSERT(pSpellInfo, "pSpellInfo not initialized"); - if (!pSpellInfo || pSpellInfo->aLastSpellPortions.empty()) // no portions -> no text to be changed + DBG_ASSERT(mpSpellInfo, "mpSpellInfo not initialized"); + if (!mpSpellInfo || mpSpellInfo->aLastSpellPortions.empty()) // no portions -> no text to be changed return; // get current paragraph length to calculate later on how the sentence length changed, // in order to place the cursor at the end of the sentence again - EditSelection aOldSel( rEditView.pImpEditView->GetEditSelection() ); + EditSelection aOldSel( rEditView.getImpl().GetEditSelection() ); sal_Int32 nOldLen = aOldSel.Max().GetNode()->Len(); UndoActionStart( EDITUNDO_INSERT ); - if(pSpellInfo->aLastSpellPortions.size() == rNewPortions.size()) + if (mpSpellInfo->aLastSpellPortions.size() == rNewPortions.size()) { - DBG_ASSERT( !rNewPortions.empty(), "rNewPortions should not be empty here" ); - DBG_ASSERT( pSpellInfo->aLastSpellPortions.size() == pSpellInfo->aLastSpellContentSelections.size(), - "aLastSpellPortions and aLastSpellContentSelections size mismatch" ); + DBG_ASSERT(!rNewPortions.empty(), "rNewPortions should not be empty here"); + DBG_ASSERT(mpSpellInfo->aLastSpellPortions.size() == mpSpellInfo->aLastSpellContentSelections.size(), + "aLastSpellPortions and aLastSpellContentSelections size mismatch"); //the simple case: the same number of elements on both sides //each changed element has to be applied to the corresponding source element svx::SpellPortions::const_iterator aCurrentNewPortion = rNewPortions.end(); - svx::SpellPortions::const_iterator aCurrentOldPortion = pSpellInfo->aLastSpellPortions.end(); - SpellContentSelections::const_iterator aCurrentOldPosition = pSpellInfo->aLastSpellContentSelections.end(); + svx::SpellPortions::const_iterator aCurrentOldPortion = mpSpellInfo->aLastSpellPortions.end(); + SpellContentSelections::const_iterator aCurrentOldPosition = mpSpellInfo->aLastSpellContentSelections.end(); bool bSetToEnd = false; do { @@ -2088,7 +2136,7 @@ void ImpEditEngine::ApplyChangedSentence(EditView const & rEditView, if(!bSetToEnd) { bSetToEnd = true; - rEditView.pImpEditView->SetEditSelection( aCurrentOldPosition->Max() ); + rEditView.getImpl().SetEditSelection( aCurrentOldPosition->Max() ); } SvtScriptType nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( aCurrentNewPortion->eLanguage ); @@ -2102,7 +2150,7 @@ void ImpEditEngine::ApplyChangedSentence(EditView const & rEditView, if(aCurrentNewPortion->sText != aCurrentOldPortion->sText) { //change text and apply language - SfxItemSet aSet( aEditDoc.GetItemPool(), nLangWhichId, nLangWhichId ); + SfxItemSet aSet( maEditDoc.GetItemPool(), nLangWhichId, nLangWhichId ); aSet.Put(SvxLanguageItem(aCurrentNewPortion->eLanguage, nLangWhichId)); SetAttribs( *aCurrentOldPosition, aSet ); ImpInsertText( *aCurrentOldPosition, aCurrentNewPortion->sText ); @@ -2110,7 +2158,7 @@ void ImpEditEngine::ApplyChangedSentence(EditView const & rEditView, else if(aCurrentNewPortion->eLanguage != aCurrentOldPortion->eLanguage) { //apply language - SfxItemSet aSet( aEditDoc.GetItemPool(), nLangWhichId, nLangWhichId); + SfxItemSet aSet( maEditDoc.GetItemPool(), nLangWhichId, nLangWhichId); aSet.Put(SvxLanguageItem(aCurrentNewPortion->eLanguage, nLangWhichId)); SetAttribs( *aCurrentOldPosition, aSet ); } @@ -2119,12 +2167,12 @@ void ImpEditEngine::ApplyChangedSentence(EditView const & rEditView, } else { - DBG_ASSERT( !pSpellInfo->aLastSpellContentSelections.empty(), "aLastSpellContentSelections should not be empty here" ); + DBG_ASSERT( !mpSpellInfo->aLastSpellContentSelections.empty(), "aLastSpellContentSelections should not be empty here" ); //select the complete sentence - SpellContentSelections::const_iterator aCurrentEndPosition = pSpellInfo->aLastSpellContentSelections.end(); + SpellContentSelections::const_iterator aCurrentEndPosition = mpSpellInfo->aLastSpellContentSelections.end(); --aCurrentEndPosition; - SpellContentSelections::const_iterator aCurrentStartPosition = pSpellInfo->aLastSpellContentSelections.begin(); + SpellContentSelections::const_iterator aCurrentStartPosition = mpSpellInfo->aLastSpellContentSelections.begin(); EditSelection aAllSentence(aCurrentStartPosition->Min(), aCurrentEndPosition->Max()); //delete the sentence completely @@ -2133,7 +2181,7 @@ void ImpEditEngine::ApplyChangedSentence(EditView const & rEditView, for(const auto& rCurrentNewPortion : rNewPortions) { //set the language attribute - LanguageType eCurLanguage = GetLanguage( aCurrentPaM ); + LanguageType eCurLanguage = GetLanguage( aCurrentPaM ).nLang; if(eCurLanguage != rCurrentNewPortion.eLanguage) { SvtScriptType nScriptType = SvtLanguageOptions::GetScriptTypeOfLanguage( rCurrentNewPortion.eLanguage ); @@ -2144,7 +2192,7 @@ void ImpEditEngine::ApplyChangedSentence(EditView const & rEditView, case SvtScriptType::COMPLEX : nLangWhichId = EE_CHAR_LANGUAGE_CTL; break; default: break; } - SfxItemSet aSet( aEditDoc.GetItemPool(), nLangWhichId, nLangWhichId); + SfxItemSet aSet( maEditDoc.GetItemPool(), nLangWhichId, nLangWhichId); aSet.Put(SvxLanguageItem(rCurrentNewPortion.eLanguage, nLangWhichId)); SetAttribs( aCurrentPaM, aSet ); } @@ -2156,28 +2204,28 @@ void ImpEditEngine::ApplyChangedSentence(EditView const & rEditView, EditPaM aNext; if (bRecheck) - aNext = pSpellInfo->aCurSentenceStart; + aNext = mpSpellInfo->aCurSentenceStart; else { // restore cursor position to the end of the modified sentence. // (This will define the continuation position for spell/grammar checking) // First: check if the sentence/para length changed - const sal_Int32 nDelta = rEditView.pImpEditView->GetEditSelection().Max().GetNode()->Len() - nOldLen; + const sal_Int32 nDelta = rEditView.getImpl().GetEditSelection().Max().GetNode()->Len() - nOldLen; const sal_Int32 nEndOfSentence = aOldSel.Max().GetIndex() + nDelta; aNext = EditPaM( aOldSel.Max().GetNode(), nEndOfSentence ); } - rEditView.pImpEditView->SetEditSelection( aNext ); + rEditView.getImpl().SetEditSelection( aNext ); if (IsUpdateLayout()) FormatAndLayout(); - aEditDoc.SetModified(true); + maEditDoc.SetModified(true); } void ImpEditEngine::PutSpellingToSentenceStart( EditView const & rEditView ) { - if( pSpellInfo && !pSpellInfo->aLastSpellContentSelections.empty() ) + if (mpSpellInfo && !mpSpellInfo->aLastSpellContentSelections.empty()) { - rEditView.pImpEditView->SetEditSelection( pSpellInfo->aLastSpellContentSelections.begin()->Min() ); + rEditView.getImpl().SetEditSelection(mpSpellInfo->aLastSpellContentSelections.begin()->Min()); } } @@ -2195,18 +2243,18 @@ void ImpEditEngine::DoOnlineSpelling( ContentNode* pThisNodeOnly, bool bSpellAtC even out properly with VDev on transitions from wrong => right) */ - if ( !xSpeller.is() ) + if (!mxSpeller.is()) return; EditPaM aCursorPos; - if( pActiveView && !bSpellAtCursorPos ) + if (mpActiveView && !bSpellAtCursorPos) { - aCursorPos = pActiveView->pImpEditView->GetEditSelection().Max(); + aCursorPos = mpActiveView->getImpl().GetEditSelection().Max(); } bool bRestartTimer = false; - ContentNode* pLastNode = aEditDoc.GetObject( aEditDoc.Count() - 1 ); + ContentNode* pLastNode = maEditDoc.GetObject( maEditDoc.Count() - 1 ); sal_Int32 nNodes = GetEditDoc().Count(); sal_Int32 nInvalids = 0; Sequence< PropertyValue > aEmptySeq; @@ -2257,7 +2305,7 @@ void ImpEditEngine::DoOnlineSpelling( ContentNode* pThisNodeOnly, bool bSpellAtC { const sal_Int32 nWStart = aSel.Min().GetIndex(); const sal_Int32 nWEnd = aSel.Max().GetIndex(); - if ( !xSpeller->isValid( aWord, static_cast<sal_uInt16>(GetLanguage( EditPaM( aSel.Min().GetNode(), nWStart+1 ) )), aEmptySeq ) ) + if (!mxSpeller->isValid( aWord, static_cast<sal_uInt16>(GetLanguage( EditPaM( aSel.Min().GetNode(), nWStart+1 ) ).nLang), aEmptySeq)) { // Check if already marked correctly... const sal_Int32 nXEnd = bDottAdded ? nWEnd -1 : nWEnd; @@ -2321,10 +2369,10 @@ void ImpEditEngine::DoOnlineSpelling( ContentNode* pThisNodeOnly, bool bSpellAtC // Invalidate? if ( nPaintFrom>=0 ) { - aStatus.GetStatusWord() |= EditStatusFlags::WRONGWORDCHANGED; + maStatus.GetStatusWord() |= EditStatusFlags::WRONGWORDCHANGED; CallStatusHdl(); - if (!aEditViews.empty()) + if (!maEditViews.empty()) { // For SimpleRepaint one was painted over a range without // reaching VDEV, but then one would have to intersect, c @@ -2333,35 +2381,35 @@ void ImpEditEngine::DoOnlineSpelling( ContentNode* pThisNodeOnly, bool bSpellAtC EditPaM aEndPaM( pNode, nPaintTo ); tools::Rectangle aStartCursor( PaMtoEditCursor( aStartPaM ) ); tools::Rectangle aEndCursor( PaMtoEditCursor( aEndPaM ) ); - DBG_ASSERT( aInvalidRect.IsEmpty(), "InvalidRect set!" ); - aInvalidRect.SetLeft( 0 ); - aInvalidRect.SetRight( GetPaperSize().Width() ); - aInvalidRect.SetTop( aStartCursor.Top() ); - aInvalidRect.SetBottom( aEndCursor.Bottom() ); - if ( pActiveView && pActiveView->HasSelection() ) + DBG_ASSERT(maInvalidRect.IsEmpty(), "InvalidRect set!"); + maInvalidRect.SetLeft( 0 ); + maInvalidRect.SetRight( GetPaperSize().Width() ); + maInvalidRect.SetTop( aStartCursor.Top() ); + maInvalidRect.SetBottom( aEndCursor.Bottom() ); + if (mpActiveView && mpActiveView->HasSelection()) { // Then no output through VDev. UpdateViews(); } else if ( bSimpleRepaint ) { - for (EditView* pView : aEditViews) + for (EditView* pView : maEditViews) { - tools::Rectangle aClipRect( aInvalidRect ); + tools::Rectangle aClipRect(maInvalidRect); aClipRect.Intersection( pView->GetVisArea() ); if ( !aClipRect.IsEmpty() ) { // convert to window coordinates... - aClipRect.SetPos( pView->pImpEditView->GetWindowPos( aClipRect.TopLeft() ) ); - pView->pImpEditView->InvalidateAtWindow(aClipRect); + aClipRect.SetPos( pView->getImpl().GetWindowPos( aClipRect.TopLeft() ) ); + pView->getImpl().InvalidateAtWindow(aClipRect); } } } else { - UpdateViews( pActiveView ); + UpdateViews(mpActiveView); } - aInvalidRect = tools::Rectangle(); + maInvalidRect = tools::Rectangle(); } } // After two corrected nodes give up the control... @@ -2377,16 +2425,16 @@ void ImpEditEngine::DoOnlineSpelling( ContentNode* pThisNodeOnly, bool bSpellAtC break; } if ( bRestartTimer ) - aOnlineSpellTimer.Start(); + maOnlineSpellTimer.Start(); } EESpellState ImpEditEngine::HasSpellErrors() { - DBG_ASSERT( xSpeller.is(), "No spell checker set!" ); + DBG_ASSERT(mxSpeller.is(), "No spell checker set!"); - ContentNode* pLastNode = aEditDoc.GetObject( aEditDoc.Count() - 1 ); - EditSelection aCurSel( aEditDoc.GetStartPaM() ); + ContentNode* pLastNode = maEditDoc.GetObject( maEditDoc.Count() - 1 ); + EditSelection aCurSel( maEditDoc.GetStartPaM() ); OUString aWord; Reference< XSpellAlternatives > xSpellAlt; @@ -2403,9 +2451,9 @@ EESpellState ImpEditEngine::HasSpellErrors() aWord = GetSelected( aCurSel ); if ( !aWord.isEmpty() ) { - LanguageType eLang = GetLanguage( aCurSel.Max() ); - SvxSpellWrapper::CheckSpellLang( xSpeller, eLang ); - xSpellAlt = xSpeller->spell( aWord, static_cast<sal_uInt16>(eLang), aEmptySeq ); + LanguageType eLang = GetLanguage( aCurSel.Max() ).nLang; + SvxSpellWrapper::CheckSpellLang(mxSpeller, eLang); + xSpellAlt = mxSpeller->spell( aWord, static_cast<sal_uInt16>(eLang), aEmptySeq ); } aCurSel = WordRight( aCurSel.Max(), css::i18n::WordType::DICTIONARY_WORD ); } @@ -2415,12 +2463,12 @@ EESpellState ImpEditEngine::HasSpellErrors() void ImpEditEngine::ClearSpellErrors() { - aEditDoc.ClearSpellErrors(); + maEditDoc.ClearSpellErrors(); } EESpellState ImpEditEngine::StartThesaurus(EditView* pEditView, weld::Widget* pDialogParent) { - EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() ); + EditSelection aCurSel( pEditView->getImpl().GetEditSelection() ); if ( !aCurSel.HasRange() ) aCurSel = SelectWord( aCurSel, css::i18n::WordType::DICTIONARY_WORD ); OUString aWord( GetSelected( aCurSel ) ); @@ -2431,13 +2479,13 @@ EESpellState ImpEditEngine::StartThesaurus(EditView* pEditView, weld::Widget* pD EditAbstractDialogFactory* pFact = EditAbstractDialogFactory::Create(); ScopedVclPtr<AbstractThesaurusDialog> xDlg(pFact->CreateThesaurusDialog(pDialogParent, xThes, - aWord, GetLanguage( aCurSel.Max() ) )); + aWord, GetLanguage( aCurSel.Max() ).nLang )); if (xDlg->Execute() == RET_OK) { // Replace Word... - pEditView->pImpEditView->DrawSelectionXOR(); - pEditView->pImpEditView->SetEditSelection( aCurSel ); - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); + pEditView->getImpl().SetEditSelection( aCurSel ); + pEditView->getImpl().DrawSelectionXOR(); pEditView->InsertText(xDlg->GetWord()); pEditView->ShowCursor(true, false); } @@ -2449,7 +2497,7 @@ sal_Int32 ImpEditEngine::StartSearchAndReplace( EditView* pEditView, const SvxSe { sal_Int32 nFound = 0; - EditSelection aCurSel( pEditView->pImpEditView->GetEditSelection() ); + EditSelection aCurSel( pEditView->getImpl().GetEditSelection() ); // FIND_ALL is not possible without multiple selection. if ( ( rSearchItem.GetCommand() == SvxSearchCmd::FIND ) || @@ -2477,10 +2525,10 @@ sal_Int32 ImpEditEngine::StartSearchAndReplace( EditView* pEditView, const SvxSe SvxSearchItem aTmpItem( rSearchItem ); aTmpItem.SetBackward( false ); - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); - aCurSel.Adjust( aEditDoc ); - EditPaM aStartPaM = aTmpItem.GetSelection() ? aCurSel.Min() : aEditDoc.GetStartPaM(); + aCurSel.Adjust( maEditDoc ); + EditPaM aStartPaM = aTmpItem.GetSelection() ? aCurSel.Min() : maEditDoc.GetStartPaM(); EditSelection aFoundSel( aCurSel.Max() ); bool bFound = ImpSearch( aTmpItem, aCurSel, aStartPaM, aFoundSel ); if ( bFound ) @@ -2496,13 +2544,13 @@ sal_Int32 ImpEditEngine::StartSearchAndReplace( EditView* pEditView, const SvxSe EditPaM aNewPaM( aFoundSel.Max() ); if ( aNewPaM.GetIndex() > aNewPaM.GetNode()->Len() ) aNewPaM.SetIndex( aNewPaM.GetNode()->Len() ); - pEditView->pImpEditView->SetEditSelection( aNewPaM ); + pEditView->getImpl().SetEditSelection( aNewPaM ); FormatAndLayout( pEditView ); UndoActionEnd(); } else { - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); pEditView->ShowCursor( true, false ); } } @@ -2511,8 +2559,8 @@ sal_Int32 ImpEditEngine::StartSearchAndReplace( EditView* pEditView, const SvxSe bool ImpEditEngine::Search( const SvxSearchItem& rSearchItem, EditView* pEditView ) { - EditSelection aSel( pEditView->pImpEditView->GetEditSelection() ); - aSel.Adjust( aEditDoc ); + EditSelection aSel( pEditView->getImpl().GetEditSelection() ); + aSel.Adjust( maEditDoc ); EditPaM aStartPaM( aSel.Max() ); if ( rSearchItem.GetSelection() && !rSearchItem.GetBackward() ) aStartPaM = aSel.Min(); @@ -2525,18 +2573,18 @@ bool ImpEditEngine::Search( const SvxSearchItem& rSearchItem, EditView* pEditVie bFound = ImpSearch( rSearchItem, aSel, aStartPaM, aFoundSel ); } - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); if ( bFound ) { // First, set the minimum, so the whole word is in the visible range. - pEditView->pImpEditView->SetEditSelection( aFoundSel.Min() ); + pEditView->getImpl().SetEditSelection( aFoundSel.Min() ); pEditView->ShowCursor( true, false ); - pEditView->pImpEditView->SetEditSelection( aFoundSel ); + pEditView->getImpl().SetEditSelection( aFoundSel ); } else - pEditView->pImpEditView->SetEditSelection( aSel.Max() ); + pEditView->getImpl().SetEditSelection( aSel.Max() ); - pEditView->pImpEditView->DrawSelectionXOR(); + pEditView->getImpl().DrawSelectionXOR(); pEditView->ShowCursor( true, false ); return bFound; } @@ -2549,15 +2597,15 @@ bool ImpEditEngine::ImpSearch( const SvxSearchItem& rSearchItem, bool bBack = rSearchItem.GetBackward(); bool bSearchInSelection = rSearchItem.GetSelection(); - sal_Int32 nStartNode = aEditDoc.GetPos( rStartPos.GetNode() ); + sal_Int32 nStartNode = maEditDoc.GetPos( rStartPos.GetNode() ); sal_Int32 nEndNode; if ( bSearchInSelection ) { - nEndNode = aEditDoc.GetPos( bBack ? rSearchSelection.Min().GetNode() : rSearchSelection.Max().GetNode() ); + nEndNode = maEditDoc.GetPos( bBack ? rSearchSelection.Min().GetNode() : rSearchSelection.Max().GetNode() ); } else { - nEndNode = bBack ? 0 : aEditDoc.Count()-1; + nEndNode = bBack ? 0 : maEditDoc.Count()-1; } utl::TextSearch aSearcher( aSearchOptions ); @@ -2571,7 +2619,7 @@ bool ImpEditEngine::ImpSearch( const SvxSearchItem& rSearchItem, if ( nNode < 0 ) return false; - ContentNode* pNode = aEditDoc.GetObject( nNode ); + ContentNode* pNode = maEditDoc.GetObject( nNode ); sal_Int32 nStartPos = 0; sal_Int32 nEndPos = pNode->GetExpandedLen(); @@ -2626,7 +2674,7 @@ bool ImpEditEngine::HasText( const SvxSearchItem& rSearchItem ) aTmpItem.SetBackward( false ); aTmpItem.SetSelection( false ); - EditPaM aStartPaM( aEditDoc.GetStartPaM() ); + EditPaM aStartPaM( maEditDoc.GetStartPaM() ); EditSelection aDummySel( aStartPaM ); EditSelection aFoundSel; return ImpSearch( aTmpItem, aDummySel, aStartPaM, aFoundSel ); @@ -2634,9 +2682,9 @@ bool ImpEditEngine::HasText( const SvxSearchItem& rSearchItem ) void ImpEditEngine::SetAutoCompleteText(const OUString& rStr, bool bClearTipWindow) { - aAutoCompleteText = rStr; - if ( bClearTipWindow && pActiveView ) - Help::ShowQuickHelp( pActiveView->GetWindow(), tools::Rectangle(), OUString() ); + maAutoCompleteText = rStr; + if ( bClearTipWindow && mpActiveView ) + Help::ShowQuickHelp( mpActiveView->GetWindow(), tools::Rectangle(), OUString() ); } namespace @@ -2658,15 +2706,16 @@ EditSelection ImpEditEngine::TransliterateText( const EditSelection& rSelection, return rSelection; EditSelection aSel( rSelection ); - aSel.Adjust( aEditDoc ); + aSel.Adjust( maEditDoc ); if ( !aSel.HasRange() ) { - /* Cursor is inside of a word */ - if (nTransliterationMode == TransliterationFlags::SENTENCE_CASE) - aSel = SelectSentence( aSel ); - else - aSel = SelectWord( aSel ); + aSel = SelectWord( aSel, css::i18n::WordType::ANYWORD_IGNOREWHITESPACES, true, true ); + if (!aSel.HasRange() && aSel.Min().GetIndex() > 0 && + OUString(".!?").indexOf(aSel.Min().GetNode()->GetChar(aSel.Min().GetIndex() - 1)) > -1 ) + { + aSel = SelectSentence(aSel); + } } // tdf#107176: if there's still no range, just return aSel @@ -2675,8 +2724,8 @@ EditSelection ImpEditEngine::TransliterateText( const EditSelection& rSelection, EditSelection aNewSel( aSel ); - const sal_Int32 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() ); - const sal_Int32 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() ); + const sal_Int32 nStartNode = maEditDoc.GetPos( aSel.Min().GetNode() ); + const sal_Int32 nEndNode = maEditDoc.GetPos( aSel.Max().GetNode() ); bool bChanges = false; bool bLenChanged = false; @@ -2687,7 +2736,7 @@ EditSelection ImpEditEngine::TransliterateText( const EditSelection& rSelection, for ( sal_Int32 nNode = nStartNode; nNode <= nEndNode; nNode++ ) { - ContentNode* pNode = aEditDoc.GetObject( nNode ); + ContentNode* pNode = maEditDoc.GetObject( nNode ); const OUString& aNodeStr = pNode->GetString(); const sal_Int32 nStartPos = nNode==nStartNode ? aSel.Min().GetIndex() : 0; const sal_Int32 nEndPos = nNode==nEndNode ? aSel.Max().GetIndex() : aNodeStr.getLength(); // can also be == nStart! @@ -2744,6 +2793,21 @@ EditSelection ImpEditEngine::TransliterateText( const EditSelection& rSelection, nWordType); } + /* Nothing to do if user selection lies entirely outside of word start and end boundary computed above. + * Skip this node, because otherwise the below logic for constraining to the selection will fail */ + if (aSttBndry.startPos >= aSel.Max().GetIndex() || aEndBndry.endPos <= aSel.Min().GetIndex()) { + continue; + } + + // prevent going outside of the user's selection, which may + // start or end in the middle of a word + if (nNode == nStartNode) { + aSttBndry.startPos = std::max(aSttBndry.startPos, aSel.Min().GetIndex()); + aSttBndry.endPos = std::min(aSttBndry.endPos, aSel.Max().GetIndex()); + aEndBndry.startPos = std::max(aEndBndry.startPos, aSttBndry.startPos); + aEndBndry.endPos = std::min(aEndBndry.endPos, aSel.Max().GetIndex()); + } + i18n::Boundary aCurWordBndry( aSttBndry ); while (aCurWordBndry.endPos && aCurWordBndry.startPos <= aEndBndry.startPos) { @@ -2754,7 +2818,7 @@ EditSelection ImpEditEngine::TransliterateText( const EditSelection& rSelection, Sequence< sal_Int32 > aOffsets; OUString aNewText( aTransliterationWrapper.transliterate(aNodeStr, - GetLanguage( EditPaM( pNode, nCurrentStart + 1 ) ), + GetLanguage( EditPaM( pNode, nCurrentStart + 1 ) ).nLang, nCurrentStart, nLen, &aOffsets )); if (aNodeStr != aNewText) @@ -2845,7 +2909,7 @@ EditSelection ImpEditEngine::TransliterateText( const EditSelection& rSelection, Sequence< sal_Int32 > aOffsets; OUString aNewText( aTransliterationWrapper.transliterate( aNodeStr, - GetLanguage( EditPaM( pNode, nCurrentStart + 1 ) ), + GetLanguage( EditPaM( pNode, nCurrentStart + 1 ) ).nLang, nCurrentStart, nLen, &aOffsets )); if (aNodeStr != aNewText) @@ -2875,7 +2939,7 @@ EditSelection ImpEditEngine::TransliterateText( const EditSelection& rSelection, { if ( bConsiderLanguage ) { - nLanguage = GetLanguage( EditPaM( pNode, nCurrentStart+1 ), &nCurrentEnd ); + nLanguage = GetLanguage( EditPaM( pNode, nCurrentStart+1 ), &nCurrentEnd ).nLang; if ( nCurrentEnd > nEndPos ) nCurrentEnd = nEndPos; } @@ -2918,7 +2982,7 @@ EditSelection ImpEditEngine::TransliterateText( const EditSelection& rSelection, aNewSel = aSel; ESelection aESel( CreateESel( aSel ) ); - pUndo.reset(new EditUndoTransliteration(pEditEngine, aESel, nTransliterationMode)); + pUndo.reset(new EditUndoTransliteration(mpEditEngine, aESel, nTransliterationMode)); const bool bSingleNode = aSel.Min().GetNode()== aSel.Max().GetNode(); const bool bHasAttribs = aSel.Min().GetNode()->GetCharAttribs().HasAttrib( aSel.Min().GetIndex(), aSel.Max().GetIndex() ); @@ -2947,9 +3011,9 @@ EditSelection ImpEditEngine::TransliterateText( const EditSelection& rSelection, if (aSel.Max().GetNode() == rData.aSelection.Max().GetNode()) aNewSel.Max().SetIndex( aNewSel.Max().GetIndex() + nDiffs ); - sal_Int32 nSelNode = aEditDoc.GetPos( rData.aSelection.Min().GetNode() ); - ParaPortion& rParaPortion = GetParaPortions()[nSelNode]; - rParaPortion.MarkSelectionInvalid( rData.nStart ); + sal_Int32 nSelNode = maEditDoc.GetPos( rData.aSelection.Min().GetNode() ); + ParaPortion& rParaPortion = GetParaPortions().getRef(nSelNode); + rParaPortion.MarkSelectionInvalid(rData.nStart); } } } @@ -3007,7 +3071,7 @@ short ImpEditEngine::ReplaceTextOnly( else { DBG_ASSERT( nDiff == 1, "TransliterateText - Diff other than expected! But should work..." ); - GetEditDoc().InsertText( EditPaM( pNode, nCurrentPos ), OUString(rNewText[n]) ); + GetEditDoc().InsertText( EditPaM( pNode, nCurrentPos ), OUStringChar(rNewText[n]) ); } nDiffs = sal::static_int_cast< short >(nDiffs + nDiff); @@ -3019,9 +3083,9 @@ short ImpEditEngine::ReplaceTextOnly( void ImpEditEngine::SetAsianCompressionMode( CharCompressType n ) { - if ( n != nAsianCompressionMode ) + if (n != mnAsianCompressionMode) { - nAsianCompressionMode = n; + mnAsianCompressionMode = n; if ( ImplHasText() ) { FormatFullDoc(); @@ -3032,9 +3096,9 @@ void ImpEditEngine::SetAsianCompressionMode( CharCompressType n ) void ImpEditEngine::SetKernAsianPunctuation( bool b ) { - if ( b != bKernAsianPunctuation ) + if ( b != mbKernAsianPunctuation ) { - bKernAsianPunctuation = b; + mbKernAsianPunctuation = b; if ( ImplHasText() ) { FormatFullDoc(); @@ -3047,7 +3111,7 @@ void ImpEditEngine::SetAddExtLeading( bool bExtLeading ) { if ( IsAddExtLeading() != bExtLeading ) { - bAddExtLeading = bExtLeading; + mbAddExtLeading = bExtLeading; if ( ImplHasText() ) { FormatFullDoc(); @@ -3066,8 +3130,21 @@ sal_Int32 ImpEditEngine::LogicToTwips(sal_Int32 n) { Size aSz(n, 0); MapMode aTwipsMode( MapUnit::MapTwip ); - aSz = pRefDev->LogicToLogic( aSz, nullptr, &aTwipsMode ); + aSz = mpRefDev->LogicToLogic( aSz, nullptr, &aTwipsMode ); return aSz.Width(); } +double ImpEditEngine::roundToNearestPt(double fInput) const +{ + if (mbRoundToNearestPt) + { + double fInputPt = o3tl::convert(fInput, o3tl::Length::mm100, o3tl::Length::pt); + return o3tl::convert(std::round(fInputPt), o3tl::Length::pt, o3tl::Length::mm100); + } + else + { + return fInput; + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/impedit5.cxx b/editeng/source/editeng/impedit5.cxx index c9d7563e2ffe..396e529c514d 100644 --- a/editeng/source/editeng/impedit5.cxx +++ b/editeng/source/editeng/impedit5.cxx @@ -22,33 +22,32 @@ #include <editeng/editeng.hxx> #include <svl/hint.hxx> #include <sfx2/app.hxx> +#include <utility> void ImpEditEngine::SetStyleSheetPool( SfxStyleSheetPool* pSPool ) { - if ( pStylePool != pSPool ) - { - pStylePool = pSPool; - } + if (mpStylePool != pSPool) + mpStylePool = pSPool; } const SfxStyleSheet* ImpEditEngine::GetStyleSheet( sal_Int32 nPara ) const { - const ContentNode* pNode = aEditDoc.GetObject( nPara ); + const ContentNode* pNode = maEditDoc.GetObject( nPara ); return pNode ? pNode->GetContentAttribs().GetStyleSheet() : nullptr; } SfxStyleSheet* ImpEditEngine::GetStyleSheet( sal_Int32 nPara ) { - ContentNode* pNode = aEditDoc.GetObject( nPara ); + ContentNode* pNode = maEditDoc.GetObject( nPara ); return pNode ? pNode->GetContentAttribs().GetStyleSheet() : nullptr; } void ImpEditEngine::SetStyleSheet( EditSelection aSel, SfxStyleSheet* pStyle ) { - aSel.Adjust( aEditDoc ); + aSel.Adjust( maEditDoc ); - sal_Int32 nStartPara = aEditDoc.GetPos( aSel.Min().GetNode() ); - sal_Int32 nEndPara = aEditDoc.GetPos( aSel.Max().GetNode() ); + sal_Int32 nStartPara = maEditDoc.GetPos( aSel.Min().GetNode() ); + sal_Int32 nEndPara = maEditDoc.GetPos( aSel.Max().GetNode() ); bool _bUpdate = SetUpdateLayout( false ); @@ -61,11 +60,11 @@ void ImpEditEngine::SetStyleSheet( EditSelection aSel, SfxStyleSheet* pStyle ) void ImpEditEngine::SetStyleSheet( sal_Int32 nPara, SfxStyleSheet* pStyle ) { DBG_ASSERT( GetStyleSheetPool() || !pStyle, "SetStyleSheet: No StyleSheetPool registered!" ); - ContentNode* pNode = aEditDoc.GetObject( nPara ); + ContentNode* pNode = maEditDoc.GetObject( nPara ); SfxStyleSheet* pCurStyle = pNode->GetStyleSheet(); if ( pStyle != pCurStyle ) { - if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() ) + if ( IsUndoEnabled() && !IsInUndo() && maStatus.DoUndoAttribs() ) { OUString aPrevStyleName; if ( pCurStyle ) @@ -76,16 +75,19 @@ void ImpEditEngine::SetStyleSheet( sal_Int32 nPara, SfxStyleSheet* pStyle ) aNewStyleName = pStyle->GetName(); InsertUndo( - std::make_unique<EditUndoSetStyleSheet>(pEditEngine, aEditDoc.GetPos( pNode ), + std::make_unique<EditUndoSetStyleSheet>(mpEditEngine, maEditDoc.GetPos( pNode ), aPrevStyleName, pCurStyle ? pCurStyle->GetFamily() : SfxStyleFamily::Para, aNewStyleName, pStyle ? pStyle->GetFamily() : SfxStyleFamily::Para, pNode->GetContentAttribs().GetItems() ) ); } if ( pCurStyle ) EndListening( *pCurStyle ); - pNode->SetStyleSheet( pStyle, aStatus.UseCharAttribs() ); + pNode->SetStyleSheet( pStyle, maStatus.UseCharAttribs() ); if ( pStyle ) - StartListening(*pStyle, DuplicateHandling::Prevent); + StartListening(*pStyle, DuplicateHandling::Allow); + + if (pNode->GetWrongList()) + pNode->GetWrongList()->ResetInvalidRange(0, pNode->Len()); ParaAttribsChanged( pNode ); } if (IsUpdateLayout()) @@ -98,17 +100,19 @@ void ImpEditEngine::UpdateParagraphsWithStyleSheet( SfxStyleSheet* pStyle ) CreateFont( aFontFromStyle, pStyle->GetItemSet() ); bool bUsed = false; - for ( sal_Int32 nNode = 0; nNode < aEditDoc.Count(); nNode++ ) + for ( sal_Int32 nNode = 0; nNode < maEditDoc.Count(); nNode++ ) { - ContentNode* pNode = aEditDoc.GetObject( nNode ); + ContentNode* pNode = maEditDoc.GetObject( nNode ); if ( pNode->GetStyleSheet() == pStyle ) { bUsed = true; - if ( aStatus.UseCharAttribs() ) + if (maStatus.UseCharAttribs()) pNode->SetStyleSheet( pStyle, aFontFromStyle ); else pNode->SetStyleSheet( pStyle, false ); + if (pNode->GetWrongList()) + pNode->GetWrongList()->ResetInvalidRange(0, pNode->Len()); ParaAttribsChanged( pNode ); } } @@ -122,9 +126,9 @@ void ImpEditEngine::UpdateParagraphsWithStyleSheet( SfxStyleSheet* pStyle ) void ImpEditEngine::RemoveStyleFromParagraphs( SfxStyleSheet const * pStyle ) { - for ( sal_Int32 nNode = 0; nNode < aEditDoc.Count(); nNode++ ) + for ( sal_Int32 nNode = 0; nNode < maEditDoc.Count(); nNode++ ) { - ContentNode* pNode = aEditDoc.GetObject(nNode); + ContentNode* pNode = maEditDoc.GetObject(nNode); if ( pNode->GetStyleSheet() == pStyle ) { pNode->SetStyleSheet( nullptr ); @@ -138,72 +142,67 @@ void ImpEditEngine::RemoveStyleFromParagraphs( SfxStyleSheet const * pStyle ) void ImpEditEngine::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) { // So that not a lot of unnecessary formatting is done when destructing: - if ( !bDowning ) + if (!mbDowning) { - - const SfxStyleSheetHint* pStyleSheetHint = dynamic_cast<const SfxStyleSheetHint*>(&rHint); - if ( pStyleSheetHint ) + SfxHintId nId = rHint.GetId(); + if ( ( nId == SfxHintId::StyleSheetInDestruction ) || + ( nId == SfxHintId::StyleSheetErased ) ) { - DBG_ASSERT( dynamic_cast< const SfxStyleSheet* >(pStyleSheetHint->GetStyleSheet()) != nullptr, "No SfxStyleSheet!" ); + const SfxStyleSheetHint* pStyleSheetHint = static_cast<const SfxStyleSheetHint*>(&rHint); SfxStyleSheet* pStyle = static_cast<SfxStyleSheet*>( pStyleSheetHint->GetStyleSheet() ); - SfxHintId nId = pStyleSheetHint->GetId(); - if ( ( nId == SfxHintId::StyleSheetInDestruction ) || - ( nId == SfxHintId::StyleSheetErased ) ) - { - RemoveStyleFromParagraphs( pStyle ); - } - else if ( nId == SfxHintId::StyleSheetModified ) - { - UpdateParagraphsWithStyleSheet( pStyle ); - } + RemoveStyleFromParagraphs( pStyle ); } - else if ( auto pStyle = dynamic_cast< SfxStyleSheet* >(&rBC) ) + else if ( nId == SfxHintId::StyleSheetModified || nId == SfxHintId::StyleSheetModifiedExtended ) { - SfxHintId nId = rHint.GetId(); - if ( nId == SfxHintId::Dying ) - { - RemoveStyleFromParagraphs( pStyle ); - } - else if ( nId == SfxHintId::DataChanged ) - { - UpdateParagraphsWithStyleSheet( pStyle ); - } + const SfxStyleSheetHint* pStyleSheetHint = static_cast<const SfxStyleSheetHint*>(&rHint); + SfxStyleSheet* pStyle = static_cast<SfxStyleSheet*>( pStyleSheetHint->GetStyleSheet() ); + UpdateParagraphsWithStyleSheet( pStyle ); + } + else if ( nId == SfxHintId::Dying && rBC.IsSfxStyleSheet() ) + { + auto pStyle = static_cast< SfxStyleSheet* >(&rBC); + RemoveStyleFromParagraphs( pStyle ); + } + else if ( nId == SfxHintId::DataChanged && rBC.IsSfxStyleSheet()) + { + auto pStyle = static_cast< SfxStyleSheet* >(&rBC); + UpdateParagraphsWithStyleSheet( pStyle ); } } - if(dynamic_cast<const SfxApplication*>(&rBC) != nullptr && rHint.GetId() == SfxHintId::Dying) + if (rHint.GetId() == SfxHintId::Dying && dynamic_cast<const SfxApplication*>(&rBC)) Dispose(); } std::unique_ptr<EditUndoSetAttribs> ImpEditEngine::CreateAttribUndo( EditSelection aSel, const SfxItemSet& rSet ) { - DBG_ASSERT( !aSel.DbgIsBuggy( aEditDoc ), "CreateAttribUndo: Incorrect selection "); - aSel.Adjust( aEditDoc ); + DBG_ASSERT( !aSel.DbgIsBuggy( maEditDoc ), "CreateAttribUndo: Incorrect selection "); + aSel.Adjust( maEditDoc ); ESelection aESel( CreateESel( aSel ) ); - sal_Int32 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() ); - sal_Int32 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() ); + sal_Int32 nStartNode = maEditDoc.GetPos( aSel.Min().GetNode() ); + sal_Int32 nEndNode = maEditDoc.GetPos( aSel.Max().GetNode() ); DBG_ASSERT( nStartNode <= nEndNode, "CreateAttribUndo: Start > End ?!" ); std::unique_ptr<EditUndoSetAttribs> pUndo; - if ( rSet.GetPool() != &aEditDoc.GetItemPool() ) + if ( rSet.GetPool() != &maEditDoc.GetItemPool() ) { SfxItemSet aTmpSet( GetEmptyItemSet() ); aTmpSet.Put( rSet ); - pUndo.reset( new EditUndoSetAttribs(pEditEngine, aESel, aTmpSet) ); + pUndo.reset( new EditUndoSetAttribs(mpEditEngine, aESel, std::move(aTmpSet)) ); } else { - pUndo.reset( new EditUndoSetAttribs(pEditEngine, aESel, rSet) ); + pUndo.reset( new EditUndoSetAttribs(mpEditEngine, aESel, rSet) ); } SfxItemPool* pPool = pUndo->GetNewAttribs().GetPool(); for ( sal_Int32 nPara = nStartNode; nPara <= nEndNode; nPara++ ) { - ContentNode* pNode = aEditDoc.GetObject( nPara ); - DBG_ASSERT( aEditDoc.GetObject( nPara ), "Node not found: CreateAttribUndo" ); + ContentNode* pNode = maEditDoc.GetObject( nPara ); + DBG_ASSERT( maEditDoc.GetObject( nPara ), "Node not found: CreateAttribUndo" ); ContentAttribsInfo* pInf = new ContentAttribsInfo( pNode->GetContentAttribs().GetItems() ); pUndo->AppendContentInfo(pInf); @@ -224,8 +223,8 @@ ViewShellId ImpEditEngine::CreateViewShellId() { ViewShellId nRet(-1); - const EditView* pEditView = pEditEngine ? pEditEngine->GetActiveView() : nullptr; - const OutlinerViewShell* pViewShell = pEditView ? pEditView->GetImpEditView()->GetViewShell() : nullptr; + const EditView* pEditView = mpEditEngine ? mpEditEngine->GetActiveView() : nullptr; + const OutlinerViewShell* pViewShell = pEditView ? pEditView->getImpl().GetViewShell() : nullptr; if (pViewShell) nRet = pViewShell->GetViewShellId(); @@ -237,8 +236,8 @@ void ImpEditEngine::UndoActionStart( sal_uInt16 nId, const ESelection& aSel ) if ( IsUndoEnabled() && !IsInUndo() ) { GetUndoManager().EnterListAction( GetEditEnginePtr()->GetUndoComment( nId ), OUString(), nId, CreateViewShellId() ); - DBG_ASSERT( !pUndoMarkSelection, "UndoAction SelectionMarker?" ); - pUndoMarkSelection.reset(new ESelection( aSel )); + DBG_ASSERT( !moUndoMarkSelection, "UndoAction SelectionMarker?" ); + moUndoMarkSelection = aSel; } } @@ -247,7 +246,7 @@ void ImpEditEngine::UndoActionStart( sal_uInt16 nId ) if ( IsUndoEnabled() && !IsInUndo() ) { GetUndoManager().EnterListAction( GetEditEnginePtr()->GetUndoComment( nId ), OUString(), nId, CreateViewShellId() ); - DBG_ASSERT( !pUndoMarkSelection, "UndoAction SelectionMarker?" ); + DBG_ASSERT( !moUndoMarkSelection, "UndoAction SelectionMarker?" ); } } @@ -256,17 +255,17 @@ void ImpEditEngine::UndoActionEnd() if ( IsUndoEnabled() && !IsInUndo() ) { GetUndoManager().LeaveListAction(); - pUndoMarkSelection.reset(); + moUndoMarkSelection.reset(); } } void ImpEditEngine::InsertUndo( std::unique_ptr<EditUndo> pUndo, bool bTryMerge ) { DBG_ASSERT( !IsInUndo(), "InsertUndo in Undo mode!" ); - if ( pUndoMarkSelection ) + if ( moUndoMarkSelection ) { - GetUndoManager().AddUndoAction( std::make_unique<EditUndoMarkSelection>(pEditEngine, *pUndoMarkSelection) ); - pUndoMarkSelection.reset(); + GetUndoManager().AddUndoAction( std::make_unique<EditUndoMarkSelection>(mpEditEngine, *moUndoMarkSelection) ); + moUndoMarkSelection.reset(); } GetUndoManager().AddUndoAction( std::move(pUndo), bTryMerge ); @@ -285,7 +284,7 @@ void ImpEditEngine::EnableUndo( bool bEnable ) if ( bEnable != IsUndoEnabled() ) ResetUndoManager(); - bUndoEnabled = bEnable; + mbUndoEnabled = bEnable; } void ImpEditEngine::Undo( EditView* pView ) @@ -309,18 +308,18 @@ void ImpEditEngine::Redo( EditView* pView ) SfxItemSet ImpEditEngine::GetAttribs( EditSelection aSel, EditEngineAttribs nOnlyHardAttrib ) { - aSel.Adjust( aEditDoc ); + aSel.Adjust( maEditDoc ); SfxItemSet aCurSet( GetEmptyItemSet() ); - sal_Int32 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() ); - sal_Int32 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() ); + sal_Int32 nStartNode = maEditDoc.GetPos( aSel.Min().GetNode() ); + sal_Int32 nEndNode = maEditDoc.GetPos( aSel.Max().GetNode() ); // iterate over the paragraphs ... for ( sal_Int32 nNode = nStartNode; nNode <= nEndNode; nNode++ ) { - ContentNode* pNode = aEditDoc.GetObject( nNode ); - DBG_ASSERT( aEditDoc.GetObject( nNode ), "Node not found: GetAttrib" ); + ContentNode* pNode = maEditDoc.GetObject( nNode ); + assert( pNode && "Node not found: GetAttrib" ); const sal_Int32 nStartPos = nNode==nStartNode ? aSel.Min().GetIndex() : 0; const sal_Int32 nEndPos = nNode==nEndNode ? aSel.Max().GetIndex() : pNode->Len(); // Can also be == nStart! @@ -331,7 +330,8 @@ SfxItemSet ImpEditEngine::GetAttribs( EditSelection aSel, EditEngineAttribs nOnl // 2) Examine Style and paragraph attributes only when OFF... // First the very hard formatting... - EditDoc::FindAttribs( pNode, nStartPos, nEndPos, aCurSet ); + if (pNode) + EditDoc::FindAttribs( pNode, nStartPos, nEndPos, aCurSet ); if( nOnlyHardAttrib != EditEngineAttribs::OnlyHard ) { @@ -386,7 +386,7 @@ SfxItemSet ImpEditEngine::GetAttribs( EditSelection aSel, EditEngineAttribs nOnl { if ( aCurSet.GetItemState( nWhich ) == SfxItemState::DEFAULT ) { - aCurSet.Put( aEditDoc.GetItemPool().GetDefaultItem( nWhich ) ); + aCurSet.Put( maEditDoc.GetItemPool().GetUserOrPoolDefaultItem( nWhich ) ); } } } @@ -400,7 +400,7 @@ SfxItemSet ImpEditEngine::GetAttribs( sal_Int32 nPara, sal_Int32 nStart, sal_Int // If this works, change GetAttribs( EditSelection ) to use this for each paragraph and merge the results! - ContentNode* pNode = const_cast<ContentNode*>(aEditDoc.GetObject(nPara)); + ContentNode* pNode = const_cast<ContentNode*>(maEditDoc.GetObject(nPara)); DBG_ASSERT( pNode, "GetAttribs - unknown paragraph!" ); DBG_ASSERT( nStart <= nEnd, "getAttribs: Start > End not supported!" ); @@ -427,8 +427,7 @@ SfxItemSet ImpEditEngine::GetAttribs( sal_Int32 nPara, sal_Int32 nStart, sal_Int if ( nFlags & GetAttribsFlags::CHARATTRIBS ) { // Make testing easier... - const SfxItemPool& rPool = GetEditDoc().GetItemPool(); - pNode->GetCharAttribs().OptimizeRanges(const_cast<SfxItemPool&>(rPool)); + pNode->GetCharAttribs().OptimizeRanges(); const CharAttribList::AttribsType& rAttrs = pNode->GetCharAttribs().GetAttribs(); for (const auto & nAttr : rAttrs) @@ -487,17 +486,17 @@ SfxItemSet ImpEditEngine::GetAttribs( sal_Int32 nPara, sal_Int32 nStart, sal_Int void ImpEditEngine::SetAttribs( EditSelection aSel, const SfxItemSet& rSet, SetAttribsMode nSpecial, bool bSetSelection ) { - aSel.Adjust( aEditDoc ); + aSel.Adjust( maEditDoc ); // When no selection => use the Attribute on the word. // ( the RTF-parser should actually never call the Method without a Range ) if ( nSpecial == SetAttribsMode::WholeWord && !aSel.HasRange() ) aSel = SelectWord( aSel, css::i18n::WordType::ANYWORD_IGNOREWHITESPACES, false ); - sal_Int32 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() ); - sal_Int32 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() ); + sal_Int32 nStartNode = maEditDoc.GetPos( aSel.Min().GetNode() ); + sal_Int32 nEndNode = maEditDoc.GetPos( aSel.Max().GetNode() ); - if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() ) + if (IsUndoEnabled() && !IsInUndo() && maStatus.DoUndoAttribs()) { std::unique_ptr<EditUndoSetAttribs> pUndo = CreateAttribUndo( aSel, rSet ); pUndo->SetSpecial( nSpecial ); @@ -519,11 +518,14 @@ void ImpEditEngine::SetAttribs( EditSelection aSel, const SfxItemSet& rSet, SetA bool bParaAttribFound = false; bool bCharAttribFound = false; - DBG_ASSERT( aEditDoc.GetObject( nNode ), "Node not found: SetAttribs" ); - DBG_ASSERT( GetParaPortions().SafeGetObject( nNode ), "Portion not found: SetAttribs" ); + DBG_ASSERT( maEditDoc.GetObject( nNode ), "Node not found: SetAttribs" ); + DBG_ASSERT(GetParaPortions().exists(nNode), "Portion not found: SetAttribs"); - ContentNode* pNode = aEditDoc.GetObject( nNode ); - ParaPortion& rPortion = GetParaPortions()[nNode]; + if (!GetParaPortions().exists(nNode)) + continue; + + ContentNode* pNode = maEditDoc.GetObject(nNode); + ParaPortion& rPortion = GetParaPortions().getRef(nNode); const sal_Int32 nStartPos = nNode==nStartNode ? aSel.Min().GetIndex() : 0; const sal_Int32 nEndPos = nNode==nEndNode ? aSel.Max().GetIndex() : pNode->Len(); // can also be == nStart! @@ -541,7 +543,7 @@ void ImpEditEngine::SetAttribs( EditSelection aSel, const SfxItemSet& rSet, SetA } else { - aEditDoc.InsertAttrib( pNode, nStartPos, nEndPos, rItem ); + maEditDoc.InsertAttrib( pNode, nStartPos, nEndPos, rItem ); bCharAttribFound = true; if ( nSpecial == SetAttribsMode::Edge ) { @@ -565,14 +567,14 @@ void ImpEditEngine::SetAttribs( EditSelection aSel, const SfxItemSet& rSet, SetA if ( bParaAttribFound ) { - ParaAttribsChanged( rPortion.GetNode() ); + ParaAttribsChanged(rPortion.GetNode()); } else if ( bCharAttribFound ) { - bFormatted = false; + mbFormatted = false; if ( !pNode->Len() || ( nStartPos != nEndPos ) ) { - rPortion.MarkSelectionInvalid( nStartPos ); + rPortion.MarkSelectionInvalid(nStartPos); if ( bCheckLanguage ) pNode->GetWrongList()->SetInvalidRange(nStartPos, nEndPos); } @@ -582,14 +584,14 @@ void ImpEditEngine::SetAttribs( EditSelection aSel, const SfxItemSet& rSet, SetA void ImpEditEngine::RemoveCharAttribs( EditSelection aSel, EERemoveParaAttribsMode eMode, sal_uInt16 nWhich ) { - aSel.Adjust( aEditDoc ); + aSel.Adjust( maEditDoc ); - sal_Int32 nStartNode = aEditDoc.GetPos( aSel.Min().GetNode() ); - sal_Int32 nEndNode = aEditDoc.GetPos( aSel.Max().GetNode() ); + sal_Int32 nStartNode = maEditDoc.GetPos( aSel.Min().GetNode() ); + sal_Int32 nEndNode = maEditDoc.GetPos( aSel.Max().GetNode() ); bool bRemoveParaAttribs = eMode == EERemoveParaAttribsMode::RemoveAll; const SfxItemSet* _pEmptyItemSet = bRemoveParaAttribs ? &GetEmptyItemSet() : nullptr; - if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() ) + if (IsUndoEnabled() && !IsInUndo() && maStatus.DoUndoAttribs()) { // Possibly a special Undo, or itemset* std::unique_ptr<EditUndoSetAttribs> pUndo = CreateAttribUndo( aSel, GetEmptyItemSet() ); @@ -602,17 +604,21 @@ void ImpEditEngine::RemoveCharAttribs( EditSelection aSel, EERemoveParaAttribsMo // iterate over the paragraphs ... for ( sal_Int32 nNode = nStartNode; nNode <= nEndNode; nNode++ ) { - ContentNode* pNode = aEditDoc.GetObject( nNode ); - ParaPortion& rPortion = GetParaPortions()[nNode]; + ContentNode* pNode = maEditDoc.GetObject( nNode ); + + DBG_ASSERT( maEditDoc.GetObject( nNode ), "Node not found: SetAttribs" ); + DBG_ASSERT(GetParaPortions().exists(nNode), "Portion not found: SetAttribs"); - DBG_ASSERT( aEditDoc.GetObject( nNode ), "Node not found: SetAttribs" ); - DBG_ASSERT( GetParaPortions().SafeGetObject( nNode ), "Portion not found: SetAttribs" ); + if (!GetParaPortions().exists(nNode)) + continue; + + ParaPortion& rPortion = GetParaPortions().getRef(nNode); const sal_Int32 nStartPos = nNode==nStartNode ? aSel.Min().GetIndex() : 0; const sal_Int32 nEndPos = nNode==nEndNode ? aSel.Max().GetIndex() : pNode->Len(); // can also be == nStart! // Optimize: If whole paragraph, then RemoveCharAttribs (nPara)? - bool bChanged = aEditDoc.RemoveAttribs( pNode, nStartPos, nEndPos, nWhich ); + bool bChanged = maEditDoc.RemoveAttribs( pNode, nStartPos, nEndPos, nWhich ); if ( bRemoveParaAttribs ) { SetParaAttribs( nNode, *_pEmptyItemSet ); // Invalidated @@ -636,15 +642,15 @@ void ImpEditEngine::RemoveCharAttribs( EditSelection aSel, EERemoveParaAttribsMo if ( bChanged && !bRemoveParaAttribs ) { - bFormatted = false; - rPortion.MarkSelectionInvalid( nStartPos ); + mbFormatted = false; + rPortion.MarkSelectionInvalid(nStartPos); } } } void ImpEditEngine::RemoveCharAttribs( sal_Int32 nPara, sal_uInt16 nWhich, bool bRemoveFeatures ) { - ContentNode* pNode = aEditDoc.GetObject( nPara ); + ContentNode* pNode = maEditDoc.GetObject( nPara ); ParaPortion* pPortion = GetParaPortions().SafeGetObject( nPara ); DBG_ASSERT( pNode, "Node not found: RemoveCharAttribs" ); @@ -677,7 +683,7 @@ void ImpEditEngine::RemoveCharAttribs( sal_Int32 nPara, sal_uInt16 nWhich, bool void ImpEditEngine::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet ) { - ContentNode* pNode = aEditDoc.GetObject( nPara ); + ContentNode* pNode = maEditDoc.GetObject( nPara ); if ( !pNode ) return; @@ -685,17 +691,17 @@ void ImpEditEngine::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet ) if ( pNode->GetContentAttribs().GetItems() == rSet ) return; - if ( IsUndoEnabled() && !IsInUndo() && aStatus.DoUndoAttribs() ) + if (IsUndoEnabled() && !IsInUndo() && maStatus.DoUndoAttribs()) { - if ( rSet.GetPool() != &aEditDoc.GetItemPool() ) + if ( rSet.GetPool() != &maEditDoc.GetItemPool() ) { SfxItemSet aTmpSet( GetEmptyItemSet() ); aTmpSet.Put( rSet ); - InsertUndo(std::make_unique<EditUndoSetParaAttribs>(pEditEngine, nPara, pNode->GetContentAttribs().GetItems(), aTmpSet)); + InsertUndo(std::make_unique<EditUndoSetParaAttribs>(mpEditEngine, nPara, pNode->GetContentAttribs().GetItems(), aTmpSet)); } else { - InsertUndo(std::make_unique<EditUndoSetParaAttribs>(pEditEngine, nPara, pNode->GetContentAttribs().GetItems(), rSet)); + InsertUndo(std::make_unique<EditUndoSetParaAttribs>(mpEditEngine, nPara, pNode->GetContentAttribs().GetItems(), rSet)); } } @@ -708,7 +714,7 @@ void ImpEditEngine::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet ) if ( bCheckLanguage && pNode->GetWrongList() ) pNode->GetWrongList()->ResetInvalidRange(0, pNode->Len()); - if ( aStatus.UseCharAttribs() ) + if (maStatus.UseCharAttribs()) pNode->CreateDefFont(); ParaAttribsChanged( pNode ); @@ -716,21 +722,21 @@ void ImpEditEngine::SetParaAttribs( sal_Int32 nPara, const SfxItemSet& rSet ) const SfxItemSet& ImpEditEngine::GetParaAttribs( sal_Int32 nPara ) const { - const ContentNode* pNode = aEditDoc.GetObject( nPara ); + const ContentNode* pNode = maEditDoc.GetObject( nPara ); assert(pNode && "Node not found: GetParaAttribs"); return pNode->GetContentAttribs().GetItems(); } bool ImpEditEngine::HasParaAttrib( sal_Int32 nPara, sal_uInt16 nWhich ) const { - const ContentNode* pNode = aEditDoc.GetObject( nPara ); + const ContentNode* pNode = maEditDoc.GetObject( nPara ); assert(pNode && "Node not found: HasParaAttrib"); return pNode->GetContentAttribs().HasItem( nWhich ); } const SfxPoolItem& ImpEditEngine::GetParaAttrib( sal_Int32 nPara, sal_uInt16 nWhich ) const { - const ContentNode* pNode = aEditDoc.GetObject(nPara); + const ContentNode* pNode = maEditDoc.GetObject(nPara); assert(pNode && "Node not found: GetParaAttrib"); return pNode->GetContentAttribs().GetItem(nWhich); } @@ -738,7 +744,7 @@ const SfxPoolItem& ImpEditEngine::GetParaAttrib( sal_Int32 nPara, sal_uInt16 nWh void ImpEditEngine::GetCharAttribs( sal_Int32 nPara, std::vector<EECharAttrib>& rLst ) const { rLst.clear(); - const ContentNode* pNode = aEditDoc.GetObject( nPara ); + const ContentNode* pNode = maEditDoc.GetObject( nPara ); if ( !pNode ) return; @@ -754,7 +760,7 @@ void ImpEditEngine::GetCharAttribs( sal_Int32 nPara, std::vector<EECharAttrib>& void ImpEditEngine::ParaAttribsToCharAttribs( ContentNode* pNode ) { - pNode->GetCharAttribs().DeleteEmptyAttribs( GetEditDoc().GetItemPool() ); + pNode->GetCharAttribs().DeleteEmptyAttribs(); sal_Int32 nEndPos = pNode->Len(); for ( sal_uInt16 nWhich = EE_CHAR_START; nWhich <= EE_CHAR_END; nWhich++ ) { @@ -768,40 +774,38 @@ void ImpEditEngine::ParaAttribsToCharAttribs( ContentNode* pNode ) { nLastEnd = pAttr->GetEnd(); if ( pAttr->GetStart() > nLastEnd ) - aEditDoc.InsertAttrib( pNode, nLastEnd, pAttr->GetStart(), rItem ); + maEditDoc.InsertAttrib( pNode, nLastEnd, pAttr->GetStart(), rItem ); // #112831# Last Attr might go from 0xffff to 0x0000 pAttr = nLastEnd ? pNode->GetCharAttribs().FindNextAttrib( nWhich, nLastEnd ) : nullptr; } // And the Rest: if ( nLastEnd < nEndPos ) - aEditDoc.InsertAttrib( pNode, nLastEnd, nEndPos, rItem ); + maEditDoc.InsertAttrib( pNode, nLastEnd, nEndPos, rItem ); } } - bFormatted = false; + mbFormatted = false; // Portion does not need to be invalidated here, happens elsewhere. } IdleFormattter::IdleFormattter() : Idle("editeng::ImpEditEngine aIdleFormatter") { - pView = nullptr; - nRestarts = 0; } IdleFormattter::~IdleFormattter() { - pView = nullptr; + mpView = nullptr; } -void IdleFormattter::DoIdleFormat( EditView* pV ) +void IdleFormattter::DoIdleFormat(EditView* pView) { - pView = pV; + mpView = pView; - if ( IsActive() ) - nRestarts++; + if (IsActive()) + mnRestarts++; - if ( nRestarts > 4 ) + if (mnRestarts > 4) ForceTimeout(); else Start(); @@ -809,36 +813,12 @@ void IdleFormattter::DoIdleFormat( EditView* pV ) void IdleFormattter::ForceTimeout() { - if ( IsActive() ) + if (IsActive()) { Stop(); Invoke(); } } -ImplIMEInfos::ImplIMEInfos( const EditPaM& rPos, const OUString& rOldTextAfterStartPos ) - : aOldTextAfterStartPos( rOldTextAfterStartPos ), - aPos(rPos), - nLen(0), - bWasCursorOverwrite(false) - { - } - -ImplIMEInfos::~ImplIMEInfos() -{ -} - -void ImplIMEInfos::CopyAttribs( const ExtTextInputAttr* pA, sal_uInt16 nL ) -{ - nLen = nL; - pAttribs.reset( new ExtTextInputAttr[ nL ] ); - memcpy( pAttribs.get(), pA, nL*sizeof(ExtTextInputAttr) ); -} - -void ImplIMEInfos::DestroyAttribs() -{ - pAttribs.reset(); - nLen = 0; -} /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/editeng/textconv.cxx b/editeng/source/editeng/textconv.cxx index 7c4ed9ddd89d..3d4c03e1ddeb 100644 --- a/editeng/source/editeng/textconv.cxx +++ b/editeng/source/editeng/textconv.cxx @@ -29,8 +29,6 @@ using namespace com::sun::star; using namespace com::sun::star::uno; -using namespace com::sun::star::beans; -using namespace com::sun::star::linguistic2; TextConvWrapper::TextConvWrapper( weld::Widget* pWindow, const Reference< XComponentContext >& rxContext, @@ -122,17 +120,17 @@ bool TextConvWrapper::ConvMore_impl() // modified version of SvxSpellWrapper::SpellMore bool bMore = false; - EditEngine* pEE = m_pEditView->GetEditEngine(); - ImpEditEngine* pImpEE = m_pEditView->GetImpEditEngine(); - ConvInfo* pConvInfo = pImpEE->GetConvInfo(); + EditEngine& rEditEngine = m_pEditView->getEditEngine(); + ImpEditEngine& rImpEditEngine = m_pEditView->getImpEditEngine(); + ConvInfo* pConvInfo = rImpEditEngine.GetConvInfo(); if ( pConvInfo->bMultipleDoc ) { - bMore = pEE->ConvertNextDocument(); + bMore = rEditEngine.ConvertNextDocument(); if ( bMore ) { // The text has been entered in this engine ... - m_pEditView->GetImpEditView()->SetEditSelection( - pEE->GetEditDoc().GetStartPaM() ); + m_pEditView->getImpl().SetEditSelection( + rEditEngine.GetEditDoc().GetStartPaM() ); } } return bMore; @@ -143,9 +141,9 @@ void TextConvWrapper::ConvStart_impl( SvxSpellArea eArea ) { // modified version of EditSpellWrapper::SpellStart - EditEngine* pEE = m_pEditView->GetEditEngine(); - ImpEditEngine* pImpEE = m_pEditView->GetImpEditEngine(); - ConvInfo* pConvInfo = pImpEE->GetConvInfo(); + EditEngine& rEditEngine = m_pEditView->getEditEngine(); + ImpEditEngine& rImpEditEngine = m_pEditView->getImpEditEngine(); + ConvInfo* pConvInfo = rImpEditEngine.GetConvInfo(); if ( eArea == SvxSpellArea::BodyStart ) { @@ -155,14 +153,13 @@ void TextConvWrapper::ConvStart_impl( SvxSpellArea eArea ) pConvInfo->bConvToEnd = false; pConvInfo->aConvTo = pConvInfo->aConvStart; pConvInfo->aConvContinue = EPaM( 0, 0 ); - m_pEditView->GetImpEditView()->SetEditSelection( - pEE->GetEditDoc().GetStartPaM() ); + m_pEditView->getImpl().SetEditSelection( + rEditEngine.GetEditDoc().GetStartPaM() ); } else { pConvInfo->bConvToEnd = true; - pConvInfo->aConvTo = pImpEE->CreateEPaM( - pEE->GetEditDoc().GetStartPaM() ); + pConvInfo->aConvTo = rImpEditEngine.CreateEPaM(rEditEngine.GetEditDoc().GetStartPaM() ); } } else if ( eArea == SvxSpellArea::BodyEnd ) @@ -179,16 +176,14 @@ void TextConvWrapper::ConvStart_impl( SvxSpellArea eArea ) else { // nothing selected: convert to end of document - pConvInfo->aConvTo = pImpEE->CreateEPaM( - pEE->GetEditDoc().GetEndPaM() ); + pConvInfo->aConvTo = rImpEditEngine.CreateEPaM(rEditEngine.GetEditDoc().GetEndPaM() ); } } else if ( eArea == SvxSpellArea::Body ) { // called by ConvNext_impl... pConvInfo->aConvContinue = pConvInfo->aConvStart; - pConvInfo->aConvTo = pImpEE->CreateEPaM( - pEE->GetEditDoc().GetEndPaM() ); + pConvInfo->aConvTo = rImpEditEngine.CreateEPaM(rEditEngine.GetEditDoc().GetEndPaM() ); } else { @@ -204,7 +199,7 @@ bool TextConvWrapper::ConvContinue_impl() // get next convertible text portion and its language m_aConvText.clear(); m_nConvTextLang = LANGUAGE_NONE; - m_pEditView->GetImpEditEngine()->ImpConvert( m_aConvText, m_nConvTextLang, + m_pEditView->getImpEditEngine().ImpConvert( m_aConvText, m_nConvTextLang, m_pEditView, GetSourceLanguage(), m_aConvSel, m_bAllowChange, GetTargetLanguage(), GetTargetFont() ); return !m_aConvText.isEmpty(); @@ -341,15 +336,15 @@ void TextConvWrapper::ReplaceUnit( m_nUnitOffset = m_nUnitOffset + nUnitStart + aNewTxt.getLength(); // remember current original language for later use - ImpEditEngine *pImpEditEng = m_pEditView->GetImpEditEngine(); + ImpEditEngine& rImpEditEngine = m_pEditView->getImpEditEngine(); ESelection aOldSel = m_pEditView->GetSelection(); - //EditSelection aOldEditSel = pEditView->GetImpEditView()->GetEditSelection(); + //EditSelection aOldEditSel = pEditView->getImpl().GetEditSelection(); #ifdef DBG_UTIL - LanguageType nOldLang = pImpEditEng->GetLanguage( pImpEditEng->CreateSel( aOldSel ).Min() ); + LanguageType nOldLang = rImpEditEngine.GetLanguage(rImpEditEngine.CreateSel( aOldSel ).Min() ).nLang; #endif - pImpEditEng->UndoActionStart( EDITUNDO_INSERT ); + rImpEditEngine.UndoActionStart( EDITUNDO_INSERT ); // according to FT we should currently not bother about keeping // attributes in Hangul/Hanja conversion and leave that untouched. @@ -380,11 +375,10 @@ void TextConvWrapper::ReplaceUnit( } } - pImpEditEng->UndoActionEnd(); + rImpEditEngine.UndoActionEnd(); // adjust ConvContinue / ConvTo if necessary - ImpEditEngine* pImpEE = m_pEditView->GetImpEditEngine(); - ConvInfo* pConvInfo = pImpEE->GetConvInfo(); + ConvInfo* pConvInfo = rImpEditEngine.GetConvInfo(); sal_Int32 nDelta = aNewTxt.getLength() - aOrigTxt.getLength(); if (nDelta != 0) { @@ -401,7 +395,7 @@ void TextConvWrapper::ReplaceUnit( void TextConvWrapper::ChangeText( const OUString &rNewText, - const OUString& rOrigText, + std::u16string_view rOrigText, const uno::Sequence< sal_Int32 > *pOffsets, ESelection *pESelection ) { @@ -443,7 +437,7 @@ void TextConvWrapper::ChangeText( const OUString &rNewText, else { nPos = nConvTextLen; - nIndex = rOrigText.getLength(); + nIndex = rOrigText.size(); } // end of string also terminates non-matching char sequence diff --git a/editeng/source/editeng/textconv.hxx b/editeng/source/editeng/textconv.hxx index 6afb20acf966..96525a98f530 100644 --- a/editeng/source/editeng/textconv.hxx +++ b/editeng/source/editeng/textconv.hxx @@ -61,7 +61,7 @@ class TextConvWrapper final : public editeng::HangulHanjaConversion const sal_Int32 nUnitEnd ); void ChangeText( const OUString &rNewText, - const OUString& rOrigText, + std::u16string_view rOrigText, const css::uno::Sequence< sal_Int32 > *pOffsets, ESelection *pESelection ); void ChangeText_impl( const OUString &rNewText, bool bKeepAttributes ); |