diff options
73 files changed, 1687 insertions, 1084 deletions
diff --git a/chart2/source/controller/itemsetwrapper/AxisItemConverter.cxx b/chart2/source/controller/itemsetwrapper/AxisItemConverter.cxx index 95f7d45bc27f..bce22df7eb58 100644 --- a/chart2/source/controller/itemsetwrapper/AxisItemConverter.cxx +++ b/chart2/source/controller/itemsetwrapper/AxisItemConverter.cxx @@ -618,7 +618,7 @@ bool AxisItemConverter::ApplySpecialItem( sal_uInt16 nWhichId, const SfxItemSet { TimeInterval aTimeInterval; aScale.TimeIncrement.MajorTimeInterval >>= aTimeInterval; - aTimeInterval.Number = static_cast<double>(fValue); + aTimeInterval.Number = static_cast<sal_Int32>(fValue); aScale.TimeIncrement.MajorTimeInterval = uno::makeAny( aTimeInterval ); bSetScale = true; } diff --git a/chart2/source/view/axes/ScaleAutomatism.cxx b/chart2/source/view/axes/ScaleAutomatism.cxx index 0ca83bf354e9..8dc1ce875411 100644 --- a/chart2/source/view/axes/ScaleAutomatism.cxx +++ b/chart2/source/view/axes/ScaleAutomatism.cxx @@ -713,7 +713,7 @@ void ScaleAutomatism::calculateExplicitIncrementAndScaleForDateTimeAxis( } } rExplicitIncrement.MajorTimeInterval.Number = nNumer; - nMainIncrementCount = nDayCount/(nNumer*nDaysPerInterval); + nMainIncrementCount = static_cast<long>(nDayCount/(nNumer*nDaysPerInterval)); } //choose minor time interval: diff --git a/chart2/source/view/axes/Tickmarks_Dates.cxx b/chart2/source/view/axes/Tickmarks_Dates.cxx index b5177fe307b8..fa466b755824 100644 --- a/chart2/source/view/axes/Tickmarks_Dates.cxx +++ b/chart2/source/view/axes/Tickmarks_Dates.cxx @@ -82,8 +82,8 @@ void DateTickFactory::getAllTicks( ::std::vector< ::std::vector< TickInfo > >& r Date aNull(m_aScale.NullDate); - Date aDate = aNull + ::rtl::math::approxFloor(m_aScale.Minimum); - Date aMaxDate = aNull + ::rtl::math::approxFloor(m_aScale.Maximum); + Date aDate = aNull + static_cast<long>(::rtl::math::approxFloor(m_aScale.Minimum)); + Date aMaxDate = aNull + static_cast<long>(::rtl::math::approxFloor(m_aScale.Maximum)); uno::Reference< chart2::XScaling > xScaling(m_aScale.Scaling); uno::Reference< chart2::XScaling > xInverseScaling(m_xInverseScaling); @@ -125,7 +125,7 @@ void DateTickFactory::getAllTicks( ::std::vector< ::std::vector< TickInfo > >& r } //create minor date tickinfos - aDate = aNull + ::rtl::math::approxFloor(m_aScale.Minimum); + aDate = aNull + static_cast<long>(::rtl::math::approxFloor(m_aScale.Minimum)); while( aDate<= aMaxDate ) { if( bShifted && aDate==aMaxDate ) diff --git a/chart2/source/view/charttypes/VSeriesPlotter.cxx b/chart2/source/view/charttypes/VSeriesPlotter.cxx index d245d44365ae..906ccae3ccda 100755..100644 --- a/chart2/source/view/charttypes/VSeriesPlotter.cxx +++ b/chart2/source/view/charttypes/VSeriesPlotter.cxx @@ -1204,11 +1204,11 @@ long VSeriesPlotter::calculateTimeResolutionOnXAxis() aNullDate = m_apNumberFormatterWrapper->getNullDate(); if( aIt!=aEnd ) { - Date aPrevious(aNullDate); aPrevious+=rtl::math::approxFloor(aIt->fValue); + Date aPrevious(aNullDate); aPrevious+=static_cast<long>(rtl::math::approxFloor(aIt->fValue)); ++aIt; for(;aIt!=aEnd;++aIt) { - Date aCurrent(aNullDate); aCurrent+=rtl::math::approxFloor(aIt->fValue); + Date aCurrent(aNullDate); aCurrent+=static_cast<long>(rtl::math::approxFloor(aIt->fValue)); if( ::com::sun::star::chart::TimeUnit::YEAR == nRet ) { if( DateHelper::IsInSameYear( aPrevious, aCurrent ) ) diff --git a/chart2/source/view/main/VLegend.cxx b/chart2/source/view/main/VLegend.cxx index 12548e888fec..e7c681d80781 100755 --- a/chart2/source/view/main/VLegend.cxx +++ b/chart2/source/view/main/VLegend.cxx @@ -918,8 +918,8 @@ void VLegend::createShapes( RelativeSize aRelativeSize; if ((xLegendProp->getPropertyValue( C2U( "RelativeSize" )) >>= aRelativeSize)) { - aLegendSize.Width = ::rtl::math::approxCeil( aRelativeSize.Primary * rPageSize.Width ); - aLegendSize.Height = ::rtl::math::approxCeil( aRelativeSize.Secondary * rPageSize.Height ); + aLegendSize.Width = static_cast<sal_Int32>( ::rtl::math::approxCeil( aRelativeSize.Primary * rPageSize.Width ) ); //i117185 + aLegendSize.Height = static_cast<sal_Int32>( ::rtl::math::approxCeil( aRelativeSize.Secondary * rPageSize.Height ) ); //i117185 } else eExpansion = ::com::sun::star::chart::ChartLegendExpansion_HIGH; diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx index 27845bbc50cf..e2c863dace7d 100644 --- a/sc/inc/compiler.hxx +++ b/sc/inc/compiler.hxx @@ -361,6 +361,12 @@ public: static void CheckTabQuotes( String& aTabName, const formula::FormulaGrammar::AddressConvention eConv = formula::FormulaGrammar::CONV_OOO ); + /** Analyzes a string for a 'Doc'#Tab construct, or 'Do''c'#Tab etc.. + + @returns the position of the unquoted # hash mark in 'Doc'#Tab, or + STRING_NOTFOUND if none. */ + static xub_StrLen GetDocTabPos( const String& rString ); + static sal_Bool EnQuote( String& rStr ); sal_Unicode GetNativeAddressSymbol( Convention::SpecialSymbolType eType ) const; diff --git a/sc/inc/dbcolect.hxx b/sc/inc/dbcolect.hxx index 2398a142ee4e..32eeb2d65353 100644 --- a/sc/inc/dbcolect.hxx +++ b/sc/inc/dbcolect.hxx @@ -2,7 +2,7 @@ * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2000, 2011 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * @@ -44,7 +44,7 @@ class ScDocument; class ScDBData : public ScDataObject, public ScRefreshTimer { - +friend class ScDBCollection; private: // DBParam String aName; @@ -219,6 +219,7 @@ public: virtual sal_Bool IsEqual(ScDataObject* pKey1, ScDataObject* pKey2) const; ScDBData* GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, sal_Bool bStartOnly) const; ScDBData* GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const; + ScDBData* GetFilterDBAtTable(SCTAB nTab) const; sal_Bool SearchName( const String& rName, sal_uInt16& rIndex ) const; diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 3786b6b850b0..ecbd73e6cd4e 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -2,7 +2,7 @@ * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2000, 2011 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * @@ -505,7 +505,7 @@ public: ScDBData* GetDBAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, sal_Bool bStartOnly = sal_False) const; ScDBData* GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2) const; - + ScDBData* GetFilterDBAtTable(SCTAB nTab) const; //UNUSED2008-05 ScRangeData* GetRangeAtCursor(SCCOL nCol, SCROW nRow, SCTAB nTab, //UNUSED2008-05 sal_Bool bStartOnly = sal_False) const; SC_DLLPUBLIC ScRangeData* GetRangeAtBlock( const ScRange& rBlock, String* pName=NULL ) const; diff --git a/sc/inc/docuno.hxx b/sc/inc/docuno.hxx index e152b4a88f97..f213806762d8 100644 --- a/sc/inc/docuno.hxx +++ b/sc/inc/docuno.hxx @@ -129,7 +129,7 @@ public: ScDocument* GetDocument() const; SfxObjectShell* GetEmbeddedObject() const; - void UpdateAllRowHeights( const ScMarkData* pTabMark = NULL ); + void UpdateAllRowHeights( const ScMarkData* pTabMark = NULL, bool bCalcOutputFactor = false ); void BeforeXMLLoading(); void AfterXMLLoading(sal_Bool bRet); diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx index 8cbc6aa8e16a..5890ca847c08 100644 --- a/sc/inc/dpobject.hxx +++ b/sc/inc/dpobject.hxx @@ -116,6 +116,7 @@ private: SC_DLLPRIVATE void CreateOutput(); sal_Bool bRefresh; long mnCacheId; + bool mbCreatingTableData; public: // Wang Xu Ming -- 2009-8-17 @@ -152,7 +153,7 @@ public: void SetHeaderLayout(bool bUseGrid); bool GetHeaderLayout() const; - void SetSheetDesc(const ScSheetSourceDesc& rDesc); + void SetSheetDesc(const ScSheetSourceDesc& rDesc, bool bFromRefUpdate = false); void SetImportDesc(const ScImportSourceDesc& rDesc); void SetServiceData(const ScDPServiceDesc& rDesc); diff --git a/sc/inc/dpsave.hxx b/sc/inc/dpsave.hxx index bd84e599d984..b5c36e9d2f72 100644 --- a/sc/inc/dpsave.hxx +++ b/sc/inc/dpsave.hxx @@ -46,6 +46,7 @@ namespace com { namespace sun { namespace star { namespace sheet { class ScDPDimensionSaveData; class ScDPTableData; +class ScDPObject; // -------------------------------------------------------------------- // @@ -272,6 +273,7 @@ public: SC_DLLPUBLIC ScDPDimensionSaveData* GetDimensionData(); // create if not there void SetDimensionData( const ScDPDimensionSaveData* pNew ); // copied void BuildAllDimensionMembers(ScDPTableData* pData); + void BuildAllDimensionMembersFromSource(ScDPObject* pDPObj); /** * Check whether a dimension has one or more invisible members. diff --git a/sc/inc/externalrefmgr.hxx b/sc/inc/externalrefmgr.hxx index 818920885493..3e78232db55a 100644 --- a/sc/inc/externalrefmgr.hxx +++ b/sc/inc/externalrefmgr.hxx @@ -257,8 +257,6 @@ public: void getAllTableNames(sal_uInt16 nFileId, ::std::vector<String>& rTabNames) const; SCsTAB getTabSpan( sal_uInt16 nFileId, const String& rStartTabName, const String& rEndTabName ) const; void getAllNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const; - bool hasCacheTable(sal_uInt16 nFileId, const String& rTabName) const; - size_t getCacheTableCount(sal_uInt16 nFileId) const; /** * Set all tables of a document as referenced, used only during @@ -508,8 +506,6 @@ public: */ void getAllCachedNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const; - bool hasCacheTable(sal_uInt16 nFileId, const String& rTabName) const; - size_t getCacheTableCount(sal_uInt16 nFileId) const; sal_uInt16 getExternalFileCount() const; /** @@ -646,6 +642,11 @@ public: void resetSrcFileData(const String& rBaseFileUrl); /** + * Replace the original URL wirh the real URL that was generated from the relative URL. + */ + void updateAbsAfterLoad(); + + /** * Stop tracking a specific formula cell. * * @param pCell pointer to cell that formerly contained external diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index b51cc084594d..5ac110373257 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -2,7 +2,7 @@ * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2000, 2011 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * @@ -684,6 +684,7 @@ public: /// @return the index of the last changed row (flags and row height, auto pagebreak is ignored). SCROW GetLastChangedRow() const; + sal_Bool IsDataFiltered() const; sal_uInt8 GetColFlags( SCCOL nCol ) const; sal_uInt8 GetRowFlags( SCROW nRow ) const; diff --git a/sc/inc/token.hxx b/sc/inc/token.hxx index 13a8038a4109..28cefeec8554 100644 --- a/sc/inc/token.hxx +++ b/sc/inc/token.hxx @@ -198,14 +198,14 @@ public: ScExternalSingleRefToken( const ScExternalSingleRefToken& r ); virtual ~ScExternalSingleRefToken(); - virtual sal_uInt16 GetIndex() const; + virtual sal_uInt16 GetIndex() const; virtual const String& GetString() const; virtual const ScSingleRefData& GetSingleRef() const; - virtual ScSingleRefData& GetSingleRef(); - virtual void CalcAbsIfRel( const ScAddress& ); - virtual void CalcRelFromAbs( const ScAddress& ); + virtual ScSingleRefData& GetSingleRef(); + virtual void CalcAbsIfRel( const ScAddress& ); + virtual void CalcRelFromAbs( const ScAddress& ); virtual sal_Bool operator==( const formula::FormulaToken& rToken ) const; - virtual FormulaToken* Clone() const { return new ScExternalSingleRefToken(*this); } + virtual FormulaToken* Clone() const { return new ScExternalSingleRefToken(*this); } }; @@ -220,20 +220,21 @@ private: public: ScExternalDoubleRefToken( sal_uInt16 nFileId, const String& rTabName, const ScComplexRefData& r ); ScExternalDoubleRefToken( const ScExternalDoubleRefToken& r ); + explicit ScExternalDoubleRefToken( const ScExternalSingleRefToken& r ); virtual ~ScExternalDoubleRefToken(); - virtual sal_uInt16 GetIndex() const; - virtual const String& GetString() const; - virtual const ScSingleRefData& GetSingleRef() const; - virtual ScSingleRefData& GetSingleRef(); - virtual const ScSingleRefData& GetSingleRef2() const; - virtual ScSingleRefData& GetSingleRef2(); - virtual const ScComplexRefData& GetDoubleRef() const; - virtual ScComplexRefData& GetDoubleRef(); - virtual void CalcAbsIfRel( const ScAddress& ); - virtual void CalcRelFromAbs( const ScAddress& ); + virtual sal_uInt16 GetIndex() const; + virtual const String& GetString() const; + virtual const ScSingleRefData& GetSingleRef() const; + virtual ScSingleRefData& GetSingleRef(); + virtual const ScSingleRefData& GetSingleRef2() const; + virtual ScSingleRefData& GetSingleRef2(); + virtual const ScComplexRefData& GetDoubleRef() const; + virtual ScComplexRefData& GetDoubleRef(); + virtual void CalcAbsIfRel( const ScAddress& ); + virtual void CalcRelFromAbs( const ScAddress& ); virtual sal_Bool operator==( const formula::FormulaToken& rToken ) const; - virtual FormulaToken* Clone() const { return new ScExternalDoubleRefToken(*this); } + virtual FormulaToken* Clone() const { return new ScExternalDoubleRefToken(*this); } }; diff --git a/sc/source/core/data/cell2.cxx b/sc/source/core/data/cell2.cxx index e4631dde2d9a..23b9934564b9 100644 --- a/sc/source/core/data/cell2.cxx +++ b/sc/source/core/data/cell2.cxx @@ -990,6 +990,10 @@ void ScFormulaCell::UpdateReference(UpdateRefMode eUpdateRefMode, pUndoDoc->PutCell( aUndoPos, pFCell ); } } + // #i116833# If the formula is changed, always invalidate the stream (even if the result is the same). + // If the formula is moved, the change is recognized separately. + if (bValChanged && pDocument->IsStreamValid(aPos.Tab())) + pDocument->SetStreamValid(aPos.Tab(), sal_False); bValChanged = sal_False; if ( pRangeData ) { // Replace shared formula with own formula diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index abc82c005408..db48b58a169a 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -244,9 +244,16 @@ long ScColumn::GetNeededSize( SCROW nRow, OutputDevice* pDev, else bBreak = ((const SfxBoolItem&)pPattern->GetItem(ATTR_LINEBREAK)).GetValue(); - if (pCell->HasValueData()) - // Cell has a value. Disable line break. - bBreak = false; + SvNumberFormatter* pFormatter = pDocument->GetFormatTable(); + sal_uLong nFormat = pPattern->GetNumberFormat( pFormatter, pCondSet ); + // #i111387# #o11817313# disable automatic line breaks only for "General" number format + if ( bBreak && pCell->HasValueData() && ( nFormat % SV_COUNTRY_LANGUAGE_OFFSET ) == 0 ) + { + // also take formula result type into account for number format + if ( pCell->GetCellType() != CELLTYPE_FORMULA || + ( static_cast<ScFormulaCell*>(pCell)->GetStandardFormat(*pFormatter, nFormat) % SV_COUNTRY_LANGUAGE_OFFSET ) == 0 ) + bBreak = false; + } // get other attributes from pattern and conditional formatting @@ -332,8 +339,6 @@ long ScColumn::GetNeededSize( SCROW nRow, OutputDevice* pDev, { String aValStr; Color* pColor; - SvNumberFormatter* pFormatter = pDocument->GetFormatTable(); - sal_uLong nFormat = pPattern->GetNumberFormat( pFormatter, pCondSet ); ScCellFormat::GetString( pCell, nFormat, aValStr, &pColor, *pFormatter, sal_True, rOptions.bFormula, ftCheck ); @@ -497,8 +502,6 @@ long ScColumn::GetNeededSize( SCROW nRow, OutputDevice* pDev, else { Color* pColor; - SvNumberFormatter* pFormatter = pDocument->GetFormatTable(); - sal_uLong nFormat = pPattern->GetNumberFormat( pFormatter, pCondSet ); String aString; ScCellFormat::GetString( pCell, nFormat, aString, &pColor, *pFormatter, diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx index 44f7e6722d69..e0242ab90305 100644 --- a/sc/source/core/data/documen2.cxx +++ b/sc/source/core/data/documen2.cxx @@ -447,7 +447,12 @@ ScDocument::~ScDocument() delete pChangeViewSettings; // und weg damit delete pVirtualDevice_100th_mm; - delete pDPCollection; + if (pDPCollection) + { + pDPCollection->FreeAll(); + RemoveUnusedDPObjectCaches(); + delete pDPCollection; + } // delete the EditEngine before destroying the xPoolHelper delete pCacheFieldEditEngine; diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx index e249d7f3bf47..3f8742ee1d56 100644 --- a/sc/source/core/data/documen3.cxx +++ b/sc/source/core/data/documen3.cxx @@ -2,7 +2,7 @@ * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2000, 2011 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * @@ -197,6 +197,14 @@ ScDBData* ScDocument::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCOL nC return NULL; } +ScDBData* ScDocument::GetFilterDBAtTable(SCTAB nTab) const +{ + if (pDBCollection) + return pDBCollection->GetFilterDBAtTable(nTab); + else + return NULL; +} + ScDPCollection* ScDocument::GetDPCollection() { if (!pDPCollection) @@ -1359,6 +1367,20 @@ sal_Bool ScDocument::GetFilterEntries( SCCOL nEndCol; SCROW nEndRow; pDBData->GetArea( nAreaTab, nStartCol, nStartRow, nEndCol, nEndRow ); + + //Add for i85305 + SCCOL nTmpStartCol = nCol; + SCROW nTmpStartRow = nRow; + SCCOL nTmpEndCol = nCol; + SCROW nTmpEndRow = nRow; + GetDataArea( nTab, nTmpStartCol, nTmpStartRow, nTmpEndCol, nTmpEndRow, sal_False, false); + if (nTmpEndRow > nEndRow) + { + nEndRow = nTmpEndRow; + pDBData->SetArea(nAreaTab, nStartCol,nStartRow, nEndCol,nEndRow); + } + //End of i85305 + if (pDBData->HasHeader()) ++nStartRow; @@ -2098,7 +2120,7 @@ void ScDocument::RemoveDPObjectCache( long nID ) void ScDocument::RemoveUnusedDPObjectCaches() { - for ( std::list<ScDPTableDataCache*>::iterator iter = m_listDPObjectsCaches.begin(); iter!=m_listDPObjectsCaches.end(); iter++ ) + for ( std::list<ScDPTableDataCache*>::iterator iter = m_listDPObjectsCaches.begin(); iter!=m_listDPObjectsCaches.end(); ) { long nID = (*iter)->GetId(); sal_uInt16 nCount = GetDPCollection()->GetCount(); @@ -2111,10 +2133,11 @@ void ScDocument::RemoveUnusedDPObjectCaches() if ( i == nCount ) { ScDPTableDataCache* pCache = *iter; - m_listDPObjectsCaches.erase( iter ); + iter = m_listDPObjectsCaches.erase( iter ); delete pCache; continue; } + ++iter; } } diff --git a/sc/source/core/data/documen9.cxx b/sc/source/core/data/documen9.cxx index 7d66ece8c570..9ad38c171489 100755 --- a/sc/source/core/data/documen9.cxx +++ b/sc/source/core/data/documen9.cxx @@ -111,17 +111,21 @@ void ScDocument::TransferDrawPage(ScDocument* pSrcDoc, SCTAB nSrcPos, SCTAB nDes SdrObject* pOldObject = aIter.Next(); while (pOldObject) { - // #116235# - SdrObject* pNewObject = pOldObject->Clone(); - // SdrObject* pNewObject = pOldObject->Clone( pNewPage, pDrawLayer ); - pNewObject->SetModel(pDrawLayer); - pNewObject->SetPage(pNewPage); + // #i112034# do not copy internal objects (detective) and note captions + if ( pOldObject->GetLayer() != SC_LAYER_INTERN && !ScDrawLayer::IsNoteCaption( pOldObject ) ) + { + // #116235# + SdrObject* pNewObject = pOldObject->Clone(); + // SdrObject* pNewObject = pOldObject->Clone( pNewPage, pDrawLayer ); + pNewObject->SetModel(pDrawLayer); + pNewObject->SetPage(pNewPage); - pNewObject->NbcMove(Size(0,0)); - pNewPage->InsertObject( pNewObject ); + pNewObject->NbcMove(Size(0,0)); + pNewPage->InsertObject( pNewObject ); - if (pDrawLayer->IsRecording()) - pDrawLayer->AddCalcUndo( new SdrUndoInsertObj( *pNewObject ) ); + if (pDrawLayer->IsRecording()) + pDrawLayer->AddCalcUndo( new SdrUndoInsertObj( *pNewObject ) ); + } pOldObject = aIter.Next(); } @@ -210,6 +214,7 @@ void ScDocument::UpdateDrawDefaults() { SfxItemPool& rDrawPool = pDrawLayer->GetItemPool(); rDrawPool.SetPoolDefaultItem( SvxAutoKernItem( sal_True, EE_CHAR_PAIRKERNING ) ); + pDrawLayer->SetDrawingLayerPoolDefaults(); } } diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx index c4a256b48f54..431b86d328a0 100644 --- a/sc/source/core/data/dpobject.cxx +++ b/sc/source/core/data/dpobject.cxx @@ -175,7 +175,8 @@ ScDPObject::ScDPObject( ScDocument* pD ) : nHeaderRows( 0 ), mbHeaderLayout(false), bRefresh( sal_False ), // Wang Xu Ming - DataPilot migration - mnCacheId( -1) // Wang Xu Ming - DataPilot migration + mnCacheId( -1 ), // Wang Xu Ming - DataPilot migration + mbCreatingTableData( false ) { } @@ -197,7 +198,8 @@ ScDPObject::ScDPObject(const ScDPObject& r) : nHeaderRows( r.nHeaderRows ), mbHeaderLayout( r.mbHeaderLayout ), bRefresh( r.bRefresh ), // Wang Xu Ming - DataPilot migration - mnCacheId ( r.mnCacheId ) // Wang Xu Ming - DataPilot migration + mnCacheId ( r.mnCacheId ), // Wang Xu Ming - DataPilot migration + mbCreatingTableData( false ) { if (r.pSaveData) pSaveData = new ScDPSaveData(*r.pSaveData); @@ -272,7 +274,7 @@ void ScDPObject::SetOutRange(const ScRange& rRange) pOutput->SetPosition( rRange.aStart ); } -void ScDPObject::SetSheetDesc(const ScSheetSourceDesc& rDesc) +void ScDPObject::SetSheetDesc(const ScSheetSourceDesc& rDesc, bool bFromRefUpdate) { if ( pSheetDesc && rDesc == *pSheetDesc ) return; // nothing to do @@ -280,7 +282,7 @@ void ScDPObject::SetSheetDesc(const ScSheetSourceDesc& rDesc) DELETEZ( pImpDesc ); DELETEZ( pServDesc ); - delete pImpDesc; + delete pSheetDesc; pSheetDesc = new ScSheetSourceDesc(rDesc); // make valid QueryParam @@ -292,6 +294,8 @@ void ScDPObject::SetSheetDesc(const ScSheetSourceDesc& rDesc) pSheetDesc->aQueryParam.bHasHeader = sal_True; InvalidateSource(); // new source must be created + if (!bFromRefUpdate) + SetCacheId( -1 ); // #i116504# don't use the same cache ID for a different range (except reference update) } void ScDPObject::SetImportDesc(const ScImportSourceDesc& rDesc) @@ -306,6 +310,7 @@ void ScDPObject::SetImportDesc(const ScImportSourceDesc& rDesc) pImpDesc = new ScImportSourceDesc(rDesc); InvalidateSource(); // new source must be created + SetCacheId( -1 ); } void ScDPObject::SetServiceData(const ScDPServiceDesc& rDesc) @@ -416,8 +421,12 @@ void ScDPObject::CreateOutput() ScDPTableData* ScDPObject::GetTableData() { - if (!mpTableData) + if (!mpTableData && !mbCreatingTableData) { + // #i117239# While filling the cache, mpTableData is still null. + // Prevent nested calls from GetPivotData and similar functions. + mbCreatingTableData = true; + shared_ptr<ScDPTableData> pData; if ( pImpDesc ) { @@ -453,6 +462,8 @@ ScDPTableData* ScDPObject::GetTableData() // End Comments mpTableData = pData; // after SetCacheId + + mbCreatingTableData = false; } return mpTableData.get(); @@ -482,16 +493,19 @@ void ScDPObject::CreateObjects() DBG_ASSERT( !pServDesc, "DPSource could not be created" ); ScDPTableData* pData = GetTableData(); - ScDPSource* pSource = new ScDPSource( pData ); - xSource = pSource; - - if ( pSaveData && bRefresh ) + if ( pData ) // nested GetTableData calls may return NULL { - pSaveData->Refresh( xSource ); - bRefresh = sal_False; + ScDPSource* pSource = new ScDPSource( pData ); + xSource = pSource; + + if ( pSaveData && bRefresh ) + { + pSaveData->Refresh( xSource ); + bRefresh = sal_False; + } } } - if (pSaveData ) + if ( xSource.is() && pSaveData ) pSaveData->WriteToSource( xSource ); } else if (bSettingsChanged) @@ -630,9 +644,12 @@ void ScDPObject::BuildAllDimensionMembers() return; // #i111857# don't always create empty mpTableData for external service. - // Ideally, xSource should be used instead of mpTableData. + // #163781# Initialize all members from xSource instead. if (pServDesc) + { + pSaveData->BuildAllDimensionMembersFromSource( this ); return; + } pSaveData->BuildAllDimensionMembers(GetTableData()); } @@ -739,7 +756,7 @@ void ScDPObject::UpdateReference( UpdateRefMode eUpdateRefMode, if (aNewDesc.aQueryParam.GetEntry(i).bDoQuery) aNewDesc.aQueryParam.GetEntry(i).nField += nDiffX; - SetSheetDesc( aNewDesc ); // allocates new pSheetDesc + SetSheetDesc( aNewDesc, true ); // allocates new pSheetDesc } } } @@ -767,7 +784,7 @@ void ScDPObject::WriteRefsTo( ScDPObject& r ) const { r.SetOutRange( aOutRange ); if ( pSheetDesc ) - r.SetSheetDesc( *pSheetDesc ); + r.SetSheetDesc( *pSheetDesc, true ); } void ScDPObject::GetPositionData(const ScAddress& rPos, DataPilotTablePositionData& rPosData) @@ -1043,6 +1060,11 @@ void ScDPObject::GetHeaderPositionData(const ScAddress& rPos, DataPilotTableHead sal_Bool ScDPObject::GetPivotData( ScDPGetPivotDataField& rTarget, const std::vector< ScDPGetPivotDataField >& rFilters ) { + // #i117239# Exit with an error if called from creating the cache for this object + // (don't create an empty pOutput object) + if (mbCreatingTableData) + return sal_False; + CreateOutput(); // create xSource and pOutput if not already done return pOutput->GetPivotData( rTarget, rFilters ); diff --git a/sc/source/core/data/dpsave.cxx b/sc/source/core/data/dpsave.cxx index 100db65df4b7..24df9f90b31f 100644 --- a/sc/source/core/data/dpsave.cxx +++ b/sc/source/core/data/dpsave.cxx @@ -34,6 +34,7 @@ #include "dpsave.hxx" #include "dpdimsave.hxx" +#include "dpobject.hxx" // GetMemberNames used in BuildAllDimensionMembersFromSource #include "miscuno.hxx" #include "scerrors.hxx" #include "unonames.hxx" @@ -874,6 +875,7 @@ ScDPSaveDimension* ScDPSaveData::GetDimensionByName(const String& rName) } ScDPSaveDimension* pNew = new ScDPSaveDimension( rName, sal_False ); aDimList.Insert( pNew, LIST_APPEND ); + mbDimensionMembersBuilt = false; // BuildAllDimensionMembers only handles existing entries in aDimList return pNew; } @@ -900,6 +902,7 @@ ScDPSaveDimension* ScDPSaveData::GetNewDimensionByName(const String& rName) } ScDPSaveDimension* pNew = new ScDPSaveDimension( rName, sal_False ); aDimList.Insert( pNew, LIST_APPEND ); + mbDimensionMembersBuilt = false; // BuildAllDimensionMembers only handles existing entries in aDimList return pNew; } @@ -911,6 +914,7 @@ ScDPSaveDimension* ScDPSaveData::GetDataLayoutDimension() ScDPSaveDimension* pNew = new ScDPSaveDimension( String(), sal_True ); aDimList.Insert( pNew, LIST_APPEND ); + mbDimensionMembersBuilt = false; // BuildAllDimensionMembers only handles existing entries in aDimList return pNew; } @@ -935,6 +939,7 @@ ScDPSaveDimension* ScDPSaveData::DuplicateDimension(const String& rName) ScDPSaveDimension* pNew = new ScDPSaveDimension( *pOld ); pNew->SetDupFlag( sal_True ); aDimList.Insert( pNew, LIST_APPEND ); + mbDimensionMembersBuilt = false; // BuildAllDimensionMembers only handles existing entries in aDimList return pNew; } @@ -958,6 +963,7 @@ ScDPSaveDimension& ScDPSaveData::DuplicateDimension( const ScDPSaveDimension& rD ScDPSaveDimension* pNew = new ScDPSaveDimension( rDim ); pNew->SetDupFlag( sal_True ); aDimList.Insert( pNew, LIST_APPEND ); + mbDimensionMembersBuilt = false; // BuildAllDimensionMembers only handles existing entries in aDimList return *pNew; } @@ -1275,6 +1281,63 @@ void ScDPSaveData::BuildAllDimensionMembers(ScDPTableData* pData) mbDimensionMembersBuilt = true; } +void ScDPSaveData::BuildAllDimensionMembersFromSource( ScDPObject* pDPObj ) +{ + // Initialize all members like BuildAllDimensionMembers, but access only the DataPilotSource, not the table data. + // This could also replace BuildAllDimensionMembers, but the performance implications still have to be checked. + // ScDPObject is used for the helper method GetMemberNames. + + if (mbDimensionMembersBuilt) + return; + + uno::Reference<sheet::XDimensionsSupplier> xSource = pDPObj->GetSource(); + uno::Reference<container::XNameAccess> xDimsName = xSource->getDimensions(); + // GetMemberNames uses the dimension index from getElementNames + uno::Sequence<OUString> aDimNames = xDimsName->getElementNames(); + + // First, build a dimension name-to-index map. + typedef hash_map<OUString, long, ::rtl::OUStringHash> NameIndexMap; + NameIndexMap aMap; + long nColCount = aDimNames.getLength(); + for (long i = 0; i < nColCount; ++i) + aMap.insert( NameIndexMap::value_type(aDimNames[i], i) ); + + NameIndexMap::const_iterator itrEnd = aMap.end(); + + sal_uInt32 n = aDimList.Count(); + for (sal_uInt32 i = 0; i < n; ++i) + { + ScDPSaveDimension* pDim = static_cast<ScDPSaveDimension*>(aDimList.GetObject(i)); + const String& rDimName = pDim->GetName(); + if (!rDimName.Len()) + // empty dimension name. It must be data layout. + continue; + + NameIndexMap::const_iterator itr = aMap.find(rDimName); + if (itr == itrEnd) + // dimension name not in the data. This should never happen! + continue; + + long nDimIndex = itr->second; + uno::Sequence<OUString> aMemberNames; + pDPObj->GetMemberNames( nDimIndex, aMemberNames ); + sal_Int32 nMemberCount = aMemberNames.getLength(); + for (sal_Int32 j = 0; j < nMemberCount; ++j) + { + String aMemName = aMemberNames[j]; + if (pDim->GetExistingMemberByName(aMemName)) + // this member instance already exists. nothing to do. + continue; + + auto_ptr<ScDPSaveMember> pNewMember(new ScDPSaveMember(aMemName)); + pNewMember->SetIsVisible(true); + pDim->AddMember(pNewMember.release()); + } + } + + mbDimensionMembersBuilt = true; +} + bool ScDPSaveData::HasInvisibleMember(const OUString& rDimName) const { ScDPSaveDimension* pDim = GetExistingDimensionByName(rDimName); diff --git a/sc/source/core/data/dpsdbtab.cxx b/sc/source/core/data/dpsdbtab.cxx index f0e060e8cc7d..977be2e182a9 100644 --- a/sc/source/core/data/dpsdbtab.cxx +++ b/sc/source/core/data/dpsdbtab.cxx @@ -214,7 +214,7 @@ ScDatabaseDPData::ScDatabaseDPData( ScDocument* pDoc, const ScImportSourceDesc& rImport, long nCacheId /*=-1 */ ) : ScDPTableData(pDoc, rImport.GetCacheId( pDoc, nCacheId) ), - aCacheTable( pDoc, rImport.GetCacheId( pDoc, nCacheId)) + aCacheTable( pDoc, GetCacheId() ) // base class ID is initialized with the GetCacheId call above { } diff --git a/sc/source/core/data/dpshttab.cxx b/sc/source/core/data/dpshttab.cxx index 33ce84cc94c2..6c376209e035 100644 --- a/sc/source/core/data/dpshttab.cxx +++ b/sc/source/core/data/dpshttab.cxx @@ -67,7 +67,7 @@ ScSheetDPData::ScSheetDPData( ScDocument* pD, const ScSheetSourceDesc& rDesc , l pSpecial(NULL), bIgnoreEmptyRows( sal_False ), bRepeatIfEmpty(sal_False), - aCacheTable( pD, rDesc.GetCacheId( pD, nCacheId)) + aCacheTable( pD, GetCacheId() ) // base class ID is initialized with the GetCacheId call above { SCSIZE nEntryCount( aQuery.GetEntryCount()); pSpecial = new sal_Bool[nEntryCount]; @@ -291,12 +291,10 @@ sal_uLong ScSheetSourceDesc::CheckValidate( ScDocument* pDoc ) const ScRange aSrcRange( aSourceRange); if ( !pDoc ) return STR_ERR_DATAPILOTSOURCE; - for(sal_uInt16 i= aSrcRange.aStart.Col();i <= aSrcRange.aEnd.Col();i++) - { - if ( pDoc->IsBlockEmpty( aSrcRange.aStart.Tab(), - i, aSrcRange.aStart.Row(),i, aSrcRange.aStart.Row())) - return STR_PIVOT_FIRSTROWEMPTYERR; - } + + // #i116457# Empty column titles were allowed before 3.3, and might be useful for hidden columns with annotations. + // Be compatible with 3.2: Allow empty titles, create columns with empty names, hide them in the dialogs. + if( pDoc->IsBlockEmpty( aSrcRange.aStart.Tab(), aSrcRange.aStart.Col(), aSrcRange.aStart.Row()+1, aSrcRange.aEnd.Col(), aSrcRange.aEnd.Row() ) ) { return STR_PIVOT_ONLYONEROWERR; diff --git a/sc/source/core/data/dptablecache.cxx b/sc/source/core/data/dptablecache.cxx index 3cf40a7ab6dc..4a80f742769b 100644 --- a/sc/source/core/data/dptablecache.cxx +++ b/sc/source/core/data/dptablecache.cxx @@ -210,13 +210,13 @@ ScDPItemData::ScDPItemData( ScDocument* pDoc, SCROW nRow, sal_uInt16 nCol, sal_u else if ( pDoc->HasValueData( nCol, nRow, nDocTab ) ) { double fVal = pDoc->GetValue(ScAddress(nCol, nRow, nDocTab)); + nNumFormat = pDoc->GetNumberFormat( ScAddress( nCol, nRow, nDocTab ) ); sal_uLong nFormat = NUMBERFORMAT_NUMBER; if ( pFormatter ) - nFormat = pFormatter->GetType( pDoc->GetNumberFormat( ScAddress( nCol, nRow, nDocTab ) ) ); + nFormat = pFormatter->GetType( nNumFormat ); aString = aDocStr; fValue = fVal; mbFlag |= MK_VAL|MK_DATA; - nNumFormat = pDoc->GetNumberFormat( ScAddress( nCol, nRow, nDocTab ) ); lcl_isDate( nFormat ) ? ( mbFlag |= MK_DATE ) : (mbFlag &= ~MK_DATE); } else if ( pDoc->HasData( nCol,nRow, nDocTab ) ) @@ -938,23 +938,28 @@ void ScDPTableDataCache::AddLabel(ScDPItemData *pData) //reset name if needed String strNewName = pData->aString; - sal_Bool bFound = sal_False; - long nIndex = 1; - do + + // #i116457# don't modify empty column titles + if ( strNewName.Len() ) { - for ( long i= mrLabelNames.size()-1; i>=0; i-- ) + sal_Bool bFound = sal_False; + long nIndex = 1; + do { - if( mrLabelNames[i]->aString == strNewName ) + for ( long i= mrLabelNames.size()-1; i>=0; i-- ) { - strNewName = pData->aString; - strNewName += String::CreateFromInt32( nIndex ); - nIndex ++ ; - bFound = sal_True; + if( mrLabelNames[i]->aString == strNewName ) + { + strNewName = pData->aString; + strNewName += String::CreateFromInt32( nIndex ); + nIndex ++ ; + bFound = sal_True; + } } + bFound = !bFound; } - bFound = !bFound; + while ( !bFound ); } - while ( !bFound ); pData->aString = strNewName; mrLabelNames.push_back( pData ); @@ -1021,10 +1026,15 @@ sal_uLong ScDPTableDataCache::GetNumberFormat( long nDim ) const { if ( nDim >= mnColumnCount ) return 0; - if ( mpTableDataValues[nDim].size()==0 ) - return 0; - else - return mpTableDataValues[nDim][0]->nNumFormat; + + // #i113411# take the number format from the first value entry + size_t nSize = mpTableDataValues[nDim].size(); + size_t nPos = 0; + while ( nPos < nSize && mpTableDataValues[nDim][nPos]->GetType() != SC_VALTYPE_VALUE ) + ++nPos; + if ( nPos < nSize ) + return mpTableDataValues[nDim][nPos]->nNumFormat; + return 0; } sal_Bool ScDPTableDataCache::IsDateDimension( long nDim ) const diff --git a/sc/source/core/data/drwlayer.cxx b/sc/source/core/data/drwlayer.cxx index d91c6a03eb3a..80cac5616f33 100644 --- a/sc/source/core/data/drwlayer.cxx +++ b/sc/source/core/data/drwlayer.cxx @@ -434,16 +434,20 @@ void ScDrawLayer::ScCopyPage( sal_uInt16 nOldPos, sal_uInt16 nNewPos, sal_Bool b SdrObject* pOldObject = aIter.Next(); while (pOldObject) { - // #116235# - SdrObject* pNewObject = pOldObject->Clone(); - //SdrObject* pNewObject = pOldObject->Clone( pNewPage, this ); - pNewObject->SetModel(this); - pNewObject->SetPage(pNewPage); - - pNewObject->NbcMove(Size(0,0)); - pNewPage->InsertObject( pNewObject ); - if (bRecording) - AddCalcUndo( new SdrUndoInsertObj( *pNewObject ) ); + // #i112034# do not copy internal objects (detective) and note captions + if ( pOldObject->GetLayer() != SC_LAYER_INTERN && !IsNoteCaption( pOldObject ) ) + { + // #116235# + SdrObject* pNewObject = pOldObject->Clone(); + //SdrObject* pNewObject = pOldObject->Clone( pNewPage, this ); + pNewObject->SetModel(this); + pNewObject->SetPage(pNewPage); + + pNewObject->NbcMove(Size(0,0)); + pNewPage->InsertObject( pNewObject ); + if (bRecording) + AddCalcUndo( new SdrUndoInsertObj( *pNewObject ) ); + } pOldObject = aIter.Next(); } diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index 3b10e51355e8..83c5412d08c3 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -2,7 +2,7 @@ * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2000, 2011 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * @@ -59,6 +59,7 @@ #include "sheetevents.hxx" #include "globstr.hrc" #include "segmenttree.hxx" +#include "dbcolect.hxx" #include <math.h> @@ -2487,8 +2488,22 @@ sal_uLong ScTable::GetScaledRowHeight( SCROW nStartRow, SCROW nEndRow, double fS { if (nLastRow > nEndRow) nLastRow = nEndRow; - sal_uInt32 nThisHeight = mpRowHeights->getSumValue(nRow, nLastRow); - nHeight += static_cast<sal_uLong>(nThisHeight * fScale); + + // #i117315# can't use getSumValue, because individual values must be rounded + while (nRow <= nLastRow) + { + ScFlatUInt16RowSegments::RangeData aData; + if (!mpRowHeights->getRangeData(nRow, aData)) + return nHeight; // shouldn't happen + + SCROW nSegmentEnd = std::min( nLastRow, aData.mnRow2 ); + + // round-down a single height value, multiply resulting (pixel) values + sal_uLong nOneHeight = static_cast<sal_uLong>( aData.mnValue * fScale ); + nHeight += nOneHeight * ( nSegmentEnd + 1 - nRow ); + + nRow = nSegmentEnd + 1; + } } nRow = nLastRow + 1; } @@ -2772,6 +2787,19 @@ void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, bool bShow) DecRecalcLevel(); } +sal_Bool ScTable::IsDataFiltered() const +{ + sal_Bool bAnyQuery = sal_False; + ScDBData* pDBData = pDocument->GetFilterDBAtTable(nTab); + if ( pDBData ) + { + ScQueryParam aParam; + pDBData->GetQueryParam( aParam ); + if ( aParam.GetEntry(0).bDoQuery ) + bAnyQuery = sal_True; + } + return bAnyQuery; +} void ScTable::SetColFlags( SCCOL nCol, sal_uInt8 nNewFlags ) { diff --git a/sc/source/core/data/table4.cxx b/sc/source/core/data/table4.cxx index 5c7c872f6c64..ba68fa53b13f 100644 --- a/sc/source/core/data/table4.cxx +++ b/sc/source/core/data/table4.cxx @@ -2,7 +2,7 @@ * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2000, 2011 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * @@ -78,6 +78,7 @@ #include "rangenam.hxx" #include "docpool.hxx" #include "progress.hxx" +#include "segmenttree.hxx" #include <math.h> @@ -198,7 +199,7 @@ void ScTable::FillAnalyse( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, rMinDigits = 0; rListData = NULL; rCmd = FILL_SIMPLE; - if ( nScFillModeMouseModifier & KEY_MOD1 ) + if (( nScFillModeMouseModifier & KEY_MOD1 )||IsDataFiltered()) //i89232 return ; // Ctrl-Taste: Copy SCCOL nAddX; @@ -567,11 +568,14 @@ void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, sal_uLong nIMin = nIStart; sal_uLong nIMax = nIEnd; PutInOrder(nIMin,nIMax); - if (bVertical) - DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), IDF_AUTOFILL); - else - DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, IDF_AUTOFILL); - + sal_Bool bHasFiltered = IsDataFiltered(); + if (!bHasFiltered) //modify for i89232 + { + if (bVertical) + DeleteArea(nCol1, static_cast<SCROW>(nIMin), nCol2, static_cast<SCROW>(nIMax), IDF_AUTOFILL); + else + DeleteArea(static_cast<SCCOL>(nIMin), nRow1, static_cast<SCCOL>(nIMax), nRow2, IDF_AUTOFILL); + } sal_uLong nProgress = rProgress.GetState(); // @@ -617,7 +621,7 @@ void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, pNewPattern = NULL; } - if ( bVertical && nISrcStart == nISrcEnd ) + if ( bVertical && nISrcStart == nISrcEnd && !bHasFiltered ) { // Attribute komplett am Stueck setzen if (pNewPattern || pSrcPattern != pDocument->GetDefPattern()) @@ -635,37 +639,44 @@ void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, break; // Schleife abbrechen } - if ( pSrcPattern != aCol[nCol].GetPattern( static_cast<SCROW>(nRow) ) ) + if ( !RowFiltered(nRow) ) { - // Vorlage auch uebernehmen - //! am AttrArray mit ApplyPattern zusammenfassen ?? - if ( pStyleSheet ) - aCol[nCol].ApplyStyle( static_cast<SCROW>(nRow), *pStyleSheet ); + if ( bHasFiltered ) + DeleteArea(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), + static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), IDF_AUTOFILL); - // ApplyPattern statt SetPattern um alte MergeFlags stehenzulassen - if ( pNewPattern ) - aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pNewPattern ); - else - aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pSrcPattern ); - } + if ( pSrcPattern != aCol[nCol].GetPattern( static_cast<SCROW>(nRow) ) ) + { + // Vorlage auch uebernehmen + //! am AttrArray mit ApplyPattern zusammenfassen ?? + if ( pStyleSheet ) + aCol[nCol].ApplyStyle( static_cast<SCROW>(nRow), *pStyleSheet ); - if (nAtSrc==nISrcEnd) - { - if ( nAtSrc != nISrcStart ) - { // mehr als eine Source-Zelle - nAtSrc = nISrcStart; + // ApplyPattern statt SetPattern um alte MergeFlags stehenzulassen + if ( pNewPattern ) + aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pNewPattern ); + else + aCol[nCol].ApplyPattern( static_cast<SCROW>(nRow), *pSrcPattern ); + } + + if (nAtSrc==nISrcEnd) + { + if ( nAtSrc != nISrcStart ) + { // mehr als eine Source-Zelle + nAtSrc = nISrcStart; + bGetPattern = sal_True; + } + } + else if (bPositive) + { + ++nAtSrc; + bGetPattern = sal_True; + } + else + { + --nAtSrc; bGetPattern = sal_True; } - } - else if (bPositive) - { - ++nAtSrc; - bGetPattern = sal_True; - } - else - { - --nAtSrc; - bGetPattern = sal_True; } if (rInner == nIEnd) break; @@ -733,7 +744,7 @@ void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, { sal_uLong nSource = nISrcStart; double nDelta; - if ( nScFillModeMouseModifier & KEY_MOD1 ) + if (( nScFillModeMouseModifier & KEY_MOD1 )||bHasFiltered) //i89232 nDelta = 0.0; else if ( bPositive ) nDelta = 1.0; @@ -750,6 +761,7 @@ void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ScBaseCell* pSrcCell = NULL; CellType eCellType = CELLTYPE_NONE; sal_Bool bIsOrdinalSuffix = sal_False; + sal_Bool bRowFiltered = sal_False; //i89232 rInner = nIStart; while (true) // #i53728# with "for (;;)" old solaris/x86 compiler mis-optimizes @@ -775,7 +787,7 @@ void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ((ScStringCell*)pSrcCell)->GetString( aValue ); else ((ScEditCell*)pSrcCell)->GetString( aValue ); - if ( !(nScFillModeMouseModifier & KEY_MOD1) ) + if ( !(nScFillModeMouseModifier & KEY_MOD1) && !bHasFiltered) //i89232 { nCellDigits = 0; // look at each source cell individually nHeadNoneTail = lcl_DecompValueString( @@ -794,92 +806,101 @@ void ScTable::FillAuto( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, else eCellType = CELLTYPE_NONE; } - switch (eCellType) + + //Modify for i89232 + bRowFiltered = mpFilteredRows->getValue(nRow); + + if (!bRowFiltered) { - case CELLTYPE_VALUE: - aCol[nCol].Insert(static_cast<SCROW>(nRow), new ScValueCell(nVal + nDelta)); - break; - case CELLTYPE_STRING: - case CELLTYPE_EDIT: - if ( nHeadNoneTail ) - { - // #i48009# with the "nStringValue+(long)nDelta" expression within the - // lcl_ValueString calls, gcc 3.4.1 makes wrong optimizations (ok in 3.4.3), - // so nNextValue is now calculated ahead. - sal_Int32 nNextValue = nStringValue+(sal_Int32)nDelta; + //End of i89232 - String aStr; - if ( nHeadNoneTail < 0 ) + switch (eCellType) + { + case CELLTYPE_VALUE: + aCol[nCol].Insert(static_cast<SCROW>(nRow), new ScValueCell(nVal + nDelta)); + break; + case CELLTYPE_STRING: + case CELLTYPE_EDIT: + if ( nHeadNoneTail ) { - aCol[nCol].Insert( static_cast<SCROW>(nRow), - lcl_getSuffixCell( pDocument, - nNextValue, nCellDigits, aValue, - eCellType, bIsOrdinalSuffix)); + // #i48009# with the "nStringValue+(long)nDelta" expression within the + // lcl_ValueString calls, gcc 3.4.1 makes wrong optimizations (ok in 3.4.3), + // so nNextValue is now calculated ahead. + sal_Int32 nNextValue = nStringValue+(sal_Int32)nDelta; + + String aStr; + if ( nHeadNoneTail < 0 ) + { + aCol[nCol].Insert( static_cast<SCROW>(nRow), + lcl_getSuffixCell( pDocument, + nNextValue, nCellDigits, aValue, + eCellType, bIsOrdinalSuffix)); + } + else + { + aStr = aValue; + aStr += lcl_ValueString( nNextValue, nCellDigits ); + aCol[nCol].Insert( static_cast<SCROW>(nRow), + new ScStringCell( aStr)); + } } else { - aStr = aValue; - aStr += lcl_ValueString( nNextValue, nCellDigits ); - aCol[nCol].Insert( static_cast<SCROW>(nRow), - new ScStringCell( aStr)); - } - } - else - { - ScAddress aDestPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), nTab ); - switch ( eCellType ) - { - case CELLTYPE_STRING: - case CELLTYPE_EDIT: - aCol[nCol].Insert( aDestPos.Row(), pSrcCell->CloneWithoutNote( *pDocument ) ); - break; - default: + ScAddress aDestPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), nTab ); + switch ( eCellType ) { - // added to avoid warnings + case CELLTYPE_STRING: + case CELLTYPE_EDIT: + aCol[nCol].Insert( aDestPos.Row(), pSrcCell->CloneWithoutNote( *pDocument ) ); + break; + default: + { + // added to avoid warnings + } } } + break; + case CELLTYPE_FORMULA : + FillFormula( nFormulaCounter, bFirst, + (ScFormulaCell*) pSrcCell, + static_cast<SCCOL>(nCol), + static_cast<SCROW>(nRow), (rInner == nIEnd) ); + if (nFormulaCounter - nActFormCnt > nMaxFormCnt) + nMaxFormCnt = nFormulaCounter - nActFormCnt; + break; + default: + { + // added to avoid warnings } - break; - case CELLTYPE_FORMULA : - FillFormula( nFormulaCounter, bFirst, - (ScFormulaCell*) pSrcCell, - static_cast<SCCOL>(nCol), - static_cast<SCROW>(nRow), (rInner == nIEnd) ); - if (nFormulaCounter - nActFormCnt > nMaxFormCnt) - nMaxFormCnt = nFormulaCounter - nActFormCnt; - break; - default: - { - // added to avoid warnings } - } - if (nSource==nISrcEnd) - { - if ( nSource != nISrcStart ) - { // mehr als eine Source-Zelle - nSource = nISrcStart; + if (nSource==nISrcEnd) + { + if ( nSource != nISrcStart ) + { // mehr als eine Source-Zelle + nSource = nISrcStart; + bGetCell = sal_True; + } + if ( !(nScFillModeMouseModifier & KEY_MOD1) && !bHasFiltered ) //i89232 + { + if ( bPositive ) + nDelta += 1.0; + else + nDelta -= 1.0; + } + nFormulaCounter = nActFormCnt; + bFirst = sal_False; + } + else if (bPositive) + { + ++nSource; bGetCell = sal_True; } - if ( !(nScFillModeMouseModifier & KEY_MOD1) ) + else { - if ( bPositive ) - nDelta += 1.0; - else - nDelta -= 1.0; + --nSource; + bGetCell = sal_True; } - nFormulaCounter = nActFormCnt; - bFirst = sal_False; - } - else if (bPositive) - { - ++nSource; - bGetCell = sal_True; - } - else - { - --nSource; - bGetCell = sal_True; } // Progress in der inneren Schleife nur bei teuren Zellen, @@ -978,6 +999,30 @@ String ScTable::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW n } else if ( eFillCmd == FILL_SIMPLE ) // Auffuellen mit Muster { + //Add for i89232 + if ((eFillDir == FILL_TO_BOTTOM)||(eFillDir == FILL_TO_TOP)) + { + long nBegin = 0; + long nEnd = 0; + if (nEndY > nRow1) + { + nBegin = nRow2+1; + nEnd = nEndY; + } + else + { + nBegin = nEndY; + nEnd = nRow1 -1; + } + long nNonFiltered = CountNonFilteredRows(nBegin, nEnd); + long nFiltered = nEnd + 1 - nBegin - nNonFiltered; + if (nIndex >0) + nIndex = nIndex - nFiltered; + else + nIndex = nIndex + nFiltered; + } + //End of i89232 + long nPosIndex = nIndex; while ( nPosIndex < 0 ) nPosIndex += nSrcCount; @@ -1008,7 +1053,7 @@ String ScTable::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW n ((ScStringCell*)pCell)->GetString( aValue ); else ((ScEditCell*)pCell)->GetString( aValue ); - if ( !(nScFillModeMouseModifier & KEY_MOD1) ) + if ( !(nScFillModeMouseModifier & KEY_MOD1) && !IsDataFiltered() ) //i89232 { sal_Int32 nVal; sal_uInt16 nCellDigits = 0; // look at each source cell individually @@ -1029,7 +1074,7 @@ String ScTable::GetAutoFillPreview( const ScRange& rSource, SCCOL nEndX, SCROW n { // dabei kann's keinen Ueberlauf geben... double nVal = ((ScValueCell*)pCell)->GetValue(); - if ( !(nScFillModeMouseModifier & KEY_MOD1) ) + if ( !(nScFillModeMouseModifier & KEY_MOD1) && !IsDataFiltered() ) //i89232 nVal += (double) nDelta; Color* pColor; diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx index 0ab37d167b01..0adef9f88348 100644 --- a/sc/source/core/inc/interpre.hxx +++ b/sc/source/core/inc/interpre.hxx @@ -696,6 +696,7 @@ double GetGamma(double x); double GetLogGamma(double x); double GetBeta(double fAlpha, double fBeta); double GetLogBeta(double fAlpha, double fBeta); +double GetBinomDistPMF(double x, double n, double p); //probability mass function void ScLogGamma(); void ScGamma(); void ScPhi(); diff --git a/sc/source/core/tool/address.cxx b/sc/source/core/tool/address.cxx index 7d9059184110..aff7a6ab21aa 100644 --- a/sc/source/core/tool/address.cxx +++ b/sc/source/core/tool/address.cxx @@ -1652,8 +1652,8 @@ void ScAddress::Format( String& r, sal_uInt16 nFlags, ScDocument* pDoc, // External Reference, same as in ScCompiler::MakeTabStr() if( aTabName.GetChar(0) == '\'' ) { // "'Doc'#Tab" - xub_StrLen nPos = ScGlobal::FindUnquoted( aTabName, SC_COMPILER_FILE_TAB_SEP); - if (nPos != STRING_NOTFOUND && nPos > 0 && aTabName.GetChar(nPos-1) == '\'') + xub_StrLen nPos = ScCompiler::GetDocTabPos( aTabName); + if (nPos != STRING_NOTFOUND) { aDocName = aTabName.Copy( 0, nPos + 1 ); aTabName.Erase( 0, nPos + 1 ); @@ -1735,8 +1735,8 @@ lcl_Split_DocTab( const ScDocument* pDoc, SCTAB nTab, // External reference, same as in ScCompiler::MakeTabStr() if ( rTabName.GetChar(0) == '\'' ) { // "'Doc'#Tab" - xub_StrLen nPos = ScGlobal::FindUnquoted( rTabName, SC_COMPILER_FILE_TAB_SEP); - if (nPos != STRING_NOTFOUND && nPos > 0 && rTabName.GetChar(nPos-1) == '\'') + xub_StrLen nPos = ScCompiler::GetDocTabPos( rTabName); + if (nPos != STRING_NOTFOUND) { rDocName = rTabName.Copy( 0, nPos + 1 ); rTabName.Erase( 0, nPos + 1 ); diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx index 3dd25801532f..31964eff34be 100644 --- a/sc/source/core/tool/compiler.cxx +++ b/sc/source/core/tool/compiler.cxx @@ -855,18 +855,14 @@ struct ConventionOOO_A1 : public Convention_A1 aString = ScGlobal::GetRscString(STR_NO_REF_TABLE); else { - if ( aString.GetChar(0) == '\'' ) - { // "'Doc'#Tab" - xub_StrLen nPos = ScGlobal::FindUnquoted( aString, SC_COMPILER_FILE_TAB_SEP); - if (nPos != STRING_NOTFOUND && nPos > 0 && aString.GetChar(nPos-1) == '\'') - { - aDoc = aString.Copy( 0, nPos + 1 ); - aString.Erase( 0, nPos + 1 ); - aDoc = INetURLObject::decode( aDoc, INET_HEX_ESCAPE, + // "'Doc'#Tab" + xub_StrLen nPos = ScCompiler::GetDocTabPos( aString); + if (nPos != STRING_NOTFOUND) + { + aDoc = aString.Copy( 0, nPos + 1 ); + aString.Erase( 0, nPos + 1 ); + aDoc = INetURLObject::decode( aDoc, INET_HEX_ESCAPE, INetURLObject::DECODE_UNAMBIGUOUS ); - } - else - aDoc.Erase(); } else aDoc.Erase(); @@ -1203,18 +1199,15 @@ struct ConventionXL } // Cheesy hack to unparse the OOO style "'Doc'#Tab" - if ( rTabName.GetChar(0) == '\'' ) + xub_StrLen nPos = ScCompiler::GetDocTabPos( rTabName); + if (nPos != STRING_NOTFOUND) { - xub_StrLen nPos = ScGlobal::FindUnquoted( rTabName, SC_COMPILER_FILE_TAB_SEP); - if (nPos != STRING_NOTFOUND && nPos > 0 && rTabName.GetChar(nPos-1) == '\'') - { - rDocName = rTabName.Copy( 0, nPos ); - // TODO : More research into how XL escapes the doc path - rDocName = INetURLObject::decode( rDocName, INET_HEX_ESCAPE, + rDocName = rTabName.Copy( 0, nPos ); + // TODO : More research into how XL escapes the doc path + rDocName = INetURLObject::decode( rDocName, INET_HEX_ESCAPE, INetURLObject::DECODE_UNAMBIGUOUS ); - rTabName.Erase( 0, nPos + 1 ); - bHasDoc = true; - } + rTabName.Erase( 0, nPos + 1 ); + bHasDoc = true; } // XL uses the same sheet name quoting conventions in both modes @@ -1872,6 +1865,18 @@ void ScCompiler::CheckTabQuotes( String& rString, } } + +xub_StrLen ScCompiler::GetDocTabPos( const String& rString ) +{ + if (rString.GetChar(0) != '\'') + return STRING_NOTFOUND; + xub_StrLen nPos = ScGlobal::FindUnquoted( rString, SC_COMPILER_FILE_TAB_SEP); + // it must be 'Doc'# + if (nPos != STRING_NOTFOUND && rString.GetChar(nPos-1) != '\'') + nPos = STRING_NOTFOUND; + return nPos; +} + //--------------------------------------------------------------------------- void ScCompiler::SetRefConvention( FormulaGrammar::AddressConvention eConv ) diff --git a/sc/source/core/tool/dbcolect.cxx b/sc/source/core/tool/dbcolect.cxx index 800716bef3b6..baf2c3de8c2a 100644 --- a/sc/source/core/tool/dbcolect.cxx +++ b/sc/source/core/tool/dbcolect.cxx @@ -2,7 +2,7 @@ * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2000, 2011 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * @@ -753,6 +753,27 @@ ScDBData* ScDBCollection::GetDBAtArea(SCTAB nTab, SCCOL nCol1, SCROW nRow1, SCCO return pNoNameData; // "unbenannt" nur zurueck, wenn sonst nichts gefunden } +ScDBData* ScDBCollection::GetFilterDBAtTable(SCTAB nTab) const +{ + ScDBData* pDataEmpty = NULL; + if (pItems) + { + for (sal_uInt16 i = 0; i < nCount; i++) + { + ScDBData* pDBTemp = (ScDBData*)pItems[i]; + if ( pDBTemp->nTable == nTab ) + { + sal_Bool bFilter = pDBTemp->HasAutoFilter() || pDBTemp->HasQueryParam(); + + if ( bFilter ) + return pDBTemp; + } + } + } + + return pDataEmpty; +} + sal_Bool ScDBCollection::SearchName( const String& rName, sal_uInt16& rIndex ) const { ScDBData aDataObj( rName, 0,0,0,0,0 ); diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index 7e015e12d16e..c507c3970bb1 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -653,6 +653,7 @@ double ScInterpreter::CompareFunc( const ScCompare& rComp, ScCompareOptions* pOp if ( !rComp.bEmpty[1] && rComp.bVal[1] && !::rtl::math::isFinite( rComp.nVal[1])) return rComp.nVal[1]; + size_t nStringQuery = 0; // 0:=no, 1:=0, 2:=1 double fRes = 0; if ( rComp.bEmpty[ 0 ] ) { @@ -709,16 +710,22 @@ double ScInterpreter::CompareFunc( const ScCompare& rComp, ScCompareOptions* pOp } } else - fRes = -1; // number is less than string + { + fRes = -1; // number is less than string + nStringQuery = 2; // 1+1 + } } else if( rComp.bVal[ 1 ] ) - fRes = 1; // number is less than string + { + fRes = 1; // string is greater than number + nStringQuery = 1; // 0+1 + } else { // Both strings. if (pOptions) { - // All similar to Sctable::ValidQuery(), *rComp.pVal[1] actually + // All similar to ScTable::ValidQuery(), *rComp.pVal[1] actually // is/must be identical to *rEntry.pStr, which is essential for // regex to work through GetSearchTextPtr(). ScQueryEntry& rEntry = pOptions->aQueryEntry; @@ -768,6 +775,20 @@ double ScInterpreter::CompareFunc( const ScCompare& rComp, ScCompareOptions* pOp fRes = (double) ScGlobal::GetCaseCollator()->compareString( *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] ); } + if (nStringQuery && pOptions) + { + const ScQueryEntry& rEntry = pOptions->aQueryEntry; + if (!rEntry.bQueryByString && rEntry.pStr->Len() && + (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL)) + { + // As in ScTable::ValidQuery() match a numeric string for a + // number query that originated from a string, e.g. in SUMIF + // and COUNTIF. Transliteration is not needed here. + bool bEqual = rComp.pVal[nStringQuery-1]->Equals( *rEntry.pStr); + // match => fRes=0, else fRes=1 + fRes = (rEntry.eOp == SC_NOT_EQUAL) ? bEqual : !bEqual; + } + } return fRes; } @@ -6223,7 +6244,7 @@ void ScInterpreter::ScDBVarP() } -ScTokenArray* lcl_CreateExternalRefTokenArray( const ScAddress& rPos, ScDocument* pDoc, +FormulaSubroutineToken* lcl_CreateExternalRefSubroutine( const ScAddress& rPos, ScDocument* pDoc, const ScAddress::ExternalInfo& rExtInfo, const ScRefAddress& rRefAd1, const ScRefAddress* pRefAd2 ) { @@ -6265,7 +6286,7 @@ ScTokenArray* lcl_CreateExternalRefTokenArray( const ScAddress& rPos, ScDocument rExtInfo.maTabName, nSheets); ScCompiler aComp( pDoc, rPos, *pTokenArray); aComp.CompileTokenArray(); - return pTokenArray; + return new FormulaSubroutineToken( pTokenArray); } @@ -6294,15 +6315,10 @@ void ScInterpreter::ScIndirect() { if (aExtInfo.mbExternal) { - /* TODO: future versions should implement a proper subroutine - * token. This procedure here is a minimally invasive fix for - * #i101645# in OOo3.1.1 */ - // Push a subroutine on the instruction code stack that - // resolves the external reference as the next instruction. - aCode.Push( lcl_CreateExternalRefTokenArray( aPos, pDok, + // Push a subroutine that resolves the external reference as + // the next instruction. + PushTempToken( lcl_CreateExternalRefSubroutine( aPos, pDok, aExtInfo, aRefAd, &aRefAd2)); - // Signal subroutine call to interpreter. - PushTempToken( new FormulaUnknownToken( ocCall)); } else PushDoubleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab(), @@ -6314,15 +6330,10 @@ void ScInterpreter::ScIndirect() { if (aExtInfo.mbExternal) { - /* TODO: future versions should implement a proper subroutine - * token. This procedure here is a minimally invasive fix for - * #i101645# in OOo3.1.1 */ - // Push a subroutine on the instruction code stack that - // resolves the external reference as the next instruction. - aCode.Push( lcl_CreateExternalRefTokenArray( aPos, pDok, + // Push a subroutine that resolves the external reference as + // the next instruction. + PushTempToken( lcl_CreateExternalRefSubroutine( aPos, pDok, aExtInfo, aRefAd, NULL)); - // Signal subroutine call to interpreter. - PushTempToken( new FormulaUnknownToken( ocCall)); } else PushSingleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab() ); @@ -6441,9 +6452,27 @@ void ScInterpreter::ScAddressFunc() const ScAddress aAdr( nCol, nRow, 0); aAdr.Format( aRefStr, nFlags, pDok, aDetails ); - if( nParamCount >= 5 ) + if( nParamCount >= 5 && sTabStr.Len() ) { - ScCompiler::CheckTabQuotes( sTabStr, eConv); + String aDoc; + if (eConv == FormulaGrammar::CONV_OOO) + { + // Isolate Tab from 'Doc'#Tab + xub_StrLen nPos = ScCompiler::GetDocTabPos( sTabStr); + if (nPos != STRING_NOTFOUND) + { + if (sTabStr.GetChar(nPos+1) == '$') + ++nPos; // also split 'Doc'#$Tab + aDoc = sTabStr.Copy( 0, nPos+1); + sTabStr.Erase( 0, nPos+1); + } + } + /* TODO: yet unsupported external reference in CONV_XL_R1C1 syntax may + * need some extra handling to isolate Tab from Doc. */ + if (sTabStr.GetChar(0) != '\'' || sTabStr.GetChar(sTabStr.Len()-1) != '\'') + ScCompiler::CheckTabQuotes( sTabStr, eConv); + if (aDoc.Len()) + sTabStr.Insert( aDoc, 0); sTabStr += static_cast<sal_Unicode>(eConv == FormulaGrammar::CONV_XL_R1C1 ? '!' : '.'); sTabStr += aRefStr; PushString( sTabStr ); @@ -6453,6 +6482,24 @@ void ScInterpreter::ScAddressFunc() } +FormulaSubroutineToken* lcl_CreateExternalRefSubroutine( const ScAddress& rPos, + ScDocument* pDoc, const FormulaTokenRef& xExtRef ) +{ + // The exact usage (which cell range) of the external table can't be + // detected during the store-to-file cycle, mark it as permanently + // referenced so it gets stored even if not directly referenced anywhere. + ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager(); + pRefMgr->setCacheTableReferencedPermanently( + static_cast<const ScToken*>(xExtRef.get())->GetIndex(), + static_cast<const ScToken*>(xExtRef.get())->GetString(), 1); + ScTokenArray* pTokenArray = new ScTokenArray; + pTokenArray->AddToken( *xExtRef); + ScCompiler aComp( pDoc, rPos, *pTokenArray); + aComp.CompileTokenArray(); + return new FormulaSubroutineToken( pTokenArray); +} + + void ScInterpreter::ScOffset() { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScOffset" ); @@ -6477,54 +6524,129 @@ void ScInterpreter::ScOffset() PushIllegalArgument(); return; } - if (GetStackType() == svSingleRef) - { - PopSingleRef(nCol1, nRow1, nTab1); - if (nParamCount == 3 || (nColNew < 0 && nRowNew < 0)) - { - nCol1 = (SCCOL)((long) nCol1 + nColPlus); - nRow1 = (SCROW)((long) nRow1 + nRowPlus); - if (!ValidCol(nCol1) || !ValidRow(nRow1)) - PushIllegalArgument(); - else - PushSingleRef(nCol1, nRow1, nTab1); - } - else - { - if (nColNew < 0) - nColNew = 1; - if (nRowNew < 0) - nRowNew = 1; - nCol1 = (SCCOL)((long)nCol1+nColPlus); // ! nCol1 wird veraendert! - nRow1 = (SCROW)((long)nRow1+nRowPlus); - nCol2 = (SCCOL)((long)nCol1+nColNew-1); - nRow2 = (SCROW)((long)nRow1+nRowNew-1); - if (!ValidCol(nCol1) || !ValidRow(nRow1) || - !ValidCol(nCol2) || !ValidRow(nRow2)) - PushIllegalArgument(); - else - PushDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab1); - } - } - else if (GetStackType() == svDoubleRef) + FormulaTokenRef xExtRef; + switch (GetStackType()) { - PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2); - if (nColNew < 0) - nColNew = nCol2 - nCol1 + 1; - if (nRowNew < 0) - nRowNew = nRow2 - nRow1 + 1; - nCol1 = (SCCOL)((long)nCol1+nColPlus); - nRow1 = (SCROW)((long)nRow1+nRowPlus); - nCol2 = (SCCOL)((long)nCol1+nColNew-1); - nRow2 = (SCROW)((long)nRow1+nRowNew-1); - if (!ValidCol(nCol1) || !ValidRow(nRow1) || - !ValidCol(nCol2) || !ValidRow(nRow2) || nTab1 != nTab2) - PushIllegalArgument(); - else - PushDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab1); + case svExternalSingleRef: + xExtRef = PopToken()->Clone(); + // fallthru + case svSingleRef: + { + if (xExtRef) + { + ScSingleRefData& rData = static_cast<ScToken*>(xExtRef.get())->GetSingleRef(); + rData.CalcAbsIfRel( aPos); + nCol1 = rData.nCol; + nRow1 = rData.nRow; + nTab1 = rData.nTab; + } + else + PopSingleRef( nCol1, nRow1, nTab1); + if (nParamCount == 3 || (nColNew < 0 && nRowNew < 0)) + { + nCol1 = (SCCOL)((long) nCol1 + nColPlus); + nRow1 = (SCROW)((long) nRow1 + nRowPlus); + if (!ValidCol(nCol1) || !ValidRow(nRow1)) + PushIllegalArgument(); + else if (xExtRef) + { + ScSingleRefData& rData = static_cast<ScToken*>(xExtRef.get())->GetSingleRef(); + rData.nCol = nCol1; + rData.nRow = nRow1; + rData.nTab = nTab1; + rData.CalcRelFromAbs( aPos); + // Push a subroutine that resolves the external + // reference as the next instruction. + PushTempToken( lcl_CreateExternalRefSubroutine( aPos, pDok, xExtRef)); + } + else + PushSingleRef(nCol1, nRow1, nTab1); + } + else + { + if (nColNew < 0) + nColNew = 1; + if (nRowNew < 0) + nRowNew = 1; + nCol1 = (SCCOL)((long)nCol1+nColPlus); // ! nCol1 is modified + nRow1 = (SCROW)((long)nRow1+nRowPlus); + nCol2 = (SCCOL)((long)nCol1+nColNew-1); + nRow2 = (SCROW)((long)nRow1+nRowNew-1); + if (!ValidCol(nCol1) || !ValidRow(nRow1) || + !ValidCol(nCol2) || !ValidRow(nRow2)) + PushIllegalArgument(); + else if (xExtRef) + { + // Convert SingleRef to DoubleRef. + xExtRef = new ScExternalDoubleRefToken( + *static_cast<const ScExternalSingleRefToken*>(xExtRef.get())); + ScComplexRefData& rData = static_cast<ScToken*>(xExtRef.get())->GetDoubleRef(); + rData.Ref1.nCol = nCol1; + rData.Ref1.nRow = nRow1; + rData.Ref1.nTab = nTab1; + rData.Ref2.nCol = nCol2; + rData.Ref2.nRow = nRow2; + rData.Ref2.nTab = nTab1; + rData.CalcRelFromAbs( aPos); + // Push a subroutine that resolves the external + // reference as the next instruction. + PushTempToken( lcl_CreateExternalRefSubroutine( aPos, pDok, xExtRef)); + } + else + PushDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab1); + } + } + break; + case svExternalDoubleRef: + xExtRef = PopToken()->Clone(); + // fallthru + case svDoubleRef: + { + if (xExtRef) + { + ScComplexRefData& rData = static_cast<ScToken*>(xExtRef.get())->GetDoubleRef(); + rData.CalcAbsIfRel( aPos); + nCol1 = rData.Ref1.nCol; + nRow1 = rData.Ref1.nRow; + nTab1 = rData.Ref1.nTab; + nCol2 = rData.Ref2.nCol; + nRow2 = rData.Ref2.nRow; + nTab2 = rData.Ref2.nTab; + } + else + PopDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab2); + if (nColNew < 0) + nColNew = nCol2 - nCol1 + 1; + if (nRowNew < 0) + nRowNew = nRow2 - nRow1 + 1; + nCol1 = (SCCOL)((long)nCol1+nColPlus); + nRow1 = (SCROW)((long)nRow1+nRowPlus); + nCol2 = (SCCOL)((long)nCol1+nColNew-1); + nRow2 = (SCROW)((long)nRow1+nRowNew-1); + if (!ValidCol(nCol1) || !ValidRow(nRow1) || + !ValidCol(nCol2) || !ValidRow(nRow2) || nTab1 != nTab2) + PushIllegalArgument(); + else if (xExtRef) + { + ScComplexRefData& rData = static_cast<ScToken*>(xExtRef.get())->GetDoubleRef(); + rData.Ref1.nCol = nCol1; + rData.Ref1.nRow = nRow1; + rData.Ref1.nTab = nTab1; + rData.Ref2.nCol = nCol2; + rData.Ref2.nRow = nRow2; + rData.Ref2.nTab = nTab1; + rData.CalcRelFromAbs( aPos); + // Push a subroutine that resolves the external + // reference as the next instruction. + PushTempToken( lcl_CreateExternalRefSubroutine( aPos, pDok, xExtRef)); + } + else + PushDoubleRef(nCol1, nRow1, nTab1, nCol2, nRow2, nTab1); + } + break; + default: + PushIllegalParameter(); } - else - PushIllegalParameter(); } } diff --git a/sc/source/core/tool/interpr3.cxx b/sc/source/core/tool/interpr3.cxx index dfcce4c06c3f..ef1a18b65def 100644 --- a/sc/source/core/tool/interpr3.cxx +++ b/sc/source/core/tool/interpr3.cxx @@ -949,17 +949,18 @@ double ScInterpreter::GetBetaDistPDF(double fX, double fA, double fB) const double fLogDblMin = log( ::std::numeric_limits<double>::min()); double fLogY = (fX < 0.1) ? ::rtl::math::log1p(-fX) : log(0.5-fX+0.5); double fLogX = log(fX); - double fAm1 = fA-1.0; - double fBm1 = fB-1.0; + double fAm1LogX = (fA-1.0) * fLogX; + double fBm1LogY = (fB-1.0) * fLogY; double fLogBeta = GetLogBeta(fA,fB); // check whether parts over- or underflow - if ( fAm1 * fLogX < fLogDblMax && fAm1 * fLogX > fLogDblMin - && fBm1 * fLogY < fLogDblMax && fBm1* fLogY > fLogDblMin - && fLogBeta < fLogDblMax && fLogBeta > fLogDblMin ) + if ( fAm1LogX < fLogDblMax && fAm1LogX > fLogDblMin + && fBm1LogY < fLogDblMax && fBm1LogY > fLogDblMin + && fLogBeta < fLogDblMax && fLogBeta > fLogDblMin + && fAm1LogX + fBm1LogY < fLogDblMax && fAm1LogX + fBm1LogY > fLogDblMin) return pow(fX,fA-1.0) * pow(0.5-fX+0.5,fB-1.0) / GetBeta(fA,fB); else // need logarithm; // might overflow as a whole, but seldom, not worth to pre-detect it - return exp((fA-1.0)*fLogX + (fB-1.0)* fLogY - fLogBeta); + return exp( fAm1LogX + fBm1LogY - fLogBeta); } @@ -1226,121 +1227,106 @@ void ScInterpreter::ScVariationen2() } } -void ScInterpreter::ScB() -{ - RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScB" ); - sal_uInt8 nParamCount = GetByte(); - if ( !MustHaveParamCount( nParamCount, 3, 4 ) ) - return ; - if (nParamCount == 3) - { - double x = ::rtl::math::approxFloor(GetDouble()); - double p = GetDouble(); - double n = ::rtl::math::approxFloor(GetDouble()); - if (n < 0.0 || x < 0.0 || x > n || p < 0.0 || p > 1.0) - PushIllegalArgument(); - else + +double ScInterpreter::GetBinomDistPMF(double x, double n, double p) +// used in ScB and ScBinomDist +// preconditions: 0.0 <= x <= n, 0.0 < p < 1.0; x,n integral although double { - double q = 1.0 - p; + double q = (0.5 - p) + 0.5; double fFactor = pow(q, n); - if (fFactor == 0.0) + if (fFactor <=::std::numeric_limits<double>::min()) { fFactor = pow(p, n); - if (fFactor == 0.0) - PushNoValue(); + if (fFactor <= ::std::numeric_limits<double>::min()) + return GetBetaDistPDF(p, x+1.0, n-x+1.0)/(n+1.0); else { - sal_uLong max = (sal_uLong) (n - x); - for (sal_uLong i = 0; i < max && fFactor > 0.0; i++) + sal_uInt32 max = static_cast<sal_uInt32>(n - x); + for (sal_uInt32 i = 0; i < max && fFactor > 0.0; i++) fFactor *= (n-i)/(i+1)*q/p; - PushDouble(fFactor); + return fFactor; } } else { - sal_uLong max = (sal_uLong) x; - for (sal_uLong i = 0; i < max && fFactor > 0.0; i++) + sal_uInt32 max = static_cast<sal_uInt32>(x); + for (sal_uInt32 i = 0; i < max && fFactor > 0.0; i++) fFactor *= (n-i)/(i+1)*p/q; - PushDouble(fFactor); - } + return fFactor; } } - else if (nParamCount == 4) - { - double xe = GetDouble(); - double xs = GetDouble(); - double p = GetDouble(); - double n = GetDouble(); -// alter Stand 300-SC -// if ((xs < n) && (xe < n) && (p < 1.0)) -// { -// double Varianz = sqrt(n * p * (1.0 - p)); -// xs = fabs(xs - (n * p /* / 2.0 STE */ )); -// xe = fabs(xe - (n * p /* / 2.0 STE */ )); -//// STE double nVal = gauss((xs + 0.5) / Varianz) + gauss((xe + 0.5) / Varianz); -// double nVal = fabs(gauss(xs / Varianz) - gauss(xe / Varianz)); -// PushDouble(nVal); -// } - bool bIsValidX = ( 0.0 <= xs && xs <= xe && xe <= n); - if ( bIsValidX && 0.0 < p && p < 1.0 ) - { - double q = 1.0 - p; - double fFactor = pow(q, n); - if (fFactor == 0.0) - { - fFactor = pow(p, n); - if (fFactor == 0.0) - PushNoValue(); - else + +double lcl_GetBinomDistRange(double n, double xs,double xe, + double fFactor /* q^n */, double p, double q) +//preconditions: 0.0 <= xs < xe <= n; xs,xe,n integral although double { - double fSum = 0.0; - sal_uLong max; - if (xe < (sal_uLong) n) - max = (sal_uLong) (n-xe)-1; - else - max = 0; - sal_uLong i; - for (i = 0; i < max && fFactor > 0.0; i++) - fFactor *= (n-i)/(i+1)*q/p; - if (xs < (sal_uLong) n) - max = (sal_uLong) (n-xs); - else - fSum = fFactor; - for (; i < max && fFactor > 0.0; i++) + sal_uInt32 i; + double fSum; + // skip summands index 0 to xs-1, start sum with index xs + sal_uInt32 nXs = static_cast<sal_uInt32>( xs ); + for (i = 1; i <= nXs && fFactor > 0.0; i++) + fFactor *= (n-i+1)/i * p/q; + fSum = fFactor; // Summand xs + sal_uInt32 nXe = static_cast<sal_uInt32>(xe); + for (i = nXs+1; i <= nXe && fFactor > 0.0; i++) { - fFactor *= (n-i)/(i+1)*q/p; + fFactor *= (n-i+1)/i * p/q; fSum += fFactor; } - PushDouble(fSum); + return (fSum>1.0) ? 1.0 : fSum; } + +void ScInterpreter::ScB() +{ + RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScB" ); + sal_uInt8 nParamCount = GetByte(); + if ( !MustHaveParamCount( nParamCount, 3, 4 ) ) + return ; + if (nParamCount == 3) // mass function + { + double x = ::rtl::math::approxFloor(GetDouble()); + double p = GetDouble(); + double n = ::rtl::math::approxFloor(GetDouble()); + if (n < 0.0 || x < 0.0 || x > n || p < 0.0 || p > 1.0) + PushIllegalArgument(); + else + if (p == 0.0) + PushDouble( (x == 0.0) ? 1.0 : 0.0 ); + else + if ( p == 1.0) + PushDouble( (x == n) ? 1.0 : 0.0); + else + PushDouble(GetBinomDistPMF(x,n,p)); } else + { // nParamCount == 4 + double xe = ::rtl::math::approxFloor(GetDouble()); + double xs = ::rtl::math::approxFloor(GetDouble()); + double p = GetDouble(); + double n = ::rtl::math::approxFloor(GetDouble()); + double q = (0.5 - p) + 0.5; + bool bIsValidX = ( 0.0 <= xs && xs <= xe && xe <= n); + if ( bIsValidX && 0.0 < p && p < 1.0) { - sal_uLong max; - double fSum; - if ( (sal_uLong) xs == 0) + if (xs == xe) // mass function + PushDouble(GetBinomDistPMF(xs,n,p)); + else { - fSum = fFactor; - max = 0; - } + double fFactor = pow(q, n); + if (fFactor > ::std::numeric_limits<double>::min()) + PushDouble(lcl_GetBinomDistRange(n,xs,xe,fFactor,p,q)); else { - max = (sal_uLong) xs-1; - fSum = 0.0; + fFactor = pow(p, n); + if (fFactor > ::std::numeric_limits<double>::min()) + { + // sum from j=xs to xe {(n choose j) * p^j * q^(n-j)} + // = sum from i = n-xe to n-xs { (n choose i) * q^i * p^(n-i)} + PushDouble(lcl_GetBinomDistRange(n,n-xe,n-xs,fFactor,q,p)); } - sal_uLong i; - for (i = 0; i < max && fFactor > 0.0; i++) - fFactor *= (n-i)/(i+1)*p/q; - if ((sal_uLong)xe == 0) // beide 0 - fSum = fFactor; else - max = (sal_uLong) xe; - for (; i < max && fFactor > 0.0; i++) - { - fFactor *= (n-i)/(i+1)*p/q; - fSum += fFactor; + PushDouble(GetBetaDist(q,n-xe,xe+1.0)-GetBetaDist(q,n-xs+1,xs) ); } - PushDouble(fSum); } } else @@ -1365,77 +1351,63 @@ void ScInterpreter::ScBinomDist() RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::ScBinomDist" ); if ( MustHaveParamCount( GetByte(), 4 ) ) { - double kum = GetDouble(); // 0 oder 1 - double p = GetDouble(); // p - double n = ::rtl::math::approxFloor(GetDouble()); // n - double x = ::rtl::math::approxFloor(GetDouble()); // x - double fFactor, q, fSum; + bool bIsCum = GetBool(); // false=mass function; true=cumulative + double p = GetDouble(); + double n = ::rtl::math::approxFloor(GetDouble()); + double x = ::rtl::math::approxFloor(GetDouble()); + double q = (0.5 - p) + 0.5; // get one bit more for p near 1.0 + double fFactor, fSum; if (n < 0.0 || x < 0.0 || x > n || p < 0.0 || p > 1.0) - PushIllegalArgument(); - else if (kum == 0.0) // Dichte { - q = 1.0 - p; - fFactor = pow(q, n); - if (fFactor == 0.0) - { - fFactor = pow(p, n); - if (fFactor == 0.0) - PushNoValue(); - else - { - sal_uLong max = (sal_uLong) (n - x); - for (sal_uLong i = 0; i < max && fFactor > 0.0; i++) - fFactor *= (n-i)/(i+1)*q/p; - PushDouble(fFactor); - } + PushIllegalArgument(); + return; } - else + if ( p == 0.0) { - sal_uLong max = (sal_uLong) x; - for (sal_uLong i = 0; i < max && fFactor > 0.0; i++) - fFactor *= (n-i)/(i+1)*p/q; - PushDouble(fFactor); + PushDouble( (x==0.0 || bIsCum) ? 1.0 : 0.0 ); + return; } + if ( p == 1.0) + { + PushDouble( (x==n) ? 1.0 : 0.0); + return; } - else // Verteilung + if (!bIsCum) + PushDouble( GetBinomDistPMF(x,n,p)); + else { - if (n == x) + if (x == n) PushDouble(1.0); else { - q = 1.0 - p; fFactor = pow(q, n); - if (fFactor == 0.0) + if (x == 0.0) + PushDouble(fFactor); + else + if (fFactor <= ::std::numeric_limits<double>::min()) { fFactor = pow(p, n); - if (fFactor == 0.0) - PushNoValue(); + if (fFactor <= ::std::numeric_limits<double>::min()) + PushDouble(GetBetaDist(q,n-x,x+1.0)); else { + if (fFactor > fMachEps) + { fSum = 1.0 - fFactor; - sal_uLong max = (sal_uLong) (n - x) - 1; - for (sal_uLong i = 0; i < max && fFactor > 0.0; i++) + sal_uInt32 max = static_cast<sal_uInt32> (n - x) - 1; + for (sal_uInt32 i = 0; i < max && fFactor > 0.0; i++) { fFactor *= (n-i)/(i+1)*q/p; fSum -= fFactor; } - if (fSum < 0.0) - PushDouble(0.0); - else - PushDouble(fSum); - } + PushDouble( (fSum < 0.0) ? 0.0 : fSum ); } else - { - fSum = fFactor; - sal_uLong max = (sal_uLong) x; - for (sal_uLong i = 0; i < max && fFactor > 0.0; i++) - { - fFactor *= (n-i)/(i+1)*p/q; - fSum += fFactor; + PushDouble(lcl_GetBinomDistRange(n,n-x,n,fFactor,q,p)); } - PushDouble(fSum); } + else + PushDouble( lcl_GetBinomDistRange(n,0.0,x,fFactor,p,q)) ; } } } diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx index e3cd6239191e..439e0375a8b9 100755 --- a/sc/source/core/tool/interpr4.cxx +++ b/sc/source/core/tool/interpr4.cxx @@ -3181,6 +3181,14 @@ void ScInterpreter::ScColRowNameAuto() void ScInterpreter::ScExternalRef() { + const FormulaToken* pNextOp = aCode.PeekNextOperator(); + if (pNextOp && pNextOp->GetOpCode() == ocOffset) + { + // Handled by OFFSET function. + PushTempToken( *pCur); + return; + } + ScExternalRefManager* pRefMgr = pDok->GetExternalRefManager(); const String* pFile = pRefMgr->getExternalFileName(pCur->GetIndex()); if (!pFile) @@ -3324,6 +3332,21 @@ void ScInterpreter::GlobalExit() // static } +// A ::std::vector<FormulaTokenRef> is not possible, a push_back() attempts to +// use a FormulaToken(const FormulaTokenRef&) ctor. Reinvent wheel.. +struct FormulaTokenRefPtr +{ + FormulaToken* mp; + FormulaTokenRefPtr() : mp(0) {} + FormulaTokenRefPtr( FormulaToken* p ) : mp(p) { if (mp) mp->IncRef(); } + FormulaTokenRefPtr( const FormulaTokenRefPtr & r ) : mp(r.mp) { if (mp) mp->IncRef(); } + ~FormulaTokenRefPtr() { if (mp) mp->DecRef(); } + FormulaTokenRefPtr& operator=( const FormulaTokenRefPtr & r ) + { if (r.mp) r.mp->IncRef(); if (mp) mp->DecRef(); mp = r.mp; return *this; } +}; +typedef ::std::vector< FormulaTokenRefPtr > FormulaTokenDtor; + + StackVar ScInterpreter::Interpret() { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "er", "ScInterpreter::Interpret" ); @@ -3342,6 +3365,7 @@ StackVar ScInterpreter::Interpret() pJumpMatrix = NULL; glSubTotal = sal_False; ScTokenMatrixMap::const_iterator aTokenMatrixMapIter; + ::boost::scoped_ptr< FormulaTokenDtor > pTokenDtor; // Once upon a time we used to have FP exceptions on, and there was a // Windows printer driver that kept switching off exceptions, so we had to @@ -3724,13 +3748,27 @@ StackVar ScInterpreter::Interpret() default : PushError( errUnknownOpCode); break; } - // If the function signalled that it pushed a subroutine on the - // instruction code stack instead of a result, continue with + // If the function pushed a subroutine as result, continue with // execution of the subroutine. - if (sp > nStackBase && pStack[sp-1]->GetOpCode() == ocCall) + if (sp > nStackBase && pStack[sp-1]->GetOpCode() == ocCall && pStack[sp-1]->GetType() == svSubroutine) { - Pop(); - continue; // while( ( pCur = aCode.Next() ) != NULL ... + FormulaTokenRef xTok = PopToken(); + const FormulaSubroutineToken* pSub = dynamic_cast<FormulaSubroutineToken*>(xTok.get()); + if (pSub) + { + // Remember token for late destruction. + if (!pTokenDtor) + pTokenDtor.reset( new FormulaTokenDtor); + pTokenDtor->push_back( FormulaTokenDtor::value_type( xTok)); + // Continue with execution of subroutine. + aCode.Push( pSub->GetTokenArray()); + continue; // while( ( pCur = aCode.Next() ) != NULL ... + } + else + { + DBG_ERRORFILE( "ScInterpreter::Interpret: ocCall svSubroutine, but no FormulaSubroutineToken?!?"); + PushError( errNoCode); + } } // Remember result matrix in case it could be reused. diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index a270969e100c..83ee5d365e63 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -561,6 +561,9 @@ sal_Bool ScToken::Is3DRef() const if ( GetSingleRef().IsFlag3D() ) return sal_True; break; + case svExternalSingleRef: + case svExternalDoubleRef: + return sal_True; default: { // added to avoid warnings @@ -922,6 +925,14 @@ ScExternalDoubleRefToken::ScExternalDoubleRefToken( const ScExternalDoubleRefTok { } +ScExternalDoubleRefToken::ScExternalDoubleRefToken( const ScExternalSingleRefToken& r ) : + ScToken( svExternalDoubleRef, ocExternalRef), + mnFileId( r.GetIndex()), + maTabName( r.GetString()) +{ + maDoubleRef.Ref1 = maDoubleRef.Ref2 = r.GetSingleRef(); +} + ScExternalDoubleRefToken::~ScExternalDoubleRefToken() { } @@ -1825,6 +1836,20 @@ void ScTokenArray::ReadjustRelative3DReferences( const ScAddress& rOldPos, } } break; + case svExternalDoubleRef: + { + ScSingleRefData& rRef2 = static_cast<ScToken*>(pCode[j])->GetSingleRef2(); + rRef2.CalcAbsIfRel( rOldPos ); + rRef2.CalcRelFromAbs( rNewPos ); + } + //! fallthru + case svExternalSingleRef: + { + ScSingleRefData& rRef1 = static_cast<ScToken*>(pCode[j])->GetSingleRef(); + rRef1.CalcAbsIfRel( rOldPos ); + rRef1.CalcRelFromAbs( rNewPos ); + } + break; default: { // added to avoid warnings diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx index ead8067ee23e..45c9b9dcc4c7 100644 --- a/sc/source/filter/xml/xmlexprt.cxx +++ b/sc/source/filter/xml/xmlexprt.cxx @@ -3255,6 +3255,9 @@ void ScXMLExport::WriteShapes(const ScMyCell& rMyCell) AddAttribute(XML_NAMESPACE_TABLE, XML_END_Y, sBuffer.makeStringAndClear()); } ExportShape(aItr->xShape, &aPoint); + // if there's an error in ExportShape, the attributes from above must be removed + CheckAttrList(); // asserts in non pro if we have attributes left + ClearAttrList(); // clears the attributes } ++aItr; } diff --git a/sc/source/filter/xml/xmlimprt.cxx b/sc/source/filter/xml/xmlimprt.cxx index d4133686d2c8..fb9241549817 100644 --- a/sc/source/filter/xml/xmlimprt.cxx +++ b/sc/source/filter/xml/xmlimprt.cxx @@ -73,6 +73,7 @@ #include "rangeutl.hxx" #include "postit.hxx" #include "formulaparserpool.hxx" +#include "externalrefmgr.hxx" #include <comphelper/extract.hxx> #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> @@ -2857,9 +2858,19 @@ throw( ::com::sun::star::xml::sax::SAXException, ::com::sun::star::uno::RuntimeE } GetProgressBarHelper()->End(); // make room for subsequent SfxProgressBars if (pDoc) + { pDoc->CompileXML(); - if (pDoc && GetModel().is()) + // After CompileXML, links must be completely changed to the new URLs. + // Otherwise, hasExternalFile for API wouldn't work (#i116940#), + // and typing a new formula would create a second link with the same "real" file name. + if (pDoc->HasExternalRefManager()) + pDoc->GetExternalRefManager()->updateAbsAfterLoad(); + } + + // If the stream contains cells outside of the current limits, the styles can't be re-created, + // so stream copying is disabled then. + if (pDoc && GetModel().is() && !pDoc->HasRangeOverflow()) { // set "valid stream" flags after loading (before UpdateRowHeights, so changed formula results // in UpdateRowHeights can already clear the flags again) diff --git a/sc/source/filter/xml/xmlsubti.cxx b/sc/source/filter/xml/xmlsubti.cxx index e6cc7b853764..3e182c919032 100644 --- a/sc/source/filter/xml/xmlsubti.cxx +++ b/sc/source/filter/xml/xmlsubti.cxx @@ -614,7 +614,8 @@ void ScMyTables::UpdateRowHeights() if (aUpdateSheets.GetSelectCount()) { pDoc->LockStreamValid( true ); // ignore draw page size (but not formula results) - ScModelObj::getImplementation(rImport.GetModel())->UpdateAllRowHeights(&aUpdateSheets); + // #i114839# make sure the output factor is valid for UpdateAllRowHeights + ScModelObj::getImplementation(rImport.GetModel())->UpdateAllRowHeights(&aUpdateSheets, true); pDoc->LockStreamValid( false ); } } diff --git a/sc/source/filter/xml/xmltabi.cxx b/sc/source/filter/xml/xmltabi.cxx index 1644ad7e7ffe..dd234bb9a76a 100644 --- a/sc/source/filter/xml/xmltabi.cxx +++ b/sc/source/filter/xml/xmltabi.cxx @@ -55,6 +55,8 @@ #include <xmloff/xmltoken.hxx> #include <xmloff/XMLEventsImportContext.hxx> +#include <tools/urlobj.hxx> + #include <com/sun/star/sheet/XSpreadsheetDocument.hpp> #include <com/sun/star/sheet/XSpreadsheets.hpp> #include <com/sun/star/sheet/XSpreadsheet.hpp> @@ -83,27 +85,29 @@ static bool lcl_isExternalRefCache(const rtl::OUString& rName, rtl::OUString& rU // 'file:///path/to/file's.ods'#Sheet (Notice the quote in the file name. // That's allowed.) - static const sal_Unicode aPrefix[] = { - '\'', 'f', 'i', 'l', 'e', ':', '/', '/' - }; + if ( rName.toChar() != '\'' ) // initial quote + return false; + + // #i114504# Other schemes besides "file:" are also allowed. + // CompareProtocolScheme is quick, only looks at the start of the string. + INetProtocol eProt = INetURLObject::CompareProtocolScheme( rName.copy(1) ); + if ( eProt == INET_PROT_NOT_VALID ) + return false; + + rtl::OUString aPrefix = INetURLObject::GetScheme( eProt ); + sal_Int32 nPrefLen = aPrefix.getLength(); rtl::OUStringBuffer aUrlBuf, aTabNameBuf; - aUrlBuf.appendAscii("file://"); + aUrlBuf.append( aPrefix ); sal_Int32 n = rName.getLength(); const sal_Unicode* p = rName.getStr(); bool bInUrl = true; sal_Unicode cPrev = 0; - for (sal_Int32 i = 0; i < n; ++i) + for (sal_Int32 i = nPrefLen+1; i < n; ++i) // start the loop after quote and prefix { const sal_Unicode c = p[i]; - if (i <= 7) - { - // Checking the prefix 'file://'. - if (c != aPrefix[i]) - return false; - } - else if (bInUrl) + if (bInUrl) { // parsing file URL if (c == '#') diff --git a/sc/source/ui/app/inputhdl.cxx b/sc/source/ui/app/inputhdl.cxx index 33f6a279a40c..a6de38258d06 100644 --- a/sc/source/ui/app/inputhdl.cxx +++ b/sc/source/ui/app/inputhdl.cxx @@ -2097,7 +2097,7 @@ sal_Bool ScInputHandler::DataChanging( sal_Unicode cTyped, sal_Bool bFromCommand return sal_False; } -void ScInputHandler::DataChanged( sal_Bool bFromTopNotify ) +void ScInputHandler::DataChanged( sal_Bool bFromTopNotify, sal_Bool bSetModified ) { ImplCreateEditEngine(); @@ -2116,7 +2116,8 @@ void ScInputHandler::DataChanged( sal_Bool bFromTopNotify ) pTopView->ShowCursor(); } - bModified = sal_True; + if (bSetModified) + bModified = sal_True; bSelIsRef = sal_False; if ( pRangeFindList && !bInRangeUpdate ) @@ -3207,7 +3208,9 @@ sal_Bool ScInputHandler::KeyInput( const KeyEvent& rKEvt, sal_Bool bStartEdit /* } } - DataChanged(); // ruft auch UpdateParenthesis() + // #i114511# don't count cursor keys as modification + sal_Bool bSetModified = !bCursorKey; + DataChanged(sal_False, bSetModified); // also calls UpdateParenthesis() InvalidateAttribs(); //! in DataChanged ? } } diff --git a/sc/source/ui/dbgui/pvfundlg.cxx b/sc/source/ui/dbgui/pvfundlg.cxx index 5ee9b320a04e..1bf258264dc9 100644 --- a/sc/source/ui/dbgui/pvfundlg.cxx +++ b/sc/source/ui/dbgui/pvfundlg.cxx @@ -748,8 +748,11 @@ ScDPShowDetailDlg::ScDPShowDetailDlg( Window* pParent, ScDPObject& rDPObj, sal_u if (pLayoutName) aName = *pLayoutName; } - maLbDims.InsertEntry( aName ); - maNameIndexMap.insert(DimNameIndexMap::value_type(aName, nDim)); + if ( aName.Len() ) + { + maLbDims.InsertEntry( aName ); + maNameIndexMap.insert(DimNameIndexMap::value_type(aName, nDim)); + } } } } diff --git a/sc/source/ui/dbgui/pvlaydlg.cxx b/sc/source/ui/dbgui/pvlaydlg.cxx index a1a90731cf0f..e5709197748e 100644 --- a/sc/source/ui/dbgui/pvlaydlg.cxx +++ b/sc/source/ui/dbgui/pvlaydlg.cxx @@ -99,7 +99,7 @@ ScPivotLayoutDlg::ScPivotLayoutDlg( SfxBindings* pB, SfxChildWindow* pCW, Window maFlAreas( this, ScResId( FL_OUTPUT ) ), maFtInArea( this, ScResId( FT_INAREA) ), - maEdInPos( this, ScResId( ED_INAREA) ), + maEdInPos( this, this, ScResId( ED_INAREA) ), maRbInPos( this, ScResId( RB_INAREA ), &maEdInPos, this ), maLbOutPos( this, ScResId( LB_OUTAREA ) ), maFtOutArea( this, ScResId( FT_OUTAREA ) ), diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx index 6414119677bf..e69458fd418b 100644 --- a/sc/source/ui/docshell/docfunc.cxx +++ b/sc/source/ui/docshell/docfunc.cxx @@ -2291,7 +2291,7 @@ sal_Bool ScDocFunc::MoveBlock( const ScRange& rSource, const ScAddress& rDestPos } ScDrawLayer::SetGlobalDrawPersist(aDragShellRef); - ScClipParam aClipParam(ScRange(nStartCol, nStartRow, 0, nEndCol, nEndRow, 0), bCut); + ScClipParam aClipParam(ScRange(nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nStartTab), bCut); pDoc->CopyToClip(aClipParam, pClipDoc, &aSourceMark, false, bScenariosAdded, true); ScDrawLayer::SetGlobalDrawPersist(NULL); diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx index 4d989158952b..fc854e63ecbb 100644 --- a/sc/source/ui/docshell/docsh.cxx +++ b/sc/source/ui/docshell/docsh.cxx @@ -499,74 +499,23 @@ sal_Bool __EXPORT ScDocShell::Load( SfxMedium& rMedium ) void __EXPORT ScDocShell::Notify( SfxBroadcaster&, const SfxHint& rHint ) { - uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents = aDocument.GetVbaEventProcessor(); - if ( xVbaEvents.is() ) try + if (rHint.ISA(ScTablesHint) ) { - using namespace ::com::sun::star::script::vba::VBAEventId; - if (rHint.ISA(ScTablesHint) ) + const ScTablesHint& rScHint = static_cast< const ScTablesHint& >( rHint ); + if (rScHint.GetId() == SC_TAB_INSERTED) { - const ScTablesHint& rScHint = static_cast< const ScTablesHint& >( rHint ); - if (rScHint.GetId() == SC_TAB_INSERTED) + uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents = aDocument.GetVbaEventProcessor(); + if ( xVbaEvents.is() ) try { uno::Sequence< uno::Any > aArgs( 1 ); aArgs[0] <<= rScHint.GetTab1(); - xVbaEvents->processVbaEvent( WORKBOOK_NEWSHEET, aArgs ); + xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKBOOK_NEWSHEET, aArgs ); } - } - else if ( rHint.ISA( SfxEventHint ) ) - { - sal_uLong nEventId = static_cast< const SfxEventHint& >( rHint ).GetEventId(); - switch ( nEventId ) + catch( uno::Exception& ) { - case SFX_EVENT_ACTIVATEDOC: - { - uno::Sequence< uno::Any > aArgs; - xVbaEvents->processVbaEvent( WORKBOOK_ACTIVATE, aArgs ); - } - break; - case SFX_EVENT_DEACTIVATEDOC: - { - uno::Sequence< uno::Any > aArgs; - xVbaEvents->processVbaEvent( WORKBOOK_DEACTIVATE, aArgs ); - } - break; - case SFX_EVENT_OPENDOC: - { - uno::Sequence< uno::Any > aArgs; - xVbaEvents->processVbaEvent( WORKBOOK_OPEN, aArgs ); - } - break; - case SFX_EVENT_SAVEDOCDONE: - case SFX_EVENT_SAVEASDOCDONE: - case SFX_EVENT_SAVETODOCDONE: - { - uno::Sequence< uno::Any > aArgs( 1 ); - aArgs[ 0 ] <<= true; - xVbaEvents->processVbaEvent( WORKBOOK_AFTERSAVE, aArgs ); - } - break; - case SFX_EVENT_SAVEASDOCFAILED: - case SFX_EVENT_SAVEDOCFAILED: - case SFX_EVENT_SAVETODOCFAILED: - { - uno::Sequence< uno::Any > aArgs( 1 ); - aArgs[ 0 ] <<= false; - xVbaEvents->processVbaEvent( WORKBOOK_AFTERSAVE, aArgs ); - } - break; - case SFX_EVENT_CLOSEDOC: - { - // #163655# prevent event processing after model is disposed - aDocument.SetVbaEventProcessor( uno::Reference< script::vba::XVBAEventProcessor >() ); - uno::Reference< lang::XEventListener >( xVbaEvents, uno::UNO_QUERY_THROW )->disposing( lang::EventObject() ); - } - break; } } } - catch( uno::Exception& ) - { - } if (rHint.ISA(SfxSimpleHint)) // ohne Parameter { diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx index e3293a7eed5b..a0581ec0d1c3 100644 --- a/sc/source/ui/docshell/externalrefmgr.cxx +++ b/sc/source/ui/docshell/externalrefmgr.cxx @@ -61,6 +61,7 @@ #include "sfx2/linkmgr.hxx" #include "tools/urlobj.hxx" #include "unotools/ucbhelper.hxx" +#include "unotools/localfilehelper.hxx" #include <memory> #include <algorithm> @@ -934,26 +935,6 @@ void ScExternalRefCache::getAllNumberFormats(vector<sal_uInt32>& rNumFmts) const rNumFmts.swap(aNumFmts); } -bool ScExternalRefCache::hasCacheTable(sal_uInt16 nFileId, const String& rTabName) const -{ - DocItem* pDoc = getDocItem(nFileId); - if (!pDoc) - return false; - - String aUpperName = ScGlobal::pCharClass->upper(rTabName); - vector<TableName>::const_iterator itrBeg = pDoc->maTableNames.begin(), itrEnd = pDoc->maTableNames.end(); - vector<TableName>::const_iterator itr = ::std::find_if( - itrBeg, itrEnd, TabNameSearchPredicate(aUpperName)); - - return itr != itrEnd; -} - -size_t ScExternalRefCache::getCacheTableCount(sal_uInt16 nFileId) const -{ - DocItem* pDoc = getDocItem(nFileId); - return pDoc ? pDoc->maTables.size() : 0; -} - bool ScExternalRefCache::setCacheDocReferenced( sal_uInt16 nFileId ) { DocItem* pDocItem = getDocItem(nFileId); @@ -1576,16 +1557,6 @@ void ScExternalRefManager::getAllCachedNumberFormats(vector<sal_uInt32>& rNumFmt maRefCache.getAllNumberFormats(rNumFmts); } -bool ScExternalRefManager::hasCacheTable(sal_uInt16 nFileId, const String& rTabName) const -{ - return maRefCache.hasCacheTable(nFileId, rTabName); -} - -size_t ScExternalRefManager::getCacheTableCount(sal_uInt16 nFileId) const -{ - return maRefCache.getCacheTableCount(nFileId); -} - sal_uInt16 ScExternalRefManager::getExternalFileCount() const { return static_cast< sal_uInt16 >( maSrcFiles.size() ); @@ -2026,7 +1997,10 @@ SfxObjectShellRef ScExternalRefManager::loadSrcDocument(sal_uInt16 nFileId, Stri return NULL; String aOptions( pFileData->maFilterOptions ); - ScDocumentLoader::GetFilterName(aFile, rFilter, aOptions, true, false); + if ( pFileData->maFilterName.Len() ) + rFilter = pFileData->maFilterName; // don't overwrite stored filter with guessed filter + else + ScDocumentLoader::GetFilterName(aFile, rFilter, aOptions, true, false); const SfxFilter* pFilter = ScDocShell::Factory().GetFilterContainer()->GetFilter4FilterName(rFilter); if (!pFileData->maRelativeName.Len()) @@ -2093,10 +2067,18 @@ bool ScExternalRefManager::isFileLoadable(const String& rFile) const if (isOwnDocument(rFile)) return false; - if (utl::UCBContentHelper::IsFolder(rFile)) - return false; + String aPhysical; + if (utl::LocalFileHelper::ConvertURLToPhysicalName(rFile, aPhysical) && aPhysical.Len()) + { + // #i114504# try IsFolder/Exists only for file URLs + + if (utl::UCBContentHelper::IsFolder(rFile)) + return false; - return utl::UCBContentHelper::Exists(rFile); + return utl::UCBContentHelper::Exists(rFile); + } + else + return true; // for http and others, Exists doesn't work, but the URL can still be opened } void ScExternalRefManager::maybeLinkExternalFile(sal_uInt16 nFileId) @@ -2111,7 +2093,16 @@ void ScExternalRefManager::maybeLinkExternalFile(sal_uInt16 nFileId) return; String aFilter, aOptions; - ScDocumentLoader::GetFilterName(*pFileName, aFilter, aOptions, true, false); + const SrcFileData* pFileData = getExternalFileData(nFileId); + if (pFileData) + { + aFilter = pFileData->maFilterName; + aOptions = pFileData->maFilterOptions; + } + // If a filter was already set (for example, loading the cached table), + // don't call GetFilterName which has to access the source file. + if (!aFilter.Len()) + ScDocumentLoader::GetFilterName(*pFileName, aFilter, aOptions, true, false); sfx2::LinkManager* pLinkMgr = mpDoc->GetLinkManager(); ScExternalRefLink* pLink = new ScExternalRefLink(mpDoc, nFileId, aFilter); DBG_ASSERT(pFileName, "ScExternalRefManager::insertExternalFileLink: file name pointer is NULL"); @@ -2344,6 +2335,22 @@ void ScExternalRefManager::resetSrcFileData(const String& rBaseFileUrl) } } +void ScExternalRefManager::updateAbsAfterLoad() +{ + String aOwn( getOwnDocumentName() ); + for (vector<SrcFileData>::iterator itr = maSrcFiles.begin(), itrEnd = maSrcFiles.end(); + itr != itrEnd; ++itr) + { + // update maFileName to the real file name, + // to be called when the original name is no longer needed (after CompileXML) + + itr->maybeCreateRealFileName( aOwn ); + String aReal = itr->maRealFileName; + if (aReal.Len()) + itr->maFileName = aReal; + } +} + void ScExternalRefManager::removeRefCell(ScFormulaCell* pCell) { for_each(maRefCells.begin(), maRefCells.end(), RemoveFormulaCell(pCell)); diff --git a/sc/source/ui/inc/inputhdl.hxx b/sc/source/ui/inc/inputhdl.hxx index 8291877bbc57..9f745b4cd96c 100644 --- a/sc/source/ui/inc/inputhdl.hxx +++ b/sc/source/ui/inc/inputhdl.hxx @@ -211,7 +211,7 @@ public: EditView* GetTopView() { return pTopView; } sal_Bool DataChanging( sal_Unicode cTyped = 0, sal_Bool bFromCommand = sal_False ); - void DataChanged( sal_Bool bFromTopNotify = sal_False ); + void DataChanged( sal_Bool bFromTopNotify = sal_False, sal_Bool bSetModified = sal_True ); sal_Bool TakesReturn() const { return ( nTipVisible != 0 ); } diff --git a/sc/source/ui/styleui/scstyles.src b/sc/source/ui/styleui/scstyles.src index 1968b6dca877..07e4dbd85151 100644 --- a/sc/source/ui/styleui/scstyles.src +++ b/sc/source/ui/styleui/scstyles.src @@ -31,6 +31,19 @@ StyleFamily = family; \ FilterList = { filter } +String STR_STYLE_FILTER_USED +{ + Text [ en-US ] = "Applied Styles" ; +}; +String STR_STYLE_FILTER_USERDEF +{ + Text [ en-US ] = "Custom Styles" ; +}; +String STR_STYLE_FILTER_ALL +{ + Text [ en-US ] = "All Styles" ; +}; + //------------------------------------------------------------------------ SfxStyleFamilies DLG_STYLE_DESIGNER { diff --git a/sc/source/ui/unoobj/addruno.cxx b/sc/source/ui/unoobj/addruno.cxx index e54c47b6bd64..0dde4fb9e880 100644 --- a/sc/source/ui/unoobj/addruno.cxx +++ b/sc/source/ui/unoobj/addruno.cxx @@ -195,7 +195,7 @@ void SAL_CALL ScAddressConversionObj::setPropertyValue( const rtl::OUString& aPr else if ( aNameStr.EqualsAscii( SC_UNONAME_PERSREPR ) || aNameStr.EqualsAscii( SC_UNONAME_XLA1REPR ) ) { ::formula::FormulaGrammar::AddressConvention eConv = aNameStr.EqualsAscii( SC_UNONAME_XLA1REPR ) ? - ::formula::FormulaGrammar::CONV_OOO : ::formula::FormulaGrammar::CONV_XL_A1; + ::formula::FormulaGrammar::CONV_XL_A1 : ::formula::FormulaGrammar::CONV_OOO; // parse the file format string rtl::OUString sRepresentation; @@ -273,7 +273,7 @@ uno::Any SAL_CALL ScAddressConversionObj::getPropertyValue( const rtl::OUString& else if ( aNameStr.EqualsAscii( SC_UNONAME_PERSREPR ) || aNameStr.EqualsAscii( SC_UNONAME_XLA1REPR ) ) { ::formula::FormulaGrammar::AddressConvention eConv = aNameStr.EqualsAscii( SC_UNONAME_XLA1REPR ) ? - ::formula::FormulaGrammar::CONV_OOO : ::formula::FormulaGrammar::CONV_XL_A1; + ::formula::FormulaGrammar::CONV_XL_A1 : ::formula::FormulaGrammar::CONV_OOO; // generate file format string - always include sheet String aFormatStr; diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx index 721c99c59846..0d39e944b194 100644 --- a/sc/source/ui/unoobj/docuno.cxx +++ b/sc/source/ui/unoobj/docuno.cxx @@ -104,6 +104,9 @@ using namespace com::sun::star; +// #i111553# provides the name of the VBA constant for this document type (e.g. 'ThisExcelDoc' for Calc) +#define SC_UNO_VBAGLOBNAME "VBAGlobalConstantName" + //------------------------------------------------------------------------ // alles ohne Which-ID, Map nur fuer PropertySetInfo @@ -118,6 +121,7 @@ const SfxItemPropertyMapEntry* lcl_GetDocOptPropertyMap() {MAP_CHAR_LEN(SC_UNO_AUTOCONTFOC), 0, &getBooleanCppuType(), 0, 0}, {MAP_CHAR_LEN(SC_UNO_BASICLIBRARIES), 0, &getCppuType((uno::Reference< script::XLibraryContainer >*)0), beans::PropertyAttribute::READONLY, 0}, {MAP_CHAR_LEN(SC_UNO_DIALOGLIBRARIES), 0, &getCppuType((uno::Reference< script::XLibraryContainer >*)0), beans::PropertyAttribute::READONLY, 0}, + {MAP_CHAR_LEN(SC_UNO_VBAGLOBNAME), 0, &getCppuType(static_cast< const rtl::OUString * >(0)), beans::PropertyAttribute::READONLY, 0}, {MAP_CHAR_LEN(SC_UNO_CALCASSHOWN), PROP_UNO_CALCASSHOWN, &getBooleanCppuType(), 0, 0}, {MAP_CHAR_LEN(SC_UNONAME_CLOCAL), 0, &getCppuType((lang::Locale*)0), 0, 0}, {MAP_CHAR_LEN(SC_UNO_CJK_CLOCAL), 0, &getCppuType((lang::Locale*)0), 0, 0}, @@ -412,10 +416,14 @@ SfxObjectShell* ScModelObj::GetEmbeddedObject() const return pDocShell; } -void ScModelObj::UpdateAllRowHeights(const ScMarkData* pTabMark) +void ScModelObj::UpdateAllRowHeights(const ScMarkData* pTabMark, bool bCalcOutputFactor) { if (pDocShell) + { + if (bCalcOutputFactor) + pDocShell->CalcOutputFactor(); pDocShell->UpdateAllRowHeights(pTabMark); + } } void ScModelObj::BeforeXMLLoading() @@ -1904,6 +1912,15 @@ uno::Any SAL_CALL ScModelObj::getPropertyValue( const rtl::OUString& aPropertyNa { aRet <<= pDocShell->GetDialogContainer(); } + else if ( aString.EqualsAscii( SC_UNO_VBAGLOBNAME ) ) + { + /* #i111553# This property provides the name of the constant that + will be used to store this model in the global Basic manager. + That constant will be equivelant to 'ThisComponent' but for + each application, so e.g. a 'ThisExcelDoc' and a 'ThisWordDoc' + constant can co-exist, as required by VBA. */ + aRet <<= rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ThisExcelDoc" ) ); + } else if ( aString.EqualsAscii( SC_UNO_RUNTIMEUID ) ) { aRet <<= getRuntimeUID(); diff --git a/sc/source/ui/unoobj/linkuno.cxx b/sc/source/ui/unoobj/linkuno.cxx index ee6c3ff1988a..8b9e1039f085 100644 --- a/sc/source/ui/unoobj/linkuno.cxx +++ b/sc/source/ui/unoobj/linkuno.cxx @@ -1641,10 +1641,17 @@ Sequence< OUString > SAL_CALL ScExternalDocLinkObj::getElementNames() ScUnoGuard aGuard; vector<String> aTabNames; mpRefMgr->getAllCachedTableNames(mnFileId, aTabNames); - size_t n = aTabNames.size(); + + // #i116940# be consistent with getByName: include only table names which have a cache already + vector<String> aValidNames; + for (vector<String>::const_iterator aIter = aTabNames.begin(); aIter != aTabNames.end(); ++aIter) + if (mpRefMgr->getCacheTable(mnFileId, *aIter, false)) + aValidNames.push_back(*aIter); + + size_t n = aValidNames.size(); Sequence<OUString> aSeq(n); for (size_t i = 0; i < n; ++i) - aSeq[i] = aTabNames[i]; + aSeq[i] = aValidNames[i]; return aSeq; } @@ -1652,25 +1659,35 @@ sal_Bool SAL_CALL ScExternalDocLinkObj::hasByName(const OUString &aName) throw (RuntimeException) { ScUnoGuard aGuard; - return static_cast<sal_Bool>(mpRefMgr->hasCacheTable(mnFileId, aName)); + + // #i116940# be consistent with getByName: allow only table names which have a cache already + ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aName, false); + return (pTable.get() != NULL); } sal_Int32 SAL_CALL ScExternalDocLinkObj::getCount() throw (RuntimeException) { ScUnoGuard aGuard; - return static_cast<sal_Int32>(mpRefMgr->getCacheTableCount(mnFileId)); + + // #i116940# be consistent with getByName: count only table names which have a cache already + return getElementNames().getLength(); } -Any SAL_CALL ScExternalDocLinkObj::getByIndex(sal_Int32 nIndex) +Any SAL_CALL ScExternalDocLinkObj::getByIndex(sal_Int32 nApiIndex) throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, RuntimeException) { ScUnoGuard aGuard; - size_t nTabCount = mpRefMgr->getCacheTableCount(mnFileId); - if (nIndex < 0 || nIndex >= static_cast<sal_Int32>(nTabCount)) + + // #i116940# Can't use nApiIndex as index for the ref manager, because the API counts only + // the entries which have a cache already. Quick solution: Use getElementNames. + + Sequence< OUString > aNames( getElementNames() ); + if (nApiIndex < 0 || nApiIndex >= aNames.getLength()) throw lang::IndexOutOfBoundsException(); - ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, static_cast<size_t>(nIndex)); + size_t nIndex = 0; + ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aNames[nApiIndex], false, &nIndex); if (!pTable) throw lang::IndexOutOfBoundsException(); @@ -1702,7 +1719,9 @@ sal_Bool SAL_CALL ScExternalDocLinkObj::hasElements() throw (RuntimeException) { ScUnoGuard aGuard; - return static_cast<sal_Bool>(mpRefMgr->getCacheTableCount(mnFileId) > 0); + + // #i116940# be consistent with getByName: count only table names which have a cache already + return ( getElementNames().getLength() > 0 ); } sal_Int32 SAL_CALL ScExternalDocLinkObj::getTokenIndex() diff --git a/sc/source/ui/vba/excelvbahelper.cxx b/sc/source/ui/vba/excelvbahelper.cxx index 04d88935acfc..50623610b5b3 100644 --- a/sc/source/ui/vba/excelvbahelper.cxx +++ b/sc/source/ui/vba/excelvbahelper.cxx @@ -247,7 +247,7 @@ getViewFrame( const uno::Reference< frame::XModel >& xModel ) return NULL; } -uno::Reference< vba::XHelperInterface > +uno::Reference< XHelperInterface > getUnoSheetModuleObj( const uno::Reference< sheet::XSpreadsheet >& xSheet ) throw ( uno::RuntimeException ) { uno::Reference< beans::XPropertySet > xProps( xSheet, uno::UNO_QUERY_THROW ); @@ -258,8 +258,7 @@ getUnoSheetModuleObj( const uno::Reference< sheet::XSpreadsheet >& xSheet ) thro // are *NO* special document module objects ( of course being able to switch between vba/non vba mode at // the document in the future could fix this, especially IF the switching of the vba mode takes care to // create the special document module objects if they don't exist. - uno::Reference< XHelperInterface > xParent( ov::getUnoDocModule( sCodeName, GetDocShellFromRange( xSheet ) ), uno::UNO_QUERY ); - return xParent; + return getUnoDocModule( sCodeName, GetDocShellFromRange( xSheet ) ); } uno::Reference< XHelperInterface > diff --git a/sc/source/ui/vba/vbaapplication.cxx b/sc/source/ui/vba/vbaapplication.cxx index d3a38b984704..d7d0ae733ab7 100644 --- a/sc/source/ui/vba/vbaapplication.cxx +++ b/sc/source/ui/vba/vbaapplication.cxx @@ -40,6 +40,7 @@ #include <ooo/vba/excel/XlMousePointer.hpp> #include <com/sun/star/sheet/XNamedRanges.hpp> #include <com/sun/star/sheet/XCellRangeAddressable.hpp> +#include <ooo/vba/XExecutableDialog.hpp> #include "vbaapplication.hxx" #include "vbaworkbooks.hxx" @@ -98,17 +99,6 @@ using namespace ::com::sun::star; uno::Any sbxToUnoValue( SbxVariable* pVar ); -class ActiveWorkbook : public ScVbaWorkbook -{ -protected: - virtual uno::Reference< frame::XModel > getModel() - { - return getCurrentExcelDoc(mxContext); - } -public: - ActiveWorkbook( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext) : ScVbaWorkbook( xParent, xContext ){} -}; - // ============================================================================ /** Global application settings shared by all open workbooks. */ @@ -215,47 +205,15 @@ ScVbaApplication::hasProperty( const ::rtl::OUString& Name ) throw(uno::RuntimeE uno::Reference< excel::XWorkbook > ScVbaApplication::getActiveWorkbook() throw (uno::RuntimeException) { - uno::Reference< excel::XWorkbook > xWrkbk; - ScDocShell* pShell = excel::getDocShell( getCurrentExcelDoc( mxContext ) ); - if ( pShell ) - { - String aName; - if ( pShell->GetDocument() ) - { - aName = pShell->GetDocument()->GetCodeName(); - xWrkbk.set( getUnoDocModule( aName, pShell ), uno::UNO_QUERY ); - // fallback ( e.g. it's possible a new document was created via the api ) - // in that case the document will not have the appropriate Document Modules - // #TODO #FIXME ( needs to be fixes as part of providing support for an overall document - // vba mode etc. ) - if ( !xWrkbk.is() ) - return new ActiveWorkbook( this, mxContext ); - } - } - return xWrkbk; + // will throw if active document is not in VBA compatibility mode (no object for codename) + return uno::Reference< excel::XWorkbook >( getVBADocument( getCurrentExcelDoc( mxContext ) ), uno::UNO_QUERY_THROW ); } uno::Reference< excel::XWorkbook > SAL_CALL ScVbaApplication::getThisWorkbook() throw (uno::RuntimeException) { - uno::Reference< excel::XWorkbook > xWrkbk; - ScDocShell* pShell = excel::getDocShell( getThisExcelDoc( mxContext ) ); - if ( pShell ) - { - String aName; - if ( pShell->GetDocument() ) - { - aName = pShell->GetDocument()->GetCodeName(); - xWrkbk.set( getUnoDocModule( aName, pShell ), uno::UNO_QUERY ); - // fallback ( e.g. it's possible a new document was created via the api ) - // in that case the document will not have the appropriate Document Modules - // #TODO #FIXME ( needs to be fixes as part of providing support for an overall document - // vba mode etc. ) - if ( !xWrkbk.is() ) - return new ActiveWorkbook( this, mxContext ); - } - } - return xWrkbk; + // should never throw as this model is in VBA compatibility mode + return uno::Reference< excel::XWorkbook >( getVBADocument( getThisExcelDoc( mxContext ) ), uno::UNO_QUERY_THROW ); } uno::Reference< XAssistant > SAL_CALL @@ -343,17 +301,8 @@ ScVbaApplication::Workbooks( const uno::Any& aIndex ) throw (uno::RuntimeExcepti uno::Any SAL_CALL ScVbaApplication::Worksheets( const uno::Any& aIndex ) throw (uno::RuntimeException) { - uno::Reference< excel::XWorkbook > xWorkbook( getActiveWorkbook(), uno::UNO_QUERY ); - uno::Any result; - if ( xWorkbook.is() ) - result = xWorkbook->Worksheets( aIndex ); - - else - // Fixme - check if this is reasonable/desired behavior - throw uno::RuntimeException( rtl::OUString::createFromAscii( - "No ActiveWorkBook available" ), uno::Reference< uno::XInterface >() ); - - return result; + uno::Reference< excel::XWorkbook > xWorkbook( getActiveWorkbook(), uno::UNO_SET_THROW ); + return xWorkbook->Worksheets( aIndex ); } uno::Any SAL_CALL @@ -384,10 +333,10 @@ ScVbaApplication::Dialogs( const uno::Any &aIndex ) throw (uno::RuntimeException uno::Reference< excel::XWindow > SAL_CALL ScVbaApplication::getActiveWindow() throw (uno::RuntimeException) { - // #FIXME sofar can't determine Parent uno::Reference< frame::XModel > xModel = getCurrentDocument(); - ScVbaWindow* pWin = new ScVbaWindow( uno::Reference< XHelperInterface >(), mxContext, xModel ); - uno::Reference< excel::XWindow > xWin( pWin ); + uno::Reference< frame::XController > xController( xModel->getCurrentController(), uno::UNO_SET_THROW ); + uno::Reference< XHelperInterface > xParent( getActiveWorkbook(), uno::UNO_QUERY_THROW ); + uno::Reference< excel::XWindow > xWin( new ScVbaWindow( xParent, mxContext, xModel, xController ) ); return xWin; } @@ -792,37 +741,36 @@ rtl::OUString ScVbaApplication::getOfficePath( const rtl::OUString& _sPathType ) } return sRetPath; } + void SAL_CALL -ScVbaApplication::setDefaultFilePath( const ::rtl::OUString& DefaultFilePath ) throw (script::BasicErrorException, uno::RuntimeException) +ScVbaApplication::setDefaultFilePath( const ::rtl::OUString& DefaultFilePath ) throw (uno::RuntimeException) { uno::Reference< beans::XPropertySet > xProps = lcl_getPathSettingsService( mxContext ); rtl::OUString aURL; osl::FileBase::getFileURLFromSystemPath( DefaultFilePath, aURL ); - xProps->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Work")), uno::makeAny( aURL ) ); - - + xProps->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Work")), uno::Any( aURL ) ); } ::rtl::OUString SAL_CALL -ScVbaApplication::getDefaultFilePath( ) throw (script::BasicErrorException, uno::RuntimeException) +ScVbaApplication::getDefaultFilePath() throw (uno::RuntimeException) { return getOfficePath( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Work"))); } ::rtl::OUString SAL_CALL -ScVbaApplication::LibraryPath( ) throw (script::BasicErrorException, uno::RuntimeException) +ScVbaApplication::getLibraryPath() throw (uno::RuntimeException) { return getOfficePath( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Basic"))); } ::rtl::OUString SAL_CALL -ScVbaApplication::TemplatesPath( ) throw (script::BasicErrorException, uno::RuntimeException) +ScVbaApplication::getTemplatesPath() throw (uno::RuntimeException) { return getOfficePath( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("Template"))); } ::rtl::OUString SAL_CALL -ScVbaApplication::PathSeparator( ) throw (script::BasicErrorException, uno::RuntimeException) +ScVbaApplication::getPathSeparator() throw (uno::RuntimeException) { static rtl::OUString sPathSep( RTL_CONSTASCII_USTRINGPARAM( FILE_PATH_SEPERATOR ) ); return sPathSep; @@ -1174,6 +1122,40 @@ ScVbaApplication::Caller( const uno::Any& /*aIndex*/ ) throw ( uno::RuntimeExcep return aRet; } +uno::Any SAL_CALL ScVbaApplication::GetOpenFilename( + const uno::Any& rFileFilter, const uno::Any& rFilterIndex, const uno::Any& rTitle, + const uno::Any& rButtonText, const uno::Any& rMultiSelect ) throw (uno::RuntimeException) +{ + uno::Sequence< uno::Any > aArgs( 6 ); + aArgs[ 0 ] <<= getThisExcelDoc( mxContext ); + aArgs[ 1 ] = rFileFilter; + aArgs[ 2 ] = rFilterIndex; + aArgs[ 3 ] = rTitle; + aArgs[ 4 ] = rButtonText; + aArgs[ 5 ] = rMultiSelect; + uno::Reference< lang::XMultiComponentFactory > xFactory( mxContext->getServiceManager(), uno::UNO_SET_THROW ); + uno::Reference< XExecutableDialog > xFilePicker( xFactory->createInstanceWithArgumentsAndContext( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.OpenFilePicker" ) ), aArgs, mxContext ), uno::UNO_QUERY_THROW ); + return xFilePicker->execute(); +} + +uno::Any SAL_CALL ScVbaApplication::GetSaveAsFilename( + const uno::Any& rInitialFileName, const uno::Any& rFileFilter, const uno::Any& rFilterIndex, + const uno::Any& rTitle, const uno::Any& rButtonText ) throw (uno::RuntimeException) +{ + uno::Sequence< uno::Any > aArgs( 6 ); + aArgs[ 0 ] <<= getThisExcelDoc( mxContext ); + aArgs[ 1 ] = rInitialFileName; + aArgs[ 2 ] = rFileFilter; + aArgs[ 3 ] = rFilterIndex; + aArgs[ 4 ] = rTitle; + aArgs[ 5 ] = rButtonText; + uno::Reference< lang::XMultiComponentFactory > xFactory( mxContext->getServiceManager(), uno::UNO_SET_THROW ); + uno::Reference< XExecutableDialog > xFilePicker( xFactory->createInstanceWithArgumentsAndContext( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.SaveAsFilePicker" ) ), aArgs, mxContext ), uno::UNO_QUERY_THROW ); + return xFilePicker->execute(); +} + uno::Reference< frame::XModel > ScVbaApplication::getCurrentDocument() throw (css::uno::RuntimeException) { diff --git a/sc/source/ui/vba/vbaapplication.hxx b/sc/source/ui/vba/vbaapplication.hxx index bb696c967a37..b09fb66a8f91 100644 --- a/sc/source/ui/vba/vbaapplication.hxx +++ b/sc/source/ui/vba/vbaapplication.hxx @@ -73,11 +73,11 @@ public: virtual sal_Bool SAL_CALL hasProperty(const rtl::OUString& Name) throw(css::uno::RuntimeException); // XApplication - virtual ::rtl::OUString SAL_CALL PathSeparator( ) throw (css::script::BasicErrorException, css::uno::RuntimeException); - virtual void SAL_CALL setDefaultFilePath( const ::rtl::OUString& DefaultFilePath ) throw (css::script::BasicErrorException, css::uno::RuntimeException); - virtual ::rtl::OUString SAL_CALL getDefaultFilePath( ) throw (css::script::BasicErrorException, css::uno::RuntimeException); - virtual ::rtl::OUString SAL_CALL LibraryPath( ) throw (css::script::BasicErrorException, css::uno::RuntimeException); - virtual ::rtl::OUString SAL_CALL TemplatesPath( ) throw (css::script::BasicErrorException, css::uno::RuntimeException); + virtual void SAL_CALL setDefaultFilePath( const ::rtl::OUString& DefaultFilePath ) throw (css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getDefaultFilePath() throw (css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getPathSeparator() throw (css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getLibraryPath() throw (css::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getTemplatesPath() throw (css::uno::RuntimeException); virtual rtl::OUString SAL_CALL getName() throw (css::uno::RuntimeException); virtual sal_Bool SAL_CALL getDisplayAlerts() throw (css::uno::RuntimeException); @@ -120,6 +120,8 @@ public: virtual void SAL_CALL Volatile( const css::uno::Any& Volatile ) throw (css::uno::RuntimeException ); virtual void SAL_CALL DoEvents() throw (css::uno::RuntimeException); virtual css::uno::Any SAL_CALL Caller( const css::uno::Any& aIndex ) throw (css::uno::RuntimeException); + virtual css::uno::Any SAL_CALL GetOpenFilename( const css::uno::Any& rFileFilter, const css::uno::Any& rFilterIndex, const css::uno::Any& rTitle, const css::uno::Any& rButtonText, const css::uno::Any& rMultiSelect ) throw (css::uno::RuntimeException); + virtual css::uno::Any SAL_CALL GetSaveAsFilename( const css::uno::Any& rInitialFileName, const css::uno::Any& rFileFilter, const css::uno::Any& rFilterIndex, const css::uno::Any& rTitle, const css::uno::Any& rButtonText ) throw (css::uno::RuntimeException); // XHelperInterface virtual rtl::OUString& getServiceImplName(); virtual css::uno::Sequence<rtl::OUString> getServiceNames(); diff --git a/sc/source/ui/vba/vbaeventshelper.cxx b/sc/source/ui/vba/vbaeventshelper.cxx index 6ea807a16eae..e96b2d001e75 100755 --- a/sc/source/ui/vba/vbaeventshelper.cxx +++ b/sc/source/ui/vba/vbaeventshelper.cxx @@ -27,21 +27,22 @@ #include "vbaeventshelper.hxx" +#include <com/sun/star/awt/XTopWindow.hpp> +#include <com/sun/star/awt/XTopWindowListener.hpp> #include <com/sun/star/awt/XWindowListener.hpp> #include <com/sun/star/frame/XBorderResizeListener.hpp> #include <com/sun/star/frame/XControllerBorder.hpp> +#include <com/sun/star/script/ModuleType.hpp> #include <com/sun/star/script/vba/VBAEventId.hpp> #include <com/sun/star/sheet/XCellRangeAddressable.hpp> #include <com/sun/star/sheet/XSheetCellRangeContainer.hpp> #include <com/sun/star/table/XCellRange.hpp> #include <com/sun/star/util/XChangesListener.hpp> #include <com/sun/star/util/XChangesNotifier.hpp> -#include <com/sun/star/util/XCloseListener.hpp> - -#include <ooo/vba/excel/XApplication.hpp> #include <cppuhelper/implbase4.hxx> #include <toolkit/unohlp.hxx> +#include <unotools/eventcfg.hxx> #include <vbahelper/helperdecl.hxx> #include <vcl/svapp.hxx> #include <vcl/window.hxx> @@ -54,6 +55,8 @@ using namespace ::com::sun::star; using namespace ::com::sun::star::script::vba::VBAEventId; using namespace ::ooo::vba; +using ::rtl::OUString; + // ============================================================================ namespace { @@ -65,9 +68,13 @@ SCTAB lclGetTabFromArgs( const uno::Sequence< uno::Any >& rArgs, sal_Int32 nInde VbaEventsHelperBase::checkArgument( rArgs, nIndex ); // first try to extract a sheet index - SCTAB nTab = -1; + sal_Int32 nTab = -1; if( rArgs[ nIndex ] >>= nTab ) - return nTab; + { + if( (nTab < 0) || (nTab > MAXTAB) ) + throw lang::IllegalArgumentException(); + return static_cast< SCTAB >( nTab ); + } // try VBA Range object uno::Reference< excel::XRange > xVbaRange = getXSomethingFromArgs< excel::XRange >( rArgs, nIndex ); @@ -97,231 +104,271 @@ SCTAB lclGetTabFromArgs( const uno::Sequence< uno::Any >& rArgs, sal_Int32 nInde throw lang::IllegalArgumentException(); } +/** Returns the AWT container window of the passed controller. */ +uno::Reference< awt::XWindow > lclGetWindowForController( const uno::Reference< frame::XController >& rxController ) +{ + if( rxController.is() ) try + { + uno::Reference< frame::XFrame > xFrame( rxController->getFrame(), uno::UNO_SET_THROW ); + return xFrame->getContainerWindow(); + } + catch( uno::Exception& ) + { + } + return 0; +} + } // namespace // ============================================================================ -typedef ::cppu::WeakImplHelper4< - awt::XWindowListener, util::XCloseListener, frame::XBorderResizeListener, util::XChangesListener > ScVbaEventsListener_BASE; +typedef ::cppu::WeakImplHelper4< awt::XTopWindowListener, awt::XWindowListener, frame::XBorderResizeListener, util::XChangesListener > ScVbaEventListener_BASE; // This class is to process Workbook window related event -class ScVbaEventsListener : public ScVbaEventsListener_BASE +class ScVbaEventListener : public ScVbaEventListener_BASE { public : - ScVbaEventsListener( ScVbaEventsHelper& rVbaEvents, const uno::Reference< frame::XModel >& rxModel, ScDocShell* pDocShell ); - virtual ~ScVbaEventsListener(); - - void startListening(); - void stopListening(); + ScVbaEventListener( ScVbaEventsHelper& rVbaEvents, const uno::Reference< frame::XModel >& rxModel, ScDocShell* pDocShell ); + virtual ~ScVbaEventListener(); + + /** Starts listening to the passed document controller. */ + void startControllerListening( const uno::Reference< frame::XController >& rxController ); + /** Stops listening to the passed document controller. */ + void stopControllerListening( const uno::Reference< frame::XController >& rxController ); + + // XTopWindowListener + virtual void SAL_CALL windowOpened( const lang::EventObject& rEvent ) throw (uno::RuntimeException); + virtual void SAL_CALL windowClosing( const lang::EventObject& rEvent ) throw (uno::RuntimeException); + virtual void SAL_CALL windowClosed( const lang::EventObject& rEvent ) throw (uno::RuntimeException); + virtual void SAL_CALL windowMinimized( const lang::EventObject& rEvent ) throw (uno::RuntimeException); + virtual void SAL_CALL windowNormalized( const lang::EventObject& rEvent ) throw (uno::RuntimeException); + virtual void SAL_CALL windowActivated( const lang::EventObject& rEvent ) throw (uno::RuntimeException); + virtual void SAL_CALL windowDeactivated( const lang::EventObject& rEvent ) throw (uno::RuntimeException); // XWindowListener - virtual void SAL_CALL windowResized( const awt::WindowEvent& aEvent ) throw (uno::RuntimeException); - virtual void SAL_CALL windowMoved( const awt::WindowEvent& aEvent ) throw (uno::RuntimeException); - virtual void SAL_CALL windowShown( const lang::EventObject& aEvent ) throw (uno::RuntimeException); - virtual void SAL_CALL windowHidden( const lang::EventObject& aEvent ) throw (uno::RuntimeException); - virtual void SAL_CALL disposing( const lang::EventObject& aEvent ) throw (uno::RuntimeException); - - // XCloseListener - virtual void SAL_CALL queryClosing( const lang::EventObject& Source, ::sal_Bool GetsOwnership ) throw (util::CloseVetoException, uno::RuntimeException); - virtual void SAL_CALL notifyClosing( const lang::EventObject& Source ) throw (uno::RuntimeException); + virtual void SAL_CALL windowResized( const awt::WindowEvent& rEvent ) throw (uno::RuntimeException); + virtual void SAL_CALL windowMoved( const awt::WindowEvent& rEvent ) throw (uno::RuntimeException); + virtual void SAL_CALL windowShown( const lang::EventObject& rEvent ) throw (uno::RuntimeException); + virtual void SAL_CALL windowHidden( const lang::EventObject& rEvent ) throw (uno::RuntimeException); // XBorderResizeListener - virtual void SAL_CALL borderWidthsChanged( const uno::Reference< uno::XInterface >& aObject, const frame::BorderWidths& aNewSize ) throw (uno::RuntimeException); + virtual void SAL_CALL borderWidthsChanged( const uno::Reference< uno::XInterface >& rSource, const frame::BorderWidths& aNewSize ) throw (uno::RuntimeException); // XChangesListener - virtual void SAL_CALL changesOccurred( const util::ChangesEvent& aEvent ) throw (uno::RuntimeException); + virtual void SAL_CALL changesOccurred( const util::ChangesEvent& rEvent ) throw (uno::RuntimeException); + + // XEventListener + virtual void SAL_CALL disposing( const lang::EventObject& rEvent ) throw (uno::RuntimeException); private: - uno::Reference< frame::XFrame > getFrame(); - uno::Reference< awt::XWindow > getContainerWindow(); - bool isMouseReleased(); - DECL_LINK( fireResizeMacro, void* ); + /** Starts listening to the document model. */ + void startModelListening(); + /** Stops listening to the document model. */ + void stopModelListening(); + + /** Returns the controller for the passed VCL window. */ + uno::Reference< frame::XController > getControllerForWindow( Window* pWindow ) const; + + /** Calls the Workbook_Window[Activate|Deactivate] event handler. */ + void processWindowActivateEvent( Window* pWindow, bool bActivate ); + /** Posts a Workbook_WindowResize user event. */ + void postWindowResizeEvent( Window* pWindow ); + /** Callback link for Application::PostUserEvent(). */ + DECL_LINK( processWindowResizeEvent, Window* ); private: - ::osl::Mutex maMutex; - ScVbaEventsHelper& mrVbaEvents; + typedef ::std::map< Window*, uno::Reference< frame::XController > > WindowControllerMap; + + ::osl::Mutex maMutex; + ScVbaEventsHelper& mrVbaEvents; uno::Reference< frame::XModel > mxModel; - ScDocShell* mpDocShell; - bool mbWindowResized; - bool mbBorderChanged; - bool mbDisposed; + ScDocShell* mpDocShell; + WindowControllerMap maControllers; /// Maps VCL top windows to their controllers. + Window* mpActiveWindow; /// Currently activated window, to prevent multiple (de)activation. + bool mbWindowResized; /// True = window resize system event processed. + bool mbBorderChanged; /// True = borders changed system event processed. + bool mbDisposed; }; // ---------------------------------------------------------------------------- -ScVbaEventsListener::ScVbaEventsListener( ScVbaEventsHelper& rVbaEvents, const uno::Reference< frame::XModel >& rxModel, ScDocShell* pDocShell ) : +ScVbaEventListener::ScVbaEventListener( ScVbaEventsHelper& rVbaEvents, const uno::Reference< frame::XModel >& rxModel, ScDocShell* pDocShell ) : mrVbaEvents( rVbaEvents ), mxModel( rxModel ), mpDocShell( pDocShell ), + mpActiveWindow( 0 ), mbWindowResized( false ), mbBorderChanged( false ), mbDisposed( !rxModel.is() ) { - OSL_TRACE( "ScVbaEventsListener::ScVbaEventsListener( 0x%x ) - ctor ", this ); + if( !mxModel.is() ) + return; + + startModelListening(); + try + { + uno::Reference< frame::XController > xController( mxModel->getCurrentController(), uno::UNO_QUERY_THROW ); + startControllerListening( xController ); + } + catch( uno::Exception& ) + { + } } -ScVbaEventsListener::~ScVbaEventsListener() +ScVbaEventListener::~ScVbaEventListener() { - OSL_TRACE( "ScVbaEventsListener::~ScVbaEventsListener( 0x%x ) - dtor ", this ); - stopListening(); } -void ScVbaEventsListener::startListening() +void ScVbaEventListener::startControllerListening( const uno::Reference< frame::XController >& rxController ) { - if( !mbDisposed ) + ::osl::MutexGuard aGuard( maMutex ); + + uno::Reference< awt::XWindow > xWindow = lclGetWindowForController( rxController ); + if( xWindow.is() ) + try { xWindow->addWindowListener( this ); } catch( uno::Exception& ) {} + + uno::Reference< awt::XTopWindow > xTopWindow( xWindow, uno::UNO_QUERY ); + if( xTopWindow.is() ) + try { xTopWindow->addTopWindowListener( this ); } catch( uno::Exception& ) {} + + uno::Reference< frame::XControllerBorder > xControllerBorder( rxController, uno::UNO_QUERY ); + if( xControllerBorder.is() ) + try { xControllerBorder->addBorderResizeListener( this ); } catch( uno::Exception& ) {} + + if( Window* pWindow = VCLUnoHelper::GetWindow( xWindow ) ) + maControllers[ pWindow ] = rxController; +} + +void ScVbaEventListener::stopControllerListening( const uno::Reference< frame::XController >& rxController ) +{ + ::osl::MutexGuard aGuard( maMutex ); + + uno::Reference< awt::XWindow > xWindow = lclGetWindowForController( rxController ); + if( xWindow.is() ) + try { xWindow->removeWindowListener( this ); } catch( uno::Exception& ) {} + + uno::Reference< awt::XTopWindow > xTopWindow( xWindow, uno::UNO_QUERY ); + if( xTopWindow.is() ) + try { xTopWindow->removeTopWindowListener( this ); } catch( uno::Exception& ) {} + + uno::Reference< frame::XControllerBorder > xControllerBorder( rxController, uno::UNO_QUERY ); + if( xControllerBorder.is() ) + try { xControllerBorder->removeBorderResizeListener( this ); } catch( uno::Exception& ) {} + + if( Window* pWindow = VCLUnoHelper::GetWindow( xWindow ) ) { - // add window listener - try - { - uno::Reference< awt::XWindow > xWindow( getContainerWindow(), uno::UNO_QUERY_THROW ); - xWindow->addWindowListener( this ); - } - catch( uno::Exception& ) - { - } - // add close listener - try - { - uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( mxModel, uno::UNO_QUERY_THROW ); - xCloseBroadcaster->addCloseListener( this ); - } - catch( uno::Exception& ) - { - } - // add Border resize listener - try - { - uno::Reference< frame::XControllerBorder > xControllerBorder( mxModel->getCurrentController(), uno::UNO_QUERY_THROW ); - xControllerBorder->addBorderResizeListener( this ); - } - catch( uno::Exception& ) - { - } - // add content change listener - try - { - uno::Reference< util::XChangesNotifier > xChangesNotifier( mxModel, uno::UNO_QUERY_THROW ); - xChangesNotifier->addChangesListener( this ); - } - catch( uno::Exception& ) - { - } + maControllers.erase( pWindow ); + if( pWindow == mpActiveWindow ) + mpActiveWindow = 0; } } -void ScVbaEventsListener::stopListening() +void SAL_CALL ScVbaEventListener::windowOpened( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException) +{ +} + +void SAL_CALL ScVbaEventListener::windowClosing( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException) { +} + +void SAL_CALL ScVbaEventListener::windowClosed( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException) +{ +} + +void SAL_CALL ScVbaEventListener::windowMinimized( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException) +{ +} + +void SAL_CALL ScVbaEventListener::windowNormalized( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException) +{ +} + +void SAL_CALL ScVbaEventListener::windowActivated( const lang::EventObject& rEvent ) throw (uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( maMutex ); + if( !mbDisposed ) { - try - { - uno::Reference< awt::XWindow > xWindow( getContainerWindow(), uno::UNO_QUERY_THROW ); - xWindow->removeWindowListener( this ); - } - catch( uno::Exception& ) - { - } - try - { - uno::Reference< util::XCloseBroadcaster > xCloseBroadcaster( mxModel, uno::UNO_QUERY_THROW ); - xCloseBroadcaster->removeCloseListener( this ); - } - catch( uno::Exception& ) - { - } - try - { - uno::Reference< frame::XControllerBorder > xControllerBorder( mxModel->getCurrentController(), uno::UNO_QUERY_THROW ); - xControllerBorder->removeBorderResizeListener( this ); - } - catch( uno::Exception& ) - { - } - try - { - uno::Reference< util::XChangesNotifier > xChangesNotifier( mxModel, uno::UNO_QUERY_THROW ); - xChangesNotifier->removeChangesListener( this ); - } - catch( uno::Exception& ) + uno::Reference< awt::XWindow > xWindow( rEvent.Source, uno::UNO_QUERY ); + Window* pWindow = VCLUnoHelper::GetWindow( xWindow ); + OSL_TRACE( "ScVbaEventListener::windowActivated - pWindow = 0x%x, mpActiveWindow = 0x%x", pWindow, mpActiveWindow ); + // do not fire activation event multiple time for the same window + if( pWindow && (pWindow != mpActiveWindow) ) { + // if another window is active, fire deactivation event first + if( mpActiveWindow ) + processWindowActivateEvent( mpActiveWindow, false ); + // fire activation event for the new window + processWindowActivateEvent( pWindow, true ); + mpActiveWindow = pWindow; } } - mbDisposed = true; } -void SAL_CALL ScVbaEventsListener::windowResized( const awt::WindowEvent& /*aEvent*/ ) throw ( uno::RuntimeException ) +void SAL_CALL ScVbaEventListener::windowDeactivated( const lang::EventObject& rEvent ) throw (uno::RuntimeException) { ::osl::MutexGuard aGuard( maMutex ); - // Workbook_window_resize event - mbWindowResized = true; - if( !mbDisposed && mbBorderChanged ) + + if( !mbDisposed ) { - if( /*Window* pWindow =*/ VCLUnoHelper::GetWindow( getContainerWindow() ) ) - { - mbBorderChanged = mbWindowResized = false; - acquire(); // ensure we don't get deleted before the event is handled - Application::PostUserEvent( LINK( this, ScVbaEventsListener, fireResizeMacro ), 0 ); - } + uno::Reference< awt::XWindow > xWindow( rEvent.Source, uno::UNO_QUERY ); + Window* pWindow = VCLUnoHelper::GetWindow( xWindow ); + OSL_TRACE( "ScVbaEventListener::windowDeactivated - pWindow = 0x%x, mpActiveWindow = 0x%x", pWindow, mpActiveWindow ); + // do not fire the deactivation event, if the window is not active (prevent multiple deactivation) + if( pWindow && (pWindow == mpActiveWindow) ) + processWindowActivateEvent( pWindow, false ); + // forget pointer to the active window + mpActiveWindow = 0; } } -void SAL_CALL ScVbaEventsListener::windowMoved( const awt::WindowEvent& /*aEvent*/ ) throw ( uno::RuntimeException ) +void SAL_CALL ScVbaEventListener::windowResized( const awt::WindowEvent& rEvent ) throw (uno::RuntimeException) { - // not interest this time -} + ::osl::MutexGuard aGuard( maMutex ); -void SAL_CALL ScVbaEventsListener::windowShown( const lang::EventObject& /*aEvent*/ ) throw ( uno::RuntimeException ) -{ - // not interest this time + mbWindowResized = true; + if( !mbDisposed && mbBorderChanged ) + { + uno::Reference< awt::XWindow > xWindow( rEvent.Source, uno::UNO_QUERY ); + postWindowResizeEvent( VCLUnoHelper::GetWindow( xWindow ) ); + } } -void SAL_CALL ScVbaEventsListener::windowHidden( const lang::EventObject& /*aEvent*/ ) throw ( uno::RuntimeException ) +void SAL_CALL ScVbaEventListener::windowMoved( const awt::WindowEvent& /*rEvent*/ ) throw (uno::RuntimeException) { - // not interest this time } -void SAL_CALL ScVbaEventsListener::disposing( const lang::EventObject& /*aEvent*/ ) throw ( uno::RuntimeException ) +void SAL_CALL ScVbaEventListener::windowShown( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException) { - ::osl::MutexGuard aGuard( maMutex ); - OSL_TRACE( "ScVbaEventsListener::disposing( 0x%x )", this ); - mbDisposed = true; } -void SAL_CALL ScVbaEventsListener::queryClosing( const lang::EventObject& /*Source*/, sal_Bool /*GetsOwnership*/ ) throw (util::CloseVetoException, uno::RuntimeException) +void SAL_CALL ScVbaEventListener::windowHidden( const lang::EventObject& /*rEvent*/ ) throw (uno::RuntimeException) { - // it can cancel the close, but need to throw a CloseVetoException, and it will be transmit to caller. } -void SAL_CALL ScVbaEventsListener::notifyClosing( const lang::EventObject& /*Source*/ ) throw (uno::RuntimeException) +void SAL_CALL ScVbaEventListener::borderWidthsChanged( const uno::Reference< uno::XInterface >& rSource, const frame::BorderWidths& /*aNewSize*/ ) throw (uno::RuntimeException) { ::osl::MutexGuard aGuard( maMutex ); - stopListening(); -} -void SAL_CALL ScVbaEventsListener::borderWidthsChanged( const uno::Reference< uno::XInterface >& /*aObject*/, const frame::BorderWidths& /*aNewSize*/ ) throw (uno::RuntimeException) -{ - ::osl::MutexGuard aGuard( maMutex ); - // work with WindowResized event to guard Window Resize event. mbBorderChanged = true; if( !mbDisposed && mbWindowResized ) { - if( /*Window* pWindow =*/ VCLUnoHelper::GetWindow( getContainerWindow() ) ) - { - mbWindowResized = mbBorderChanged = false; - acquire(); // ensure we don't get deleted before the timer fires. - Application::PostUserEvent( LINK( this, ScVbaEventsListener, fireResizeMacro ), 0 ); - } + uno::Reference< frame::XController > xController( rSource, uno::UNO_QUERY ); + uno::Reference< awt::XWindow > xWindow = lclGetWindowForController( xController ); + postWindowResizeEvent( VCLUnoHelper::GetWindow( xWindow ) ); } } -void SAL_CALL ScVbaEventsListener::changesOccurred( const util::ChangesEvent& aEvent ) throw (uno::RuntimeException) +void SAL_CALL ScVbaEventListener::changesOccurred( const util::ChangesEvent& rEvent ) throw (uno::RuntimeException) { - sal_Int32 nCount = aEvent.Changes.getLength(); - if( nCount == 0 ) + ::osl::MutexGuard aGuard( maMutex ); + + sal_Int32 nCount = rEvent.Changes.getLength(); + if( mbDisposed || !mpDocShell || (nCount == 0) ) return; - util::ElementChange aChange = aEvent.Changes[ 0 ]; - rtl::OUString sOperation; + util::ElementChange aChange = rEvent.Changes[ 0 ]; + OUString sOperation; aChange.Accessor >>= sOperation; if( !sOperation.equalsIgnoreAsciiCaseAscii("cell-change") ) return; @@ -334,7 +381,7 @@ void SAL_CALL ScVbaEventsListener::changesOccurred( const util::ChangesEvent& aE { uno::Sequence< uno::Any > aArgs( 1 ); aArgs[0] <<= xRangeObj; - mrVbaEvents.processVbaEvent( WORKSHEET_CHANGE, aArgs ); + mrVbaEvents.processVbaEventNoThrow( WORKSHEET_CHANGE, aArgs ); } return; } @@ -342,7 +389,7 @@ void SAL_CALL ScVbaEventsListener::changesOccurred( const util::ChangesEvent& aE ScRangeList aRangeList; for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex ) { - aChange = aEvent.Changes[ nIndex ]; + aChange = rEvent.Changes[ nIndex ]; aChange.Accessor >>= sOperation; uno::Reference< table::XCellRange > xRangeObj; aChange.ReplacedElement >>= xRangeObj; @@ -358,62 +405,117 @@ void SAL_CALL ScVbaEventsListener::changesOccurred( const util::ChangesEvent& aE } } - if( (aRangeList.Count() > 0) && mpDocShell ) + if( aRangeList.Count() > 0 ) { uno::Reference< sheet::XSheetCellRangeContainer > xRanges( new ScCellRangesObj( mpDocShell, aRangeList ) ); uno::Sequence< uno::Any > aArgs(1); aArgs[0] <<= xRanges; - mrVbaEvents.processVbaEvent( WORKSHEET_CHANGE, aArgs ); + mrVbaEvents.processVbaEventNoThrow( WORKSHEET_CHANGE, aArgs ); } } -// ---------------------------------------------------------------------------- +void SAL_CALL ScVbaEventListener::disposing( const lang::EventObject& rEvent ) throw (uno::RuntimeException) +{ + ::osl::MutexGuard aGuard( maMutex ); + + uno::Reference< frame::XModel > xModel( rEvent.Source, uno::UNO_QUERY ); + if( xModel.is() ) + { + OSL_ENSURE( xModel.get() == mxModel.get(), "ScVbaEventListener::disposing - disposing from unknown model" ); + stopModelListening(); + mbDisposed = true; + return; + } + + uno::Reference< frame::XController > xController( rEvent.Source, uno::UNO_QUERY ); + if( xController.is() ) + { + stopControllerListening( xController ); + return; + } +} -uno::Reference< frame::XFrame > ScVbaEventsListener::getFrame() +// private -------------------------------------------------------------------- + +void ScVbaEventListener::startModelListening() { - if( !mbDisposed && mxModel.is() ) try + try { - uno::Reference< frame::XController > xController( mxModel->getCurrentController(), uno::UNO_QUERY_THROW ); - return xController->getFrame(); + uno::Reference< util::XChangesNotifier > xChangesNotifier( mxModel, uno::UNO_QUERY_THROW ); + xChangesNotifier->addChangesListener( this ); } catch( uno::Exception& ) { } - return uno::Reference< frame::XFrame >(); } -uno::Reference< awt::XWindow > ScVbaEventsListener::getContainerWindow() +void ScVbaEventListener::stopModelListening() { try { - uno::Reference< frame::XFrame > xFrame( getFrame(), uno::UNO_SET_THROW ); - return xFrame->getContainerWindow(); + uno::Reference< util::XChangesNotifier > xChangesNotifier( mxModel, uno::UNO_QUERY_THROW ); + xChangesNotifier->removeChangesListener( this ); } catch( uno::Exception& ) { } - return uno::Reference< awt::XWindow >(); } -bool ScVbaEventsListener::isMouseReleased() +uno::Reference< frame::XController > ScVbaEventListener::getControllerForWindow( Window* pWindow ) const { - if( Window* pWindow = VCLUnoHelper::GetWindow( getContainerWindow() ) ) + WindowControllerMap::const_iterator aIt = maControllers.find( pWindow ); + return (aIt == maControllers.end()) ? uno::Reference< frame::XController >() : aIt->second; +} + +void ScVbaEventListener::processWindowActivateEvent( Window* pWindow, bool bActivate ) +{ + uno::Reference< frame::XController > xController = getControllerForWindow( pWindow ); + if( xController.is() ) { - Window::PointerState aPointerState = pWindow->GetPointerState(); - return (aPointerState.mnState & ( MOUSE_LEFT | MOUSE_MIDDLE | MOUSE_RIGHT )) == 0; + uno::Sequence< uno::Any > aArgs( 1 ); + aArgs[ 0 ] <<= xController; + mrVbaEvents.processVbaEventNoThrow( bActivate ? WORKBOOK_WINDOWACTIVATE : WORKBOOK_WINDOWDEACTIVATE, aArgs ); } - return false; } -IMPL_LINK( ScVbaEventsListener, fireResizeMacro, void*, EMPTYARG ) +void ScVbaEventListener::postWindowResizeEvent( Window* pWindow ) { - if( !mbDisposed && isMouseReleased() ) try + // check that the passed window is still alive (it must be registered in maControllers) + if( pWindow && (maControllers.count( pWindow ) > 0) ) { - mrVbaEvents.processVbaEvent( WORKBOOK_WINDOWRESIZE, uno::Sequence< uno::Any >() ); + mbWindowResized = mbBorderChanged = false; + acquire(); // ensure we don't get deleted before the timer fires + Application::PostUserEvent( LINK( this, ScVbaEventListener, processWindowResizeEvent ), pWindow ); } - catch( uno::Exception& ) +} + +IMPL_LINK( ScVbaEventListener, processWindowResizeEvent, Window*, EMPTYARG pWindow ) +{ + ::osl::MutexGuard aGuard( maMutex ); + + /* Check that the passed window is still alive (it must be registered in + maControllers). While closing a document, postWindowResizeEvent() may + be called on the last window which posts a user event via + Application::PostUserEvent to call this event handler. VCL will trigger + the handler some time later. Sometimes, the window gets deleted before. + This is handled via the disposing() function which removes the window + pointer from the member maControllers. Thus, checking whether + maControllers contains pWindow ensures that the window is still alive. */ + if( !mbDisposed && pWindow && (maControllers.count( pWindow ) > 0) ) { - // #163419# do not throw exceptions into application core + // do not fire event unless all mouse buttons have been released + Window::PointerState aPointerState = pWindow->GetPointerState(); + if( (aPointerState.mnState & (MOUSE_LEFT | MOUSE_MIDDLE | MOUSE_RIGHT)) == 0 ) + { + uno::Reference< frame::XController > xController = getControllerForWindow( pWindow ); + if( xController.is() ) + { + uno::Sequence< uno::Any > aArgs( 1 ); + aArgs[ 0 ] <<= xController; + // #163419# do not throw exceptions into application core + mrVbaEvents.processVbaEventNoThrow( WORKBOOK_WINDOWRESIZE, aArgs ); + } + } } release(); return 0; @@ -431,19 +533,19 @@ ScVbaEventsHelper::ScVbaEventsHelper( const uno::Sequence< uno::Any >& rArgs, co if( !mxModel.is() || !mpDocShell || !mpDoc ) return; -#define REGISTER_EVENT( eventid, eventname, type, cancelindex, worksheet ) \ - registerEventHandler( eventid, eventname, type, cancelindex, uno::Any( worksheet ) ) - +#define REGISTER_EVENT( eventid, moduletype, classname, eventname, cancelindex, worksheet ) \ + registerEventHandler( eventid, moduletype, classname "_" eventname, cancelindex, uno::Any( worksheet ) ) +#define REGISTER_AUTO_EVENT( eventid, eventname ) \ + REGISTER_EVENT( AUTO_##eventid, script::ModuleType::NORMAL, "Auto", eventname, -1, false ) #define REGISTER_WORKBOOK_EVENT( eventid, eventname, cancelindex ) \ - REGISTER_EVENT( WORKBOOK_##eventid, "Workbook_" eventname, EVENTHANDLER_DOCUMENT, cancelindex, false ) - + REGISTER_EVENT( WORKBOOK_##eventid, script::ModuleType::DOCUMENT, "Workbook", eventname, cancelindex, false ) #define REGISTER_WORKSHEET_EVENT( eventid, eventname, cancelindex ) \ - REGISTER_EVENT( WORKSHEET_##eventid, "Worksheet_" eventname, EVENTHANDLER_DOCUMENT, cancelindex, true ); \ - REGISTER_EVENT( (USERDEFINED_START + WORKSHEET_##eventid), "Workbook_Sheet" eventname, EVENTHANDLER_DOCUMENT, (((cancelindex) >= 0) ? ((cancelindex) + 1) : -1), false ) + REGISTER_EVENT( WORKSHEET_##eventid, script::ModuleType::DOCUMENT, "Worksheet", eventname, cancelindex, true ); \ + REGISTER_EVENT( (USERDEFINED_START + WORKSHEET_##eventid), script::ModuleType::DOCUMENT, "Workbook", "Sheet" eventname, (((cancelindex) >= 0) ? ((cancelindex) + 1) : -1), false ) // global - REGISTER_EVENT( AUTO_OPEN, "Auto_Open", EVENTHANDLER_GLOBAL, -1, false ); - REGISTER_EVENT( AUTO_CLOSE, "Auto_Close", EVENTHANDLER_GLOBAL, -1, false ); + REGISTER_AUTO_EVENT( OPEN, "Open" ); + REGISTER_AUTO_EVENT( CLOSE, "Close" ); // Workbook REGISTER_WORKBOOK_EVENT( ACTIVATE, "Activate", -1 ); @@ -468,19 +570,68 @@ ScVbaEventsHelper::ScVbaEventsHelper( const uno::Sequence< uno::Any >& rArgs, co REGISTER_WORKSHEET_EVENT( SELECTIONCHANGE, "SelectionChange", -1 ); REGISTER_WORKSHEET_EVENT( FOLLOWHYPERLINK, "FollowHyperlink", -1 ); -#undef REGISTER_EVENT -#undef REGISTER_WORKBOOK_EVENT #undef REGISTER_WORKSHEET_EVENT +#undef REGISTER_WORKBOOK_EVENT +#undef REGISTER_AUTO_EVENT +#undef REGISTER_EVENT } ScVbaEventsHelper::~ScVbaEventsHelper() { } -void SAL_CALL ScVbaEventsHelper::disposing( const lang::EventObject& rSource ) throw (uno::RuntimeException) +void SAL_CALL ScVbaEventsHelper::notifyEvent( const css::document::EventObject& rEvent ) throw (css::uno::RuntimeException) { - mxListener.clear(); - VbaEventsHelperBase::disposing( rSource ); + static const uno::Sequence< uno::Any > saEmptyArgs; + if( (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_OPENDOC )) || + (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_CREATEDOC )) ) // CREATEDOC triggered e.g. during VBA Workbooks.Add + { + processVbaEventNoThrow( WORKBOOK_OPEN, saEmptyArgs ); + } + else if( rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_ACTIVATEDOC ) ) + { + processVbaEventNoThrow( WORKBOOK_ACTIVATE, saEmptyArgs ); + } + else if( rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_DEACTIVATEDOC ) ) + { + processVbaEventNoThrow( WORKBOOK_DEACTIVATE, saEmptyArgs ); + } + else if( (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_SAVEDOCDONE )) || + (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_SAVEASDOCDONE )) || + (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_SAVETODOCDONE )) ) + { + uno::Sequence< uno::Any > aArgs( 1 ); + aArgs[ 0 ] <<= true; + processVbaEventNoThrow( WORKBOOK_AFTERSAVE, aArgs ); + } + else if( (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_SAVEDOCFAILED )) || + (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_SAVEASDOCFAILED )) || + (rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_SAVETODOCFAILED )) ) + { + uno::Sequence< uno::Any > aArgs( 1 ); + aArgs[ 0 ] <<= false; + processVbaEventNoThrow( WORKBOOK_AFTERSAVE, aArgs ); + } + else if( rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_CLOSEDOC ) ) + { + /* Trigger the WORKBOOK_WINDOWDEACTIVATE and WORKBOOK_DEACTIVATE + events and stop listening to the model (done in base class). */ + uno::Reference< frame::XController > xController( mxModel->getCurrentController() ); + if( xController.is() ) + { + uno::Sequence< uno::Any > aArgs( 1 ); + aArgs[ 0 ] <<= xController; + processVbaEventNoThrow( WORKBOOK_WINDOWDEACTIVATE, aArgs ); + } + processVbaEventNoThrow( WORKBOOK_DEACTIVATE, saEmptyArgs ); + } + else if( rEvent.EventName == GlobalEventConfig::GetEventName( STR_EVENT_VIEWCREATED ) ) + { + uno::Reference< frame::XController > xController( mxModel->getCurrentController() ); + if( mxListener.get() && xController.is() ) + mxListener->startControllerListening( xController ); + } + VbaEventsHelperBase::notifyEvent( rEvent ); } // protected ------------------------------------------------------------------ @@ -492,25 +643,35 @@ bool ScVbaEventsHelper::implPrepareEvent( EventQueue& rEventQueue, if( !mpShell || !mpDoc ) throw uno::RuntimeException(); - // framework and Calc fire a few events before 'opened', ignore them - bool bExecuteEvent = mbOpened; + /* For document events: check if events are enabled via the + Application.EnableEvents symbol (this is an Excel-only attribute). + Check this again for every event, as the event handler may change the + state of the EnableEvents symbol. Global events such as AUTO_OPEN and + AUTO_CLOSE are always enabled. */ + bool bExecuteEvent = (rInfo.mnModuleType != script::ModuleType::DOCUMENT) || ScVbaApplication::getDocumentEventsEnabled(); + + // framework and Calc fire a few events before 'OnLoad', ignore them + if( bExecuteEvent ) + bExecuteEvent = (rInfo.mnEventId == WORKBOOK_OPEN) ? !mbOpened : mbOpened; // special handling for some events - switch( rInfo.mnEventId ) + if( bExecuteEvent ) switch( rInfo.mnEventId ) { case WORKBOOK_OPEN: - bExecuteEvent = !mbOpened; - if( bExecuteEvent ) - { - // execute delayed Activate event too (see above) - rEventQueue.push_back( WORKBOOK_ACTIVATE ); - rEventQueue.push_back( WORKBOOK_WINDOWACTIVATE ); - rEventQueue.push_back( AUTO_OPEN ); - } + { + // execute delayed Activate event too (see above) + rEventQueue.push_back( WORKBOOK_ACTIVATE ); + uno::Sequence< uno::Any > aArgs( 1 ); + aArgs[ 0 ] <<= mxModel->getCurrentController(); + rEventQueue.push_back( EventQueueEntry( WORKBOOK_WINDOWACTIVATE, aArgs ) ); + rEventQueue.push_back( AUTO_OPEN ); + // remember initial selection + maOldSelection <<= mxModel->getCurrentSelection(); + } break; case WORKSHEET_SELECTIONCHANGE: // if selection is not changed, then do not fire the event - bExecuteEvent = bExecuteEvent && isSelectionChanged( rArgs, 0 ); + bExecuteEvent = isSelectionChanged( rArgs, 0 ); break; } @@ -520,14 +681,6 @@ bool ScVbaEventsHelper::implPrepareEvent( EventQueue& rEventQueue, bool bSheetEvent = false; if( (rInfo.maUserData >>= bSheetEvent) && bSheetEvent ) rEventQueue.push_back( EventQueueEntry( rInfo.mnEventId + USERDEFINED_START, rArgs ) ); - - /* For document events: check if events are enabled via the - Application.EnableEvents symbol (this is an Excel-only attribute). - Check this again for every event, as the event handler may change - the state of the EnableEvents symbol. Global events such as - AUTO_OPEN and AUTO_CLOSE are always enabled. */ - if( rInfo.meType == EVENTHANDLER_DOCUMENT ) - bExecuteEvent = ScVbaApplication::getDocumentEventsEnabled(); } return bExecuteEvent; @@ -574,7 +727,7 @@ uno::Sequence< uno::Any > ScVbaEventsHelper::implBuildArgumentList( const EventH case WORKBOOK_WINDOWDEACTIVATE: case WORKBOOK_WINDOWRESIZE: aVbaArgs.realloc( 1 ); - aVbaArgs[ 0 ] = createWindow(); + aVbaArgs[ 0 ] = createWindow( rArgs, 0 ); break; // 1 arg: worksheet case WORKBOOK_NEWSHEET: @@ -625,7 +778,7 @@ uno::Sequence< uno::Any > ScVbaEventsHelper::implBuildArgumentList( const EventH } void ScVbaEventsHelper::implPostProcessEvent( EventQueue& rEventQueue, - const EventHandlerInfo& rInfo, bool /*bSuccess*/, bool bCancel ) throw (uno::RuntimeException) + const EventHandlerInfo& rInfo, bool bCancel ) throw (uno::RuntimeException) { switch( rInfo.mnEventId ) { @@ -633,10 +786,7 @@ void ScVbaEventsHelper::implPostProcessEvent( EventQueue& rEventQueue, mbOpened = true; // register the listeners if( !mxListener.is() ) - { - mxListener = new ScVbaEventsListener( *this, mxModel, mpDocShell ); - mxListener->startListening(); - } + mxListener = new ScVbaEventListener( *this, mxModel, mpDocShell ); break; case WORKBOOK_BEFORECLOSE: /* Execute Auto_Close only if not cancelled by event handler, but @@ -647,7 +797,7 @@ void ScVbaEventsHelper::implPostProcessEvent( EventQueue& rEventQueue, } } -::rtl::OUString ScVbaEventsHelper::implGetDocumentModuleName( const EventHandlerInfo& rInfo, +OUString ScVbaEventsHelper::implGetDocumentModuleName( const EventHandlerInfo& rInfo, const uno::Sequence< uno::Any >& rArgs ) const throw (lang::IllegalArgumentException) { bool bSheetEvent = false; @@ -746,11 +896,13 @@ uno::Any ScVbaEventsHelper::createHyperlink( const uno::Sequence< uno::Any >& rA return uno::Any( xHyperlink ); } -uno::Any ScVbaEventsHelper::createWindow() const throw (uno::RuntimeException) +uno::Any ScVbaEventsHelper::createWindow( const uno::Sequence< uno::Any >& rArgs, sal_Int32 nIndex ) const + throw (lang::IllegalArgumentException, uno::RuntimeException) { - uno::Sequence< uno::Any > aArgs( 2 ); - aArgs[ 0 ] <<= createVBAUnoAPIService( mpShell, "ooo.vba.Application" ); + uno::Sequence< uno::Any > aArgs( 3 ); + aArgs[ 0 ] <<= getVBADocument( mxModel ); aArgs[ 1 ] <<= mxModel; + aArgs[ 2 ] <<= getXSomethingFromArgs< frame::XController >( rArgs, nIndex, false ); uno::Reference< uno::XInterface > xWindow( createVBAUnoAPIServiceWithArgs( mpShell, "ooo.vba.excel.Window", aArgs ), uno::UNO_SET_THROW ); return uno::Any( xWindow ); } diff --git a/sc/source/ui/vba/vbaeventshelper.hxx b/sc/source/ui/vba/vbaeventshelper.hxx index f1e8a4fb712d..4e7e3b52f610 100755 --- a/sc/source/ui/vba/vbaeventshelper.hxx +++ b/sc/source/ui/vba/vbaeventshelper.hxx @@ -25,15 +25,15 @@ * ************************************************************************/ -#ifndef SC_VBAEVENTS_HXX -#define SC_VBAEVENTS_HXX +#ifndef SC_VBAEVENTSHELPER_HXX +#define SC_VBAEVENTSHELPER_HXX #include <rtl/ref.hxx> #include <vbahelper/vbaeventshelperbase.hxx> #include "excelvbahelper.hxx" #include "rangelst.hxx" -class ScVbaEventsListener; +class ScVbaEventListener; // ============================================================================ @@ -45,13 +45,12 @@ public: const css::uno::Reference< css::uno::XComponentContext >& rxContext ); virtual ~ScVbaEventsHelper(); - // XEventListener - virtual void SAL_CALL disposing( const css::lang::EventObject& rSource ) throw (css::uno::RuntimeException); + virtual void SAL_CALL notifyEvent( const css::document::EventObject& rEvent ) throw (css::uno::RuntimeException); protected: virtual bool implPrepareEvent( EventQueue& rEventQueue, const EventHandlerInfo& rInfo, const css::uno::Sequence< css::uno::Any >& rArgs ) throw (css::uno::RuntimeException); virtual css::uno::Sequence< css::uno::Any > implBuildArgumentList( const EventHandlerInfo& rInfo, const css::uno::Sequence< css::uno::Any >& rArgs ) throw (css::lang::IllegalArgumentException); - virtual void implPostProcessEvent( EventQueue& rEventQueue, const EventHandlerInfo& rInfo, bool bSuccess, bool bCancel ) throw (css::uno::RuntimeException); + virtual void implPostProcessEvent( EventQueue& rEventQueue, const EventHandlerInfo& rInfo, bool bCancel ) throw (css::uno::RuntimeException); virtual ::rtl::OUString implGetDocumentModuleName( const EventHandlerInfo& rInfo, const css::uno::Sequence< css::uno::Any >& rArgs ) const throw (css::lang::IllegalArgumentException); private: @@ -65,11 +64,11 @@ private: css::uno::Any createRange( const css::uno::Sequence< css::uno::Any >& rArgs, sal_Int32 nIndex ) const throw (css::lang::IllegalArgumentException, css::uno::RuntimeException); /** Creates a VBA Hyperlink object (the argument must contain a UNO cell). */ css::uno::Any createHyperlink( const css::uno::Sequence< css::uno::Any >& rArgs, sal_Int32 nIndex ) const throw (css::lang::IllegalArgumentException, css::uno::RuntimeException); - /** Creates a VBA Window object. */ - css::uno::Any createWindow() const throw (css::uno::RuntimeException); + /** Creates a VBA Window object (the argument must contain a model controller). */ + css::uno::Any createWindow( const css::uno::Sequence< css::uno::Any >& rArgs, sal_Int32 nIndex ) const throw (css::lang::IllegalArgumentException, css::uno::RuntimeException); private: - ::rtl::Reference< ScVbaEventsListener > mxListener; + ::rtl::Reference< ScVbaEventListener > mxListener; css::uno::Any maOldSelection; ScDocShell* mpDocShell; ScDocument* mpDoc; diff --git a/sc/source/ui/vba/vbaformat.cxx b/sc/source/ui/vba/vbaformat.cxx index 3b0ba2367c1a..0186b5a78645 100644 --- a/sc/source/ui/vba/vbaformat.cxx +++ b/sc/source/ui/vba/vbaformat.cxx @@ -62,10 +62,10 @@ ScVbaFormat< Ifc1 >::ScVbaFormat( const uno::Reference< XHelperInterface >& xPar { try { - mxServiceInfo.set( mxPropertySet, uno::UNO_QUERY_THROW ); if ( !mxModel.is() ) DebugHelper::exception(SbERR_METHOD_FAILED, rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "XModel Interface could not be retrieved") ) ); - mxNumberFormatsSupplier.set( mxModel, uno::UNO_QUERY_THROW ); + // mxServiceInfo is unused, + // mxNumberFormatsSupplier is initialized when needed in initializeNumberFormats. } catch (uno::Exception& ) { diff --git a/sc/source/ui/vba/vbaformat.hxx b/sc/source/ui/vba/vbaformat.hxx index bfa88d6c7cb8..b875f84c69cd 100644 --- a/sc/source/ui/vba/vbaformat.hxx +++ b/sc/source/ui/vba/vbaformat.hxx @@ -52,7 +52,6 @@ protected: css::uno::Reference< css::util::XNumberFormats > xNumberFormats; css::uno::Reference< css::util::XNumberFormatTypes > xNumberFormatTypes; css::uno::Reference< css::frame::XModel > mxModel; - css::uno::Reference< css::lang::XServiceInfo > mxServiceInfo; css::uno::Reference< css::beans::XPropertyState > xPropertyState; sal_Bool mbCheckAmbiguoity; sal_Bool mbAddIndent; @@ -69,7 +68,6 @@ public: ScVbaFormat( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext > & xContext, const css::uno::Reference< css::beans::XPropertySet >& _xPropertySet, const css::uno::Reference< css::frame::XModel >& xModel, bool bCheckAmbiguoity ) throw ( css::script::BasicErrorException ); virtual ~ScVbaFormat() {} virtual css::uno::Reference< ov::XHelperInterface > thisHelperIface() = 0; - css::uno::Reference< css::lang::XServiceInfo > getXServiceInfo() { return mxServiceInfo; } void SAL_CALL setAddIndent( const css::uno::Any& _BAddIndent) throw( css::uno::RuntimeException ) { _BAddIndent >>= mbAddIndent; } css::uno::Any SAL_CALL getAddIndent() throw( css::uno::RuntimeException ) { return css::uno::makeAny( mbAddIndent ); } // Interface Methods diff --git a/sc/source/ui/vba/vbaglobals.cxx b/sc/source/ui/vba/vbaglobals.cxx index c70a7f83726d..f9ab063937cf 100644 --- a/sc/source/ui/vba/vbaglobals.cxx +++ b/sc/source/ui/vba/vbaglobals.cxx @@ -234,11 +234,9 @@ ScVbaGlobals::getDebug() throw (uno::RuntimeException) { try // return empty object on error { - uno::Sequence< uno::Any > aArgs( 1 ); - aArgs[ 0 ] <<= uno::Reference< XHelperInterface >( this ); uno::Reference< lang::XMultiComponentFactory > xServiceManager( mxContext->getServiceManager(), uno::UNO_SET_THROW ); - uno::Reference< uno::XInterface > xVBADebug = xServiceManager->createInstanceWithArgumentsAndContext( - ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.Debug" ) ), aArgs, mxContext ); + uno::Reference< uno::XInterface > xVBADebug = xServiceManager->createInstanceWithContext( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.Debug" ) ), mxContext ); return uno::Any( xVBADebug ); } catch( uno::Exception& ) diff --git a/sc/source/ui/vba/vbarange.cxx b/sc/source/ui/vba/vbarange.cxx index 5cb6d44fc902..72f300d6463a 100755 --- a/sc/source/ui/vba/vbarange.cxx +++ b/sc/source/ui/vba/vbarange.cxx @@ -406,7 +406,7 @@ ScDocShell* getDocShellFromRange( const uno::Reference< table::XCellRange >& xRange ) throw ( uno::RuntimeException ) { // need the ScCellRangesBase to get docshell - uno::Reference< uno::XInterface > xIf( xRange, uno::UNO_QUERY_THROW ); + uno::Reference< uno::XInterface > xIf( xRange ); return getDocShellFromIf(xIf ); } @@ -414,7 +414,7 @@ ScDocShell* getDocShellFromRanges( const uno::Reference< sheet::XSheetCellRangeContainer >& xRanges ) throw ( uno::RuntimeException ) { // need the ScCellRangesBase to get docshell - uno::Reference< uno::XInterface > xIf( xRanges, uno::UNO_QUERY_THROW ); + uno::Reference< uno::XInterface > xIf( xRanges ); return getDocShellFromIf(xIf ); } @@ -426,7 +426,8 @@ uno::Reference< frame::XModel > getModelFromXIf( const uno::Reference< uno::XInt uno::Reference< frame::XModel > getModelFromRange( const uno::Reference< table::XCellRange >& xRange ) throw ( uno::RuntimeException ) { - uno::Reference< uno::XInterface > xIf( xRange, uno::UNO_QUERY_THROW ); + // the XInterface for getImplementation can be any derived interface, no need for queryInterface + uno::Reference< uno::XInterface > xIf( xRange ); return getModelFromXIf( xIf ); } @@ -1469,9 +1470,9 @@ uno::Reference< XCollection >& ScVbaRange::getBorders() void ScVbaRange::visitArray( ArrayVisitor& visitor ) { - uno::Reference< table::XColumnRowRange > xColumnRowRange(mxRange, uno::UNO_QUERY_THROW ); - sal_Int32 nRowCount = xColumnRowRange->getRows()->getCount(); - sal_Int32 nColCount = xColumnRowRange->getColumns()->getCount(); + table::CellRangeAddress aRangeAddr = lclGetRangeAddress( mxRange ); + sal_Int32 nRowCount = aRangeAddr.EndRow - aRangeAddr.StartRow + 1; + sal_Int32 nColCount = aRangeAddr.EndColumn - aRangeAddr.StartColumn + 1; for ( sal_Int32 i=0; i<nRowCount; ++i ) { for ( sal_Int32 j=0; j<nColCount; ++j ) @@ -3572,9 +3573,12 @@ ScVbaRange::End( ::sal_Int32 Direction ) throw (uno::RuntimeException) bool ScVbaRange::isSingleCellRange() { - uno::Reference< table::XColumnRowRange > xColumnRowRange(mxRange, uno::UNO_QUERY); - if ( xColumnRowRange.is() && xColumnRowRange->getRows()->getCount() == 1 && xColumnRowRange->getColumns()->getCount() == 1 ) - return true; + uno::Reference< sheet::XCellRangeAddressable > xAddressable( mxRange, uno::UNO_QUERY ); + if ( xAddressable.is() ) + { + table::CellRangeAddress aRangeAddr = xAddressable->getRangeAddress(); + return ( aRangeAddr.EndColumn == aRangeAddr.StartColumn && aRangeAddr.EndRow == aRangeAddr.StartRow ); + } return false; } diff --git a/sc/source/ui/vba/vbawindow.cxx b/sc/source/ui/vba/vbawindow.cxx index 5964fe98317c..ed10e52cca7a 100644 --- a/sc/source/ui/vba/vbawindow.cxx +++ b/sc/source/ui/vba/vbawindow.cxx @@ -59,11 +59,9 @@ typedef std::hash_map< rtl::OUString, SCTAB, ::rtl::OUStringHash, ::std::equal_to< ::rtl::OUString > > NameIndexHash; -typedef std::vector < uno::Reference< sheet::XSpreadsheet > > Sheets; +typedef std::vector< uno::Reference< sheet::XSpreadsheet > > Sheets; -typedef ::cppu::WeakImplHelper1< container::XEnumeration - -> Enumeration_BASE; +typedef ::cppu::WeakImplHelper1< container::XEnumeration > Enumeration_BASE; typedef ::cppu::WeakImplHelper3< container::XEnumerationAccess , com::sun::star::container::XIndexAccess @@ -200,13 +198,20 @@ public: }; -ScVbaWindow::ScVbaWindow( const uno::Reference< XHelperInterface >& xParent, const uno::Reference< uno::XComponentContext >& xContext, const uno::Reference< frame::XModel >& xModel ) : WindowImpl_BASE( xParent, xContext, xModel ) +ScVbaWindow::ScVbaWindow( + const uno::Reference< XHelperInterface >& xParent, + const uno::Reference< uno::XComponentContext >& xContext, + const uno::Reference< frame::XModel >& xModel, + const uno::Reference< frame::XController >& xController ) throw (uno::RuntimeException) : + WindowImpl_BASE( xParent, xContext, xModel, xController ) { init(); } -ScVbaWindow::ScVbaWindow( uno::Sequence< uno::Any > const & args, uno::Reference< uno::XComponentContext > const & xContext ) - : WindowImpl_BASE( args, xContext ) +ScVbaWindow::ScVbaWindow( + const uno::Sequence< uno::Any >& args, + const uno::Reference< uno::XComponentContext >& xContext ) throw (uno::RuntimeException) : + WindowImpl_BASE( args, xContext ) { init(); } @@ -218,20 +223,42 @@ ScVbaWindow::init() still zero. The implementation of ActivePane() uses a UNO reference of this (to set this window as parent of the pane obejct). This requires the own refcount to be non-zero, otherwise this instance will be - desctructed immediately! */ + desctructed immediately! Guard the call to ActivePane() in try/catch to + not miss the decrementation of the reference count on exception. */ osl_incrementInterlockedCount( &m_refCount ); - uno::Reference< frame::XController > xController( m_xModel->getCurrentController(), uno::UNO_QUERY_THROW ); - m_xViewPane.set( xController, uno::UNO_QUERY_THROW ); - m_xViewFreezable.set( xController, uno::UNO_QUERY_THROW ); - m_xViewSplitable.set( xController, uno::UNO_QUERY_THROW ); - m_xPane.set( ActivePane(), uno::UNO_QUERY_THROW ); - m_xDevice.set( xController->getFrame()->getComponentWindow(), uno::UNO_QUERY_THROW ); + try + { + m_xPane = ActivePane(); + } + catch( uno::Exception& ) + { + } osl_decrementInterlockedCount( &m_refCount ); } +uno::Reference< beans::XPropertySet > +ScVbaWindow::getControllerProps() throw (uno::RuntimeException) +{ + return uno::Reference< beans::XPropertySet >( getController(), uno::UNO_QUERY_THROW ); +} + +uno::Reference< beans::XPropertySet > +ScVbaWindow::getFrameProps() throw (uno::RuntimeException) +{ + return uno::Reference< beans::XPropertySet >( getController()->getFrame(), uno::UNO_QUERY_THROW ); +} + +uno::Reference< awt::XDevice > +ScVbaWindow::getDevice() throw (uno::RuntimeException) +{ + return uno::Reference< awt::XDevice >( getWindow(), uno::UNO_QUERY_THROW ); +} + void ScVbaWindow::Scroll( const uno::Any& Down, const uno::Any& Up, const uno::Any& ToRight, const uno::Any& ToLeft, bool bLargeScroll ) throw (uno::RuntimeException) { + if( !m_xPane.is() ) + throw uno::RuntimeException(); if( bLargeScroll ) m_xPane->LargeScroll( Down, Up, ToRight, ToLeft ); else @@ -253,7 +280,7 @@ ScVbaWindow::LargeScroll( const uno::Any& Down, const uno::Any& Up, const uno::A uno::Any SAL_CALL ScVbaWindow::SelectedSheets( const uno::Any& aIndex ) throw (uno::RuntimeException) { - uno::Reference< container::XEnumerationAccess > xEnumAccess( new SelectedSheetsEnumAccess( mxContext, m_xModel ) ); + uno::Reference< container::XEnumerationAccess > xEnumAccess( new SelectedSheetsEnumAccess( mxContext, m_xModel ) ); // #FIXME needs a workbook as a parent uno::Reference< excel::XWorksheets > xSheets( new ScVbaWorksheets( uno::Reference< XHelperInterface >(), mxContext, xEnumAccess, m_xModel ) ); if ( aIndex.hasValue() ) @@ -283,16 +310,6 @@ ScVbaWindow::ScrollWorkbookTabs( const uno::Any& /*Sheets*/, const uno::Any& /*P */ } -uno::Reference< beans::XPropertySet > -getPropsFromModel( const uno::Reference< frame::XModel >& xModel ) -{ - uno::Reference< frame::XController > xController = xModel->getCurrentController(); - if ( !xController.is() ) - throw uno::RuntimeException( rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM ("No controller for model") ), uno::Reference< uno::XInterface >() ); - return uno::Reference< beans::XPropertySet >( xController->getFrame(), uno::UNO_QUERY ); -} - uno::Any SAL_CALL ScVbaWindow::getCaption() throw (uno::RuntimeException) @@ -300,9 +317,8 @@ ScVbaWindow::getCaption() throw (uno::RuntimeException) static rtl::OUString sCrud(RTL_CONSTASCII_USTRINGPARAM(" - OpenOffice.org Calc" ) ); static sal_Int32 nCrudLen = sCrud.getLength(); - uno::Reference< beans::XPropertySet > xProps = getPropsFromModel( m_xModel ); rtl::OUString sTitle; - xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SC_UNONAME_TITLE ) ) ) >>= sTitle; + getFrameProps()->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( SC_UNONAME_TITLE ) ) ) >>= sTitle; sal_Int32 nCrudIndex = sTitle.indexOf( sCrud ); // adjust title ( by removing crud ) // sCrud string present @@ -338,16 +354,14 @@ ScVbaWindow::getCaption() throw (uno::RuntimeException) void SAL_CALL ScVbaWindow::setCaption( const uno::Any& _caption ) throw (uno::RuntimeException) { - - uno::Reference< beans::XPropertySet > xProps = getPropsFromModel( m_xModel ); - xProps->setPropertyValue( rtl::OUString( - RTL_CONSTASCII_USTRINGPARAM ( SC_UNONAME_TITLE ) ) , _caption ); + getFrameProps()->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_TITLE ) ), _caption ); } uno::Any SAL_CALL ScVbaWindow::getScrollRow() throw (uno::RuntimeException) { sal_Int32 nValue = 0; + // !! TODO !! get view shell from controller ScTabViewShell* pViewShell = excel::getBestViewShell( m_xModel ); if ( pViewShell ) { @@ -361,6 +375,7 @@ ScVbaWindow::getScrollRow() throw (uno::RuntimeException) void SAL_CALL ScVbaWindow::setScrollRow( const uno::Any& _scrollrow ) throw (uno::RuntimeException) { + // !! TODO !! get view shell from controller ScTabViewShell* pViewShell = excel::getBestViewShell( m_xModel ); if ( pViewShell ) { @@ -376,6 +391,7 @@ uno::Any SAL_CALL ScVbaWindow::getScrollColumn() throw (uno::RuntimeException) { sal_Int32 nValue = 0; + // !! TODO !! get view shell from controller ScTabViewShell* pViewShell = excel::getBestViewShell( m_xModel ); if ( pViewShell ) { @@ -389,6 +405,7 @@ ScVbaWindow::getScrollColumn() throw (uno::RuntimeException) void SAL_CALL ScVbaWindow::setScrollColumn( const uno::Any& _scrollcolumn ) throw (uno::RuntimeException) { + // !! TODO !! get view shell from controller ScTabViewShell* pViewShell = excel::getBestViewShell( m_xModel ); if ( pViewShell ) { @@ -404,6 +421,7 @@ uno::Any SAL_CALL ScVbaWindow::getWindowState() throw (uno::RuntimeException) { sal_Int32 nwindowState = xlNormal; + // !! TODO !! get view shell from controller ScTabViewShell* pViewShell = excel::getBestViewShell( m_xModel ); SfxViewFrame* pViewFrame = pViewShell -> GetViewFrame(); WorkWindow* pWork = (WorkWindow*) pViewFrame->GetFrame().GetSystemWindow(); @@ -422,6 +440,7 @@ ScVbaWindow::setWindowState( const uno::Any& _windowstate ) throw (uno::RuntimeE { sal_Int32 nwindowState = xlMaximized; _windowstate >>= nwindowState; + // !! TODO !! get view shell from controller ScTabViewShell* pViewShell = excel::getBestViewShell( m_xModel ); SfxViewFrame* pViewFrame = pViewShell -> GetViewFrame(); WorkWindow* pWork = (WorkWindow*) pViewFrame->GetFrame().GetSystemWindow(); @@ -456,7 +475,8 @@ ScVbaWindow::Close( const uno::Any& SaveChanges, const uno::Any& FileName, const uno::Reference< excel::XPane > SAL_CALL ScVbaWindow::ActivePane() throw (script::BasicErrorException, uno::RuntimeException) { - return new ScVbaPane( this, mxContext, m_xModel, m_xViewPane ); + uno::Reference< sheet::XViewPane > xViewPane( getController(), uno::UNO_QUERY_THROW ); + return new ScVbaPane( this, mxContext, m_xModel, xViewPane ); } uno::Reference< excel::XRange > SAL_CALL @@ -484,10 +504,9 @@ ScVbaWindow::RangeSelection() throw (script::BasicErrorException, uno::RuntimeEx ::sal_Bool SAL_CALL ScVbaWindow::getDisplayGridlines() throw (uno::RuntimeException) { - uno::Reference< beans::XPropertySet > xProps( m_xModel->getCurrentController(), uno::UNO_QUERY_THROW ); rtl::OUString sName( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_SHOWGRID ) ); sal_Bool bGrid = sal_True; - xProps->getPropertyValue( sName ) >>= bGrid; + getControllerProps()->getPropertyValue( sName ) >>= bGrid; return bGrid; } @@ -495,131 +514,125 @@ ScVbaWindow::getDisplayGridlines() throw (uno::RuntimeException) void SAL_CALL ScVbaWindow::setDisplayGridlines( ::sal_Bool _displaygridlines ) throw (uno::RuntimeException) { - uno::Reference< beans::XPropertySet > xProps( m_xModel->getCurrentController(), uno::UNO_QUERY_THROW ); rtl::OUString sName( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_SHOWGRID ) ); - xProps->setPropertyValue( sName, uno::makeAny( _displaygridlines )); + getControllerProps()->setPropertyValue( sName, uno::makeAny( _displaygridlines )); } ::sal_Bool SAL_CALL ScVbaWindow::getDisplayHeadings() throw (uno::RuntimeException) { - uno::Reference< beans::XPropertySet > xProps( m_xModel->getCurrentController(), uno::UNO_QUERY_THROW ); rtl::OUString sName( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_COLROWHDR ) ); sal_Bool bHeading = sal_True; - xProps->getPropertyValue( sName ) >>= bHeading; + getControllerProps()->getPropertyValue( sName ) >>= bHeading; return bHeading; } void SAL_CALL ScVbaWindow::setDisplayHeadings( ::sal_Bool _bDisplayHeadings ) throw (uno::RuntimeException) { - uno::Reference< beans::XPropertySet > xProps( m_xModel->getCurrentController(), uno::UNO_QUERY_THROW ); rtl::OUString sName( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_COLROWHDR ) ); - xProps->setPropertyValue( sName, uno::makeAny( _bDisplayHeadings )); + getControllerProps()->setPropertyValue( sName, uno::makeAny( _bDisplayHeadings )); } ::sal_Bool SAL_CALL ScVbaWindow::getDisplayHorizontalScrollBar() throw (uno::RuntimeException) { - uno::Reference< beans::XPropertySet > xProps( m_xModel->getCurrentController(), uno::UNO_QUERY_THROW ); rtl::OUString sName( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_HORSCROLL ) ); sal_Bool bHorizontalScrollBar = sal_True; - xProps->getPropertyValue( sName ) >>= bHorizontalScrollBar; + getControllerProps()->getPropertyValue( sName ) >>= bHorizontalScrollBar; return bHorizontalScrollBar; } void SAL_CALL ScVbaWindow::setDisplayHorizontalScrollBar( ::sal_Bool _bDisplayHorizontalScrollBar ) throw (uno::RuntimeException) { - uno::Reference< beans::XPropertySet > xProps( m_xModel->getCurrentController(), uno::UNO_QUERY_THROW ); rtl::OUString sName( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_HORSCROLL ) ); - xProps->setPropertyValue( sName, uno::makeAny( _bDisplayHorizontalScrollBar )); + getControllerProps()->setPropertyValue( sName, uno::makeAny( _bDisplayHorizontalScrollBar )); } ::sal_Bool SAL_CALL ScVbaWindow::getDisplayOutline() throw (uno::RuntimeException) { - uno::Reference< beans::XPropertySet > xProps( m_xModel->getCurrentController(), uno::UNO_QUERY_THROW ); rtl::OUString sName( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_OUTLSYMB ) ); sal_Bool bOutline = sal_True; - xProps->getPropertyValue( sName ) >>= bOutline; + getControllerProps()->getPropertyValue( sName ) >>= bOutline; return bOutline; } void SAL_CALL ScVbaWindow::setDisplayOutline( ::sal_Bool _bDisplayOutline ) throw (uno::RuntimeException) { - uno::Reference< beans::XPropertySet > xProps( m_xModel->getCurrentController(), uno::UNO_QUERY_THROW ); rtl::OUString sName( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_OUTLSYMB ) ); - xProps->setPropertyValue( sName, uno::makeAny( _bDisplayOutline )); + getControllerProps()->setPropertyValue( sName, uno::makeAny( _bDisplayOutline )); } ::sal_Bool SAL_CALL ScVbaWindow::getDisplayVerticalScrollBar() throw (uno::RuntimeException) { - uno::Reference< beans::XPropertySet > xProps( m_xModel->getCurrentController(), uno::UNO_QUERY_THROW ); rtl::OUString sName( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_VERTSCROLL ) ); sal_Bool bVerticalScrollBar = sal_True; - xProps->getPropertyValue( sName ) >>= bVerticalScrollBar; + getControllerProps()->getPropertyValue( sName ) >>= bVerticalScrollBar; return bVerticalScrollBar; } void SAL_CALL ScVbaWindow::setDisplayVerticalScrollBar( ::sal_Bool _bDisplayVerticalScrollBar ) throw (uno::RuntimeException) { - uno::Reference< beans::XPropertySet > xProps( m_xModel->getCurrentController(), uno::UNO_QUERY_THROW ); rtl::OUString sName( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_VERTSCROLL ) ); - xProps->setPropertyValue( sName, uno::makeAny( _bDisplayVerticalScrollBar )); + getControllerProps()->setPropertyValue( sName, uno::makeAny( _bDisplayVerticalScrollBar )); } ::sal_Bool SAL_CALL ScVbaWindow::getDisplayWorkbookTabs() throw (uno::RuntimeException) { - uno::Reference< beans::XPropertySet > xProps( m_xModel->getCurrentController(), uno::UNO_QUERY_THROW ); rtl::OUString sName( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_SHEETTABS ) ); sal_Bool bWorkbookTabs = sal_True; - xProps->getPropertyValue( sName ) >>= bWorkbookTabs; + getControllerProps()->getPropertyValue( sName ) >>= bWorkbookTabs; return bWorkbookTabs; } void SAL_CALL ScVbaWindow::setDisplayWorkbookTabs( ::sal_Bool _bDisplayWorkbookTabs ) throw (uno::RuntimeException) { - uno::Reference< beans::XPropertySet > xProps( m_xModel->getCurrentController(), uno::UNO_QUERY_THROW ); rtl::OUString sName( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_SHEETTABS ) ); - xProps->setPropertyValue( sName, uno::makeAny( _bDisplayWorkbookTabs )); + getControllerProps()->setPropertyValue( sName, uno::makeAny( _bDisplayWorkbookTabs )); } ::sal_Bool SAL_CALL ScVbaWindow::getFreezePanes() throw (uno::RuntimeException) { - return m_xViewFreezable->hasFrozenPanes(); + uno::Reference< sheet::XViewFreezable > xViewFreezable( getController(), uno::UNO_QUERY_THROW ); + return xViewFreezable->hasFrozenPanes(); } void SAL_CALL ScVbaWindow::setFreezePanes( ::sal_Bool /*_bFreezePanes*/ ) throw (uno::RuntimeException) { - if( m_xViewSplitable->getIsWindowSplit() ) + uno::Reference< sheet::XViewPane > xViewPane( getController(), uno::UNO_QUERY_THROW ); + uno::Reference< sheet::XViewSplitable > xViewSplitable( xViewPane, uno::UNO_QUERY_THROW ); + uno::Reference< sheet::XViewFreezable > xViewFreezable( xViewPane, uno::UNO_QUERY_THROW ); + if( xViewSplitable->getIsWindowSplit() ) { // if there is a split we freeze at the split sal_Int32 nColumn = getSplitColumn(); sal_Int32 nRow = getSplitRow(); - m_xViewFreezable->freezeAtPosition( nColumn, nRow ); + xViewFreezable->freezeAtPosition( nColumn, nRow ); } else { // otherwise we freeze in the center of the visible sheet - table::CellRangeAddress aCellRangeAddress = m_xViewPane->getVisibleRange(); + table::CellRangeAddress aCellRangeAddress = xViewPane->getVisibleRange(); sal_Int32 nColumn = aCellRangeAddress.StartColumn + (( aCellRangeAddress.EndColumn - aCellRangeAddress.StartColumn )/2 ); sal_Int32 nRow = aCellRangeAddress.StartRow + (( aCellRangeAddress.EndRow - aCellRangeAddress.StartRow )/2 ); - m_xViewFreezable->freezeAtPosition( nColumn, nRow ); + xViewFreezable->freezeAtPosition( nColumn, nRow ); } } ::sal_Bool SAL_CALL ScVbaWindow::getSplit() throw (uno::RuntimeException) { - return m_xViewSplitable->getIsWindowSplit(); + uno::Reference< sheet::XViewSplitable > xViewSplitable( getController(), uno::UNO_QUERY_THROW ); + return xViewSplitable->getIsWindowSplit(); } void SAL_CALL @@ -627,14 +640,16 @@ ScVbaWindow::setSplit( ::sal_Bool _bSplit ) throw (uno::RuntimeException) { if( !_bSplit ) { - m_xViewSplitable->splitAtPosition(0,0); + uno::Reference< sheet::XViewSplitable > xViewSplitable( getController(), uno::UNO_QUERY_THROW ); + xViewSplitable->splitAtPosition(0,0); } else { + uno::Reference< sheet::XViewFreezable > xViewFreezable( getController(), uno::UNO_QUERY_THROW ); uno::Reference< excel::XRange > xRange = ActiveCell(); sal_Int32 nRow = xRange->getRow(); sal_Int32 nColumn = xRange->getColumn(); - m_xViewFreezable->freezeAtPosition( nColumn-1, nRow-1 ); + xViewFreezable->freezeAtPosition( nColumn-1, nRow-1 ); SplitAtDefinedPosition( sal_True ); } } @@ -642,7 +657,8 @@ ScVbaWindow::setSplit( ::sal_Bool _bSplit ) throw (uno::RuntimeException) sal_Int32 SAL_CALL ScVbaWindow::getSplitColumn() throw (uno::RuntimeException) { - return m_xViewSplitable->getSplitColumn(); + uno::Reference< sheet::XViewSplitable > xViewSplitable( getController(), uno::UNO_QUERY_THROW ); + return xViewSplitable->getSplitColumn(); } void SAL_CALL @@ -650,9 +666,10 @@ ScVbaWindow::setSplitColumn( sal_Int32 _splitcolumn ) throw (uno::RuntimeExcepti { if( getSplitColumn() != _splitcolumn ) { + uno::Reference< sheet::XViewFreezable > xViewFreezable( getController(), uno::UNO_QUERY_THROW ); sal_Bool bFrozen = getFreezePanes(); sal_Int32 nRow = getSplitRow(); - m_xViewFreezable->freezeAtPosition( _splitcolumn, nRow ); + xViewFreezable->freezeAtPosition( _splitcolumn, nRow ); SplitAtDefinedPosition( !bFrozen ); } } @@ -660,22 +677,23 @@ ScVbaWindow::setSplitColumn( sal_Int32 _splitcolumn ) throw (uno::RuntimeExcepti double SAL_CALL ScVbaWindow::getSplitHorizontal() throw (uno::RuntimeException) { - double fSplitHorizontal = m_xViewSplitable->getSplitHorizontal(); - double fHoriPoints = PixelsToPoints( m_xDevice, fSplitHorizontal, sal_True ); - return fHoriPoints; + uno::Reference< sheet::XViewSplitable > xViewSplitable( getController(), uno::UNO_QUERY_THROW ); + return PixelsToPoints( getDevice(), xViewSplitable->getSplitHorizontal(), sal_True ); } void SAL_CALL ScVbaWindow::setSplitHorizontal( double _splithorizontal ) throw (uno::RuntimeException) { - double fHoriPixels = PointsToPixels( m_xDevice, _splithorizontal, sal_True ); - m_xViewSplitable->splitAtPosition( static_cast<sal_Int32>( fHoriPixels ), 0 ); + uno::Reference< sheet::XViewSplitable > xViewSplitable( getController(), uno::UNO_QUERY_THROW ); + double fHoriPixels = PointsToPixels( getDevice(), _splithorizontal, sal_True ); + xViewSplitable->splitAtPosition( static_cast< sal_Int32 >( fHoriPixels ), 0 ); } sal_Int32 SAL_CALL ScVbaWindow::getSplitRow() throw (uno::RuntimeException) { - sal_Int32 nValue = m_xViewSplitable->getSplitRow(); + uno::Reference< sheet::XViewSplitable > xViewSplitable( getController(), uno::UNO_QUERY_THROW ); + sal_Int32 nValue = xViewSplitable->getSplitRow(); return nValue ? nValue - 1 : nValue; } @@ -684,9 +702,10 @@ ScVbaWindow::setSplitRow( sal_Int32 _splitrow ) throw (uno::RuntimeException) { if( getSplitRow() != _splitrow ) { + uno::Reference< sheet::XViewFreezable > xViewFreezable( getController(), uno::UNO_QUERY_THROW ); sal_Bool bFrozen = getFreezePanes(); sal_Int32 nColumn = getSplitColumn(); - m_xViewFreezable->freezeAtPosition( nColumn , _splitrow ); + xViewFreezable->freezeAtPosition( nColumn , _splitrow ); SplitAtDefinedPosition( !bFrozen ); } } @@ -694,33 +713,33 @@ ScVbaWindow::setSplitRow( sal_Int32 _splitrow ) throw (uno::RuntimeException) double SAL_CALL ScVbaWindow::getSplitVertical() throw (uno::RuntimeException) { - double fSplitVertical = m_xViewSplitable->getSplitVertical(); - double fVertiPoints = PixelsToPoints( m_xDevice, fSplitVertical, sal_False ); - return fVertiPoints; + uno::Reference< sheet::XViewSplitable > xViewSplitable( getController(), uno::UNO_QUERY_THROW ); + return PixelsToPoints( getDevice(), xViewSplitable->getSplitVertical(), sal_False ); } void SAL_CALL ScVbaWindow::setSplitVertical(double _splitvertical ) throw (uno::RuntimeException) { - double fVertiPixels = PointsToPixels( m_xDevice, _splitvertical, sal_False ); - m_xViewSplitable->splitAtPosition( 0, static_cast<sal_Int32>( fVertiPixels ) ); + uno::Reference< sheet::XViewSplitable > xViewSplitable( getController(), uno::UNO_QUERY_THROW ); + double fVertiPixels = PointsToPixels( getDevice(), _splitvertical, sal_False ); + xViewSplitable->splitAtPosition( 0, static_cast<sal_Int32>( fVertiPixels ) ); } void ScVbaWindow::SplitAtDefinedPosition(sal_Bool _bUnFreezePane) { - sal_Int32 nVertSplit = m_xViewSplitable->getSplitVertical(); - sal_Int32 nHoriSplit = m_xViewSplitable->getSplitHorizontal(); + uno::Reference< sheet::XViewSplitable > xViewSplitable( getController(), uno::UNO_QUERY_THROW ); + uno::Reference< sheet::XViewFreezable > xViewFreezable( xViewSplitable, uno::UNO_QUERY_THROW ); + sal_Int32 nVertSplit = xViewSplitable->getSplitVertical(); + sal_Int32 nHoriSplit = xViewSplitable->getSplitHorizontal(); if( _bUnFreezePane ) - { - m_xViewFreezable->freezeAtPosition(0,0); - } - m_xViewSplitable->splitAtPosition(nHoriSplit, nVertSplit); + xViewFreezable->freezeAtPosition(0,0); + xViewSplitable->splitAtPosition(nHoriSplit, nVertSplit); } uno::Any SAL_CALL ScVbaWindow::getZoom() throw (uno::RuntimeException) { - uno::Reference< beans::XPropertySet > xProps( m_xModel->getCurrentController(), uno::UNO_QUERY_THROW ); + uno::Reference< beans::XPropertySet > xProps = getControllerProps(); rtl::OUString sName( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_ZOOMTYPE ) ); sal_Int16 nZoomType = view::DocumentZoomType::PAGE_WIDTH; xProps->getPropertyValue( sName ) >>= nZoomType; @@ -785,6 +804,7 @@ ScVbaWindow::setView( const uno::Any& _view) throw (uno::RuntimeException) default: DebugHelper::exception(SbERR_BAD_PARAMETER, rtl::OUString() ); } + // !! TODO !! get view shell from controller ScTabViewShell* pViewShell = excel::getBestViewShell( m_xModel ); if ( pViewShell ) dispatchExecute( pViewShell, nSlot ); @@ -793,7 +813,7 @@ ScVbaWindow::setView( const uno::Any& _view) throw (uno::RuntimeException) uno::Reference< excel::XRange > SAL_CALL ScVbaWindow::getVisibleRange() throw (uno::RuntimeException) { - uno::Reference< container::XIndexAccess > xPanesIA( m_xViewPane, uno::UNO_QUERY_THROW ); + uno::Reference< container::XIndexAccess > xPanesIA( getController(), uno::UNO_QUERY_THROW ); uno::Reference< sheet::XViewPane > xTopLeftPane( xPanesIA->getByIndex( 0 ), uno::UNO_QUERY_THROW ); uno::Reference< excel::XPane > xPane( new ScVbaPane( this, mxContext, m_xModel, xTopLeftPane ) ); return xPane->getVisibleRange(); @@ -803,7 +823,7 @@ sal_Int32 SAL_CALL ScVbaWindow::PointsToScreenPixelsX(sal_Int32 _points) throw (css::script::BasicErrorException, css::uno::RuntimeException) { sal_Int32 nHundredthsofOneMillimeters = Millimeter::getInHundredthsOfOneMillimeter( _points ); - double fConvertFactor = (m_xDevice->getInfo().PixelPerMeterX/100000); + double fConvertFactor = (getDevice()->getInfo().PixelPerMeterX/100000); return static_cast<sal_Int32>(fConvertFactor * nHundredthsofOneMillimeters ); } @@ -811,7 +831,7 @@ sal_Int32 SAL_CALL ScVbaWindow::PointsToScreenPixelsY(sal_Int32 _points) throw (css::script::BasicErrorException, css::uno::RuntimeException) { sal_Int32 nHundredthsofOneMillimeters = Millimeter::getInHundredthsOfOneMillimeter( _points ); - double fConvertFactor = (m_xDevice->getInfo().PixelPerMeterY/100000); + double fConvertFactor = (getDevice()->getInfo().PixelPerMeterY/100000); return static_cast<sal_Int32>(fConvertFactor * nHundredthsofOneMillimeters ); } @@ -819,6 +839,7 @@ void SAL_CALL ScVbaWindow::PrintOut( const css::uno::Any& From, const css::uno::Any&To, const css::uno::Any& Copies, const css::uno::Any& Preview, const css::uno::Any& ActivePrinter, const css::uno::Any& PrintToFile, const css::uno::Any& Collate, const css::uno::Any& PrToFileName ) throw (css::script::BasicErrorException, css::uno::RuntimeException) { // need test, print current active sheet + // !! TODO !! get view shell from controller PrintOutHelper( excel::getBestViewShell( m_xModel ), From, To, Copies, Preview, ActivePrinter, PrintToFile, Collate, PrToFileName, sal_True ); } @@ -826,6 +847,7 @@ void SAL_CALL ScVbaWindow::PrintPreview( const css::uno::Any& EnableChanges ) throw (css::script::BasicErrorException, css::uno::RuntimeException) { // need test, print preview current active sheet + // !! TODO !! get view shell from controller PrintPreviewHelper( EnableChanges, excel::getBestViewShell( m_xModel ) ); } diff --git a/sc/source/ui/vba/vbawindow.hxx b/sc/source/ui/vba/vbawindow.hxx index d58d2a07cb4b..d183ee346185 100644 --- a/sc/source/ui/vba/vbawindow.hxx +++ b/sc/source/ui/vba/vbawindow.hxx @@ -27,7 +27,6 @@ #ifndef SC_VBA_WINDOW_HXX #define SC_VBA_WINDOW_HXX -#include <cppuhelper/implbase1.hxx> #include <ooo/vba/excel/XWindow.hpp> #include <com/sun/star/uno/XComponentContext.hpp> #include <com/sun/star/sheet/XViewPane.hpp> @@ -46,19 +45,30 @@ typedef cppu::ImplInheritanceHelper1< VbaWindowBase, ov::excel::XWindow > Window class ScVbaWindow : public WindowImpl_BASE { private: - css::uno::Reference< css::sheet::XViewPane > m_xViewPane; - css::uno::Reference< css::sheet::XViewFreezable > m_xViewFreezable; - css::uno::Reference< css::sheet::XViewSplitable > m_xViewSplitable; css::uno::Reference< ov::excel::XPane > m_xPane; - css::uno::Reference< css::awt::XDevice > m_xDevice; + void init(); + css::uno::Reference< css::beans::XPropertySet > getControllerProps() throw (css::uno::RuntimeException); + css::uno::Reference< css::beans::XPropertySet > getFrameProps() throw (css::uno::RuntimeException); + css::uno::Reference< css::awt::XDevice > getDevice() throw (css::uno::RuntimeException); + protected: void SplitAtDefinedPosition(sal_Bool _bUnFreezePane); + public: - void Scroll( const css::uno::Any& Down, const css::uno::Any& Up, const css::uno::Any& ToRight, const css::uno::Any& ToLeft, bool bLargeScroll = false ) throw (css::uno::RuntimeException); + void Scroll( const css::uno::Any& Down, const css::uno::Any& Up, const css::uno::Any& ToRight, const css::uno::Any& ToLeft, bool bLargeScroll = false ) throw (css::uno::RuntimeException); + public: - ScVbaWindow( const css::uno::Reference< ov::XHelperInterface >& xParent, const css::uno::Reference< css::uno::XComponentContext >& xContext, const css::uno::Reference< css::frame::XModel >& xModel ); - ScVbaWindow( css::uno::Sequence< css::uno::Any > const& aArgs, css::uno::Reference< css::uno::XComponentContext > const& xContext ); + ScVbaWindow( + const css::uno::Reference< ov::XHelperInterface >& xParent, + const css::uno::Reference< css::uno::XComponentContext >& xContext, + const css::uno::Reference< css::frame::XModel >& xModel, + const css::uno::Reference< css::frame::XController >& xController ) + throw (css::uno::RuntimeException); + ScVbaWindow( + const css::uno::Sequence< css::uno::Any >& aArgs, + const css::uno::Reference< css::uno::XComponentContext >& xContext ) + throw (css::uno::RuntimeException); // XWindow virtual css::uno::Reference< ov::excel::XRange > SAL_CALL ActiveCell( ) throw (css::script::BasicErrorException, css::uno::RuntimeException); diff --git a/sc/source/ui/vba/vbawindows.cxx b/sc/source/ui/vba/vbawindows.cxx index 3ddc5f5b3b45..80f215629126 100644 --- a/sc/source/ui/vba/vbawindows.cxx +++ b/sc/source/ui/vba/vbawindows.cxx @@ -53,7 +53,9 @@ uno::Reference< XHelperInterface > lcl_createWorkbookHIParent( const uno::Refere uno::Any ComponentToWindow( const uno::Any& aSource, uno::Reference< uno::XComponentContext > & xContext, const uno::Any& aApplication ) { uno::Reference< frame::XModel > xModel( aSource, uno::UNO_QUERY_THROW ); - uno::Reference< excel::XWindow > xWin( new ScVbaWindow( lcl_createWorkbookHIParent( xModel, xContext, aApplication ), xContext,xModel ) ); + // !! TODO !! iterate over all controllers + uno::Reference< frame::XController > xController( xModel->getCurrentController(), uno::UNO_SET_THROW ); + uno::Reference< excel::XWindow > xWin( new ScVbaWindow( lcl_createWorkbookHIParent( xModel, xContext, aApplication ), xContext, xModel, xController ) ); return uno::makeAny( xWin ); } @@ -138,8 +140,10 @@ public: { m_windows.push_back( xNext ); uno::Reference< frame::XModel > xModel( xNext, uno::UNO_QUERY_THROW ); // that the spreadsheetdocument is a xmodel is a given + // !! TODO !! iterate over all controllers + uno::Reference< frame::XController > xController( xModel->getCurrentController(), uno::UNO_SET_THROW ); uno::Reference< XHelperInterface > xTemp; // temporary needed for g++ 3.3.5 - ScVbaWindow window( xTemp, m_xContext, xModel ); + ScVbaWindow window( xTemp, m_xContext, xModel, xController ); rtl::OUString sCaption; window.getCaption() >>= sCaption; namesToIndices[ sCaption ] = nIndex++; diff --git a/sc/source/ui/vba/vbaworkbook.cxx b/sc/source/ui/vba/vbaworkbook.cxx index 1e2acd6252b8..e0d50c592e6c 100644 --- a/sc/source/ui/vba/vbaworkbook.cxx +++ b/sc/source/ui/vba/vbaworkbook.cxx @@ -218,14 +218,9 @@ ScVbaWorkbook::getActiveSheet() throw (uno::RuntimeException) { uno::Reference< frame::XModel > xModel( getCurrentExcelDoc( mxContext ), uno::UNO_SET_THROW ); uno::Reference< sheet::XSpreadsheetView > xView( xModel->getCurrentController(), uno::UNO_QUERY_THROW ); - uno::Reference< beans::XPropertySet > xSheetProps( xView->getActiveSheet(), uno::UNO_QUERY_THROW ); - // #162503# return the original document module wrapper object, instead of a new instance - ::rtl::OUString aCodeName; - xSheetProps->getPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_CODENAME ) ) ) >>= aCodeName; - ScDocShell* pShell = excel::getDocShell( xModel ); - if( !pShell ) - throw uno::RuntimeException(); - return uno::Reference< excel::XWorksheet >( getUnoDocModule( aCodeName, pShell ), uno::UNO_QUERY_THROW ); + uno::Reference< sheet::XSpreadsheet > xSheet( xView->getActiveSheet(), uno::UNO_SET_THROW ); + // #162503# return the original sheet module wrapper object, instead of a new instance + return uno::Reference< excel::XWorksheet >( excel::getUnoSheetModuleObj( xSheet ), uno::UNO_QUERY_THROW ); } uno::Any SAL_CALL diff --git a/sc/source/ui/vba/vbaworkbooks.cxx b/sc/source/ui/vba/vbaworkbooks.cxx index a9f1970be34e..9fec863f5463 100644 --- a/sc/source/ui/vba/vbaworkbooks.cxx +++ b/sc/source/ui/vba/vbaworkbooks.cxx @@ -134,18 +134,6 @@ void setUpDocumentModules( const uno::Reference< sheet::XSpreadsheetDocument >& } } } - - /* Trigger the Workbook_Open event, event processor will register - itself as listener for specific events. */ - try - { - uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( pShell->GetDocument()->GetVbaEventProcessor(), uno::UNO_SET_THROW ); - uno::Sequence< uno::Any > aArgs; - xVbaEvents->processVbaEvent( script::vba::VBAEventId::WORKBOOK_OPEN, aArgs ); - } - catch( uno::Exception& ) - { - } } } @@ -157,19 +145,14 @@ getWorkbook( uno::Reference< uno::XComponentContext >& xContext, const uno::Refe if( !xModel.is() ) return uno::Any(); - ScDocShell* pShell = excel::getDocShell( xModel ); - if ( pShell ) + uno::Reference< excel::XWorkbook > xWb( getVBADocument( xModel ), uno::UNO_QUERY ); + if ( xWb.is() ) { - String sCodeName = pShell->GetDocument()->GetCodeName(); - uno::Reference< uno::XInterface > xIf = getUnoDocModule( sCodeName, pShell ); - if ( xIf.is() ) - { - OSL_TRACE(" *** Returning Module uno Object *** "); - return uno::makeAny( xIf ); - } + OSL_TRACE(" *** Returning Module uno Object *** "); + return uno::Any( xWb ); } - ScVbaWorkbook *pWb = new ScVbaWorkbook( xParent, xContext, xModel ); + ScVbaWorkbook *pWb = new ScVbaWorkbook( xParent, xContext, xModel ); return uno::Any( uno::Reference< excel::XWorkbook > (pWb) ); } diff --git a/sc/source/ui/vba/vbaworksheets.cxx b/sc/source/ui/vba/vbaworksheets.cxx index bd21cb396c66..cf74f90b5941 100644 --- a/sc/source/ui/vba/vbaworksheets.cxx +++ b/sc/source/ui/vba/vbaworksheets.cxx @@ -68,23 +68,6 @@ typedef std::vector< uno::Reference< sheet::XSpreadsheet > > SheetMap; // #FIXME #TODO the implementation of the Sheets collections sucks, // e.g. there is no support for tracking sheets added/removed from the collection -uno::Reference< uno::XInterface > -lcl_getModulAsUnoObject( const uno::Reference< sheet::XSpreadsheet >& xSheet, const uno::Reference< frame::XModel >& xModel ) throw ( uno::RuntimeException ) -{ - uno::Reference< uno::XInterface > xRet; - if ( !xSheet.is() ) - throw uno::RuntimeException(); - uno::Reference< beans::XPropertySet > xProps( xSheet, uno::UNO_QUERY_THROW ); - rtl::OUString sName; - xProps->getPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_CODENAME ) ) ) >>= sName; - - ScDocShell* pShell = excel::getDocShell( xModel ); - - if ( pShell ) - xRet = getUnoDocModule( sName, pShell ); - return xRet; -} - class WorkSheetsEnumeration : public SheetEnumeration_BASE { SheetMap mSheetMap; @@ -173,16 +156,16 @@ public: virtual uno::Any SAL_CALL nextElement( ) throw (container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException) { uno::Reference< sheet::XSpreadsheet > xSheet( m_xEnumeration->nextElement(), uno::UNO_QUERY_THROW ); - uno::Reference< uno::XInterface > xIf = lcl_getModulAsUnoObject( xSheet, m_xModel ); + uno::Reference< XHelperInterface > xIf = excel::getUnoSheetModuleObj( xSheet ); uno::Any aRet; if ( !xIf.is() ) - { + { // if the Sheet is in a document created by the api unfortunately ( at the // moment, it actually wont have the special Document modules uno::Reference< excel::XWorksheet > xNewSheet( new ScVbaWorksheet( m_xParent, m_xContext, xSheet, m_xModel ) ); aRet <<= xNewSheet; - } - else + } + else aRet <<= xIf; return aRet; } @@ -220,7 +203,7 @@ uno::Any ScVbaWorksheets::createCollectionObject( const uno::Any& aSource ) { uno::Reference< sheet::XSpreadsheet > xSheet( aSource, uno::UNO_QUERY ); - uno::Reference< XInterface > xIf = lcl_getModulAsUnoObject( xSheet, mxModel ); + uno::Reference< XHelperInterface > xIf = excel::getUnoSheetModuleObj( xSheet ); uno::Any aRet; if ( !xIf.is() ) { diff --git a/sc/source/ui/view/editsh.cxx b/sc/source/ui/view/editsh.cxx index e07e15267198..f75ebcbe770f 100644 --- a/sc/source/ui/view/editsh.cxx +++ b/sc/source/ui/view/editsh.cxx @@ -199,6 +199,7 @@ void ScEditShell::Execute( SfxRequest& rReq ) pHdl->DataChanging(); sal_Bool bSetSelIsRef = sal_False; + sal_Bool bSetModified = sal_True; switch ( nSlot ) { @@ -234,6 +235,7 @@ void ScEditShell::Execute( SfxRequest& rReq ) case SID_COPY: pTableView->Copy(); + bSetModified = sal_False; break; case SID_CUT: @@ -334,6 +336,7 @@ void ScEditShell::Execute( SfxRequest& rReq ) if (pTopView) pTopView->SetSelection(ESelection(0,0,nPar-1,nLen)); } + bSetModified = sal_False; } break; @@ -615,7 +618,7 @@ void ScEditShell::Execute( SfxRequest& rReq ) break; } - pHdl->DataChanged(); + pHdl->DataChanged(sal_False, bSetModified); if (bSetSelIsRef) pHdl->SetSelIsRef(sal_True); } diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx index 335f5ad14490..d58d2266618d 100644 --- a/sc/source/ui/view/gridwin.cxx +++ b/sc/source/ui/view/gridwin.cxx @@ -2,7 +2,7 @@ * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * Copyright 2000, 2010 Oracle and/or its affiliates. + * Copyright 2000, 2011 Oracle and/or its affiliates. * * OpenOffice.org - a multi-platform office productivity suite * @@ -1682,6 +1682,7 @@ void ScGridWindow::HandleMouseButtonDown( const MouseEvent& rMEvt ) pDoc->GetAttr( nPosX, nPosY, nTab, ATTR_MERGE_FLAG ); if (pAttr->HasAutoFilter()) { + SC_MOD()->InputEnterHandler(); //Add for i85305 if (DoAutoFilterButton(nPosX, nPosY, rMEvt)) return; } diff --git a/sc/source/ui/view/gridwin2.cxx b/sc/source/ui/view/gridwin2.cxx index 67cc1d318fdb..89fd1027877d 100644 --- a/sc/source/ui/view/gridwin2.cxx +++ b/sc/source/ui/view/gridwin2.cxx @@ -456,6 +456,18 @@ private: } +bool lcl_GetLabelIndex( size_t& rLabelIndex, long nDimension, const ScDPLabelDataVector& rLabelArray ) +{ + size_t n = rLabelArray.size(); + for (size_t i = 0; i < n; ++i) + if (static_cast<long>(rLabelArray[i].mnCol) == nDimension) + { + rLabelIndex = i; + return true; + } + return false; +} + void ScGridWindow::DPLaunchFieldPopupMenu( const Point& rScrPos, const Size& rScrSize, const ScAddress& rPos, ScDPObject* pDPObj) { @@ -467,11 +479,12 @@ void ScGridWindow::DPLaunchFieldPopupMenu( sal_uInt16 nOrient; pDPData->mnDim = pDPObj->GetHeaderDim(rPos, nOrient); - if (pDPData->maDPParam.maLabelArray.size() <= static_cast<size_t>(pDPData->mnDim)) - // out-of-bound dimension ID. This should never happen! + // #i116457# FillLabelData skips empty column names, so mnDim can't be used directly as index into maLabelArray. + size_t nLabelIndex = 0; + if (!lcl_GetLabelIndex( nLabelIndex, pDPData->mnDim, pDPData->maDPParam.maLabelArray )) return; - const ScDPLabelData& rLabelData = pDPData->maDPParam.maLabelArray[pDPData->mnDim]; + const ScDPLabelData& rLabelData = pDPData->maDPParam.maLabelArray[nLabelIndex]; mpDPFieldPopup.reset(new ScDPFieldPopupWindow(this, pViewData->GetDocument())); mpDPFieldPopup->setName(OUString::createFromAscii("Pivot table field member popup")); @@ -567,8 +580,11 @@ void ScGridWindow::UpdateDPFromFieldPopupMenu() if (!pDim) return; + size_t nLabelIndex = 0; + lcl_GetLabelIndex( nLabelIndex, pDPData->mnDim, pDPData->maDPParam.maLabelArray ); + // Build a map of layout names to original names. - const ScDPLabelData& rLabelData = pDPData->maDPParam.maLabelArray[pDPData->mnDim]; + const ScDPLabelData& rLabelData = pDPData->maDPParam.maLabelArray[nLabelIndex]; MemNameMapType aMemNameMap; for (vector<ScDPLabelData::Member>::const_iterator itr = rLabelData.maMembers.begin(), itrEnd = rLabelData.maMembers.end(); itr != itrEnd; ++itr) diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx index 2df47d16e195..0b9a1c4084e4 100644 --- a/sc/source/ui/view/output2.cxx +++ b/sc/source/ui/view/output2.cxx @@ -75,8 +75,6 @@ #include "scmod.hxx" #include "fillinfo.hxx" -#include <boost/ptr_container/ptr_vector.hpp> - #include <math.h> //! Autofilter-Breite mit column.cxx zusammenfassen @@ -154,6 +152,8 @@ public: const Size& GetTextSize() const { return aTextSize; } long GetOriginalWidth() const { return nOriginalWidth; } + sal_uLong GetResultValueFormat( const ScBaseCell* pCell ) const; + sal_uLong GetValueFormat() const { return nValueFormat; } sal_Bool GetLineBreak() const { return bLineBreak; } sal_Bool IsRepeat() const { return bRepeat; } @@ -542,7 +542,7 @@ void ScDrawStringsVars::SetTextToWidthOrHash( ScBaseCell* pCell, long nWidth ) return; } - sal_uLong nFormat = GetValueFormat(); + sal_uLong nFormat = GetResultValueFormat(pCell); if ((nFormat % SV_COUNTRY_LANGUAGE_OFFSET) != 0) { // Not 'General' number format. Set hash text and bail out. @@ -719,6 +719,17 @@ sal_Bool ScDrawStringsVars::HasEditCharacters() const return aString.SearchChar( pChars ) != STRING_NOTFOUND; } +sal_uLong ScDrawStringsVars::GetResultValueFormat( const ScBaseCell* pCell ) const +{ + // Get the effective number format, including formula result types. + // This assumes that a formula cell has already been calculated. + + if ( (nValueFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 && pCell && pCell->GetCellType() == CELLTYPE_FORMULA ) + return static_cast<const ScFormulaCell*>(pCell)->GetStandardFormat(*pOutput->pDoc->GetFormatTable(), nValueFormat); + else + return nValueFormat; +} + //================================================================== double ScOutputData::GetStretch() @@ -1361,10 +1372,6 @@ void ScOutputData::DrawStrings( sal_Bool bPixelToLogic ) const SfxItemSet* pOldCondSet = NULL; sal_uInt8 nOldScript = 0; - // alternative pattern instances in case we need to modify the pattern - // before processing the cell value. - ::boost::ptr_vector<ScPatternAttr> aAltPatterns; - long nPosY = nScrY; for (SCSIZE nArrY=1; nArrY+1<nArrCount; nArrY++) { @@ -1501,18 +1508,6 @@ void ScOutputData::DrawStrings( sal_Bool bPixelToLogic ) pCondSet = pDoc->GetCondResult( nCellX, nCellY, nTab ); } - if (pCell->HasValueData() && - static_cast<const SfxBoolItem&>( - pPattern->GetItem(ATTR_LINEBREAK, pCondSet)).GetValue()) - { - // Disable line break when the cell content is numeric. - aAltPatterns.push_back(new ScPatternAttr(*pPattern)); - ScPatternAttr* pAltPattern = &aAltPatterns.back(); - SfxBoolItem aLineBreak(ATTR_LINEBREAK, false); - pAltPattern->GetItemSet().Put(aLineBreak); - pPattern = pAltPattern; - } - sal_uInt8 nScript = GetScriptType( pDoc, pCell, pPattern, pCondSet ); if (nScript == 0) nScript = ScGlobal::GetDefaultScriptType(); if ( pPattern != pOldPattern || pCondSet != pOldCondSet || @@ -1562,6 +1557,11 @@ void ScOutputData::DrawStrings( sal_Bool bPixelToLogic ) eOutHorJust = SVX_HOR_JUSTIFY_LEFT; // repeat is not yet implemented sal_Bool bBreak = ( aVars.GetLineBreak() || aVars.GetHorJust() == SVX_HOR_JUSTIFY_BLOCK ); + + // #i111387# #o11817313# disable automatic line breaks only for "General" number format + if ( bBreak && bCellIsValue && ( aVars.GetResultValueFormat(pCell) % SV_COUNTRY_LANGUAGE_OFFSET ) == 0 ) + bBreak = sal_False; + sal_Bool bRepeat = aVars.IsRepeat() && !bBreak; sal_Bool bShrink = aVars.IsShrink() && !bBreak && !bRepeat; diff --git a/sc/source/ui/view/tabcont.cxx b/sc/source/ui/view/tabcont.cxx index 6e41548dc31f..48de6a0ee731 100644 --- a/sc/source/ui/view/tabcont.cxx +++ b/sc/source/ui/view/tabcont.cxx @@ -458,12 +458,13 @@ void ScTabControl::DoDrag( const Region& /* rRegion */ ) ScDocument* pDoc = pDocSh->GetDocument(); SCTAB nTab = pViewData->GetTabNo(); + ScRange aTabRange( 0, 0, nTab, MAXCOL, MAXROW, nTab ); ScMarkData aTabMark = pViewData->GetMarkData(); aTabMark.ResetMark(); // doesn't change marked table information - aTabMark.SetMarkArea( ScRange(0,0,nTab,MAXCOL,MAXROW,nTab) ); + aTabMark.SetMarkArea( aTabRange ); ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP ); - ScClipParam aClipParam(ScRange(0, 0, 0, MAXCOL, MAXROW, 0), false); + ScClipParam aClipParam(aTabRange, false); pDoc->CopyToClip(aClipParam, pClipDoc, &aTabMark, false); TransferableObjectDescriptor aObjDesc; diff --git a/sc/source/ui/view/viewfun3.cxx b/sc/source/ui/view/viewfun3.cxx index 0f4893cf3512..f25aa500cc72 100644 --- a/sc/source/ui/view/viewfun3.cxx +++ b/sc/source/ui/view/viewfun3.cxx @@ -1104,7 +1104,20 @@ sal_Bool ScViewFunc::PasteFromClip( sal_uInt16 nFlags, ScDocument* pClipDoc, if (nBlockAddX > nDestSizeX) nMarkAddX = nBlockAddX - nDestSizeX; // fuer Merge-Test else + { nEndCol = nStartCol + nDestSizeX; + if (nEndCol > aMarkRange.aEnd.Col()) + { + // #i113553# larger range has to be included in aFilteredMark (for undo), but extending columns can't changed the filtered status + aMarkRange = ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ); + aFilteredMark.SetMarkArea( aMarkRange ); + if (bMarkIsFiltered) + { + ScViewUtil::UnmarkFiltered( aFilteredMark, pDoc ); + aFilteredMark.FillRangeListWithMarks( &aRangeList, sal_True ); + } + } + } if (nBlockAddY > nDestSizeY) nMarkAddY = nBlockAddY - nDestSizeY; // fuer Merge-Test diff --git a/sc/source/ui/view/viewfun5.cxx b/sc/source/ui/view/viewfun5.cxx index fff42faecb51..1d2b636c4259 100644 --- a/sc/source/ui/view/viewfun5.cxx +++ b/sc/source/ui/view/viewfun5.cxx @@ -165,7 +165,7 @@ sal_Bool ScViewFunc::PasteDataFormat( sal_uLong nFormatId, nFirstCol = nLastCol = 0; nFirstRow = nLastRow = 0; } - ScClipParam aClipParam(ScRange(nFirstCol, nFirstRow, 0, nLastCol, nLastRow, 0), false); + ScClipParam aClipParam(ScRange(nFirstCol, nFirstRow, nSrcTab, nLastCol, nLastRow, nSrcTab), false); pSrcDoc->CopyToClip(aClipParam, pClipDoc, &aSrcMark); ScGlobal::SetClipDocName( xDocShRef->GetTitle( SFX_TITLE_FULLNAME ) ); diff --git a/sc/util/makefile.mk b/sc/util/makefile.mk index dd0a6043c8fd..a7ce2f9407dc 100644 --- a/sc/util/makefile.mk +++ b/sc/util/makefile.mk @@ -311,6 +311,7 @@ SHL9STDLIBS= \ $(VCLLIB) \ $(TKLIB) \ $(MSFILTERLIB) \ + $(UNOTOOLSLIB) \ $(FORLIB) SHL9DEPN=$(SHL1TARGETN) $(SHL8TARGETN) |