880 lines
27 KiB
C++
880 lines
27 KiB
C++
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
/*
|
|
* This file is part of the LibreOffice project.
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
*
|
|
* This file incorporates work covered by the following license notice:
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed
|
|
* with this work for additional information regarding copyright
|
|
* ownership. The ASF licenses this file to you under the Apache
|
|
* License, Version 2.0 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
|
|
*/
|
|
|
|
#include <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 <utility>
|
|
#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
|
|
};
|
|
|
|
// modify PropertyMap to include CONVERT_TWIPS flag for font height
|
|
// (headers/footers are in twips)
|
|
|
|
for (auto & rEntry : aHdFtPropertyMap_Impl)
|
|
{
|
|
if ( ( rEntry.nWID == EE_CHAR_FONTHEIGHT ||
|
|
rEntry.nWID == EE_CHAR_FONTHEIGHT_CJK ||
|
|
rEntry.nWID == EE_CHAR_FONTHEIGHT_CTL ) &&
|
|
rEntry.nMemberId == MID_FONTHEIGHT )
|
|
{
|
|
rEntry.nMemberId |= CONVERT_TWIPS;
|
|
}
|
|
}
|
|
|
|
return SvxItemPropertySet(aHdFtPropertyMap_Impl, SdrObject::GetGlobalDrawObjectItemPool());
|
|
}();
|
|
return &aHdFtPropertySet_Impl;
|
|
}
|
|
|
|
SC_SIMPLE_SERVICE_INFO( ScHeaderFooterContentObj, u"ScHeaderFooterContentObj"_ustr, u"com.sun.star.sheet.HeaderFooterContent"_ustr )
|
|
SC_SIMPLE_SERVICE_INFO( ScHeaderFooterTextObj, u"ScHeaderFooterTextObj"_ustr, u"stardiv.one.Text.Text"_ustr )
|
|
|
|
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;
|
|
}
|
|
|
|
rtl::Reference<ScHeaderFooterContentObj> ScHeaderFooterContentObj::getImplementation(
|
|
const uno::Reference<sheet::XHeaderFooterContent>& rObj)
|
|
{
|
|
return dynamic_cast<ScHeaderFooterContentObj*>(rObj.get());
|
|
}
|
|
|
|
void ScHeaderFooterContentObj::Init( const EditTextObject* pLeft,
|
|
const EditTextObject* pCenter,
|
|
const EditTextObject* pRight )
|
|
{
|
|
mxLeftText = rtl::Reference<ScHeaderFooterTextObj>(new ScHeaderFooterTextObj(this, ScHeaderFooterPart::LEFT, pLeft));
|
|
mxCenterText = rtl::Reference<ScHeaderFooterTextObj>(new ScHeaderFooterTextObj(this, ScHeaderFooterPart::CENTER, pCenter));
|
|
mxRightText = rtl::Reference<ScHeaderFooterTextObj>(new ScHeaderFooterTextObj(this, ScHeaderFooterPart::RIGHT, pRight));
|
|
}
|
|
|
|
ScHeaderFooterTextData::ScHeaderFooterTextData(
|
|
unotools::WeakReference<ScHeaderFooterContentObj> xContent, ScHeaderFooterPart nP, const EditTextObject* pTextObj) :
|
|
mpTextObj(pTextObj ? pTextObj->Clone() : nullptr),
|
|
xContentObj(std::move( 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();
|
|
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
|
|
ScDocShell* pDocSh(dynamic_cast<ScDocShell*>(SfxObjectShell::Current()));
|
|
std::unique_ptr<CellAttributeHelper> pTmp;
|
|
const ScPatternAttr* pCellAttributeDefault(nullptr);
|
|
|
|
if (nullptr != pDocSh)
|
|
{
|
|
// we can use default CellAttribute from ScDocument
|
|
pCellAttributeDefault = &pDocSh->GetDocument().getCellAttributeHelper().getDefaultCellAttribute();
|
|
}
|
|
else
|
|
{
|
|
// no access to ScDocument, use temporary default CellAttributeHelper
|
|
// was: "use global pool from module" which is usually ScMessagePool
|
|
// and gets set in ScTabViewObj::SelectionChanged() by
|
|
// ScFormatShell::ScFormatShell which calls
|
|
// SetPool( &pTabViewShell->GetPool() );
|
|
pTmp.reset(new CellAttributeHelper(ScModule::get()->GetPool()));
|
|
pCellAttributeDefault = &pTmp->getDefaultCellAttribute();
|
|
}
|
|
|
|
auto pDefaults = std::make_unique<SfxItemSet>(pHdrEngine->GetEmptyItemSet());
|
|
pCellAttributeDefault->FillEditItemSet(pDefaults.get());
|
|
// FillEditItemSet adjusts font height to 1/100th mm,
|
|
// but for header/footer twips is needed, as in the PatternAttr:
|
|
pDefaults->Put( pCellAttributeDefault->GetItem(ATTR_FONT_HEIGHT).CloneSetWhich(EE_CHAR_FONTHEIGHT) );
|
|
pDefaults->Put( pCellAttributeDefault->GetItem(ATTR_CJK_FONT_HEIGHT).CloneSetWhich(EE_CHAR_FONTHEIGHT_CJK) ) ;
|
|
pDefaults->Put( pCellAttributeDefault->GetItem(ATTR_CTL_FONT_HEIGHT).CloneSetWhich(EE_CHAR_FONTHEIGHT_CTL) );
|
|
pHdrEngine->SetDefaults(std::move(pDefaults));
|
|
|
|
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 unotools::WeakReference<ScHeaderFooterContentObj>& 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(u"???"_ustr);
|
|
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;
|
|
|
|
rtl::Reference<ScHeaderFooterContentObj> xContentObj = aTextData.GetContentObj();
|
|
if (!xContentObj.is())
|
|
throw css::uno::RuntimeException(
|
|
u"ScHeaderFooterTextObj::getString: no ContentObj"_ustr);
|
|
|
|
switch ( aTextData.GetPart() )
|
|
{
|
|
case ScHeaderFooterPart::LEFT:
|
|
pData = xContentObj->GetLeftEditObject();
|
|
break;
|
|
case ScHeaderFooterPart::CENTER:
|
|
pData = xContentObj->GetCenterEditObject();
|
|
break;
|
|
case ScHeaderFooterPart::RIGHT:
|
|
pData = xContentObj->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 = dynamic_cast<ScEditFieldObj*>( xContent.get() );
|
|
|
|
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.CollapseToEnd();
|
|
}
|
|
|
|
SvxFieldItem aItem(pHeaderField->CreateFieldItem());
|
|
|
|
SvxTextForwarder* pForwarder = pEditSource->GetTextForwarder();
|
|
pForwarder->QuickInsertField( aItem, aSelection );
|
|
pEditSource->UpdateData();
|
|
|
|
// new selection: a digit
|
|
aSelection.Adjust();
|
|
aSelection.end.nPara = aSelection.start.nPara;
|
|
aSelection.end.nIndex = aSelection.start.nIndex + 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.start.nIndex = aSelection.end.nIndex;
|
|
|
|
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 = dynamic_cast<ScEditFieldObj*>(xContent.get());
|
|
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.CollapseToStart();
|
|
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.CollapseToEnd();
|
|
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.CollapseToStart();
|
|
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.CollapseToEnd();
|
|
pNew->SetSelection( aNewSel );
|
|
|
|
return static_cast<SvxUnoTextRangeBase*>(pNew.get());
|
|
}
|
|
|
|
// XUnoTunnel
|
|
|
|
UNO3_GETIMPLEMENTATION2_IMPL(ScHeaderFooterTextCursor, SvxUnoTextCursor);
|
|
|
|
ScDrawTextCursor::ScDrawTextCursor( uno::Reference<text::XText> xParent,
|
|
const SvxUnoTextBase& rText ) :
|
|
SvxUnoTextCursor( rText ),
|
|
xParentText(std::move( 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.CollapseToStart();
|
|
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.CollapseToEnd();
|
|
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 );
|
|
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();
|
|
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();
|
|
|
|
auto pDefaults = std::make_unique<SfxItemSet>(pEditEngine->GetEmptyItemSet());
|
|
if( const ScPatternAttr* pPattern =
|
|
rDoc.GetPattern( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab() ) )
|
|
{
|
|
pPattern->FillEditItemSet(pDefaults.get());
|
|
pPattern->FillEditParaItems(pDefaults.get()); // including alignment etc. (for reading)
|
|
}
|
|
|
|
ScRefCellValue aCell(rDoc, aCellPos);
|
|
if (aCell.getType() == CELLTYPE_EDIT)
|
|
{
|
|
const EditTextObject* pObj = aCell.getEditText();
|
|
pEditEngine->SetTextNewDefaults(*pObj, std::move(pDefaults));
|
|
}
|
|
else
|
|
{
|
|
sal_uInt32 nFormat = rDoc.GetNumberFormat(ScRange(aCellPos));
|
|
OUString aText = ScCellFormat::GetInputString(aCell, nFormat, nullptr, rDoc);
|
|
// tdf#157568 check if edit engine already has text
|
|
// If the input string is empty but the edit engine's existing
|
|
// text is not empty, force update of the edit engine's text.
|
|
// Otherwise, the edit engine will still to be set to its
|
|
// existing text.
|
|
// Note: CppunitTest_sc_macros_test testTdf116127 will fail if
|
|
// pEditEngine->SetTextNewDefaults() is passed an empty string
|
|
// and pEditEngine->GetText() is empty string.
|
|
if (!aText.isEmpty() || pEditEngine->HasText())
|
|
pEditEngine->SetTextNewDefaults(aText, std::move(pDefaults));
|
|
else
|
|
pEditEngine->SetDefaults(std::move(pDefaults));
|
|
}
|
|
}
|
|
|
|
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: */
|