diff options
Diffstat (limited to 'sc/source/ui/unoobj/textuno.cxx')
-rw-r--r-- | sc/source/ui/unoobj/textuno.cxx | 1139 |
1 files changed, 1139 insertions, 0 deletions
diff --git a/sc/source/ui/unoobj/textuno.cxx b/sc/source/ui/unoobj/textuno.cxx new file mode 100644 index 000000000000..4e21b587294d --- /dev/null +++ b/sc/source/ui/unoobj/textuno.cxx @@ -0,0 +1,1139 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.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 <svx/unomid.hxx> +#include <editeng/unoprnms.hxx> +#include <editeng/unofored.hxx> +#include <rtl/uuid.h> +#include <vcl/virdev.hxx> +#include <vcl/svapp.hxx> +#include <com/sun/star/awt/FontSlant.hpp> + +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <editeng/unoipset.hxx> +#include "textuno.hxx" +#include "fielduno.hxx" +#include "servuno.hxx" +#include "editsrc.hxx" +#include "docsh.hxx" +#include "editutil.hxx" +#include "miscuno.hxx" +#include "cellsuno.hxx" +#include "hints.hxx" +#include "patattr.hxx" +#include "cell.hxx" +#include "docfunc.hxx" +#include "scmod.hxx" + +using namespace com::sun::star; + +//------------------------------------------------------------------------ + +const SvxItemPropertySet * lcl_GetHdFtPropertySet() +{ + static SfxItemPropertyMapEntry aHdFtPropertyMap_Impl[] = + { + SVX_UNOEDIT_CHAR_PROPERTIES, + SVX_UNOEDIT_FONT_PROPERTIES, + SVX_UNOEDIT_PARA_PROPERTIES, + SVX_UNOEDIT_NUMBERING_PROPERTIE, // for completeness of service ParagraphProperties + {0,0,0,0,0,0} + }; + static sal_Bool bTwipsSet = false; + + if (!bTwipsSet) + { + // modify PropertyMap to include CONVERT_TWIPS flag for font height + // (headers/footers are in twips) + + SfxItemPropertyMapEntry* pEntry = aHdFtPropertyMap_Impl; + while (pEntry->pName) + { + 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; + } + bTwipsSet = sal_True; + } + static SvxItemPropertySet aHdFtPropertySet_Impl( 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( const EditTextObject* pLeft, + const EditTextObject* pCenter, + const EditTextObject* pRight ) : + pLeftText ( NULL ), + pCenterText ( NULL ), + pRightText ( NULL ) +{ + if ( pLeft ) + pLeftText = pLeft->Clone(); + if ( pCenter ) + pCenterText = pCenter->Clone(); + if ( pRight ) + pRightText = pRight->Clone(); +} + +ScHeaderFooterContentObj::~ScHeaderFooterContentObj() +{ + delete pLeftText; + delete pCenterText; + delete pRightText; +} + +void ScHeaderFooterContentObj::AddListener( SfxListener& rListener ) +{ + rListener.StartListening( aBC ); +} + +void ScHeaderFooterContentObj::RemoveListener( SfxListener& rListener ) +{ + rListener.EndListening( aBC ); +} + +void ScHeaderFooterContentObj::UpdateText( sal_uInt16 nPart, EditEngine& rSource ) +{ + EditTextObject* pNew = rSource.CreateTextObject(); + switch (nPart) + { + case SC_HDFT_LEFT: + delete pLeftText; + pLeftText = pNew; + break; + case SC_HDFT_CENTER: + delete pCenterText; + pCenterText = pNew; + break; + default: // SC_HDFT_RIGHT + delete pRightText; + pRightText = pNew; + break; + } + + aBC.Broadcast( ScHeaderFooterChangedHint( nPart ) ); +} + +// XHeaderFooterContent + +uno::Reference<text::XText> SAL_CALL ScHeaderFooterContentObj::getLeftText() + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + return new ScHeaderFooterTextObj( *this, SC_HDFT_LEFT ); +} + +uno::Reference<text::XText> SAL_CALL ScHeaderFooterContentObj::getCenterText() + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + return new ScHeaderFooterTextObj( *this, SC_HDFT_CENTER ); +} + +uno::Reference<text::XText> SAL_CALL ScHeaderFooterContentObj::getRightText() + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + return new ScHeaderFooterTextObj( *this, SC_HDFT_RIGHT ); +} + +// XUnoTunnel + +sal_Int64 SAL_CALL ScHeaderFooterContentObj::getSomething( + const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); + } + return 0; +} + +const uno::Sequence<sal_Int8>& ScHeaderFooterContentObj::getUnoTunnelId() +{ + static uno::Sequence<sal_Int8> * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +ScHeaderFooterContentObj* ScHeaderFooterContentObj::getImplementation( + const uno::Reference<sheet::XHeaderFooterContent> xObj ) +{ + ScHeaderFooterContentObj* pRet = NULL; + uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); + if (xUT.is()) + pRet = reinterpret_cast<ScHeaderFooterContentObj*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId()))); + return pRet; +} + + +//------------------------------------------------------------------------ + +ScHeaderFooterTextData::ScHeaderFooterTextData( ScHeaderFooterContentObj& rContent, + sal_uInt16 nP ) : + rContentObj( rContent ), + nPart( nP ), + pEditEngine( NULL ), + pForwarder( NULL ), + bDataValid( false ), + bInUpdate( false ) +{ + rContentObj.acquire(); // must not go away + rContentObj.AddListener( *this ); +} + +ScHeaderFooterTextData::~ScHeaderFooterTextData() +{ + SolarMutexGuard aGuard; // needed for EditEngine dtor + + rContentObj.RemoveListener( *this ); + + delete pForwarder; + delete pEditEngine; + + rContentObj.release(); +} + +void ScHeaderFooterTextData::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( ScHeaderFooterChangedHint ) ) + { + if ( ((const ScHeaderFooterChangedHint&)rHint).GetPart() == nPart ) + { + if (!bInUpdate) // not for own updates + bDataValid = false; // text has to be fetched again + } + } +} + +SvxTextForwarder* ScHeaderFooterTextData::GetTextForwarder() +{ + if (!pEditEngine) + { + SfxItemPool* pEnginePool = EditEngine::CreatePool(); + pEnginePool->FreezeIdRanges(); + ScHeaderEditEngine* pHdrEngine = new ScHeaderEditEngine( pEnginePool, sal_True ); + + pHdrEngine->EnableUndo( false ); + pHdrEngine->SetRefMapMode( MAP_TWIP ); + + // default font must be set, independently of document + // -> use global pool from module + + SfxItemSet aDefaults( pHdrEngine->GetEmptyItemSet() ); + const ScPatternAttr& rPattern = (const ScPatternAttr&)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), EE_CHAR_FONTHEIGHT ); + aDefaults.Put( rPattern.GetItem(ATTR_CJK_FONT_HEIGHT), EE_CHAR_FONTHEIGHT_CJK ); + aDefaults.Put( rPattern.GetItem(ATTR_CTL_FONT_HEIGHT), EE_CHAR_FONTHEIGHT_CTL ); + pHdrEngine->SetDefaults( aDefaults ); + + ScHeaderFieldData aData; + ScHeaderFooterTextObj::FillDummyFieldData( aData ); + pHdrEngine->SetData( aData ); + + pEditEngine = pHdrEngine; + pForwarder = new SvxEditEngineForwarder(*pEditEngine); + } + + if (bDataValid) + return pForwarder; + + const EditTextObject* pData; + if (nPart == SC_HDFT_LEFT) + pData = rContentObj.GetLeftEditObject(); + else if (nPart == SC_HDFT_CENTER) + pData = rContentObj.GetCenterEditObject(); + else + pData = rContentObj.GetRightEditObject(); + + if (pData) + pEditEngine->SetText(*pData); + + bDataValid = sal_True; + return pForwarder; +} + +void ScHeaderFooterTextData::UpdateData() +{ + if ( pEditEngine ) + { + bInUpdate = sal_True; // don't reset bDataValid during UpdateText + + rContentObj.UpdateText( nPart, *pEditEngine ); + + bInUpdate = false; + } +} + +//------------------------------------------------------------------------ + +ScHeaderFooterTextObj::ScHeaderFooterTextObj( ScHeaderFooterContentObj& rContent, + sal_uInt16 nP ) : + aTextData( rContent, nP ), + pUnoText( NULL ) +{ + // ScHeaderFooterTextData acquires rContent + // pUnoText is created on demand (getString/setString work without it) +} + +void ScHeaderFooterTextObj::CreateUnoText_Impl() +{ + if ( !pUnoText ) + { + // can't be aggregated because getString/setString is handled here + ScSharedHeaderFooterEditSource aEditSource( &aTextData ); + pUnoText = new SvxUnoText( &aEditSource, lcl_GetHdFtPropertySet(), uno::Reference<text::XText>() ); + pUnoText->acquire(); + } +} + +ScHeaderFooterTextObj::~ScHeaderFooterTextObj() +{ + if (pUnoText) + pUnoText->release(); +} + +const SvxUnoText& ScHeaderFooterTextObj::GetUnoText() +{ + if (!pUnoText) + CreateUnoText_Impl(); + return *pUnoText; +} + +// XText + +uno::Reference<text::XTextCursor> SAL_CALL ScHeaderFooterTextObj::createTextCursor() + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + return new ScHeaderFooterTextCursor( *this ); +} + +uno::Reference<text::XTextCursor> SAL_CALL ScHeaderFooterTextObj::createTextCursorByRange( + const uno::Reference<text::XTextRange>& aTextPosition ) + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pUnoText) + CreateUnoText_Impl(); + return pUnoText->createTextCursorByRange(aTextPosition); + //! wie ScCellObj::createTextCursorByRange, wenn SvxUnoTextRange_getReflection verfuegbar +} + +void ScHeaderFooterTextObj::FillDummyFieldData( ScHeaderFieldData& rData ) +{ + String aDummy(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM( "???" ))); + rData.aTitle = aDummy; + rData.aLongDocName = aDummy; + rData.aShortDocName = aDummy; + rData.aTabName = aDummy; + rData.nPageNo = 1; + rData.nTotalPages = 99; +} + +rtl::OUString SAL_CALL ScHeaderFooterTextObj::getString() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + rtl::OUString aRet; + const EditTextObject* pData; + + sal_uInt16 nPart = aTextData.GetPart(); + ScHeaderFooterContentObj& rContentObj = aTextData.GetContentObj(); + + if (nPart == SC_HDFT_LEFT) + pData = rContentObj.GetLeftEditObject(); + else if (nPart == SC_HDFT_CENTER) + pData = rContentObj.GetCenterEditObject(); + else + pData = rContentObj.GetRightEditObject(); + if (pData) + { + // for pure text, no font info is needed in pool defaults + ScHeaderEditEngine aEditEngine( EditEngine::CreatePool(), sal_True ); + + ScHeaderFieldData aData; + FillDummyFieldData( aData ); + aEditEngine.SetData( aData ); + + aEditEngine.SetText(*pData); + aRet = ScEditUtil::GetSpaceDelimitedString( aEditEngine ); + } + return aRet; +} + +void SAL_CALL ScHeaderFooterTextObj::setString( const rtl::OUString& aText ) throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + String aString(aText); + + // for pure text, no font info is needed in pool defaults + ScHeaderEditEngine aEditEngine( EditEngine::CreatePool(), sal_True ); + aEditEngine.SetText( aString ); + + aTextData.GetContentObj().UpdateText( aTextData.GetPart(), aEditEngine ); +} + +void SAL_CALL ScHeaderFooterTextObj::insertString( const uno::Reference<text::XTextRange>& xRange, + const rtl::OUString& aString, sal_Bool bAbsorb ) + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pUnoText) + CreateUnoText_Impl(); + pUnoText->insertString( xRange, aString, bAbsorb ); +} + +void SAL_CALL ScHeaderFooterTextObj::insertControlCharacter( + const uno::Reference<text::XTextRange>& xRange, + sal_Int16 nControlCharacter, sal_Bool bAbsorb ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pUnoText) + CreateUnoText_Impl(); + pUnoText->insertControlCharacter( xRange, nControlCharacter, bAbsorb ); +} + +void SAL_CALL ScHeaderFooterTextObj::insertTextContent( + const uno::Reference<text::XTextRange >& xRange, + const uno::Reference<text::XTextContent >& xContent, + sal_Bool bAbsorb ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + SolarMutexGuard aGuard; + if ( xContent.is() && xRange.is() ) + { + ScHeaderFieldObj* pHeaderField = ScHeaderFieldObj::getImplementation( xContent ); + + SvxUnoTextRangeBase* pTextRange = + ScHeaderFooterTextCursor::getImplementation( 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(); + + // neue Selektion: ein Zeichen + aSelection.Adjust(); + aSelection.nEndPara = aSelection.nStartPara; + aSelection.nEndPos = aSelection.nStartPos + 1; + pHeaderField->InitDoc( &aTextData.GetContentObj(), aTextData.GetPart(), 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 (!pUnoText) + CreateUnoText_Impl(); + pUnoText->insertTextContent( xRange, xContent, bAbsorb ); +} + +void SAL_CALL ScHeaderFooterTextObj::removeTextContent( + const uno::Reference<text::XTextContent>& xContent ) + throw(container::NoSuchElementException, uno::RuntimeException) +{ + SolarMutexGuard aGuard; + if ( xContent.is() ) + { + ScHeaderFieldObj* pHeaderField = ScHeaderFieldObj::getImplementation( xContent ); + if ( pHeaderField && pHeaderField->IsInserted() ) + { + //! Testen, ob das Feld in dieser Zelle ist + pHeaderField->DeleteField(); + return; + } + } + if (!pUnoText) + CreateUnoText_Impl(); + pUnoText->removeTextContent( xContent ); +} + +uno::Reference<text::XText> SAL_CALL ScHeaderFooterTextObj::getText() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pUnoText) + CreateUnoText_Impl(); + return pUnoText->getText(); +} + +uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextObj::getStart() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pUnoText) + CreateUnoText_Impl(); + return pUnoText->getStart(); +} + +uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextObj::getEnd() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pUnoText) + CreateUnoText_Impl(); + return pUnoText->getEnd(); +} + +// XTextFieldsSupplier + +uno::Reference<container::XEnumerationAccess> SAL_CALL ScHeaderFooterTextObj::getTextFields() + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + // all fields + return new ScHeaderFieldsObj( &aTextData.GetContentObj(), aTextData.GetPart(), SC_SERVICE_INVALID ); +} + +uno::Reference<container::XNameAccess> SAL_CALL ScHeaderFooterTextObj::getTextFieldMasters() + throw(uno::RuntimeException) +{ + // sowas gibts nicht im Calc (?) + return NULL; +} + +// XTextRangeMover + +void SAL_CALL ScHeaderFooterTextObj::moveTextRange( + const uno::Reference<text::XTextRange>& xRange, + sal_Int16 nParagraphs ) + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pUnoText) + CreateUnoText_Impl(); + pUnoText->moveTextRange( xRange, nParagraphs ); +} + +// XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScHeaderFooterTextObj::createEnumeration() + throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pUnoText) + CreateUnoText_Impl(); + return pUnoText->createEnumeration(); +} + +// XElementAccess + +uno::Type SAL_CALL ScHeaderFooterTextObj::getElementType() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pUnoText) + CreateUnoText_Impl(); + return pUnoText->getElementType(); +} + +sal_Bool SAL_CALL ScHeaderFooterTextObj::hasElements() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + if (!pUnoText) + CreateUnoText_Impl(); + return pUnoText->hasElements(); +} + +//------------------------------------------------------------------------ + +ScCellTextCursor::ScCellTextCursor(const ScCellTextCursor& rOther) : + SvxUnoTextCursor( rOther ), + rTextObj( rOther.rTextObj ) +{ + rTextObj.acquire(); +} + +ScCellTextCursor::ScCellTextCursor(ScCellObj& rText) : + SvxUnoTextCursor( rText.GetUnoText() ), + rTextObj( rText ) +{ + rTextObj.acquire(); +} + +ScCellTextCursor::~ScCellTextCursor() throw() +{ + rTextObj.release(); +} + +// SvxUnoTextCursor methods reimplemented here to return the right objects: + +uno::Reference<text::XText> SAL_CALL ScCellTextCursor::getText() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + return &rTextObj; +} + +uno::Reference<text::XTextRange> SAL_CALL ScCellTextCursor::getStart() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + + //! use other object for range than cursor? + + ScCellTextCursor* pNew = new ScCellTextCursor( *this ); + uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) ); + + ESelection aNewSel(GetSelection()); + aNewSel.nEndPara = aNewSel.nStartPara; + aNewSel.nEndPos = aNewSel.nStartPos; + pNew->SetSelection( aNewSel ); + + return xRange; +} + +uno::Reference<text::XTextRange> SAL_CALL ScCellTextCursor::getEnd() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + + //! use other object for range than cursor? + + ScCellTextCursor* pNew = new ScCellTextCursor( *this ); + uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) ); + + ESelection aNewSel(GetSelection()); + aNewSel.nStartPara = aNewSel.nEndPara; + aNewSel.nStartPos = aNewSel.nEndPos; + pNew->SetSelection( aNewSel ); + + return xRange; +} + +// XUnoTunnel + +sal_Int64 SAL_CALL ScCellTextCursor::getSomething( + const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); + } + return SvxUnoTextCursor::getSomething( rId ); +} + +const uno::Sequence<sal_Int8>& ScCellTextCursor::getUnoTunnelId() +{ + static uno::Sequence<sal_Int8> * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +ScCellTextCursor* ScCellTextCursor::getImplementation( const uno::Reference<uno::XInterface> xObj ) +{ + ScCellTextCursor* pRet = NULL; + uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); + if (xUT.is()) + pRet = reinterpret_cast<ScCellTextCursor*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId()))); + return pRet; +} + +//------------------------------------------------------------------------ + +ScHeaderFooterTextCursor::ScHeaderFooterTextCursor(const ScHeaderFooterTextCursor& rOther) : + SvxUnoTextCursor( rOther ), + rTextObj( rOther.rTextObj ) +{ + rTextObj.acquire(); +} + +ScHeaderFooterTextCursor::ScHeaderFooterTextCursor(ScHeaderFooterTextObj& rText) : + SvxUnoTextCursor( rText.GetUnoText() ), + rTextObj( rText ) +{ + rTextObj.acquire(); +} + +ScHeaderFooterTextCursor::~ScHeaderFooterTextCursor() throw() +{ + rTextObj.release(); +} + +// SvxUnoTextCursor methods reimplemented here to return the right objects: + +uno::Reference<text::XText> SAL_CALL ScHeaderFooterTextCursor::getText() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + return &rTextObj; +} + +uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextCursor::getStart() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + + //! use other object for range than cursor? + + ScHeaderFooterTextCursor* pNew = new ScHeaderFooterTextCursor( *this ); + uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) ); + + ESelection aNewSel(GetSelection()); + aNewSel.nEndPara = aNewSel.nStartPara; + aNewSel.nEndPos = aNewSel.nStartPos; + pNew->SetSelection( aNewSel ); + + return xRange; +} + +uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextCursor::getEnd() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + + //! use other object for range than cursor? + + ScHeaderFooterTextCursor* pNew = new ScHeaderFooterTextCursor( *this ); + uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) ); + + ESelection aNewSel(GetSelection()); + aNewSel.nStartPara = aNewSel.nEndPara; + aNewSel.nStartPos = aNewSel.nEndPos; + pNew->SetSelection( aNewSel ); + + return xRange; +} + +// XUnoTunnel + +sal_Int64 SAL_CALL ScHeaderFooterTextCursor::getSomething( + const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); + } + return SvxUnoTextCursor::getSomething( rId ); +} + +const uno::Sequence<sal_Int8>& ScHeaderFooterTextCursor::getUnoTunnelId() +{ + static uno::Sequence<sal_Int8> * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +ScHeaderFooterTextCursor* ScHeaderFooterTextCursor::getImplementation( + const uno::Reference<uno::XInterface> xObj ) +{ + ScHeaderFooterTextCursor* pRet = NULL; + uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); + if (xUT.is()) + pRet = reinterpret_cast<ScHeaderFooterTextCursor*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId()))); + return pRet; +} + +//------------------------------------------------------------------------ + +ScDrawTextCursor::ScDrawTextCursor(const ScDrawTextCursor& rOther) : + SvxUnoTextCursor( rOther ), + xParentText( rOther.xParentText ) +{ +} + +ScDrawTextCursor::ScDrawTextCursor( const uno::Reference<text::XText>& xParent, + const SvxUnoTextBase& rText ) : + SvxUnoTextCursor( rText ), + xParentText( xParent ) + +{ +} + +ScDrawTextCursor::~ScDrawTextCursor() throw() +{ +} + +// SvxUnoTextCursor methods reimplemented here to return the right objects: + +uno::Reference<text::XText> SAL_CALL ScDrawTextCursor::getText() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + return xParentText; +} + +uno::Reference<text::XTextRange> SAL_CALL ScDrawTextCursor::getStart() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + + //! use other object for range than cursor? + + ScDrawTextCursor* pNew = new ScDrawTextCursor( *this ); + uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) ); + + ESelection aNewSel(GetSelection()); + aNewSel.nEndPara = aNewSel.nStartPara; + aNewSel.nEndPos = aNewSel.nStartPos; + pNew->SetSelection( aNewSel ); + + return xRange; +} + +uno::Reference<text::XTextRange> SAL_CALL ScDrawTextCursor::getEnd() throw(uno::RuntimeException) +{ + SolarMutexGuard aGuard; + + //! use other object for range than cursor? + + ScDrawTextCursor* pNew = new ScDrawTextCursor( *this ); + uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) ); + + ESelection aNewSel(GetSelection()); + aNewSel.nStartPara = aNewSel.nEndPara; + aNewSel.nStartPos = aNewSel.nEndPos; + pNew->SetSelection( aNewSel ); + + return xRange; +} + +// XUnoTunnel + +sal_Int64 SAL_CALL ScDrawTextCursor::getSomething( + const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); + } + return SvxUnoTextCursor::getSomething( rId ); +} + +const uno::Sequence<sal_Int8>& ScDrawTextCursor::getUnoTunnelId() +{ + static uno::Sequence<sal_Int8> * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +ScDrawTextCursor* ScDrawTextCursor::getImplementation( const uno::Reference<uno::XInterface> xObj ) +{ + ScDrawTextCursor* pRet = NULL; + uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); + if (xUT.is()) + pRet = reinterpret_cast<ScDrawTextCursor*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId()))); + return pRet; +} + +//------------------------------------------------------------------------ + +ScSimpleEditSourceHelper::ScSimpleEditSourceHelper() +{ + SfxItemPool* pEnginePool = EditEngine::CreatePool(); + pEnginePool->SetDefaultMetric( SFX_MAPUNIT_100TH_MM ); + pEnginePool->FreezeIdRanges(); + + pEditEngine = new ScFieldEditEngine( pEnginePool, NULL, sal_True ); // TRUE: become owner of pool + pForwarder = new SvxEditEngineForwarder( *pEditEngine ); + pOriginalSource = new ScSimpleEditSource( pForwarder ); +} + +ScSimpleEditSourceHelper::~ScSimpleEditSourceHelper() +{ + SolarMutexGuard aGuard; // needed for EditEngine dtor + + delete pOriginalSource; + delete pForwarder; + delete pEditEngine; +} + +ScEditEngineTextObj::ScEditEngineTextObj() : + SvxUnoText( GetOriginalSource(), ScCellObj::GetEditPropertySet(), uno::Reference<text::XText>() ) +{ +} + +ScEditEngineTextObj::~ScEditEngineTextObj() throw() +{ +} + +void ScEditEngineTextObj::SetText( const EditTextObject& rTextObject ) +{ + GetEditEngine()->SetText( rTextObject ); + + ESelection aSel; + ::GetSelection( aSel, GetEditSource()->GetTextForwarder() ); + SetSelection( aSel ); +} + +EditTextObject* ScEditEngineTextObj::CreateTextObject() +{ + return GetEditEngine()->CreateTextObject(); +} + +//------------------------------------------------------------------------ + +ScCellTextData::ScCellTextData(ScDocShell* pDocSh, const ScAddress& rP) : + pDocShell( pDocSh ), + aCellPos( rP ), + pEditEngine( NULL ), + pForwarder( NULL ), + pOriginalSource( NULL ), + bDataValid( false ), + bInUpdate( false ), + bDirty( false ), + bDoUpdate( sal_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 + delete pEditEngine; + + delete pForwarder; + + delete pOriginalSource; +} + +ScSharedCellEditSource* ScCellTextData::GetOriginalSource() +{ + if (!pOriginalSource) + pOriginalSource = new ScSharedCellEditSource( this ); + return pOriginalSource; +} + +void ScCellTextData::GetCellText(const ScAddress& rCellPos, String& rText) +{ + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + pDoc->GetInputString( rCellPos.Col(), rCellPos.Row(), rCellPos.Tab(), rText ); + } +} + +SvxTextForwarder* ScCellTextData::GetTextForwarder() +{ + if (!pEditEngine) + { + if ( pDocShell ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + pEditEngine = pDoc->CreateFieldEditEngine(); + } + else + { + SfxItemPool* pEnginePool = EditEngine::CreatePool(); + pEnginePool->FreezeIdRanges(); + pEditEngine = new ScFieldEditEngine( pEnginePool, NULL, sal_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( MAP_100TH_MM ); + pForwarder = new SvxEditEngineForwarder(*pEditEngine); + } + + if (bDataValid) + return pForwarder; + + String aText; + + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + + SfxItemSet aDefaults( pEditEngine->GetEmptyItemSet() ); + if( const ScPatternAttr* pPattern = + pDoc->GetPattern( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab() ) ) + { + pPattern->FillEditItemSet( &aDefaults ); + pPattern->FillEditParaItems( &aDefaults ); // including alignment etc. (for reading) + } + + const ScBaseCell* pCell = pDoc->GetCell( aCellPos ); + if ( pCell && pCell->GetCellType() == CELLTYPE_EDIT ) + pEditEngine->SetTextNewDefaults( *((const ScEditCell*)pCell)->GetData(), aDefaults ); + else + { + GetCellText( aCellPos, aText ); + if (aText.Len()) + pEditEngine->SetTextNewDefaults( aText, aDefaults ); + else + pEditEngine->SetDefaults(aDefaults); + } + } + + bDataValid = sal_True; + return pForwarder; +} + +void ScCellTextData::UpdateData() +{ + if ( bDoUpdate ) + { + DBG_ASSERT(pEditEngine != NULL, "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 = sal_True; // prevents bDataValid from being reset + + ScDocFunc aFunc(*pDocShell); + aFunc.PutData( aCellPos, *pEditEngine, false, sal_True ); // always as text + + bInUpdate = false; + bDirty = false; + } + } + else + bDirty = sal_True; +} + +void ScCellTextData::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( ScUpdateRefHint ) ) + { +// const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint; + + //! Ref-Update + } + else if ( rHint.ISA( SfxSimpleHint ) ) + { + sal_uLong nId = ((const SfxSimpleHint&)rHint).GetId(); + if ( nId == SFX_HINT_DYING ) + { + pDocShell = NULL; // invalid now + + DELETEZ( pForwarder ); + DELETEZ( pEditEngine ); // EditEngine uses document's pool + } + else if ( nId == SFX_HINT_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() throw() +{ +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |