| /************************************************************** |
| * |
| * 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 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the 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 <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 "unoguard.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 = sal_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) |
| { |
| ScUnoGuard aGuard; |
| return new ScHeaderFooterTextObj( *this, SC_HDFT_LEFT ); |
| } |
| |
| uno::Reference<text::XText> SAL_CALL ScHeaderFooterContentObj::getCenterText() |
| throw(uno::RuntimeException) |
| { |
| ScUnoGuard aGuard; |
| return new ScHeaderFooterTextObj( *this, SC_HDFT_CENTER ); |
| } |
| |
| uno::Reference<text::XText> SAL_CALL ScHeaderFooterContentObj::getRightText() |
| throw(uno::RuntimeException) |
| { |
| ScUnoGuard 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; |
| } |
| |
| // static |
| 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; |
| } |
| |
| // static |
| 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( sal_False ), |
| bInUpdate( sal_False ) |
| { |
| rContentObj.acquire(); // must not go away |
| rContentObj.AddListener( *this ); |
| } |
| |
| ScHeaderFooterTextData::~ScHeaderFooterTextData() |
| { |
| ScUnoGuard 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 = sal_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( sal_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 = sal_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) |
| { |
| ScUnoGuard aGuard; |
| return new ScHeaderFooterTextCursor( *this ); |
| } |
| |
| uno::Reference<text::XTextCursor> SAL_CALL ScHeaderFooterTextObj::createTextCursorByRange( |
| const uno::Reference<text::XTextRange>& aTextPosition ) |
| throw(uno::RuntimeException) |
| { |
| ScUnoGuard aGuard; |
| if (!pUnoText) |
| CreateUnoText_Impl(); |
| return pUnoText->createTextCursorByRange(aTextPosition); |
| //! wie ScCellObj::createTextCursorByRange, wenn SvxUnoTextRange_getReflection verfuegbar |
| } |
| |
| void ScHeaderFooterTextObj::FillDummyFieldData( ScHeaderFieldData& rData ) // static |
| { |
| 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) |
| { |
| ScUnoGuard 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) |
| { |
| ScUnoGuard 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) |
| { |
| ScUnoGuard 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) |
| { |
| ScUnoGuard 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) |
| { |
| ScUnoGuard aGuard; |
| if ( xContent.is() && xRange.is() ) |
| { |
| ScHeaderFieldObj* pHeaderField = ScHeaderFieldObj::getImplementation( xContent ); |
| |
| SvxUnoTextRangeBase* pTextRange = |
| ScHeaderFooterTextCursor::getImplementation( xRange ); |
| |
| #if 0 |
| if (!pTextRange) |
| pTextRange = (SvxUnoTextRange*)xRange->getImplementation( |
| SvxUnoTextRange_getReflection() ); |
| //! bei SvxUnoTextRange testen, ob in passendem Objekt !!! |
| #endif |
| |
| 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 ); |
| |
| // #91431# for bAbsorb=sal_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) |
| { |
| ScUnoGuard 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) |
| { |
| ScUnoGuard aGuard; |
| if (!pUnoText) |
| CreateUnoText_Impl(); |
| return pUnoText->getText(); |
| } |
| |
| uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextObj::getStart() throw(uno::RuntimeException) |
| { |
| ScUnoGuard aGuard; |
| if (!pUnoText) |
| CreateUnoText_Impl(); |
| return pUnoText->getStart(); |
| } |
| |
| uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextObj::getEnd() throw(uno::RuntimeException) |
| { |
| ScUnoGuard aGuard; |
| if (!pUnoText) |
| CreateUnoText_Impl(); |
| return pUnoText->getEnd(); |
| } |
| |
| // XTextFieldsSupplier |
| |
| uno::Reference<container::XEnumerationAccess> SAL_CALL ScHeaderFooterTextObj::getTextFields() |
| throw(uno::RuntimeException) |
| { |
| ScUnoGuard 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) |
| { |
| ScUnoGuard aGuard; |
| if (!pUnoText) |
| CreateUnoText_Impl(); |
| pUnoText->moveTextRange( xRange, nParagraphs ); |
| } |
| |
| // XEnumerationAccess |
| |
| uno::Reference<container::XEnumeration> SAL_CALL ScHeaderFooterTextObj::createEnumeration() |
| throw(uno::RuntimeException) |
| { |
| ScUnoGuard aGuard; |
| if (!pUnoText) |
| CreateUnoText_Impl(); |
| return pUnoText->createEnumeration(); |
| } |
| |
| // XElementAccess |
| |
| uno::Type SAL_CALL ScHeaderFooterTextObj::getElementType() throw(uno::RuntimeException) |
| { |
| ScUnoGuard aGuard; |
| if (!pUnoText) |
| CreateUnoText_Impl(); |
| return pUnoText->getElementType(); |
| } |
| |
| sal_Bool SAL_CALL ScHeaderFooterTextObj::hasElements() throw(uno::RuntimeException) |
| { |
| ScUnoGuard 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) |
| { |
| ScUnoGuard aGuard; |
| return &rTextObj; |
| } |
| |
| uno::Reference<text::XTextRange> SAL_CALL ScCellTextCursor::getStart() throw(uno::RuntimeException) |
| { |
| ScUnoGuard 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) |
| { |
| ScUnoGuard 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 ); |
| } |
| |
| // static |
| 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; |
| } |
| |
| // static |
| 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) |
| { |
| ScUnoGuard aGuard; |
| return &rTextObj; |
| } |
| |
| uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextCursor::getStart() throw(uno::RuntimeException) |
| { |
| ScUnoGuard 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) |
| { |
| ScUnoGuard 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 ); |
| } |
| |
| // static |
| 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; |
| } |
| |
| // static |
| 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) |
| { |
| ScUnoGuard aGuard; |
| return xParentText; |
| } |
| |
| uno::Reference<text::XTextRange> SAL_CALL ScDrawTextCursor::getStart() throw(uno::RuntimeException) |
| { |
| ScUnoGuard 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) |
| { |
| ScUnoGuard 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 ); |
| } |
| |
| // static |
| 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; |
| } |
| |
| // static |
| 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() |
| { |
| ScUnoGuard 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( sal_False ), |
| bInUpdate( sal_False ), |
| bDirty( sal_False ), |
| bDoUpdate( sal_True ) |
| { |
| if (pDocShell) |
| pDocShell->GetDocument()->AddUnoObject(*this); |
| } |
| |
| ScCellTextData::~ScCellTextData() |
| { |
| ScUnoGuard 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( sal_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, sal_False, sal_True ); // always as text |
| |
| bInUpdate = sal_False; |
| bDirty = sal_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 = sal_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() |
| { |
| } |
| |