diff options
Diffstat (limited to 'sc/source/ui/unoobj/textuno.cxx')
-rw-r--r-- | sc/source/ui/unoobj/textuno.cxx | 886 |
1 files changed, 886 insertions, 0 deletions
diff --git a/sc/source/ui/unoobj/textuno.cxx b/sc/source/ui/unoobj/textuno.cxx new file mode 100644 index 000000000..46ec6dbf2 --- /dev/null +++ b/sc/source/ui/unoobj/textuno.cxx @@ -0,0 +1,886 @@ +/* -*- 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 <memory> +#include <sal/config.h> +#include <sal/log.hxx> + +#include <scitems.hxx> +#include <editeng/eeitem.hxx> +#include <svx/svdpool.hxx> +#include <svx/svdobj.hxx> +#include <editeng/editeng.hxx> +#include <editeng/editobj.hxx> +#include <editeng/flditem.hxx> +#include <editeng/fhgtitem.hxx> +#include <editeng/unoprnms.hxx> +#include <editeng/unofored.hxx> +#include <vcl/svapp.hxx> + +#include <editeng/unoipset.hxx> +#include <textuno.hxx> +#include <fielduno.hxx> +#include <editsrc.hxx> +#include <docsh.hxx> +#include <editutil.hxx> +#include <miscuno.hxx> +#include <cellsuno.hxx> +#include <cellvalue.hxx> +#include <cellform.hxx> +#include <patattr.hxx> +#include <docfunc.hxx> +#include <scmod.hxx> + +using namespace com::sun::star; + +static const SvxItemPropertySet * lcl_GetHdFtPropertySet() +{ + static const SvxItemPropertySet aHdFtPropertySet_Impl = [] { + static SfxItemPropertyMapEntry aHdFtPropertyMap_Impl[] = + { + SVX_UNOEDIT_CHAR_PROPERTIES, + SVX_UNOEDIT_FONT_PROPERTIES, + SVX_UNOEDIT_PARA_PROPERTIES, + SVX_UNOEDIT_NUMBERING_PROPERTY, // for completeness of service ParagraphProperties + { u"", 0, css::uno::Type(), 0, 0 } + }; + + // modify PropertyMap to include CONVERT_TWIPS flag for font height + // (headers/footers are in twips) + + SfxItemPropertyMapEntry* pEntry = aHdFtPropertyMap_Impl; + while (!pEntry->aName.isEmpty()) + { + if ( ( pEntry->nWID == EE_CHAR_FONTHEIGHT || + pEntry->nWID == EE_CHAR_FONTHEIGHT_CJK || + pEntry->nWID == EE_CHAR_FONTHEIGHT_CTL ) && + pEntry->nMemberId == MID_FONTHEIGHT ) + { + pEntry->nMemberId |= CONVERT_TWIPS; + } + + ++pEntry; + } + + return SvxItemPropertySet(aHdFtPropertyMap_Impl, SdrObject::GetGlobalDrawObjectItemPool()); + }(); + return &aHdFtPropertySet_Impl; +} + +SC_SIMPLE_SERVICE_INFO( ScHeaderFooterContentObj, "ScHeaderFooterContentObj", "com.sun.star.sheet.HeaderFooterContent" ) +SC_SIMPLE_SERVICE_INFO( ScHeaderFooterTextObj, "ScHeaderFooterTextObj", "stardiv.one.Text.Text" ) + +ScHeaderFooterContentObj::ScHeaderFooterContentObj() +{ +} + +ScHeaderFooterContentObj::~ScHeaderFooterContentObj() {} + +const EditTextObject* ScHeaderFooterContentObj::GetLeftEditObject() const +{ + return mxLeftText->GetTextObject(); +} + +const EditTextObject* ScHeaderFooterContentObj::GetCenterEditObject() const +{ + return mxCenterText->GetTextObject(); +} + +const EditTextObject* ScHeaderFooterContentObj::GetRightEditObject() const +{ + return mxRightText->GetTextObject(); +} + +// XHeaderFooterContent + +uno::Reference<text::XText> SAL_CALL ScHeaderFooterContentObj::getLeftText() +{ + SolarMutexGuard aGuard; + uno::Reference<text::XText> xInt(*mxLeftText, uno::UNO_QUERY); + return xInt; +} + +uno::Reference<text::XText> SAL_CALL ScHeaderFooterContentObj::getCenterText() +{ + SolarMutexGuard aGuard; + uno::Reference<text::XText> xInt(*mxCenterText, uno::UNO_QUERY); + return xInt; +} + +uno::Reference<text::XText> SAL_CALL ScHeaderFooterContentObj::getRightText() +{ + SolarMutexGuard aGuard; + uno::Reference<text::XText> xInt(*mxRightText, uno::UNO_QUERY); + return xInt; +} + +// XUnoTunnel + +sal_Int64 SAL_CALL ScHeaderFooterContentObj::getSomething( + const uno::Sequence<sal_Int8 >& rId ) +{ + return comphelper::getSomethingImpl(rId, this); +} + +const uno::Sequence<sal_Int8>& ScHeaderFooterContentObj::getUnoTunnelId() +{ + static const comphelper::UnoIdInit theScHeaderFooterContentObjUnoTunnelId; + return theScHeaderFooterContentObjUnoTunnelId.getSeq(); +} + +rtl::Reference<ScHeaderFooterContentObj> ScHeaderFooterContentObj::getImplementation( + const uno::Reference<sheet::XHeaderFooterContent>& rObj) +{ + return comphelper::getFromUnoTunnel<ScHeaderFooterContentObj>(rObj); +} + +void ScHeaderFooterContentObj::Init( const EditTextObject* pLeft, + const EditTextObject* pCenter, + const EditTextObject* pRight ) +{ + uno::Reference<css::sheet::XHeaderFooterContent> xThis(this); + mxLeftText = rtl::Reference<ScHeaderFooterTextObj>(new ScHeaderFooterTextObj(xThis, ScHeaderFooterPart::LEFT, pLeft)); + mxCenterText = rtl::Reference<ScHeaderFooterTextObj>(new ScHeaderFooterTextObj(xThis, ScHeaderFooterPart::CENTER, pCenter)); + mxRightText = rtl::Reference<ScHeaderFooterTextObj>(new ScHeaderFooterTextObj(xThis, ScHeaderFooterPart::RIGHT, pRight)); +} + +ScHeaderFooterTextData::ScHeaderFooterTextData( + uno::WeakReference<sheet::XHeaderFooterContent> const & xContent, ScHeaderFooterPart nP, const EditTextObject* pTextObj) : + mpTextObj(pTextObj ? pTextObj->Clone() : nullptr), + xContentObj( xContent ), + nPart( nP ), + bDataValid(false) +{ +} + +ScHeaderFooterTextData::~ScHeaderFooterTextData() +{ + SolarMutexGuard aGuard; // needed for EditEngine dtor + + pForwarder.reset(); + pEditEngine.reset(); +} + +SvxTextForwarder* ScHeaderFooterTextData::GetTextForwarder() +{ + if (!pEditEngine) + { + rtl::Reference<SfxItemPool> pEnginePool = EditEngine::CreatePool(); + pEnginePool->FreezeIdRanges(); + std::unique_ptr<ScHeaderEditEngine> pHdrEngine(new ScHeaderEditEngine( pEnginePool.get() )); + + pHdrEngine->EnableUndo( false ); + pHdrEngine->SetRefMapMode(MapMode(MapUnit::MapTwip)); + + // default font must be set, independently of document + // -> use global pool from module + + SfxItemSet aDefaults( pHdrEngine->GetEmptyItemSet() ); + const ScPatternAttr& rPattern = SC_MOD()->GetPool().GetDefaultItem(ATTR_PATTERN); + rPattern.FillEditItemSet( &aDefaults ); + // FillEditItemSet adjusts font height to 1/100th mm, + // but for header/footer twips is needed, as in the PatternAttr: + aDefaults.Put( rPattern.GetItem(ATTR_FONT_HEIGHT).CloneSetWhich(EE_CHAR_FONTHEIGHT) ); + aDefaults.Put( rPattern.GetItem(ATTR_CJK_FONT_HEIGHT).CloneSetWhich(EE_CHAR_FONTHEIGHT_CJK) ) ; + aDefaults.Put( rPattern.GetItem(ATTR_CTL_FONT_HEIGHT).CloneSetWhich(EE_CHAR_FONTHEIGHT_CTL) ); + pHdrEngine->SetDefaults( aDefaults ); + + ScHeaderFieldData aData; + ScHeaderFooterTextObj::FillDummyFieldData( aData ); + pHdrEngine->SetData( aData ); + + pEditEngine = std::move(pHdrEngine); + pForwarder.reset( new SvxEditEngineForwarder(*pEditEngine) ); + } + + if (bDataValid) + return pForwarder.get(); + + if (mpTextObj) + pEditEngine->SetTextCurrentDefaults(*mpTextObj); + + bDataValid = true; + return pForwarder.get(); +} + +void ScHeaderFooterTextData::UpdateData() +{ + if (pEditEngine) + { + mpTextObj = pEditEngine->CreateTextObject(); + } +} + +void ScHeaderFooterTextData::UpdateData(EditEngine& rEditEngine) +{ + mpTextObj = rEditEngine.CreateTextObject(); + bDataValid = false; +} + +ScHeaderFooterTextObj::ScHeaderFooterTextObj( + const uno::WeakReference<sheet::XHeaderFooterContent>& xContent, ScHeaderFooterPart nP, const EditTextObject* pTextObj) : + aTextData(xContent, nP, pTextObj) +{ + // ScHeaderFooterTextData acquires rContent + // pUnoText is created on demand (getString/setString work without it) +} + +void ScHeaderFooterTextObj::CreateUnoText_Impl() +{ + if (!mxUnoText.is()) + { + // can't be aggregated because getString/setString is handled here + ScHeaderFooterEditSource aEditSrc(aTextData); + mxUnoText.set(new SvxUnoText(&aEditSrc, lcl_GetHdFtPropertySet(), uno::Reference<text::XText>())); + } +} + +ScHeaderFooterTextObj::~ScHeaderFooterTextObj() {} + +const EditTextObject* ScHeaderFooterTextObj::GetTextObject() const +{ + return aTextData.GetTextObject(); +} + +const SvxUnoText& ScHeaderFooterTextObj::GetUnoText() +{ + if (!mxUnoText.is()) + CreateUnoText_Impl(); + return *mxUnoText; +} + +// XText + +uno::Reference<text::XTextCursor> SAL_CALL ScHeaderFooterTextObj::createTextCursor() +{ + SolarMutexGuard aGuard; + return new ScHeaderFooterTextCursor( this ); +} + +uno::Reference<text::XTextCursor> SAL_CALL ScHeaderFooterTextObj::createTextCursorByRange( + const uno::Reference<text::XTextRange>& aTextPosition ) +{ + SolarMutexGuard aGuard; + if (!mxUnoText.is()) + CreateUnoText_Impl(); + return mxUnoText->createTextCursorByRange(aTextPosition); + //! like ScCellObj::createTextCursorByRange, if SvxUnoTextRange_getReflection available +} + +void ScHeaderFooterTextObj::FillDummyFieldData( ScHeaderFieldData& rData ) +{ + OUString aDummy("???"); + rData.aTitle = aDummy; + rData.aLongDocName = aDummy; + rData.aShortDocName = aDummy; + rData.aTabName = aDummy; + rData.nPageNo = 1; + rData.nTotalPages = 99; +} + +OUString SAL_CALL ScHeaderFooterTextObj::getString() +{ + SolarMutexGuard aGuard; + OUString aRet; + const EditTextObject* pData; + + uno::Reference<css::sheet::XHeaderFooterContent> xContentObj = aTextData.GetContentObj(); + if (!xContentObj.is()) + throw css::uno::RuntimeException( + "ScHeaderFooterTextObj::getString: no ContentObj"); + + rtl::Reference<ScHeaderFooterContentObj> pObj = ScHeaderFooterContentObj::getImplementation(xContentObj); + + switch ( aTextData.GetPart() ) + { + case ScHeaderFooterPart::LEFT: + pData = pObj->GetLeftEditObject(); + break; + case ScHeaderFooterPart::CENTER: + pData = pObj->GetCenterEditObject(); + break; + case ScHeaderFooterPart::RIGHT: + pData = pObj->GetRightEditObject(); + break; + default: + SAL_WARN("sc.ui","unexpected enum value of ScHeaderFooterPart"); + pData = nullptr; + } + + if (pData) + { + // for pure text, no font info is needed in pool defaults + ScHeaderEditEngine aEditEngine( EditEngine::CreatePool().get() ); + + ScHeaderFieldData aData; + FillDummyFieldData( aData ); + aEditEngine.SetData( aData ); + + aEditEngine.SetTextCurrentDefaults(*pData); + aRet = ScEditUtil::GetSpaceDelimitedString( aEditEngine ); + } + return aRet; +} + +void SAL_CALL ScHeaderFooterTextObj::setString( const OUString& aText ) +{ + SolarMutexGuard aGuard; + + // for pure text, no font info is needed in pool defaults + ScHeaderEditEngine aEditEngine(EditEngine::CreatePool().get()); + aEditEngine.SetTextCurrentDefaults( aText ); + aTextData.UpdateData(aEditEngine); +} + +void SAL_CALL ScHeaderFooterTextObj::insertString( const uno::Reference<text::XTextRange>& xRange, + const OUString& aString, sal_Bool bAbsorb ) +{ + SolarMutexGuard aGuard; + if (!mxUnoText.is()) + CreateUnoText_Impl(); + mxUnoText->insertString( xRange, aString, bAbsorb ); +} + +void SAL_CALL ScHeaderFooterTextObj::insertControlCharacter( + const uno::Reference<text::XTextRange>& xRange, + sal_Int16 nControlCharacter, sal_Bool bAbsorb ) +{ + SolarMutexGuard aGuard; + if (!mxUnoText.is()) + CreateUnoText_Impl(); + mxUnoText->insertControlCharacter( xRange, nControlCharacter, bAbsorb ); +} + +void SAL_CALL ScHeaderFooterTextObj::insertTextContent( + const uno::Reference<text::XTextRange >& xRange, + const uno::Reference<text::XTextContent >& xContent, + sal_Bool bAbsorb ) +{ + SolarMutexGuard aGuard; + if ( xContent.is() && xRange.is() ) + { + ScEditFieldObj* pHeaderField = comphelper::getFromUnoTunnel<ScEditFieldObj>( xContent ); + + SvxUnoTextRangeBase* pTextRange = + comphelper::getFromUnoTunnel<ScHeaderFooterTextCursor>( xRange ); + + if ( pHeaderField && !pHeaderField->IsInserted() && pTextRange ) + { + SvxEditSource* pEditSource = pTextRange->GetEditSource(); + ESelection aSelection(pTextRange->GetSelection()); + + if (!bAbsorb) + { + // don't replace -> append at end + aSelection.Adjust(); + aSelection.nStartPara = aSelection.nEndPara; + aSelection.nStartPos = aSelection.nEndPos; + } + + SvxFieldItem aItem(pHeaderField->CreateFieldItem()); + + SvxTextForwarder* pForwarder = pEditSource->GetTextForwarder(); + pForwarder->QuickInsertField( aItem, aSelection ); + pEditSource->UpdateData(); + + // new selection: a digit + aSelection.Adjust(); + aSelection.nEndPara = aSelection.nStartPara; + aSelection.nEndPos = aSelection.nStartPos + 1; + + uno::Reference<text::XTextRange> xTextRange; + switch ( aTextData.GetPart() ) + { + case ScHeaderFooterPart::LEFT: + xTextRange = aTextData.GetContentObj()->getLeftText(); + break; + case ScHeaderFooterPart::CENTER: + xTextRange = aTextData.GetContentObj()->getCenterText(); + break; + case ScHeaderFooterPart::RIGHT: + xTextRange = aTextData.GetContentObj()->getRightText(); + break; + } + + pHeaderField->InitDoc(xTextRange, std::make_unique<ScHeaderFooterEditSource>(aTextData), aSelection); + + // for bAbsorb=FALSE, the new selection must be behind the inserted content + // (the xml filter relies on this) + if (!bAbsorb) + aSelection.nStartPos = aSelection.nEndPos; + + pTextRange->SetSelection( aSelection ); + + return; + } + } + + if (!mxUnoText.is()) + CreateUnoText_Impl(); + mxUnoText->insertTextContent( xRange, xContent, bAbsorb ); +} + +void SAL_CALL ScHeaderFooterTextObj::removeTextContent( + const uno::Reference<text::XTextContent>& xContent ) +{ + SolarMutexGuard aGuard; + if ( xContent.is() ) + { + ScEditFieldObj* pHeaderField = comphelper::getFromUnoTunnel<ScEditFieldObj>(xContent); + if ( pHeaderField && pHeaderField->IsInserted() ) + { + //! check if the field is in this cell + pHeaderField->DeleteField(); + return; + } + } + if (!mxUnoText.is()) + CreateUnoText_Impl(); + mxUnoText->removeTextContent( xContent ); +} + +uno::Reference<text::XText> SAL_CALL ScHeaderFooterTextObj::getText() +{ + SolarMutexGuard aGuard; + if (!mxUnoText.is()) + CreateUnoText_Impl(); + return mxUnoText->getText(); +} + +uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextObj::getStart() +{ + SolarMutexGuard aGuard; + if (!mxUnoText.is()) + CreateUnoText_Impl(); + return mxUnoText->getStart(); +} + +uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextObj::getEnd() +{ + SolarMutexGuard aGuard; + if (!mxUnoText.is()) + CreateUnoText_Impl(); + return mxUnoText->getEnd(); +} + +// XTextFieldsSupplier + +uno::Reference<container::XEnumerationAccess> SAL_CALL ScHeaderFooterTextObj::getTextFields() +{ + SolarMutexGuard aGuard; + // all fields + return new ScHeaderFieldsObj(aTextData); +} + +uno::Reference<container::XNameAccess> SAL_CALL ScHeaderFooterTextObj::getTextFieldMasters() +{ + // this does not exists in Calc (?) + return nullptr; +} + +// XTextRangeMover + +void SAL_CALL ScHeaderFooterTextObj::moveTextRange( + const uno::Reference<text::XTextRange>& xRange, + sal_Int16 nParagraphs ) +{ + SolarMutexGuard aGuard; + if (!mxUnoText.is()) + CreateUnoText_Impl(); + mxUnoText->moveTextRange( xRange, nParagraphs ); +} + +// XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScHeaderFooterTextObj::createEnumeration() +{ + SolarMutexGuard aGuard; + if (!mxUnoText.is()) + CreateUnoText_Impl(); + return mxUnoText->createEnumeration(); +} + +// XElementAccess + +uno::Type SAL_CALL ScHeaderFooterTextObj::getElementType() +{ + SolarMutexGuard aGuard; + if (!mxUnoText.is()) + CreateUnoText_Impl(); + return mxUnoText->getElementType(); +} + +sal_Bool SAL_CALL ScHeaderFooterTextObj::hasElements() +{ + SolarMutexGuard aGuard; + if (!mxUnoText.is()) + CreateUnoText_Impl(); + return mxUnoText->hasElements(); +} + +ScCellTextCursor::ScCellTextCursor(ScCellObj& rText) : + SvxUnoTextCursor( rText.GetUnoText() ), + mxTextObj( &rText ) +{ +} + +ScCellTextCursor::~ScCellTextCursor() noexcept +{ +} + +// SvxUnoTextCursor methods reimplemented here to return the right objects: + +uno::Reference<text::XText> SAL_CALL ScCellTextCursor::getText() +{ + return mxTextObj; +} + +uno::Reference<text::XTextRange> SAL_CALL ScCellTextCursor::getStart() +{ + SolarMutexGuard aGuard; + + //! use other object for range than cursor? + + rtl::Reference<ScCellTextCursor> pNew = new ScCellTextCursor( *this ); + + ESelection aNewSel(GetSelection()); + aNewSel.nEndPara = aNewSel.nStartPara; + aNewSel.nEndPos = aNewSel.nStartPos; + pNew->SetSelection( aNewSel ); + + return static_cast<SvxUnoTextRangeBase*>(pNew.get()); +} + +uno::Reference<text::XTextRange> SAL_CALL ScCellTextCursor::getEnd() +{ + SolarMutexGuard aGuard; + + //! use other object for range than cursor? + + rtl::Reference<ScCellTextCursor> pNew = new ScCellTextCursor( *this ); + + ESelection aNewSel(GetSelection()); + aNewSel.nStartPara = aNewSel.nEndPara; + aNewSel.nStartPos = aNewSel.nEndPos; + pNew->SetSelection( aNewSel ); + + return static_cast<SvxUnoTextRangeBase*>(pNew.get()); +} + +// XUnoTunnel + +UNO3_GETIMPLEMENTATION2_IMPL(ScCellTextCursor, SvxUnoTextCursor); + +ScHeaderFooterTextCursor::ScHeaderFooterTextCursor(rtl::Reference<ScHeaderFooterTextObj> const & rText) : + SvxUnoTextCursor( rText->GetUnoText() ), + rTextObj( rText ) +{} + +ScHeaderFooterTextCursor::~ScHeaderFooterTextCursor() noexcept {}; + +// SvxUnoTextCursor methods reimplemented here to return the right objects: + +uno::Reference<text::XText> SAL_CALL ScHeaderFooterTextCursor::getText() +{ + SolarMutexGuard aGuard; + return rTextObj; +} + +uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextCursor::getStart() +{ + SolarMutexGuard aGuard; + + //! use other object for range than cursor? + + rtl::Reference<ScHeaderFooterTextCursor> pNew = new ScHeaderFooterTextCursor( *this ); + + ESelection aNewSel(GetSelection()); + aNewSel.nEndPara = aNewSel.nStartPara; + aNewSel.nEndPos = aNewSel.nStartPos; + pNew->SetSelection( aNewSel ); + + return static_cast<SvxUnoTextRangeBase*>(pNew.get()); +} + +uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextCursor::getEnd() +{ + SolarMutexGuard aGuard; + + //! use other object for range than cursor? + + rtl::Reference<ScHeaderFooterTextCursor> pNew = new ScHeaderFooterTextCursor( *this ); + + ESelection aNewSel(GetSelection()); + aNewSel.nStartPara = aNewSel.nEndPara; + aNewSel.nStartPos = aNewSel.nEndPos; + pNew->SetSelection( aNewSel ); + + return static_cast<SvxUnoTextRangeBase*>(pNew.get()); +} + +// XUnoTunnel + +UNO3_GETIMPLEMENTATION2_IMPL(ScHeaderFooterTextCursor, SvxUnoTextCursor); + +ScDrawTextCursor::ScDrawTextCursor( const uno::Reference<text::XText>& xParent, + const SvxUnoTextBase& rText ) : + SvxUnoTextCursor( rText ), + xParentText( xParent ) + +{ +} + +ScDrawTextCursor::~ScDrawTextCursor() noexcept +{ +} + +// SvxUnoTextCursor methods reimplemented here to return the right objects: + +uno::Reference<text::XText> SAL_CALL ScDrawTextCursor::getText() +{ + SolarMutexGuard aGuard; + return xParentText; +} + +uno::Reference<text::XTextRange> SAL_CALL ScDrawTextCursor::getStart() +{ + SolarMutexGuard aGuard; + + //! use other object for range than cursor? + + rtl::Reference<ScDrawTextCursor> pNew = new ScDrawTextCursor( *this ); + + ESelection aNewSel(GetSelection()); + aNewSel.nEndPara = aNewSel.nStartPara; + aNewSel.nEndPos = aNewSel.nStartPos; + pNew->SetSelection( aNewSel ); + + return static_cast<SvxUnoTextRangeBase*>(pNew.get()); +} + +uno::Reference<text::XTextRange> SAL_CALL ScDrawTextCursor::getEnd() +{ + SolarMutexGuard aGuard; + + //! use other object for range than cursor? + + rtl::Reference<ScDrawTextCursor> pNew = new ScDrawTextCursor( *this ); + + ESelection aNewSel(GetSelection()); + aNewSel.nStartPara = aNewSel.nEndPara; + aNewSel.nStartPos = aNewSel.nEndPos; + pNew->SetSelection( aNewSel ); + + return static_cast<SvxUnoTextRangeBase*>(pNew.get()); +} + +// XUnoTunnel + +UNO3_GETIMPLEMENTATION2_IMPL(ScDrawTextCursor, SvxUnoTextCursor); + +ScSimpleEditSourceHelper::ScSimpleEditSourceHelper() +{ + rtl::Reference<SfxItemPool> pEnginePool = EditEngine::CreatePool(); + pEnginePool->SetDefaultMetric( MapUnit::Map100thMM ); + pEnginePool->FreezeIdRanges(); + + pEditEngine.reset( new ScFieldEditEngine(nullptr, pEnginePool.get(), nullptr, true) ); // TRUE: become owner of pool + pForwarder.reset( new SvxEditEngineForwarder( *pEditEngine ) ); + pOriginalSource.reset( new ScSimpleEditSource( pForwarder.get() ) ); +} + +ScSimpleEditSourceHelper::~ScSimpleEditSourceHelper() +{ + SolarMutexGuard aGuard; // needed for EditEngine dtor + + pOriginalSource.reset(); + pForwarder.reset(); + pEditEngine.reset(); +} + +ScEditEngineTextObj::ScEditEngineTextObj() : + SvxUnoText( GetOriginalSource(), ScCellObj::GetEditPropertySet(), uno::Reference<text::XText>() ) +{ +} + +ScEditEngineTextObj::~ScEditEngineTextObj() noexcept +{ +} + +void ScEditEngineTextObj::SetText( const EditTextObject& rTextObject ) +{ + GetEditEngine()->SetTextCurrentDefaults( rTextObject ); + + ESelection aSel; + ::GetSelection( aSel, GetEditSource()->GetTextForwarder() ); + SetSelection( aSel ); +} + +std::unique_ptr<EditTextObject> ScEditEngineTextObj::CreateTextObject() +{ + return GetEditEngine()->CreateTextObject(); +} + +ScCellTextData::ScCellTextData(ScDocShell* pDocSh, const ScAddress& rP) : + pDocShell( pDocSh ), + aCellPos( rP ), + bDataValid( false ), + bInUpdate( false ), + bDirty( false ), + bDoUpdate( true ) +{ + if (pDocShell) + pDocShell->GetDocument().AddUnoObject(*this); +} + +ScCellTextData::~ScCellTextData() +{ + SolarMutexGuard aGuard; // needed for EditEngine dtor + + if (pDocShell) + { + pDocShell->GetDocument().RemoveUnoObject(*this); + pDocShell->GetDocument().DisposeFieldEditEngine(pEditEngine); + } + else + pEditEngine.reset(); + + pForwarder.reset(); + + pOriginalSource.reset(); +} + +ScCellEditSource* ScCellTextData::GetOriginalSource() +{ + if (!pOriginalSource) + pOriginalSource.reset( new ScCellEditSource(pDocShell, aCellPos) ); + return pOriginalSource.get(); +} + +SvxTextForwarder* ScCellTextData::GetTextForwarder() +{ + if (!pEditEngine) + { + if ( pDocShell ) + { + ScDocument& rDoc = pDocShell->GetDocument(); + pEditEngine = rDoc.CreateFieldEditEngine(); + } + else + { + rtl::Reference<SfxItemPool> pEnginePool = EditEngine::CreatePool(); + pEnginePool->FreezeIdRanges(); + pEditEngine.reset( new ScFieldEditEngine(nullptr, pEnginePool.get(), nullptr, true) ); + } + // currently, GetPortions doesn't work if UpdateMode is sal_False, + // this will be fixed (in EditEngine) by src600 +// pEditEngine->SetUpdateMode( sal_False ); + pEditEngine->EnableUndo( false ); + if (pDocShell) + pEditEngine->SetRefDevice(pDocShell->GetRefDevice()); + else + pEditEngine->SetRefMapMode(MapMode(MapUnit::Map100thMM)); + pForwarder.reset( new SvxEditEngineForwarder(*pEditEngine) ); + } + + if (bDataValid) + return pForwarder.get(); + + if (pDocShell) + { + ScDocument& rDoc = pDocShell->GetDocument(); + + SfxItemSet aDefaults( pEditEngine->GetEmptyItemSet() ); + if( const ScPatternAttr* pPattern = + rDoc.GetPattern( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab() ) ) + { + pPattern->FillEditItemSet( &aDefaults ); + pPattern->FillEditParaItems( &aDefaults ); // including alignment etc. (for reading) + } + + ScRefCellValue aCell(rDoc, aCellPos); + if (aCell.meType == CELLTYPE_EDIT) + { + const EditTextObject* pObj = aCell.mpEditText; + pEditEngine->SetTextNewDefaults(*pObj, aDefaults); + } + else + { + sal_uInt32 nFormat = rDoc.GetNumberFormat(aCellPos); + OUString aText = ScCellFormat::GetInputString(aCell, nFormat, *rDoc.GetFormatTable(), rDoc); + if (!aText.isEmpty()) + pEditEngine->SetTextNewDefaults(aText, aDefaults); + else + pEditEngine->SetDefaults(aDefaults); + } + } + + bDataValid = true; + return pForwarder.get(); +} + +void ScCellTextData::UpdateData() +{ + if ( bDoUpdate ) + { + OSL_ENSURE(pEditEngine != nullptr, "no EditEngine for UpdateData()"); + if ( pDocShell && pEditEngine ) + { + // during the own UpdateData call, bDataValid must not be reset, + // or things like attributes after the text would be lost + // (are not stored in the cell) + bInUpdate = true; // prevents bDataValid from being reset + pDocShell->GetDocFunc().PutData(aCellPos, *pEditEngine, true); // always as text + + bInUpdate = false; + bDirty = false; + } + } + else + bDirty = true; +} + +void ScCellTextData::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + const SfxHintId nId = rHint.GetId(); + if ( nId == SfxHintId::Dying ) + { + pDocShell = nullptr; // invalid now + + pForwarder.reset(); + pEditEngine.reset(); // EditEngine uses document's pool + } + else if ( nId == SfxHintId::DataChanged ) + { + if (!bInUpdate) // not for own UpdateData calls + bDataValid = false; // text has to be read from the cell again + } +} + +ScCellTextObj::ScCellTextObj(ScDocShell* pDocSh, const ScAddress& rP) : + ScCellTextData( pDocSh, rP ), + SvxUnoText( GetOriginalSource(), ScCellObj::GetEditPropertySet(), uno::Reference<text::XText>() ) +{ +} + +ScCellTextObj::~ScCellTextObj() COVERITY_NOEXCEPT_FALSE +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |