diff options
Diffstat (limited to 'sc/source/ui/unoobj')
50 files changed, 49125 insertions, 0 deletions
diff --git a/sc/source/ui/unoobj/ChartRangeSelectionListener.cxx b/sc/source/ui/unoobj/ChartRangeSelectionListener.cxx new file mode 100644 index 000000000000..e8000d71518b --- /dev/null +++ b/sc/source/ui/unoobj/ChartRangeSelectionListener.cxx @@ -0,0 +1,95 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +#include "ChartRangeSelectionListener.hxx" + +#include <com/sun/star/chart2/data/XRangeHighlighter.hpp> + +#include <sfx2/viewfrm.hxx> +#include "tabvwsh.hxx" +#include "unonames.hxx" +#include "miscuno.hxx" + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +SC_SIMPLE_SERVICE_INFO( ScChartRangeSelectionListener, "ScChartRangeSelectionListener", + SC_SERVICENAME_CHRANGEHILIGHT ) + +ScChartRangeSelectionListener::ScChartRangeSelectionListener( ScTabViewShell * pViewShell ) : + ScChartRangeSelectionListener_Base( m_aMutex ), + m_pViewShell( pViewShell ) +{} + +ScChartRangeSelectionListener::~ScChartRangeSelectionListener() +{} + +// ____ XModifyListener ____ +void SAL_CALL ScChartRangeSelectionListener::selectionChanged( const lang::EventObject& aEvent ) + throw (uno::RuntimeException) +{ + Reference< chart2::data::XRangeHighlighter > xRangeHighlighter( aEvent.Source, uno::UNO_QUERY ); + if( xRangeHighlighter.is()) + { + Sequence< chart2::data::HighlightedRange > aRanges( xRangeHighlighter->getSelectedRanges()); + + // search the view on which the chart is active + + if( m_pViewShell ) + { + m_pViewShell->DoChartSelection( aRanges ); + } +// SfxViewFrame *pFrame = SfxViewFrame::GetFirst( m_pDocShell ); +// while (pFrame) +// { +// SfxViewShell* pSh = pFrame->GetViewShell(); +// if (pSh && pSh->ISA(ScTabViewShell)) +// { +// ScTabViewShell* pViewSh = (ScTabViewShell*)pSh; +// } +// pFrame = SfxViewFrame::GetNext( *pFrame, m_pDocShell ); +// } + } +} + +// ____ XEventListener ____ +void SAL_CALL ScChartRangeSelectionListener::disposing( const lang::EventObject& /*Source*/ ) + throw (uno::RuntimeException) +{ +} + +// ____ WeakComponentImplHelperBase ____ +void SAL_CALL ScChartRangeSelectionListener::disposing() +{ + m_pViewShell = 0; +} diff --git a/sc/source/ui/unoobj/addruno.cxx b/sc/source/ui/unoobj/addruno.cxx new file mode 100644 index 000000000000..10627222be80 --- /dev/null +++ b/sc/source/ui/unoobj/addruno.cxx @@ -0,0 +1,315 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include <com/sun/star/table/CellAddress.hpp> +#include <com/sun/star/table/CellRangeAddress.hpp> + +#include <svl/itemprop.hxx> + +#include "docsh.hxx" +#include "unonames.hxx" +#include "unoguard.hxx" +#include "miscuno.hxx" +#include "convuno.hxx" +#include "addruno.hxx" + +using namespace com::sun::star; + +//------------------------------------------------------------------------ + +ScAddressConversionObj::ScAddressConversionObj(ScDocShell* pDocSh, sal_Bool bForRange) : + pDocShell( pDocSh ), + nRefSheet( 0 ), + bIsRange( bForRange ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScAddressConversionObj::~ScAddressConversionObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScAddressConversionObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // invalid + } +} + +sal_Bool ScAddressConversionObj::ParseUIString( const String& rUIString ) +{ + if (!pDocShell) + return sal_False; + + ScDocument* pDoc = pDocShell->GetDocument(); + sal_Bool bSuccess = sal_False; + if ( bIsRange ) + { + USHORT nResult = aRange.ParseAny( rUIString, pDoc ); + if ( nResult & SCA_VALID ) + { + if ( ( nResult & SCA_TAB_3D ) == 0 ) + aRange.aStart.SetTab( static_cast<SCTAB>(nRefSheet) ); + if ( ( nResult & SCA_TAB2_3D ) == 0 ) + aRange.aEnd.SetTab( aRange.aStart.Tab() ); + // different sheets are not supported in CellRangeAddress + if ( aRange.aStart.Tab() == aRange.aEnd.Tab() ) + bSuccess = sal_True; + } + } + else + { + USHORT nResult = aRange.aStart.Parse( rUIString, pDoc ); + if ( nResult & SCA_VALID ) + { + if ( ( nResult & SCA_TAB_3D ) == 0 ) + aRange.aStart.SetTab( static_cast<SCTAB>(nRefSheet) ); + bSuccess = sal_True; + } + } + return bSuccess; +} + +// XPropertySet + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScAddressConversionObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if ( bIsRange ) + { + static SfxItemPropertyMapEntry aPropertyMap[] = + { + {MAP_CHAR_LEN(SC_UNONAME_ADDRESS), 0, &getCppuType((table::CellRangeAddress*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PERSREPR), 0, &getCppuType((rtl::OUString*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_REFSHEET), 0, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_UIREPR), 0, &getCppuType((rtl::OUString*)0), 0, 0 }, + {0,0,0,0,0,0} + }; + static uno::Reference<beans::XPropertySetInfo> aRef(new SfxItemPropertySetInfo( aPropertyMap )); + return aRef; + } + else + { + static SfxItemPropertyMapEntry aPropertyMap[] = + { + {MAP_CHAR_LEN(SC_UNONAME_ADDRESS), 0, &getCppuType((table::CellAddress*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PERSREPR), 0, &getCppuType((rtl::OUString*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_REFSHEET), 0, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_UIREPR), 0, &getCppuType((rtl::OUString*)0), 0, 0 }, + {0,0,0,0,0,0} + }; + static uno::Reference<beans::XPropertySetInfo> aRef(new SfxItemPropertySetInfo( aPropertyMap )); + return aRef; + } +} + +void SAL_CALL ScAddressConversionObj::setPropertyValue( const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + if ( !pDocShell ) + throw uno::RuntimeException(); + + sal_Bool bSuccess = sal_False; + String aNameStr(aPropertyName); + if ( aNameStr.EqualsAscii( SC_UNONAME_ADDRESS ) ) + { + // read the cell/range address from API struct + if ( bIsRange ) + { + table::CellRangeAddress aRangeAddress; + if ( aValue >>= aRangeAddress ) + { + ScUnoConversion::FillScRange( aRange, aRangeAddress ); + bSuccess = sal_True; + } + } + else + { + table::CellAddress aCellAddress; + if ( aValue >>= aCellAddress ) + { + ScUnoConversion::FillScAddress( aRange.aStart, aCellAddress ); + bSuccess = sal_True; + } + } + } + else if ( aNameStr.EqualsAscii( SC_UNONAME_REFSHEET ) ) + { + // set the reference sheet + sal_Int32 nIntVal = 0; + if ( aValue >>= nIntVal ) + { + nRefSheet = nIntVal; + bSuccess = sal_True; + } + } + else if ( aNameStr.EqualsAscii( SC_UNONAME_UIREPR ) ) + { + // parse the UI representation string + rtl::OUString sRepresentation; + if (aValue >>= sRepresentation) + { + String aUIString = sRepresentation; + bSuccess = ParseUIString( aUIString ); + } + } + else if ( aNameStr.EqualsAscii( SC_UNONAME_PERSREPR ) ) + { + // parse the file format string + rtl::OUString sRepresentation; + if (aValue >>= sRepresentation) + { + String aUIString(sRepresentation); + + // cell or range: strip a single "." at the start + if ( aUIString.GetChar(0) == (sal_Unicode) '.' ) + aUIString.Erase( 0, 1 ); + + if ( bIsRange ) + { + // range: also strip a "." after the last colon + sal_Int32 nColon = rtl::OUString(aUIString).lastIndexOf( (sal_Unicode) ':' ); + if ( nColon >= 0 && nColon < aUIString.Len() - 1 && + aUIString.GetChar((xub_StrLen)nColon+1) == (sal_Unicode) '.' ) + aUIString.Erase( (xub_StrLen)nColon+1, 1 ); + } + + // parse the rest like a UI string + bSuccess = ParseUIString( aUIString ); + } + } + else + throw beans::UnknownPropertyException(); + + if ( !bSuccess ) + throw lang::IllegalArgumentException(); +} + +uno::Any SAL_CALL ScAddressConversionObj::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + if ( !pDocShell ) + throw uno::RuntimeException(); + + ScDocument* pDoc = pDocShell->GetDocument(); + uno::Any aRet; + + String aNameStr(aPropertyName); + if ( aNameStr.EqualsAscii( SC_UNONAME_ADDRESS ) ) + { + if ( bIsRange ) + { + table::CellRangeAddress aRangeAddress; + ScUnoConversion::FillApiRange( aRangeAddress, aRange ); + aRet <<= aRangeAddress; + } + else + { + table::CellAddress aCellAddress; + ScUnoConversion::FillApiAddress( aCellAddress, aRange.aStart ); + aRet <<= aCellAddress; + } + } + else if ( aNameStr.EqualsAscii( SC_UNONAME_REFSHEET ) ) + { + aRet <<= nRefSheet; + } + else if ( aNameStr.EqualsAscii( SC_UNONAME_UIREPR ) ) + { + // generate UI representation string - include sheet only if different from ref sheet + String aFormatStr; + USHORT nFlags = SCA_VALID; + if ( aRange.aStart.Tab() != nRefSheet ) + nFlags |= SCA_TAB_3D; + if ( bIsRange ) + aRange.Format( aFormatStr, nFlags, pDoc ); + else + aRange.aStart.Format( aFormatStr, nFlags, pDoc ); + aRet <<= rtl::OUString( aFormatStr ); + } + else if ( aNameStr.EqualsAscii( SC_UNONAME_PERSREPR ) ) + { + // generate file format string - always include sheet + String aFormatStr; + aRange.aStart.Format( aFormatStr, SCA_VALID | SCA_TAB_3D, pDoc ); + if ( bIsRange ) + { + // manually concatenate range so both parts always have the sheet name + aFormatStr.Append( (sal_Unicode) ':' ); + String aSecond; + aRange.aEnd.Format( aSecond, SCA_VALID | SCA_TAB_3D, pDoc ); + aFormatStr.Append( aSecond ); + } + aRet <<= rtl::OUString( aFormatStr ); + } + else + throw beans::UnknownPropertyException(); + + return aRet; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScAddressConversionObj ) + +// lang::XServiceInfo + +rtl::OUString SAL_CALL ScAddressConversionObj::getImplementationName() throw(uno::RuntimeException) +{ + return rtl::OUString::createFromAscii( "ScAddressConversionObj" ); +} + +sal_Bool SAL_CALL ScAddressConversionObj::supportsService( const rtl::OUString& rServiceName ) + throw(uno::RuntimeException) +{ + String aServiceStr( rServiceName ); + return aServiceStr.EqualsAscii( bIsRange ? SC_SERVICENAME_RANGEADDRESS + : SC_SERVICENAME_CELLADDRESS ); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScAddressConversionObj::getSupportedServiceNames() + throw(uno::RuntimeException) +{ + uno::Sequence<rtl::OUString> aRet(1); + rtl::OUString* pArray = aRet.getArray(); + pArray[0] = rtl::OUString::createFromAscii( bIsRange ? SC_SERVICENAME_RANGEADDRESS + : SC_SERVICENAME_CELLADDRESS ); + return aRet; +} + diff --git a/sc/source/ui/unoobj/afmtuno.cxx b/sc/source/ui/unoobj/afmtuno.cxx new file mode 100644 index 000000000000..481c611773ed --- /dev/null +++ b/sc/source/ui/unoobj/afmtuno.cxx @@ -0,0 +1,882 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include "scitems.hxx" +#include <editeng/memberids.hrc> +#include <tools/debug.hxx> +#include <tools/shl.hxx> +#include <svl/poolitem.hxx> +#include <svx/unomid.hxx> +#include "unowids.hxx" +#include <rtl/uuid.h> +#include <com/sun/star/table/BorderLine.hpp> +#include <com/sun/star/table/CellVertJustify.hpp> +#include <com/sun/star/table/ShadowLocation.hpp> +#include <com/sun/star/table/TableBorder.hpp> +#include <com/sun/star/table/ShadowFormat.hpp> +#include <com/sun/star/table/CellRangeAddress.hpp> +#include <com/sun/star/table/CellContentType.hpp> +#include <com/sun/star/table/TableOrientation.hpp> +#include <com/sun/star/table/CellHoriJustify.hpp> +#include <com/sun/star/util/SortField.hpp> +#include <com/sun/star/util/SortFieldType.hpp> +#include <com/sun/star/table/CellOrientation.hpp> +#include <com/sun/star/table/CellAddress.hpp> +#include <com/sun/star/awt/SimpleFontMetric.hpp> +#include <com/sun/star/awt/FontWeight.hpp> +#include <com/sun/star/awt/FontSlant.hpp> +#include <com/sun/star/awt/CharSet.hpp> +#include <com/sun/star/awt/FontDescriptor.hpp> +#include <com/sun/star/awt/FontWidth.hpp> +#include <com/sun/star/awt/XFont.hpp> +#include <com/sun/star/awt/FontType.hpp> +#include <com/sun/star/awt/FontUnderline.hpp> +#include <com/sun/star/awt/FontStrikeout.hpp> +#include <com/sun/star/awt/FontFamily.hpp> +#include <com/sun/star/awt/FontPitch.hpp> + +#include "afmtuno.hxx" +#include "miscuno.hxx" +#include "autoform.hxx" +#include "unoguard.hxx" +#include "scdll.hxx" +#include "unonames.hxx" +#include "cellsuno.hxx" + +using namespace ::com::sun::star; + +//------------------------------------------------------------------------ + +// ein AutoFormat hat immer 16 Eintraege +#define SC_AF_FIELD_COUNT 16 + +//------------------------------------------------------------------------ + +// AutoFormat-Map nur fuer PropertySetInfo, ohne Which-IDs + +const SfxItemPropertyMapEntry* lcl_GetAutoFormatMap() +{ + static SfxItemPropertyMapEntry aAutoFormatMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_INCBACK), 0, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_INCBORD), 0, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_INCFONT), 0, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_INCJUST), 0, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_INCNUM), 0, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_INCWIDTH), 0, &::getBooleanCppuType(), 0, 0 }, + {0,0,0,0,0,0} + }; + return aAutoFormatMap_Impl; +} + +//! Zahlformat (String/Language) ??? (in XNumberFormat nur ReadOnly) +//! table::TableBorder ??!? + +const SfxItemPropertyMapEntry* lcl_GetAutoFieldMap() +{ + static SfxItemPropertyMapEntry aAutoFieldMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_CELLBACK), ATTR_BACKGROUND, &::getCppuType((const sal_Int32*)0), 0, MID_BACK_COLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CCOLOR), ATTR_FONT_COLOR, &::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_COUTL), ATTR_FONT_CONTOUR, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CCROSS), ATTR_FONT_CROSSEDOUT, &::getBooleanCppuType(), 0, MID_CROSSED_OUT }, + {MAP_CHAR_LEN(SC_UNONAME_CFONT), ATTR_FONT, &::getCppuType((const sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNONAME_CFCHARS), ATTR_FONT, &::getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFCHARS), ATTR_CJK_FONT, &::getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFCHARS), ATTR_CTL_FONT, &::getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNONAME_CFFAMIL), ATTR_FONT, &::getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFFAMIL), ATTR_CJK_FONT, &::getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFFAMIL), ATTR_CTL_FONT, &::getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNONAME_CFNAME), ATTR_FONT, &::getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFNAME), ATTR_CJK_FONT, &::getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFNAME), ATTR_CTL_FONT, &::getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNONAME_CFPITCH), ATTR_FONT, &::getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFPITCH), ATTR_CJK_FONT, &::getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFPITCH), ATTR_CTL_FONT, &::getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNONAME_CFSTYLE), ATTR_FONT, &::getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFSTYLE), ATTR_CJK_FONT, &::getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFSTYLE), ATTR_CTL_FONT, &::getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNONAME_CHEIGHT), ATTR_FONT_HEIGHT, &::getCppuType((float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_CJK_CHEIGHT), ATTR_CJK_FONT_HEIGHT, &::getCppuType((float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_CTL_CHEIGHT), ATTR_CTL_FONT_HEIGHT, &::getCppuType((float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_COVER), ATTR_FONT_OVERLINE, &::getCppuType((const sal_Int16*)0), 0, MID_TL_STYLE }, + {MAP_CHAR_LEN(SC_UNONAME_CPOST), ATTR_FONT_POSTURE, &::getCppuType((awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNO_CJK_CPOST), ATTR_CJK_FONT_POSTURE, &::getCppuType((awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNO_CTL_CPOST), ATTR_CTL_FONT_POSTURE, &::getCppuType((awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNONAME_CSHADD), ATTR_FONT_SHADOWED, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_TBLBORD), SC_WID_UNO_TBLBORD, &::getCppuType((table::TableBorder*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_CUNDER), ATTR_FONT_UNDERLINE, &::getCppuType((const sal_Int16*)0), 0, MID_TL_STYLE }, + {MAP_CHAR_LEN(SC_UNONAME_CWEIGHT), ATTR_FONT_WEIGHT, &::getCppuType((float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNO_CJK_CWEIGHT), ATTR_CJK_FONT_WEIGHT, &::getCppuType((float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNO_CTL_CWEIGHT), ATTR_CTL_FONT_WEIGHT, &::getCppuType((float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNONAME_CELLHJUS), ATTR_HOR_JUSTIFY, &::getCppuType((const table::CellHoriJustify*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLTRAN), ATTR_BACKGROUND, &::getBooleanCppuType(), 0, MID_GRAPHIC_TRANSPARENT }, + {MAP_CHAR_LEN(SC_UNONAME_WRAP), ATTR_LINEBREAK, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLORI), ATTR_STACKED, &::getCppuType((const table::CellOrientation*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PBMARGIN), ATTR_MARGIN, &::getCppuType((const sal_Int32*)0), 0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PLMARGIN), ATTR_MARGIN, &::getCppuType((const sal_Int32*)0), 0, MID_MARGIN_L_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PRMARGIN), ATTR_MARGIN, &::getCppuType((const sal_Int32*)0), 0, MID_MARGIN_R_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PTMARGIN), ATTR_MARGIN, &::getCppuType((const sal_Int32*)0), 0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_ROTANG), ATTR_ROTATE_VALUE, &::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_ROTREF), ATTR_ROTATE_MODE, &::getCppuType((const table::CellVertJustify*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLVJUS), ATTR_VER_JUSTIFY, &::getCppuType((const table::CellVertJustify*)0), 0, 0 }, + {0,0,0,0,0,0} + }; + return aAutoFieldMap_Impl; +} + +//------------------------------------------------------------------------ + +#define SCAUTOFORMATSOBJ_SERVICE "com.sun.star.sheet.TableAutoFormats" + +SC_SIMPLE_SERVICE_INFO( ScAutoFormatFieldObj, "ScAutoFormatFieldObj", "com.sun.star.sheet.TableAutoFormatField" ) +SC_SIMPLE_SERVICE_INFO( ScAutoFormatObj, "ScAutoFormatObj", "com.sun.star.sheet.TableAutoFormat" ) +SC_SIMPLE_SERVICE_INFO( ScAutoFormatsObj, "ScAutoFormatsObj", SCAUTOFORMATSOBJ_SERVICE ) + +//------------------------------------------------------------------------ + +sal_Bool lcl_FindAutoFormatIndex( const ScAutoFormat& rFormats, const String& rName, sal_uInt16& rOutIndex ) +{ + String aEntryName; + sal_uInt16 nCount = rFormats.GetCount(); + for( sal_uInt16 nPos=0; nPos<nCount; nPos++ ) + { + ScAutoFormatData* pEntry = rFormats[nPos]; + pEntry->GetName( aEntryName ); + if ( aEntryName == rName ) + { + rOutIndex = nPos; + return sal_True; + } + } + return sal_False; // is nich +} + +//------------------------------------------------------------------------ + +ScAutoFormatsObj::ScAutoFormatsObj() +{ + //! Dieses Objekt darf es nur einmal geben, und es muss an den Auto-Format-Daten + //! bekannt sein, damit Aenderungen gebroadcasted werden koennen +} + +ScAutoFormatsObj::~ScAutoFormatsObj() +{ +} + +// stuff for exService_... + +uno::Reference<uno::XInterface> SAL_CALL ScAutoFormatsObj_CreateInstance( + const uno::Reference<lang::XMultiServiceFactory>& ) +{ + ScUnoGuard aGuard; + ScDLL::Init(); + static uno::Reference< uno::XInterface > xInst((::cppu::OWeakObject*) new ScAutoFormatsObj); + return xInst; +} + +rtl::OUString ScAutoFormatsObj::getImplementationName_Static() +{ + return rtl::OUString::createFromAscii( "stardiv.StarCalc.ScAutoFormatsObj" ); +} + +uno::Sequence<rtl::OUString> ScAutoFormatsObj::getSupportedServiceNames_Static() +{ + uno::Sequence<rtl::OUString> aRet(1); + rtl::OUString* pArray = aRet.getArray(); + pArray[0] = rtl::OUString::createFromAscii( SCAUTOFORMATSOBJ_SERVICE ); + return aRet; +} + +// XTableAutoFormats + +ScAutoFormatObj* ScAutoFormatsObj::GetObjectByIndex_Impl(sal_uInt16 nIndex) +{ + ScAutoFormat* pFormats = ScGlobal::GetAutoFormat(); + if (pFormats && nIndex < pFormats->GetCount()) + return new ScAutoFormatObj(nIndex); + + return NULL; // falscher Index +} + +ScAutoFormatObj* ScAutoFormatsObj::GetObjectByName_Impl(const rtl::OUString& aName) +{ + ScAutoFormat* pFormats = ScGlobal::GetAutoFormat(); + if (pFormats) + { + String aString(aName); + sal_uInt16 nIndex; + if (lcl_FindAutoFormatIndex( *pFormats, aString, nIndex )) + return GetObjectByIndex_Impl(nIndex); + } + return NULL; +} + +// container::XNameContainer + +void SAL_CALL ScAutoFormatsObj::insertByName( const rtl::OUString& aName, const uno::Any& aElement ) + throw(lang::IllegalArgumentException, container::ElementExistException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + sal_Bool bDone = sal_False; + // Reflection muss nicht uno::XInterface sein, kann auch irgendein Interface sein... + uno::Reference< uno::XInterface > xInterface(aElement, uno::UNO_QUERY); + if ( xInterface.is() ) + { + ScAutoFormatObj* pFormatObj = ScAutoFormatObj::getImplementation( xInterface ); + if ( pFormatObj && !pFormatObj->IsInserted() ) // noch nicht eingefuegt? + { + String aNameStr(aName); + ScAutoFormat* pFormats = ScGlobal::GetAutoFormat(); + + sal_uInt16 nDummy; + if (pFormats && !lcl_FindAutoFormatIndex( *pFormats, aNameStr, nDummy )) + { + ScAutoFormatData* pNew = new ScAutoFormatData(); + pNew->SetName( aNameStr ); + + if (pFormats->Insert( pNew )) + { + //! Notify fuer andere Objekte + pFormats->Save(); // sofort speichern + + sal_uInt16 nNewIndex; + if (lcl_FindAutoFormatIndex( *pFormats, aNameStr, nNewIndex )) + { + pFormatObj->InitFormat( nNewIndex ); // kann jetzt benutzt werden + bDone = sal_True; + } + } + else + { + delete pNew; + DBG_ERROR("AutoFormat konnte nicht eingefuegt werden"); + throw uno::RuntimeException(); + } + } + else + { + throw container::ElementExistException(); + } + } + } + + if (!bDone) + { + // other errors are handled above + throw lang::IllegalArgumentException(); + } +} + +void SAL_CALL ScAutoFormatsObj::replaceByName( const rtl::OUString& aName, const uno::Any& aElement ) + throw(lang::IllegalArgumentException, container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + //! zusammenfassen? + removeByName( aName ); + insertByName( aName, aElement ); +} + +void SAL_CALL ScAutoFormatsObj::removeByName( const rtl::OUString& aName ) + throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aNameStr(aName); + ScAutoFormat* pFormats = ScGlobal::GetAutoFormat(); + + sal_uInt16 nIndex; + if (pFormats && lcl_FindAutoFormatIndex( *pFormats, aNameStr, nIndex )) + { + pFormats->AtFree( nIndex ); + + //! Notify fuer andere Objekte + pFormats->Save(); // sofort speichern + } + else + { + throw container::NoSuchElementException(); + } +} + +// container::XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScAutoFormatsObj::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.TableAutoFormatEnumeration"))); +} + +// container::XIndexAccess + +sal_Int32 SAL_CALL ScAutoFormatsObj::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScAutoFormat* pFormats = ScGlobal::GetAutoFormat(); + if (pFormats) + return pFormats->GetCount(); + + return 0; +} + +uno::Any SAL_CALL ScAutoFormatsObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference< container::XNamed > xFormat(GetObjectByIndex_Impl((sal_uInt16)nIndex)); + if (!xFormat.is()) + throw lang::IndexOutOfBoundsException(); + return uno::makeAny(xFormat); +} + +uno::Type SAL_CALL ScAutoFormatsObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ::getCppuType((const uno::Reference< container::XNamed >*)0); // muss zu getByIndex passen +} + +sal_Bool SAL_CALL ScAutoFormatsObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +// container::XNameAccess + +uno::Any SAL_CALL ScAutoFormatsObj::getByName( const rtl::OUString& aName ) + throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference< container::XNamed > xFormat(GetObjectByName_Impl(aName)); + if (!xFormat.is()) + throw container::NoSuchElementException(); + return uno::makeAny(xFormat); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScAutoFormatsObj::getElementNames() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScAutoFormat* pFormats = ScGlobal::GetAutoFormat(); + if (pFormats) + { + String aName; + sal_uInt16 nCount = pFormats->GetCount(); + uno::Sequence<rtl::OUString> aSeq(nCount); + rtl::OUString* pAry = aSeq.getArray(); + for (sal_uInt16 i=0; i<nCount; i++) + { + (*pFormats)[i]->GetName(aName); + pAry[i] = aName; + } + return aSeq; + } + return uno::Sequence<rtl::OUString>(0); +} + +sal_Bool SAL_CALL ScAutoFormatsObj::hasByName( const rtl::OUString& aName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScAutoFormat* pFormats = ScGlobal::GetAutoFormat(); + if (pFormats) + { + String aString(aName); + sal_uInt16 nDummy; + return lcl_FindAutoFormatIndex( *pFormats, aString, nDummy ); + } + return sal_False; +} + +//------------------------------------------------------------------------ + +ScAutoFormatObj::ScAutoFormatObj(sal_uInt16 nIndex) : + aPropSet( lcl_GetAutoFormatMap() ), + nFormatIndex( nIndex ) +{ + //! Listening !!! +} + +ScAutoFormatObj::~ScAutoFormatObj() +{ + // Wenn ein AutoFormat-Objekt losgelassen wird, werden eventuelle Aenderungen + // gespeichert, damit sie z.B. im Writer sichtbar sind + + if (IsInserted()) + { + ScAutoFormat* pFormats = ScGlobal::GetAutoFormat(); + if ( pFormats && pFormats->IsSaveLater() ) + pFormats->Save(); + + // Save() setzt SaveLater Flag zurueck + } +} + +void ScAutoFormatObj::InitFormat( sal_uInt16 nNewIndex ) +{ + DBG_ASSERT( nFormatIndex == SC_AFMTOBJ_INVALID, "ScAutoFormatObj::InitFormat mehrfach" ); + nFormatIndex = nNewIndex; + //! Listening !!! +} + +// XUnoTunnel + +sal_Int64 SAL_CALL ScAutoFormatObj::getSomething( + const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); + } + return 0; +} + +// static +const uno::Sequence<sal_Int8>& ScAutoFormatObj::getUnoTunnelId() +{ + static uno::Sequence<sal_Int8> * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +// static +ScAutoFormatObj* ScAutoFormatObj::getImplementation( + const uno::Reference<uno::XInterface> xObj ) +{ + ScAutoFormatObj* pRet = NULL; + uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); + if (xUT.is()) + pRet = reinterpret_cast<ScAutoFormatObj*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId()))); + return pRet; +} + +void ScAutoFormatObj::Notify( SfxBroadcaster& /* rBC */, const SfxHint& /* rHint */ ) +{ + // spaeter... +} + +// XTableAutoFormat + +ScAutoFormatFieldObj* ScAutoFormatObj::GetObjectByIndex_Impl(sal_uInt16 nIndex) +{ + if ( IsInserted() && nIndex < SC_AF_FIELD_COUNT ) + return new ScAutoFormatFieldObj( nFormatIndex, nIndex ); + + return NULL; +} + +// container::XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScAutoFormatObj::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.TableAutoFormatEnumeration"))); +} + +// container::XIndexAccess + +sal_Int32 SAL_CALL ScAutoFormatObj::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (IsInserted()) + return SC_AF_FIELD_COUNT; // immer 16 Elemente + else + return 0; +} + +uno::Any SAL_CALL ScAutoFormatObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if ( nIndex < 0 || nIndex >= getCount() ) + throw lang::IndexOutOfBoundsException(); + + if (IsInserted()) + return uno::makeAny(uno::Reference< beans::XPropertySet >(GetObjectByIndex_Impl((sal_uInt16)nIndex))); + return uno::Any(); +} + +uno::Type SAL_CALL ScAutoFormatObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ::getCppuType((const uno::Reference< beans::XPropertySet >*)0); // muss zu getByIndex passen +} + +sal_Bool SAL_CALL ScAutoFormatObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +// container::XNamed + +rtl::OUString SAL_CALL ScAutoFormatObj::getName() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScAutoFormat* pFormats = ScGlobal::GetAutoFormat(); + if (pFormats && IsInserted() && nFormatIndex < pFormats->GetCount()) + { + String aName; + (*pFormats)[nFormatIndex]->GetName(aName); + return aName; + } + return rtl::OUString(); +} + +void SAL_CALL ScAutoFormatObj::setName( const rtl::OUString& aNewName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aNewString(aNewName); + ScAutoFormat* pFormats = ScGlobal::GetAutoFormat(); + + sal_uInt16 nDummy; + if (pFormats && IsInserted() && nFormatIndex < pFormats->GetCount() && + !lcl_FindAutoFormatIndex( *pFormats, aNewString, nDummy )) + { + ScAutoFormatData* pData = (*pFormats)[nFormatIndex]; + DBG_ASSERT(pData,"AutoFormat Daten nicht da"); + + ScAutoFormatData* pNew = new ScAutoFormatData(*pData); + pNew->SetName( aNewString ); + + pFormats->AtFree( nFormatIndex ); + if (pFormats->Insert( pNew )) + { + nFormatIndex = pFormats->IndexOf( pNew ); // ist evtl. anders einsortiert... + + //! Notify fuer andere Objekte + pFormats->SetSaveLater(sal_True); + } + else + { + delete pNew; + DBG_ERROR("AutoFormat konnte nicht eingefuegt werden"); + nFormatIndex = 0; //! alter Index ist ungueltig + } + } + else + { + // not inserted or name exists + throw uno::RuntimeException(); + } +} + +// beans::XPropertySet + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScAutoFormatObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference< beans::XPropertySetInfo > aRef(new SfxItemPropertySetInfo( aPropSet.getPropertyMap() )); + return aRef; +} + +void SAL_CALL ScAutoFormatObj::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScAutoFormat* pFormats = ScGlobal::GetAutoFormat(); + if (pFormats && IsInserted() && nFormatIndex < pFormats->GetCount()) + { + ScAutoFormatData* pData = (*pFormats)[nFormatIndex]; + DBG_ASSERT(pData,"AutoFormat Daten nicht da"); + + String aPropString(aPropertyName); + sal_Bool bBool = sal_Bool(); + if (aPropString.EqualsAscii( SC_UNONAME_INCBACK ) && (aValue >>= bBool)) + pData->SetIncludeBackground( bBool ); + else if (aPropString.EqualsAscii( SC_UNONAME_INCBORD ) && (aValue >>= bBool)) + pData->SetIncludeFrame( bBool ); + else if (aPropString.EqualsAscii( SC_UNONAME_INCFONT ) && (aValue >>= bBool)) + pData->SetIncludeFont( bBool ); + else if (aPropString.EqualsAscii( SC_UNONAME_INCJUST ) && (aValue >>= bBool)) + pData->SetIncludeJustify( bBool ); + else if (aPropString.EqualsAscii( SC_UNONAME_INCNUM ) && (aValue >>= bBool)) + pData->SetIncludeValueFormat( bBool ); + else if (aPropString.EqualsAscii( SC_UNONAME_INCWIDTH ) && (aValue >>= bBool)) + pData->SetIncludeWidthHeight( bBool ); + + // else Fehler + + //! Notify fuer andere Objekte + pFormats->SetSaveLater(sal_True); + } +} + +uno::Any SAL_CALL ScAutoFormatObj::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Any aAny; + + ScAutoFormat* pFormats = ScGlobal::GetAutoFormat(); + if (pFormats && IsInserted() && nFormatIndex < pFormats->GetCount()) + { + ScAutoFormatData* pData = (*pFormats)[nFormatIndex]; + DBG_ASSERT(pData,"AutoFormat Daten nicht da"); + + sal_Bool bValue; + sal_Bool bError = sal_False; + + String aPropString(aPropertyName); + if (aPropString.EqualsAscii( SC_UNONAME_INCBACK )) + bValue = pData->GetIncludeBackground(); + else if (aPropString.EqualsAscii( SC_UNONAME_INCBORD )) + bValue = pData->GetIncludeFrame(); + else if (aPropString.EqualsAscii( SC_UNONAME_INCFONT )) + bValue = pData->GetIncludeFont(); + else if (aPropString.EqualsAscii( SC_UNONAME_INCJUST )) + bValue = pData->GetIncludeJustify(); + else if (aPropString.EqualsAscii( SC_UNONAME_INCNUM )) + bValue = pData->GetIncludeValueFormat(); + else if (aPropString.EqualsAscii( SC_UNONAME_INCWIDTH )) + bValue = pData->GetIncludeWidthHeight(); + else + bError = sal_True; // unbekannte Property + + if (!bError) + aAny <<= bValue; + } + + return aAny; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScAutoFormatObj ) + +//------------------------------------------------------------------------ + +ScAutoFormatFieldObj::ScAutoFormatFieldObj(sal_uInt16 nFormat, sal_uInt16 nField) : + aPropSet( lcl_GetAutoFieldMap() ), + nFormatIndex( nFormat ), + nFieldIndex( nField ) +{ + //! Listening !!! +} + +ScAutoFormatFieldObj::~ScAutoFormatFieldObj() +{ +} + +void ScAutoFormatFieldObj::Notify( SfxBroadcaster& /* rBC */, const SfxHint& /* rHint */ ) +{ + // spaeter... +} + +// beans::XPropertySet + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScAutoFormatFieldObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference< beans::XPropertySetInfo > aRef(new SfxItemPropertySetInfo( aPropSet.getPropertyMap() )); + return aRef; +} + +void SAL_CALL ScAutoFormatFieldObj::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScAutoFormat* pFormats = ScGlobal::GetAutoFormat(); + const SfxItemPropertySimpleEntry* pEntry = + aPropSet.getPropertyMap()->getByName( aPropertyName ); + + if ( pEntry && pEntry->nWID && pFormats && nFormatIndex < pFormats->GetCount() ) + { + ScAutoFormatData* pData = (*pFormats)[nFormatIndex]; + + if ( IsScItemWid( pEntry->nWID ) ) + { + if( const SfxPoolItem* pItem = pData->GetItem( nFieldIndex, pEntry->nWID ) ) + { + sal_Bool bDone = sal_False; + + switch( pEntry->nWID ) + { + case ATTR_STACKED: + { + table::CellOrientation eOrient; + if( aValue >>= eOrient ) + { + switch( eOrient ) + { + case table::CellOrientation_STANDARD: + pData->PutItem( nFieldIndex, SfxBoolItem( ATTR_STACKED, FALSE ) ); + break; + case table::CellOrientation_TOPBOTTOM: + pData->PutItem( nFieldIndex, SfxBoolItem( ATTR_STACKED, FALSE ) ); + pData->PutItem( nFieldIndex, SfxInt32Item( ATTR_ROTATE_VALUE, 27000 ) ); + break; + case table::CellOrientation_BOTTOMTOP: + pData->PutItem( nFieldIndex, SfxBoolItem( ATTR_STACKED, FALSE ) ); + pData->PutItem( nFieldIndex, SfxInt32Item( ATTR_ROTATE_VALUE, 9000 ) ); + break; + case table::CellOrientation_STACKED: + pData->PutItem( nFieldIndex, SfxBoolItem( ATTR_STACKED, TRUE ) ); + break; + default: + { + // added to avoid warnings + } + } + bDone = sal_True; + } + } + break; + default: + SfxPoolItem* pNewItem = pItem->Clone(); + bDone = pNewItem->PutValue( aValue, pEntry->nMemberId ); + if (bDone) + pData->PutItem( nFieldIndex, *pNewItem ); + delete pNewItem; + } + + if (bDone) + //! Notify fuer andere Objekte? + pFormats->SetSaveLater(sal_True); + } + } + else + { + switch (pEntry->nWID) + { + case SC_WID_UNO_TBLBORD: + { + table::TableBorder aBorder; + if ( aValue >>= aBorder ) // empty = nothing to do + { + SvxBoxItem aOuter(ATTR_BORDER); + SvxBoxInfoItem aInner(ATTR_BORDER_INNER); + ScHelperFunctions::FillBoxItems( aOuter, aInner, aBorder ); + pData->PutItem( nFieldIndex, aOuter ); + + //! Notify fuer andere Objekte? + pFormats->SetSaveLater(sal_True); + } + } + break; + } + } + } +} + +uno::Any SAL_CALL ScAutoFormatFieldObj::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Any aVal; + + ScAutoFormat* pFormats = ScGlobal::GetAutoFormat(); + const SfxItemPropertySimpleEntry* pEntry = + aPropSet.getPropertyMap()->getByName( aPropertyName ); + + if ( pEntry && pEntry->nWID && pFormats && nFormatIndex < pFormats->GetCount() ) + { + const ScAutoFormatData* pData = (*pFormats)[nFormatIndex]; + + if ( IsScItemWid( pEntry->nWID ) ) + { + if( const SfxPoolItem* pItem = pData->GetItem( nFieldIndex, pEntry->nWID ) ) + { + switch( pEntry->nWID ) + { + case ATTR_STACKED: + { + const SfxInt32Item* pRotItem = (const SfxInt32Item*)pData->GetItem( nFieldIndex, ATTR_ROTATE_VALUE ); + sal_Int32 nRot = pRotItem ? pRotItem->GetValue() : 0; + BOOL bStacked = ((const SfxBoolItem*)pItem)->GetValue(); + SvxOrientationItem( nRot, bStacked, 0 ).QueryValue( aVal ); + } + break; + default: + pItem->QueryValue( aVal, pEntry->nMemberId ); + } + } + } + else + { + switch (pEntry->nWID) + { + case SC_WID_UNO_TBLBORD: + { + const SfxPoolItem* pItem = pData->GetItem(nFieldIndex, ATTR_BORDER); + if (pItem) + { + SvxBoxItem aOuter(*(static_cast<const SvxBoxItem*>(pItem))); + SvxBoxInfoItem aInner(ATTR_BORDER_INNER); + + table::TableBorder aBorder; + ScHelperFunctions::FillTableBorder( aBorder, aOuter, aInner ); + aVal <<= aBorder; + } + } + break; + } + } + } + + return aVal; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScAutoFormatFieldObj ) + +//------------------------------------------------------------------------ + + + diff --git a/sc/source/ui/unoobj/appluno.cxx b/sc/source/ui/unoobj/appluno.cxx new file mode 100644 index 000000000000..437c220ba1c3 --- /dev/null +++ b/sc/source/ui/unoobj/appluno.cxx @@ -0,0 +1,966 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +#include "appluno.hxx" +#include "sal/types.h" +#include <osl/diagnose.h> +#include <cppuhelper/factory.hxx> + +#include <sfx2/app.hxx> +#include <sfx2/sfxmodelfactory.hxx> +#include "afmtuno.hxx" +#include "funcuno.hxx" +#include "filtuno.hxx" +#include "miscuno.hxx" +#include "scmod.hxx" +#include "appoptio.hxx" +#include "inputopt.hxx" +#include "printopt.hxx" +#include "userlist.hxx" +#include "sc.hrc" // VAR_ARGS +#include "unoguard.hxx" +#include "unonames.hxx" +#include "funcdesc.hxx" +#include <com/sun/star/sheet/FunctionArgument.hpp> + +using namespace com::sun::star; + +//------------------------------------------------------------------------ + +// Calc document +extern uno::Sequence< rtl::OUString > SAL_CALL ScDocument_getSupportedServiceNames() throw(); +extern rtl::OUString SAL_CALL ScDocument_getImplementationName() throw(); +extern uno::Reference< uno::XInterface > SAL_CALL ScDocument_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr, const sal_uInt64 _nCreationFlags ) throw( uno::Exception ); + +// Calc XML import +extern uno::Sequence< rtl::OUString > SAL_CALL ScXMLImport_getSupportedServiceNames() throw(); +extern rtl::OUString SAL_CALL ScXMLImport_getImplementationName() throw(); +extern uno::Reference< uno::XInterface > SAL_CALL ScXMLImport_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr ) throw( uno::Exception ); +extern uno::Sequence< rtl::OUString > SAL_CALL ScXMLImport_Meta_getSupportedServiceNames() throw(); +extern rtl::OUString SAL_CALL ScXMLImport_Meta_getImplementationName() throw(); +extern uno::Reference< uno::XInterface > SAL_CALL ScXMLImport_Meta_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr ) throw( uno::Exception ); +extern uno::Sequence< rtl::OUString > SAL_CALL ScXMLImport_Styles_getSupportedServiceNames() throw(); +extern rtl::OUString SAL_CALL ScXMLImport_Styles_getImplementationName() throw(); +extern uno::Reference< uno::XInterface > SAL_CALL ScXMLImport_Styles_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr ) throw( uno::Exception ); +extern uno::Sequence< rtl::OUString > SAL_CALL ScXMLImport_Content_getSupportedServiceNames() throw(); +extern rtl::OUString SAL_CALL ScXMLImport_Content_getImplementationName() throw(); +extern uno::Reference< uno::XInterface > SAL_CALL ScXMLImport_Content_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr ) throw( uno::Exception ); +extern uno::Sequence< rtl::OUString > SAL_CALL ScXMLImport_Settings_getSupportedServiceNames() throw(); +extern rtl::OUString SAL_CALL ScXMLImport_Settings_getImplementationName() throw(); +extern uno::Reference< uno::XInterface > SAL_CALL ScXMLImport_Settings_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr ) throw( uno::Exception ); + +// Calc XML export +extern uno::Sequence< rtl::OUString > SAL_CALL ScXMLOOoExport_getSupportedServiceNames() throw(); +extern rtl::OUString SAL_CALL ScXMLOOoExport_getImplementationName() throw(); +extern uno::Reference< uno::XInterface > SAL_CALL ScXMLOOoExport_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr ) throw( uno::Exception ); +extern uno::Sequence< rtl::OUString > SAL_CALL ScXMLOOoExport_Meta_getSupportedServiceNames() throw(); +extern rtl::OUString SAL_CALL ScXMLOOoExport_Meta_getImplementationName() throw(); +extern uno::Reference< uno::XInterface > SAL_CALL ScXMLOOoExport_Meta_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr ) throw( uno::Exception ); +extern uno::Sequence< rtl::OUString > SAL_CALL ScXMLOOoExport_Styles_getSupportedServiceNames() throw(); +extern rtl::OUString SAL_CALL ScXMLOOoExport_Styles_getImplementationName() throw(); +extern uno::Reference< uno::XInterface > SAL_CALL ScXMLOOoExport_Styles_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr ) throw( uno::Exception ); +extern uno::Sequence< rtl::OUString > SAL_CALL ScXMLOOoExport_Content_getSupportedServiceNames() throw(); +extern rtl::OUString SAL_CALL ScXMLOOoExport_Content_getImplementationName() throw(); +extern uno::Reference< uno::XInterface > SAL_CALL ScXMLOOoExport_Content_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr ) throw( uno::Exception ); +extern uno::Sequence< rtl::OUString > SAL_CALL ScXMLOOoExport_Settings_getSupportedServiceNames() throw(); +extern rtl::OUString SAL_CALL ScXMLOOoExport_Settings_getImplementationName() throw(); +extern uno::Reference< uno::XInterface > SAL_CALL ScXMLOOoExport_Settings_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr ) throw( uno::Exception ); + +// Calc XML Oasis export +extern uno::Sequence< rtl::OUString > SAL_CALL ScXMLOasisExport_getSupportedServiceNames() throw(); +extern rtl::OUString SAL_CALL ScXMLOasisExport_getImplementationName() throw(); +extern uno::Reference< uno::XInterface > SAL_CALL ScXMLOasisExport_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr ) throw( uno::Exception ); +extern uno::Sequence< rtl::OUString > SAL_CALL ScXMLOasisExport_Meta_getSupportedServiceNames() throw(); +extern rtl::OUString SAL_CALL ScXMLOasisExport_Meta_getImplementationName() throw(); +extern uno::Reference< uno::XInterface > SAL_CALL ScXMLOasisExport_Meta_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr ) throw( uno::Exception ); +extern uno::Sequence< rtl::OUString > SAL_CALL ScXMLOasisExport_Styles_getSupportedServiceNames() throw(); +extern rtl::OUString SAL_CALL ScXMLOasisExport_Styles_getImplementationName() throw(); +extern uno::Reference< uno::XInterface > SAL_CALL ScXMLOasisExport_Styles_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr ) throw( uno::Exception ); +extern uno::Sequence< rtl::OUString > SAL_CALL ScXMLOasisExport_Content_getSupportedServiceNames() throw(); +extern rtl::OUString SAL_CALL ScXMLOasisExport_Content_getImplementationName() throw(); +extern uno::Reference< uno::XInterface > SAL_CALL ScXMLOasisExport_Content_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr ) throw( uno::Exception ); +extern uno::Sequence< rtl::OUString > SAL_CALL ScXMLOasisExport_Settings_getSupportedServiceNames() throw(); +extern rtl::OUString SAL_CALL ScXMLOasisExport_Settings_getImplementationName() throw(); +extern uno::Reference< uno::XInterface > SAL_CALL ScXMLOasisExport_Settings_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & rSMgr ) throw( uno::Exception ); + +//------------------------------------------------------------------------ + +// Anzahl der Funktionen, die als zuletzt benutzt gespeichert werden +//! Define mit funcpage.hxx und dwfunctr.hxx zusammenfassen !!! +#define LRU_MAX 10 + +// Spezial-Werte fuer Zoom +//! irgendwo zentral +#define SC_ZOOMVAL_OPTIMAL (-1) +#define SC_ZOOMVAL_WHOLEPAGE (-2) +#define SC_ZOOMVAL_PAGEWIDTH (-3) + +// Anzahl der PropertyValues in einer Function-Description +#define SC_FUNCDESC_PROPCOUNT 5 + +//------------------------------------------------------------------------ + +// alles ohne Which-ID, Map nur fuer PropertySetInfo + +static const SfxItemPropertyMapEntry* lcl_GetSettingsPropertyMap() +{ + static SfxItemPropertyMapEntry aSettingsPropertyMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_DOAUTOCP), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_ENTERED), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_EXPREF), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_EXTFMT), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_LINKUPD), 0, &getCppuType((sal_Int16*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_MARKHDR), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_METRIC), 0, &getCppuType((sal_Int16*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_MOVEDIR), 0, &getCppuType((sal_Int16*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_MOVESEL), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_PRALLSH), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_PREMPTY), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_RANGEFIN), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_SCALE), 0, &getCppuType((sal_Int16*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_STBFUNC), 0, &getCppuType((sal_Int16*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_ULISTS), 0, &getCppuType((uno::Sequence<rtl::OUString>*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_PRMETRICS),0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_USETABCOL),0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_REPLWARN), 0, &getBooleanCppuType(), 0, 0}, + {0,0,0,0,0,0} + }; + return aSettingsPropertyMap_Impl; +} + +//------------------------------------------------------------------------ + +#define SCFUNCTIONLISTOBJ_SERVICE "com.sun.star.sheet.FunctionDescriptions" +#define SCRECENTFUNCTIONSOBJ_SERVICE "com.sun.star.sheet.RecentFunctions" +#define SCSPREADSHEETSETTINGS_SERVICE "com.sun.star.sheet.GlobalSheetSettings" + +SC_SIMPLE_SERVICE_INFO( ScFunctionListObj, "ScFunctionListObj", SCFUNCTIONLISTOBJ_SERVICE ) +SC_SIMPLE_SERVICE_INFO( ScRecentFunctionsObj, "ScRecentFunctionsObj", SCRECENTFUNCTIONSOBJ_SERVICE ) +SC_SIMPLE_SERVICE_INFO( ScSpreadsheetSettings, "ScSpreadsheetSettings", SCSPREADSHEETSETTINGS_SERVICE ) + +//------------------------------------------------------------------------ + +extern "C" { + +SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment( + const sal_Char ** ppEnvTypeName, uno_Environment ** /* ppEnv */ ) +{ + *ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME; +} + +SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory( + const sal_Char * pImplName, void * pServiceManager, void * /* pRegistryKey */ ) +{ + if (!pServiceManager) + return NULL; + + uno::Reference<lang::XSingleServiceFactory> xFactory; + rtl::OUString aImpl(rtl::OUString::createFromAscii(pImplName)); + + if ( aImpl == ScSpreadsheetSettings::getImplementationName_Static() ) + xFactory.set(cppu::createOneInstanceFactory( + reinterpret_cast<lang::XMultiServiceFactory*>(pServiceManager), + ScSpreadsheetSettings::getImplementationName_Static(), + ScSpreadsheetSettings_CreateInstance, + ScSpreadsheetSettings::getSupportedServiceNames_Static() )); + + if ( aImpl == ScRecentFunctionsObj::getImplementationName_Static() ) + xFactory.set(cppu::createOneInstanceFactory( + reinterpret_cast<lang::XMultiServiceFactory*>(pServiceManager), + ScRecentFunctionsObj::getImplementationName_Static(), + ScRecentFunctionsObj_CreateInstance, + ScRecentFunctionsObj::getSupportedServiceNames_Static() )); + + if ( aImpl == ScFunctionListObj::getImplementationName_Static() ) + xFactory.set(cppu::createOneInstanceFactory( + reinterpret_cast<lang::XMultiServiceFactory*>(pServiceManager), + ScFunctionListObj::getImplementationName_Static(), + ScFunctionListObj_CreateInstance, + ScFunctionListObj::getSupportedServiceNames_Static() )); + + if ( aImpl == ScAutoFormatsObj::getImplementationName_Static() ) + xFactory.set(cppu::createOneInstanceFactory( + reinterpret_cast<lang::XMultiServiceFactory*>(pServiceManager), + ScAutoFormatsObj::getImplementationName_Static(), + ScAutoFormatsObj_CreateInstance, + ScAutoFormatsObj::getSupportedServiceNames_Static() )); + + if ( aImpl == ScFunctionAccess::getImplementationName_Static() ) + xFactory.set(cppu::createOneInstanceFactory( + reinterpret_cast<lang::XMultiServiceFactory*>(pServiceManager), + ScFunctionAccess::getImplementationName_Static(), + ScFunctionAccess_CreateInstance, + ScFunctionAccess::getSupportedServiceNames_Static() )); + + if ( aImpl == ScFilterOptionsObj::getImplementationName_Static() ) + xFactory.set(cppu::createSingleFactory( + reinterpret_cast<lang::XMultiServiceFactory*>(pServiceManager), + ScFilterOptionsObj::getImplementationName_Static(), + ScFilterOptionsObj_CreateInstance, + ScFilterOptionsObj::getSupportedServiceNames_Static() )); + + if ( aImpl == ScXMLImport_getImplementationName() ) + xFactory.set(cppu::createSingleFactory( + reinterpret_cast<lang::XMultiServiceFactory*>(pServiceManager), + ScXMLImport_getImplementationName(), + ScXMLImport_createInstance, + ScXMLImport_getSupportedServiceNames() )); + + if ( aImpl == ScXMLImport_Meta_getImplementationName() ) + xFactory.set(cppu::createSingleFactory( + reinterpret_cast<lang::XMultiServiceFactory*>(pServiceManager), + ScXMLImport_Meta_getImplementationName(), + ScXMLImport_Meta_createInstance, + ScXMLImport_Meta_getSupportedServiceNames() )); + + if ( aImpl == ScXMLImport_Styles_getImplementationName() ) + xFactory.set(cppu::createSingleFactory( + reinterpret_cast<lang::XMultiServiceFactory*>(pServiceManager), + ScXMLImport_Styles_getImplementationName(), + ScXMLImport_Styles_createInstance, + ScXMLImport_Styles_getSupportedServiceNames() )); + + if ( aImpl == ScXMLImport_Content_getImplementationName() ) + xFactory.set(cppu::createSingleFactory( + reinterpret_cast<lang::XMultiServiceFactory*>(pServiceManager), + ScXMLImport_Content_getImplementationName(), + ScXMLImport_Content_createInstance, + ScXMLImport_Content_getSupportedServiceNames() )); + + if ( aImpl == ScXMLImport_Settings_getImplementationName() ) + xFactory.set(cppu::createSingleFactory( + reinterpret_cast<lang::XMultiServiceFactory*>(pServiceManager), + ScXMLImport_Settings_getImplementationName(), + ScXMLImport_Settings_createInstance, + ScXMLImport_Settings_getSupportedServiceNames() )); + + if ( aImpl == ScXMLOOoExport_getImplementationName() ) + xFactory = cppu::createSingleFactory( + reinterpret_cast<lang::XMultiServiceFactory*>(pServiceManager), + ScXMLOOoExport_getImplementationName(), + ScXMLOOoExport_createInstance, + ScXMLOOoExport_getSupportedServiceNames() ); + + if ( aImpl == ScXMLOOoExport_Meta_getImplementationName() ) + xFactory = cppu::createSingleFactory( + reinterpret_cast<lang::XMultiServiceFactory*>(pServiceManager), + ScXMLOOoExport_Meta_getImplementationName(), + ScXMLOOoExport_Meta_createInstance, + ScXMLOOoExport_Meta_getSupportedServiceNames() ); + + if ( aImpl == ScXMLOOoExport_Styles_getImplementationName() ) + xFactory = cppu::createSingleFactory( + reinterpret_cast<lang::XMultiServiceFactory*>(pServiceManager), + ScXMLOOoExport_Styles_getImplementationName(), + ScXMLOOoExport_Styles_createInstance, + ScXMLOOoExport_Styles_getSupportedServiceNames() ); + + if ( aImpl == ScXMLOOoExport_Content_getImplementationName() ) + xFactory = cppu::createSingleFactory( + reinterpret_cast<lang::XMultiServiceFactory*>(pServiceManager), + ScXMLOOoExport_Content_getImplementationName(), + ScXMLOOoExport_Content_createInstance, + ScXMLOOoExport_Content_getSupportedServiceNames() ); + + if ( aImpl == ScXMLOOoExport_Settings_getImplementationName() ) + xFactory = cppu::createSingleFactory( + reinterpret_cast<lang::XMultiServiceFactory*>(pServiceManager), + ScXMLOOoExport_Settings_getImplementationName(), + ScXMLOOoExport_Settings_createInstance, + ScXMLOOoExport_Settings_getSupportedServiceNames() ); + + if ( aImpl == ScXMLOasisExport_getImplementationName() ) + xFactory = cppu::createSingleFactory( + reinterpret_cast<lang::XMultiServiceFactory*>(pServiceManager), + ScXMLOasisExport_getImplementationName(), + ScXMLOasisExport_createInstance, + ScXMLOasisExport_getSupportedServiceNames() ); + if ( aImpl == ScXMLOasisExport_Meta_getImplementationName() ) + xFactory = cppu::createSingleFactory( + reinterpret_cast<lang::XMultiServiceFactory*>(pServiceManager), + ScXMLOasisExport_Meta_getImplementationName(), + ScXMLOasisExport_Meta_createInstance, + ScXMLOasisExport_Meta_getSupportedServiceNames() ); + if ( aImpl == ScXMLOasisExport_Styles_getImplementationName() ) + xFactory = cppu::createSingleFactory( + reinterpret_cast<lang::XMultiServiceFactory*>(pServiceManager), + ScXMLOasisExport_Styles_getImplementationName(), + ScXMLOasisExport_Styles_createInstance, + ScXMLOasisExport_Styles_getSupportedServiceNames() ); + if ( aImpl == ScXMLOasisExport_Content_getImplementationName() ) + xFactory = cppu::createSingleFactory( + reinterpret_cast<lang::XMultiServiceFactory*>(pServiceManager), + ScXMLOasisExport_Content_getImplementationName(), + ScXMLOasisExport_Content_createInstance, + ScXMLOasisExport_Content_getSupportedServiceNames() ); + if ( aImpl == ScXMLOasisExport_Settings_getImplementationName() ) + xFactory = cppu::createSingleFactory( + reinterpret_cast<lang::XMultiServiceFactory*>(pServiceManager), + ScXMLOasisExport_Settings_getImplementationName(), + ScXMLOasisExport_Settings_createInstance, + ScXMLOasisExport_Settings_getSupportedServiceNames() ); + + if ( aImpl == ScDocument_getImplementationName() ) + xFactory.set(sfx2::createSfxModelFactory( + reinterpret_cast<lang::XMultiServiceFactory*>(pServiceManager), + ScDocument_getImplementationName(), + ScDocument_createInstance, + ScDocument_getSupportedServiceNames() )); + + void* pRet = NULL; + if (xFactory.is()) + { + xFactory->acquire(); + pRet = xFactory.get(); + } + return pRet; +} + +} // extern C + +//------------------------------------------------------------------------ + +ScSpreadsheetSettings::ScSpreadsheetSettings() : + aPropSet( lcl_GetSettingsPropertyMap() ) +{ +} + +ScSpreadsheetSettings::~ScSpreadsheetSettings() +{ +} + +uno::Reference<uno::XInterface> SAL_CALL ScSpreadsheetSettings_CreateInstance( + const uno::Reference<lang::XMultiServiceFactory>& /* rSMgr */ ) +{ + ScUnoGuard aGuard; + ScDLL::Init(); + static uno::Reference<uno::XInterface> xInst((cppu::OWeakObject*)new ScSpreadsheetSettings()); + return xInst; +} + +rtl::OUString ScSpreadsheetSettings::getImplementationName_Static() +{ + return rtl::OUString::createFromAscii( "stardiv.StarCalc.ScSpreadsheetSettings" ); +} + +uno::Sequence<rtl::OUString> ScSpreadsheetSettings::getSupportedServiceNames_Static() +{ + uno::Sequence<rtl::OUString> aRet(1); + rtl::OUString* pArray = aRet.getArray(); + pArray[0] = rtl::OUString::createFromAscii( SCSPREADSHEETSETTINGS_SERVICE ); + return aRet; +} + +// XPropertySet + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScSpreadsheetSettings::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef( + new SfxItemPropertySetInfo( aPropSet.getPropertyMap() )); + return aRef; +} + +void SAL_CALL ScSpreadsheetSettings::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aString(aPropertyName); + + ScModule* pScMod = SC_MOD(); + ScAppOptions aAppOpt(pScMod->GetAppOptions()); + ScInputOptions aInpOpt(pScMod->GetInputOptions()); + BOOL bSaveApp = FALSE; + BOOL bSaveInp = FALSE; + // print options aren't loaded until needed + + if (aString.EqualsAscii( SC_UNONAME_DOAUTOCP )) + { + aAppOpt.SetAutoComplete( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + bSaveApp = TRUE; + } + else if (aString.EqualsAscii( SC_UNONAME_ENTERED )) + { + aInpOpt.SetEnterEdit( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + bSaveInp = TRUE; + } + else if (aString.EqualsAscii( SC_UNONAME_EXPREF )) + { + aInpOpt.SetExpandRefs( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + bSaveInp = TRUE; + } + else if (aString.EqualsAscii( SC_UNONAME_EXTFMT )) + { + aInpOpt.SetExtendFormat( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + bSaveInp = TRUE; + } + else if (aString.EqualsAscii( SC_UNONAME_LINKUPD )) + { + aAppOpt.SetLinkMode( (ScLkUpdMode) ScUnoHelpFunctions::GetInt16FromAny( aValue ) ); + bSaveApp = TRUE; + } + else if (aString.EqualsAscii( SC_UNONAME_MARKHDR )) + { + aInpOpt.SetMarkHeader( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + bSaveInp = TRUE; + } + else if (aString.EqualsAscii( SC_UNONAME_MOVESEL )) + { + aInpOpt.SetMoveSelection( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + bSaveInp = TRUE; + } + else if (aString.EqualsAscii( SC_UNONAME_RANGEFIN )) + { + aInpOpt.SetRangeFinder( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + bSaveInp = TRUE; + } + else if (aString.EqualsAscii( SC_UNONAME_USETABCOL )) + { + aInpOpt.SetUseTabCol( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + bSaveInp = TRUE; + } + else if (aString.EqualsAscii( SC_UNONAME_PRMETRICS )) + { + aInpOpt.SetTextWysiwyg( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + bSaveInp = TRUE; + } + else if (aString.EqualsAscii( SC_UNONAME_REPLWARN )) + { + aInpOpt.SetReplaceCellsWarn( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + bSaveInp = TRUE; + } + else if (aString.EqualsAscii( SC_UNONAME_METRIC )) + { + aAppOpt.SetAppMetric( (FieldUnit) ScUnoHelpFunctions::GetInt16FromAny( aValue ) ); + bSaveApp = TRUE; + } + else if (aString.EqualsAscii( SC_UNONAME_MOVEDIR )) + { + aInpOpt.SetMoveDir( ScUnoHelpFunctions::GetInt16FromAny( aValue ) ); + bSaveInp = TRUE; + } + else if (aString.EqualsAscii( SC_UNONAME_SCALE )) + { + short nVal = ScUnoHelpFunctions::GetInt16FromAny( aValue ); + if ( nVal < 0 ) + { + SvxZoomType eType = SVX_ZOOM_PERCENT; + switch (nVal) + { + case SC_ZOOMVAL_OPTIMAL: eType = SVX_ZOOM_OPTIMAL; break; + case SC_ZOOMVAL_WHOLEPAGE: eType = SVX_ZOOM_WHOLEPAGE; break; + case SC_ZOOMVAL_PAGEWIDTH: eType = SVX_ZOOM_PAGEWIDTH; break; + } + aAppOpt.SetZoomType( eType ); + } + else if ( nVal >= MINZOOM && nVal <= MAXZOOM ) + { + aAppOpt.SetZoom( nVal ); + aAppOpt.SetZoomType( SVX_ZOOM_PERCENT ); + } + bSaveApp = TRUE; + } + else if (aString.EqualsAscii( SC_UNONAME_STBFUNC )) + { + aAppOpt.SetStatusFunc( ScUnoHelpFunctions::GetInt16FromAny( aValue ) ); + bSaveApp = TRUE; + } + else if (aString.EqualsAscii( SC_UNONAME_ULISTS )) + { + ScUserList* pUserList = ScGlobal::GetUserList(); + uno::Sequence<rtl::OUString> aSeq; + if ( pUserList && ( aValue >>= aSeq ) ) + { + // es wird direkt die "lebende" Liste veraendert, + // mehr tut ScGlobal::SetUserList auch nicht + + pUserList->FreeAll(); // alle Eintraege raus + USHORT nCount = (USHORT)aSeq.getLength(); + const rtl::OUString* pAry = aSeq.getConstArray(); + for (USHORT i=0; i<nCount; i++) + { + String aEntry = pAry[i]; + ScUserListData* pData = new ScUserListData(aEntry); + if (!pUserList->Insert(pData)) // hinten anhaengen + delete pData; // sollte nicht vorkommen + } + bSaveApp = TRUE; // Liste wird mit den App-Optionen gespeichert + } + } + else if (aString.EqualsAscii( SC_UNONAME_PRALLSH )) + { + ScPrintOptions aPrintOpt(pScMod->GetPrintOptions()); + aPrintOpt.SetAllSheets( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + pScMod->SetPrintOptions( aPrintOpt ); + } + else if (aString.EqualsAscii( SC_UNONAME_PREMPTY )) + { + ScPrintOptions aPrintOpt(pScMod->GetPrintOptions()); + aPrintOpt.SetSkipEmpty( !ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); // reversed + pScMod->SetPrintOptions( aPrintOpt ); + SFX_APP()->Broadcast( SfxSimpleHint( SID_SCPRINTOPTIONS ) ); // update previews + } + + if ( bSaveApp ) + pScMod->SetAppOptions( aAppOpt ); + if ( bSaveInp ) + pScMod->SetInputOptions( aInpOpt ); +} + +uno::Any SAL_CALL ScSpreadsheetSettings::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aString = aPropertyName; + uno::Any aRet; + + ScModule* pScMod = SC_MOD(); + ScAppOptions aAppOpt = pScMod->GetAppOptions(); + ScInputOptions aInpOpt = pScMod->GetInputOptions(); + // print options aren't loaded until needed + + if (aString.EqualsAscii( SC_UNONAME_DOAUTOCP )) ScUnoHelpFunctions::SetBoolInAny( aRet, aAppOpt.GetAutoComplete() ); + else if (aString.EqualsAscii( SC_UNONAME_ENTERED )) ScUnoHelpFunctions::SetBoolInAny( aRet, aInpOpt.GetEnterEdit() ); + else if (aString.EqualsAscii( SC_UNONAME_EXPREF )) ScUnoHelpFunctions::SetBoolInAny( aRet, aInpOpt.GetExpandRefs() ); + else if (aString.EqualsAscii( SC_UNONAME_EXTFMT )) ScUnoHelpFunctions::SetBoolInAny( aRet, aInpOpt.GetExtendFormat() ); + else if (aString.EqualsAscii( SC_UNONAME_LINKUPD )) aRet <<= (sal_Int16) aAppOpt.GetLinkMode(); + else if (aString.EqualsAscii( SC_UNONAME_MARKHDR )) ScUnoHelpFunctions::SetBoolInAny( aRet, aInpOpt.GetMarkHeader() ); + else if (aString.EqualsAscii( SC_UNONAME_MOVESEL )) ScUnoHelpFunctions::SetBoolInAny( aRet, aInpOpt.GetMoveSelection() ); + else if (aString.EqualsAscii( SC_UNONAME_RANGEFIN )) ScUnoHelpFunctions::SetBoolInAny( aRet, aInpOpt.GetRangeFinder() ); + else if (aString.EqualsAscii( SC_UNONAME_USETABCOL )) ScUnoHelpFunctions::SetBoolInAny( aRet, aInpOpt.GetUseTabCol() ); + else if (aString.EqualsAscii( SC_UNONAME_PRMETRICS )) ScUnoHelpFunctions::SetBoolInAny( aRet, aInpOpt.GetTextWysiwyg() ); + else if (aString.EqualsAscii( SC_UNONAME_REPLWARN )) ScUnoHelpFunctions::SetBoolInAny( aRet, aInpOpt.GetReplaceCellsWarn() ); + else if (aString.EqualsAscii( SC_UNONAME_METRIC )) aRet <<= (sal_Int16) aAppOpt.GetAppMetric(); + else if (aString.EqualsAscii( SC_UNONAME_MOVEDIR )) aRet <<= (sal_Int16) aInpOpt.GetMoveDir(); + else if (aString.EqualsAscii( SC_UNONAME_STBFUNC )) aRet <<= (sal_Int16) aAppOpt.GetStatusFunc(); + else if (aString.EqualsAscii( SC_UNONAME_SCALE )) + { + INT16 nZoomVal = 0; + switch ( aAppOpt.GetZoomType() ) + { + case SVX_ZOOM_PERCENT: nZoomVal = aAppOpt.GetZoom(); break; + case SVX_ZOOM_OPTIMAL: nZoomVal = SC_ZOOMVAL_OPTIMAL; break; + case SVX_ZOOM_WHOLEPAGE: nZoomVal = SC_ZOOMVAL_WHOLEPAGE; break; + case SVX_ZOOM_PAGEWIDTH: nZoomVal = SC_ZOOMVAL_PAGEWIDTH; break; + default: + { + // added to avoid warnings + } + } + aRet <<= (sal_Int16) nZoomVal; + } + else if (aString.EqualsAscii( SC_UNONAME_ULISTS )) + { + ScUserList* pUserList = ScGlobal::GetUserList(); + if (pUserList) + { + USHORT nCount = pUserList->GetCount(); + uno::Sequence<rtl::OUString> aSeq(nCount); + rtl::OUString* pAry = aSeq.getArray(); + for (USHORT i=0; i<nCount; i++) + { + String aEntry((*pUserList)[i]->GetString()); + pAry[i] = aEntry; + } + aRet <<= aSeq; + } + } + else if (aString.EqualsAscii( SC_UNONAME_PRALLSH )) + ScUnoHelpFunctions::SetBoolInAny( aRet, pScMod->GetPrintOptions().GetAllSheets() ); + else if (aString.EqualsAscii( SC_UNONAME_PREMPTY )) + ScUnoHelpFunctions::SetBoolInAny( aRet, !pScMod->GetPrintOptions().GetSkipEmpty() ); // reversed + + return aRet; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScSpreadsheetSettings ) + +//------------------------------------------------------------------------ + +ScRecentFunctionsObj::ScRecentFunctionsObj() +{ +} + +ScRecentFunctionsObj::~ScRecentFunctionsObj() +{ +} + +// stuff for exService_... + +uno::Reference<uno::XInterface> SAL_CALL ScRecentFunctionsObj_CreateInstance( + const uno::Reference<lang::XMultiServiceFactory>& /* rSMgr */ ) +{ + ScUnoGuard aGuard; + ScDLL::Init(); + static uno::Reference<uno::XInterface> xInst((cppu::OWeakObject*)new ScRecentFunctionsObj()); + return xInst; +} + +rtl::OUString ScRecentFunctionsObj::getImplementationName_Static() +{ + return rtl::OUString::createFromAscii( "stardiv.StarCalc.ScRecentFunctionsObj" ); +} + +uno::Sequence<rtl::OUString> ScRecentFunctionsObj::getSupportedServiceNames_Static() +{ + uno::Sequence<rtl::OUString> aRet(1); + rtl::OUString* pArray = aRet.getArray(); + pArray[0] = rtl::OUString::createFromAscii( SCRECENTFUNCTIONSOBJ_SERVICE ); + return aRet; +} + +// XRecentFunctions + +uno::Sequence<sal_Int32> SAL_CALL ScRecentFunctionsObj::getRecentFunctionIds() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + const ScAppOptions& rOpt = SC_MOD()->GetAppOptions(); + USHORT nCount = rOpt.GetLRUFuncListCount(); + const USHORT* pFuncs = rOpt.GetLRUFuncList(); + if (pFuncs) + { + uno::Sequence<sal_Int32> aSeq(nCount); + sal_Int32* pAry = aSeq.getArray(); + for (USHORT i=0; i<nCount; i++) + pAry[i] = pFuncs[i]; + return aSeq; + } + return uno::Sequence<sal_Int32>(0); +} + +void SAL_CALL ScRecentFunctionsObj::setRecentFunctionIds( + const uno::Sequence<sal_Int32>& aRecentFunctionIds ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + USHORT nCount = (USHORT) Min( aRecentFunctionIds.getLength(), (INT32) LRU_MAX ); + const INT32* pAry = aRecentFunctionIds.getConstArray(); + + USHORT* pFuncs = nCount ? new USHORT[nCount] : NULL; + for (USHORT i=0; i<nCount; i++) + pFuncs[i] = (USHORT)pAry[i]; //! auf gueltige Werte testen? + + ScModule* pScMod = SC_MOD(); + ScAppOptions aNewOpts(pScMod->GetAppOptions()); + aNewOpts.SetLRUFuncList(pFuncs, nCount); + pScMod->SetAppOptions(aNewOpts); + + pScMod->RecentFunctionsChanged(); // update function list child window + + delete[] pFuncs; +} + +sal_Int32 SAL_CALL ScRecentFunctionsObj::getMaxRecentFunctions() throw(uno::RuntimeException) +{ + return LRU_MAX; +} + +//------------------------------------------------------------------------ + +ScFunctionListObj::ScFunctionListObj() +{ +} + +ScFunctionListObj::~ScFunctionListObj() +{ +} + +// stuff for exService_... + +uno::Reference<uno::XInterface> SAL_CALL ScFunctionListObj_CreateInstance( + const uno::Reference<lang::XMultiServiceFactory>& /* rSMgr */ ) +{ + ScUnoGuard aGuard; + ScDLL::Init(); + static uno::Reference<uno::XInterface> xInst((cppu::OWeakObject*)new ScFunctionListObj()); + return xInst; +} + +rtl::OUString ScFunctionListObj::getImplementationName_Static() +{ + return rtl::OUString::createFromAscii( "stardiv.StarCalc.ScFunctionListObj" ); +} + +uno::Sequence<rtl::OUString> ScFunctionListObj::getSupportedServiceNames_Static() +{ + uno::Sequence<rtl::OUString> aRet(1); + rtl::OUString* pArray = aRet.getArray(); + pArray[0] = rtl::OUString::createFromAscii( SCFUNCTIONLISTOBJ_SERVICE ); + return aRet; +} + + +static void lcl_FillSequence( uno::Sequence<beans::PropertyValue>& rSequence, const ScFuncDesc& rDesc ) +{ + rDesc.initArgumentInfo(); // full argument info is needed + + DBG_ASSERT( rSequence.getLength() == SC_FUNCDESC_PROPCOUNT, "Falscher Count" ); + + beans::PropertyValue* pArray = rSequence.getArray(); + + pArray[0].Name = rtl::OUString::createFromAscii( SC_UNONAME_ID ); + pArray[0].Value <<= (sal_Int32) rDesc.nFIndex; + + pArray[1].Name = rtl::OUString::createFromAscii( SC_UNONAME_CATEGORY ); + pArray[1].Value <<= (sal_Int32) rDesc.nCategory; + + pArray[2].Name = rtl::OUString::createFromAscii( SC_UNONAME_NAME ); + if (rDesc.pFuncName) + pArray[2].Value <<= rtl::OUString( *rDesc.pFuncName ); + + pArray[3].Name = rtl::OUString::createFromAscii( SC_UNONAME_DESCRIPTION ); + if (rDesc.pFuncDesc) + pArray[3].Value <<= rtl::OUString( *rDesc.pFuncDesc ); + + pArray[4].Name = rtl::OUString::createFromAscii( SC_UNONAME_ARGUMENTS ); + if (rDesc.ppDefArgNames && rDesc.ppDefArgDescs && rDesc.pDefArgFlags ) + { + USHORT nCount = rDesc.nArgCount; + if (nCount >= VAR_ARGS) + nCount -= VAR_ARGS - 1; + USHORT nSeqCount = rDesc.GetSuppressedArgCount(); + if (nSeqCount >= VAR_ARGS) + nSeqCount -= VAR_ARGS - 1; + + if (nSeqCount) + { + uno::Sequence<sheet::FunctionArgument> aArgSeq(nSeqCount); + sheet::FunctionArgument* pArgAry = aArgSeq.getArray(); + for (USHORT i=0, j=0; i<nCount; i++) + { + if (!rDesc.pDefArgFlags[i].bSuppress) + { + String aArgName; + if (rDesc.ppDefArgNames[i]) aArgName = *rDesc.ppDefArgNames[i]; + String aArgDesc; + if (rDesc.ppDefArgDescs[i]) aArgDesc = *rDesc.ppDefArgDescs[i]; + sheet::FunctionArgument aArgument; + aArgument.Name = aArgName; + aArgument.Description = aArgDesc; + aArgument.IsOptional = rDesc.pDefArgFlags[i].bOptional; + pArgAry[j++] = aArgument; + } + } + pArray[4].Value <<= aArgSeq; + } + } +} + +// XFunctionDescriptions + +uno::Sequence<beans::PropertyValue> SAL_CALL ScFunctionListObj::getById( sal_Int32 nId ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList(); + if ( pFuncList ) + { + USHORT nCount = (USHORT)pFuncList->GetCount(); + for (USHORT nIndex=0; nIndex<nCount; nIndex++) + { + const ScFuncDesc* pDesc = pFuncList->GetFunction(nIndex); + if ( pDesc && pDesc->nFIndex == nId ) + { + uno::Sequence<beans::PropertyValue> aSeq( SC_FUNCDESC_PROPCOUNT ); + lcl_FillSequence( aSeq, *pDesc ); + return aSeq; + } + } + + throw lang::IllegalArgumentException(); // not found + } + else + throw uno::RuntimeException(); // should not happen + +// return uno::Sequence<beans::PropertyValue>(0); +} + +// XNameAccess + +uno::Any SAL_CALL ScFunctionListObj::getByName( const rtl::OUString& aName ) + throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aNameStr(aName); + const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList(); + if ( pFuncList ) + { + USHORT nCount = (USHORT)pFuncList->GetCount(); + for (USHORT nIndex=0; nIndex<nCount; nIndex++) + { + const ScFuncDesc* pDesc = pFuncList->GetFunction(nIndex); + //! Case-insensitiv ??? + if ( pDesc && pDesc->pFuncName && aNameStr == *pDesc->pFuncName ) + { + uno::Sequence<beans::PropertyValue> aSeq( SC_FUNCDESC_PROPCOUNT ); + lcl_FillSequence( aSeq, *pDesc ); + return uno::makeAny(aSeq); + } + } + + throw container::NoSuchElementException(); // not found + } + else + throw uno::RuntimeException(); // should not happen + +// return uno::Any(); +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScFunctionListObj::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + USHORT nCount = 0; + const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList(); + if ( pFuncList ) + nCount = (USHORT)pFuncList->GetCount(); + return nCount; +} + +uno::Any SAL_CALL ScFunctionListObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList(); + if ( pFuncList ) + { + if ( nIndex >= 0 && nIndex < (sal_Int32)pFuncList->GetCount() ) + { + const ScFuncDesc* pDesc = pFuncList->GetFunction(nIndex); + if ( pDesc ) + { + uno::Sequence<beans::PropertyValue> aSeq( SC_FUNCDESC_PROPCOUNT ); + lcl_FillSequence( aSeq, *pDesc ); + return uno::makeAny(aSeq); + } + } + + throw lang::IndexOutOfBoundsException(); // illegal index + } + else + throw uno::RuntimeException(); // should not happen + +// return uno::Any(); +} + +// XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScFunctionListObj::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.FunctionDescriptionEnumeration"))); +} + +// XElementAccess + +uno::Type SAL_CALL ScFunctionListObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((uno::Sequence<beans::PropertyValue>*)0); +} + +sal_Bool SAL_CALL ScFunctionListObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() > 0 ); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScFunctionListObj::getElementNames() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList(); + if ( pFuncList ) + { + USHORT nCount = (USHORT)pFuncList->GetCount(); + uno::Sequence<rtl::OUString> aSeq(nCount); + rtl::OUString* pAry = aSeq.getArray(); + for (USHORT nIndex=0; nIndex<nCount; nIndex++) + { + const ScFuncDesc* pDesc = pFuncList->GetFunction(nIndex); + if ( pDesc && pDesc->pFuncName ) + pAry[nIndex] = *pDesc->pFuncName; + } + return aSeq; + } + return uno::Sequence<rtl::OUString>(0); +} + +sal_Bool SAL_CALL ScFunctionListObj::hasByName( const rtl::OUString& aName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aNameStr(aName); + const ScFunctionList* pFuncList = ScGlobal::GetStarCalcFunctionList(); + if ( pFuncList ) + { + USHORT nCount = (USHORT)pFuncList->GetCount(); + for (USHORT nIndex=0; nIndex<nCount; nIndex++) + { + const ScFuncDesc* pDesc = pFuncList->GetFunction(nIndex); + //! Case-insensitiv ??? + if ( pDesc && pDesc->pFuncName && aNameStr == *pDesc->pFuncName ) + return TRUE; + } + } + return FALSE; +} + +//------------------------------------------------------------------------ + + + + diff --git a/sc/source/ui/unoobj/celllistsource.cxx b/sc/source/ui/unoobj/celllistsource.cxx new file mode 100644 index 000000000000..246555d06f25 --- /dev/null +++ b/sc/source/ui/unoobj/celllistsource.cxx @@ -0,0 +1,449 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" +#include "celllistsource.hxx" +#include <tools/debug.hxx> +#include <com/sun/star/text/XTextRange.hpp> +#include <com/sun/star/sheet/XCellRangeAddressable.hpp> +#include <com/sun/star/util/XModifyBroadcaster.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/NamedValue.hpp> + +//......................................................................... +namespace calc +{ +//......................................................................... + +#define PROP_HANDLE_RANGE_ADDRESS 1 + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::table; + using namespace ::com::sun::star::text; + using namespace ::com::sun::star::sheet; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::form::binding; + + //===================================================================== + //= OCellListSource + //===================================================================== + DBG_NAME( OCellListSource ) + //--------------------------------------------------------------------- +#ifdef DBG_UTIL + const char* OCellListSource::checkConsistency_static( const void* _pThis ) + { + return static_cast< const OCellListSource* >( _pThis )->checkConsistency( ); + } + + const char* OCellListSource::checkConsistency( ) const + { + const char* pAssertion = NULL; + + // TODO: place any checks here to ensure consistency of this instance + + return pAssertion; + } +#endif + + //--------------------------------------------------------------------- + OCellListSource::OCellListSource( const Reference< XSpreadsheetDocument >& _rxDocument ) + :OCellListSource_Base( m_aMutex ) + ,OCellListSource_PBase( OCellListSource_Base::rBHelper ) + ,m_xDocument( _rxDocument ) + ,m_aListEntryListeners( m_aMutex ) + ,m_bInitialized( sal_False ) + { + DBG_CTOR( OCellListSource, checkConsistency_static ); + + OSL_PRECOND( m_xDocument.is(), "OCellListSource::OCellListSource: invalid document!" ); + + // register our property at the base class + CellRangeAddress aInitialPropValue; + registerPropertyNoMember( + ::rtl::OUString::createFromAscii( "CellRange" ), + PROP_HANDLE_RANGE_ADDRESS, + PropertyAttribute::BOUND | PropertyAttribute::READONLY, + ::getCppuType( &aInitialPropValue ), + &aInitialPropValue + ); + } + + //--------------------------------------------------------------------- + OCellListSource::~OCellListSource( ) + { + if ( !OCellListSource_Base::rBHelper.bDisposed ) + { + acquire(); // prevent duplicate dtor + dispose(); + } + + DBG_DTOR( OCellListSource, checkConsistency_static ); + } + + //-------------------------------------------------------------------- + IMPLEMENT_FORWARD_XINTERFACE2( OCellListSource, OCellListSource_Base, OCellListSource_PBase ) + + //-------------------------------------------------------------------- + IMPLEMENT_FORWARD_XTYPEPROVIDER2( OCellListSource, OCellListSource_Base, OCellListSource_PBase ) + + //-------------------------------------------------------------------- + void SAL_CALL OCellListSource::disposing() + { + ::osl::MutexGuard aGuard( m_aMutex ); + DBG_CHKTHIS( OCellListSource, checkConsistency_static ); + + Reference<XModifyBroadcaster> xBroadcaster( m_xRange, UNO_QUERY ); + if ( xBroadcaster.is() ) + { + xBroadcaster->removeModifyListener( this ); + } + + EventObject aDisposeEvent( *this ); + m_aListEntryListeners.disposeAndClear( aDisposeEvent ); + +// OCellListSource_Base::disposing(); + WeakAggComponentImplHelperBase::disposing(); + + // TODO: clean up here whatever you need to clean up (e.g. revoking listeners etc.) + } + + //-------------------------------------------------------------------- + Reference< XPropertySetInfo > SAL_CALL OCellListSource::getPropertySetInfo( ) throw(RuntimeException) + { + DBG_CHKTHIS( OCellListSource, checkConsistency_static ); + return createPropertySetInfo( getInfoHelper() ) ; + } + + //-------------------------------------------------------------------- + ::cppu::IPropertyArrayHelper& SAL_CALL OCellListSource::getInfoHelper() + { + return *OCellListSource_PABase::getArrayHelper(); + } + + //-------------------------------------------------------------------- + ::cppu::IPropertyArrayHelper* OCellListSource::createArrayHelper( ) const + { + Sequence< Property > aProps; + describeProperties( aProps ); + return new ::cppu::OPropertyArrayHelper(aProps); + } + + //-------------------------------------------------------------------- + void SAL_CALL OCellListSource::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const + { + DBG_CHKTHIS( OCellListSource, checkConsistency_static ); + DBG_ASSERT( _nHandle == PROP_HANDLE_RANGE_ADDRESS, "OCellListSource::getFastPropertyValue: invalid handle!" ); + // we only have this one property .... + (void)_nHandle; // avoid warning in product version + + _rValue <<= getRangeAddress( ); + } + + //-------------------------------------------------------------------- + void OCellListSource::checkDisposed( ) const SAL_THROW( ( DisposedException ) ) + { + if ( OCellListSource_Base::rBHelper.bInDispose || OCellListSource_Base::rBHelper.bDisposed ) + throw DisposedException(); + // TODO: is it worth having an error message here? + } + + //-------------------------------------------------------------------- + void OCellListSource::checkInitialized() SAL_THROW( ( RuntimeException ) ) + { + if ( !m_bInitialized ) + throw RuntimeException(); + // TODO: error message + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OCellListSource::getImplementationName( ) throw (RuntimeException) + { + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.sheet.OCellListSource" ) ); + } + + //-------------------------------------------------------------------- + sal_Bool SAL_CALL OCellListSource::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) + { + Sequence< ::rtl::OUString > aSupportedServices( getSupportedServiceNames() ); + const ::rtl::OUString* pLookup = aSupportedServices.getConstArray(); + const ::rtl::OUString* pLookupEnd = aSupportedServices.getConstArray() + aSupportedServices.getLength(); + while ( pLookup != pLookupEnd ) + if ( *pLookup++ == _rServiceName ) + return sal_True; + + return sal_False; + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL OCellListSource::getSupportedServiceNames( ) throw (RuntimeException) + { + Sequence< ::rtl::OUString > aServices( 2 ); + aServices[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.table.CellRangeListSource" ) ); + aServices[ 1 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.binding.ListEntrySource" ) ); + return aServices; + } + + //-------------------------------------------------------------------- + CellRangeAddress OCellListSource::getRangeAddress( ) const + { + OSL_PRECOND( m_xRange.is(), "OCellListSource::getRangeAddress: invalid range!" ); + + CellRangeAddress aAddress; + Reference< XCellRangeAddressable > xRangeAddress( m_xRange, UNO_QUERY ); + if ( xRangeAddress.is() ) + aAddress = xRangeAddress->getRangeAddress( ); + return aAddress; + } + + //-------------------------------------------------------------------- + ::rtl::OUString OCellListSource::getCellTextContent_noCheck( sal_Int32 _nRangeRelativeColumn, sal_Int32 _nRangeRelativeRow ) + { + OSL_PRECOND( m_xRange.is(), "OCellListSource::getRangeAddress: invalid range!" ); + Reference< XTextRange > xCellText; + if ( m_xRange.is() ) + xCellText.set(xCellText.query( m_xRange->getCellByPosition( _nRangeRelativeColumn, _nRangeRelativeRow ) )); + + ::rtl::OUString sText; + if ( xCellText.is() ) + sText = xCellText->getString(); + return sText; + } + + //-------------------------------------------------------------------- + sal_Int32 SAL_CALL OCellListSource::getListEntryCount( ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + DBG_CHKTHIS( OCellListSource, checkConsistency_static ); + checkDisposed(); + checkInitialized(); + + CellRangeAddress aAddress( getRangeAddress( ) ); + return aAddress.EndRow - aAddress.StartRow + 1; + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OCellListSource::getListEntry( sal_Int32 _nPosition ) throw (IndexOutOfBoundsException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + DBG_CHKTHIS( OCellListSource, checkConsistency_static ); + checkDisposed(); + checkInitialized(); + + if ( _nPosition >= getListEntryCount() ) + throw IndexOutOfBoundsException(); + + return getCellTextContent_noCheck( 0, _nPosition ); + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL OCellListSource::getAllListEntries( ) throw (RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + DBG_CHKTHIS( OCellListSource, checkConsistency_static ); + checkDisposed(); + checkInitialized(); + + Sequence< ::rtl::OUString > aAllEntries( getListEntryCount() ); + ::rtl::OUString* pAllEntries = aAllEntries.getArray(); + for ( sal_Int32 i = 0; i < aAllEntries.getLength(); ++i ) + { + *pAllEntries++ = getCellTextContent_noCheck( 0, i ); + } + + return aAllEntries; + } + + //-------------------------------------------------------------------- + void SAL_CALL OCellListSource::addListEntryListener( const Reference< XListEntryListener >& _rxListener ) throw (NullPointerException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + DBG_CHKTHIS( OCellListSource, checkConsistency_static ); + checkDisposed(); + checkInitialized(); + + if ( !_rxListener.is() ) + throw NullPointerException(); + + m_aListEntryListeners.addInterface( _rxListener ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OCellListSource::removeListEntryListener( const Reference< XListEntryListener >& _rxListener ) throw (NullPointerException, RuntimeException) + { + ::osl::MutexGuard aGuard( m_aMutex ); + DBG_CHKTHIS( OCellListSource, checkConsistency_static ); + checkDisposed(); + checkInitialized(); + + if ( !_rxListener.is() ) + throw NullPointerException(); + + m_aListEntryListeners.removeInterface( _rxListener ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OCellListSource::modified( const EventObject& /* aEvent */ ) throw (RuntimeException) + { + DBG_CHKTHIS( OCellListSource, checkConsistency_static ); + + notifyModified(); + } + + //-------------------------------------------------------------------- + void OCellListSource::notifyModified() + { + EventObject aEvent; + aEvent.Source.set(*this); + + ::cppu::OInterfaceIteratorHelper aIter( m_aListEntryListeners ); + while ( aIter.hasMoreElements() ) + { + try + { + static_cast< XListEntryListener* >( aIter.next() )->allEntriesChanged( aEvent ); + } + catch( const RuntimeException& ) + { + // silent this + } + catch( const Exception& ) + { + DBG_ERROR( "OCellListSource::notifyModified: caught a (non-runtime) exception!" ); + } + } + + } + + //-------------------------------------------------------------------- + void SAL_CALL OCellListSource::disposing( const EventObject& aEvent ) throw (RuntimeException) + { + DBG_CHKTHIS( OCellListSource, checkConsistency_static ); + + Reference<XInterface> xRangeInt( m_xRange, UNO_QUERY ); + if ( xRangeInt == aEvent.Source ) + { + // release references to range object + m_xRange.clear(); + } + } + + //-------------------------------------------------------------------- + void SAL_CALL OCellListSource::initialize( const Sequence< Any >& _rArguments ) throw (Exception, RuntimeException) + { + if ( m_bInitialized ) + throw Exception(); + // TODO: error message + + // get the cell address + CellRangeAddress aRangeAddress; + sal_Bool bFoundAddress = sal_False; + + const Any* pLoop = _rArguments.getConstArray(); + const Any* pLoopEnd = _rArguments.getConstArray() + _rArguments.getLength(); + for ( ; ( pLoop != pLoopEnd ) && !bFoundAddress; ++pLoop ) + { + NamedValue aValue; + if ( *pLoop >>= aValue ) + { + if ( aValue.Name.equalsAscii( "CellRange" ) ) + { + if ( aValue.Value >>= aRangeAddress ) + bFoundAddress = sal_True; + } + } + } + + if ( !bFoundAddress ) + // TODO: error message + throw Exception(); + + // determine the range we're bound to + try + { + if ( m_xDocument.is() ) + { + // first the sheets collection + Reference< XIndexAccess > xSheets(m_xDocument->getSheets( ), UNO_QUERY); + DBG_ASSERT( xSheets.is(), "OCellListSource::initialize: could not retrieve the sheets!" ); + + if ( xSheets.is() ) + { + // the concrete sheet + Reference< XCellRange > xSheet(xSheets->getByIndex( aRangeAddress.Sheet ), UNO_QUERY); + DBG_ASSERT( xSheet.is(), "OCellListSource::initialize: NULL sheet, but no exception!" ); + + // the concrete cell + if ( xSheet.is() ) + { + m_xRange.set(xSheet->getCellRangeByPosition( + aRangeAddress.StartColumn, aRangeAddress.StartRow, + aRangeAddress.EndColumn, aRangeAddress.EndRow)); + DBG_ASSERT( Reference< XCellRangeAddressable >( m_xRange, UNO_QUERY ).is(), "OCellListSource::initialize: either NULL range, or cell without address access!" ); + } + } + } + } + catch( const Exception& ) + { + DBG_ERROR( "OCellListSource::initialize: caught an exception while retrieving the cell object!" ); + } + + + if ( !m_xRange.is() ) + throw Exception(); + // TODO error message + + Reference<XModifyBroadcaster> xBroadcaster( m_xRange, UNO_QUERY ); + if ( xBroadcaster.is() ) + { + xBroadcaster->addModifyListener( this ); + } + + // TODO: add as XEventListener to the cell range, so we get notified when it dies, + // and can dispose ourself then + + // TODO: somehow add as listener so we get notified when the address of the cell range changes + // We need to forward this as change in our CellRange property to our property change listeners + + // TODO: somehow add as listener to the cells in the range, so that we get notified + // when their content changes. We need to forward this to our list entry listeners then + + // TODO: somehow add as listener so that we get notified of insertions and removals of rows in our + // range. In this case, we need to fire a change in our CellRange property, and additionally + // notify our XListEntryListeners + + m_bInitialized = sal_True; + } + +//......................................................................... +} // namespace calc +//......................................................................... diff --git a/sc/source/ui/unoobj/celllistsource.hxx b/sc/source/ui/unoobj/celllistsource.hxx new file mode 100644 index 000000000000..f6b52f0b50f8 --- /dev/null +++ b/sc/source/ui/unoobj/celllistsource.hxx @@ -0,0 +1,175 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SC_CELLLISTSOURCE_HXX +#define SC_CELLLISTSOURCE_HXX + +#include <com/sun/star/form/binding/XListEntrySource.hpp> +#include <cppuhelper/compbase4.hxx> +#include <comphelper/propertycontainer.hxx> +#include <comphelper/uno3.hxx> +#include <comphelper/broadcasthelper.hxx> +#include <comphelper/proparrhlp.hxx> +#include <com/sun/star/table/XCellRange.hpp> +#include <com/sun/star/table/CellRangeAddress.hpp> +#include <com/sun/star/sheet/XSpreadsheetDocument.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/util/XModifyListener.hpp> + + +//......................................................................... +namespace calc +{ +//......................................................................... + + //===================================================================== + //= OCellListSource + //===================================================================== + class OCellListSource; + // the base for our interfaces + typedef ::cppu::WeakAggComponentImplHelper4 < ::com::sun::star::form::binding::XListEntrySource + , ::com::sun::star::util::XModifyListener + , ::com::sun::star::lang::XServiceInfo + , ::com::sun::star::lang::XInitialization + > OCellListSource_Base; + // the base for the property handling + typedef ::comphelper::OPropertyContainer OCellListSource_PBase; + // the second base for property handling + typedef ::comphelper::OPropertyArrayUsageHelper< OCellListSource > + OCellListSource_PABase; + + class OCellListSource :public ::comphelper::OBaseMutex + ,public OCellListSource_Base // order matters! before OCellListSource_PBase, so rBHelper gets initialized + ,public OCellListSource_PBase + ,public OCellListSource_PABase + { + private: + ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XSpreadsheetDocument > + m_xDocument; /// the document where our cell lives + ::com::sun::star::uno::Reference< ::com::sun::star::table::XCellRange > + m_xRange; /// the range of cells we're bound to + ::cppu::OInterfaceContainerHelper + m_aListEntryListeners; /// our listeners + sal_Bool m_bInitialized; /// has XInitialization::initialize been called? + + public: + OCellListSource( + const ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XSpreadsheetDocument >& _rxDocument + ); + + using OCellListSource_PBase::getFastPropertyValue; + + protected: + ~OCellListSource( ); + + protected: + // XInterface + DECLARE_XINTERFACE() + + // XTypeProvider + DECLARE_XTYPEPROVIDER() + + // XListEntrySource + virtual sal_Int32 SAL_CALL getListEntryCount( ) throw (::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getListEntry( sal_Int32 Position ) throw (::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getAllListEntries( ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL addListEntryListener( const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntryListener >& Listener ) throw (::com::sun::star::lang::NullPointerException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeListEntryListener( const ::com::sun::star::uno::Reference< ::com::sun::star::form::binding::XListEntryListener >& Listener ) throw (::com::sun::star::lang::NullPointerException, ::com::sun::star::uno::RuntimeException); + + // OComponentHelper/XComponent + virtual void SAL_CALL disposing(); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); + + // XPropertySet + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException); + + // OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + virtual void SAL_CALL getFastPropertyValue( ::com::sun::star::uno::Any& _rValue, sal_Int32 _nHandle ) const; + + // ::comphelper::OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + + // XModifyListener + virtual void SAL_CALL modified( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); + + // XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + private: + void checkDisposed( ) const + SAL_THROW( ( ::com::sun::star::lang::DisposedException ) ); + void checkInitialized() + SAL_THROW( ( ::com::sun::star::uno::RuntimeException ) ); + + /** retrieves the actual address of our cell range + @precond + our m_xRange is not <NULL/> + */ + ::com::sun::star::table::CellRangeAddress + getRangeAddress( ) const; + + /** retrievs the text of a cell within our range + @param _nRangeRelativeColumn + the relative column index of the cell within our range + @param _nRangeRelativeRow + the relative row index of the cell within our range + @precond + our m_xRange is not <NULL/> + */ + ::rtl::OUString + getCellTextContent_noCheck( + sal_Int32 _nRangeRelativeColumn, + sal_Int32 _nRangeRelativeRow + ); + + void notifyModified(); + + private: + OCellListSource(); // never implemented + OCellListSource( const OCellListSource& ); // never implemented + OCellListSource& operator=( const OCellListSource& ); // never implemented + +#ifdef DBG_UTIL + private: + static const char* checkConsistency_static( const void* _pThis ); + const char* checkConsistency( ) const; +#endif + }; + +//......................................................................... +} // namespace calc +//......................................................................... + +#endif // SC_CELLLISTSOURCE_HXX diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx new file mode 100644 index 000000000000..dea7cc056756 --- /dev/null +++ b/sc/source/ui/unoobj/cellsuno.cxx @@ -0,0 +1,9842 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + +#include "scitems.hxx" +#include <editeng/eeitem.hxx> +#include <svx/svdpool.hxx> + +#include <svx/algitem.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/brshitem.hxx> +#include <editeng/editeng.hxx> +#include <editeng/flditem.hxx> +#include <svx/fmdpage.hxx> +#include <editeng/langitem.hxx> +#include <sfx2/linkmgr.hxx> +#include <svl/srchitem.hxx> +#include <svx/unomid.hxx> +#include <editeng/unoprnms.hxx> +#include <editeng/unotext.hxx> +#include <svx/svdpage.hxx> +#include <sfx2/bindings.hxx> +#include <svl/zforlist.hxx> +#include <svl/zformat.hxx> +#include <rtl/uuid.h> +#include <float.h> // DBL_MIN + +#include <com/sun/star/awt/XBitmap.hpp> +#include <com/sun/star/util/CellProtection.hpp> +#include <com/sun/star/table/CellHoriJustify.hpp> +#include <com/sun/star/table/CellOrientation.hpp> +#include <com/sun/star/table/CellVertJustify.hpp> +#include <com/sun/star/table/ShadowFormat.hpp> +#include <com/sun/star/table/TableBorder.hpp> +#include <com/sun/star/sheet/CellFlags.hpp> +#include <com/sun/star/sheet/FormulaResult.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/lang/Locale.hpp> +#include <com/sun/star/beans/TolerantPropertySetResultType.hpp> +#include <com/sun/star/beans/SetPropertyTolerantFailed.hpp> +#include <com/sun/star/text/WritingMode2.hpp> + +#include "autoform.hxx" +#include "cellsuno.hxx" +#include "cursuno.hxx" +#include "textuno.hxx" +#include "editsrc.hxx" +#include "notesuno.hxx" +#include "fielduno.hxx" +#include "docuno.hxx" // ScTableColumnsObj etc +#include "datauno.hxx" +#include "dapiuno.hxx" +#include "chartuno.hxx" +#include "fmtuno.hxx" +#include "miscuno.hxx" +#include "convuno.hxx" +#include "srchuno.hxx" +#include "targuno.hxx" +#include "tokenuno.hxx" +#include "eventuno.hxx" +#include "docsh.hxx" +#include "markdata.hxx" +#include "patattr.hxx" +#include "docpool.hxx" +#include "docfunc.hxx" +#include "dbdocfun.hxx" +#include "olinefun.hxx" +#include "hints.hxx" +#include "cell.hxx" +#include "undocell.hxx" +#include "undotab.hxx" +#include "undoblk.hxx" // fuer lcl_ApplyBorder - nach docfunc verschieben! +#include "stlsheet.hxx" +#include "dbcolect.hxx" +#include "attrib.hxx" +#include "chartarr.hxx" +#include "chartlis.hxx" +#include "drwlayer.hxx" +#include "printfun.hxx" +#include "prnsave.hxx" +#include "tablink.hxx" +#include "dociter.hxx" +#include "rangeutl.hxx" +#include "conditio.hxx" +#include "validat.hxx" +#include "sc.hrc" +#include "brdcst.hxx" +#include "unoguard.hxx" +#include "cellform.hxx" +#include "globstr.hrc" +#include "unonames.hxx" +#include "styleuno.hxx" +#include "rangeseq.hxx" +#include "unowids.hxx" +#include "paramisc.hxx" +#include "formula/errorcodes.hxx" +#include "unoreflist.hxx" +#include "formula/grammar.hxx" + +#include <list> + +using namespace com::sun::star; + +//------------------------------------------------------------------------ + + +class ScNamedEntry +{ + String aName; + ScRange aRange; + +public: + ScNamedEntry(const String& rN, const ScRange& rR) : + aName(rN), aRange(rR) {} + + const String& GetName() const { return aName; } + const ScRange& GetRange() const { return aRange; } +}; + + +//------------------------------------------------------------------------ + +// Die Namen in den Maps muessen (nach strcmp) sortiert sein! +//! statt Which-ID 0 special IDs verwenden, und nicht ueber Namen vergleichen !!!!!!!!! + +// Left/Right/Top/BottomBorder are mapped directly to the core items, +// not collected/applied to the borders of a range -> ATTR_BORDER can be used directly + +const SfxItemPropertySet* lcl_GetCellsPropertySet() +{ + static SfxItemPropertyMapEntry aCellsPropertyMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_ABSNAME), SC_WID_UNO_ABSNAME, &getCppuType((rtl::OUString*)0), 0 | beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_ASIANVERT),ATTR_VERTICAL_ASIAN,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_BOTTBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, BOTTOM_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_CELLBACK), ATTR_BACKGROUND, &getCppuType((sal_Int32*)0), 0, MID_BACK_COLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CELLPRO), ATTR_PROTECTION, &getCppuType((util::CellProtection*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLSTYL), SC_WID_UNO_CELLSTYL,&getCppuType((rtl::OUString*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CCOLOR), ATTR_FONT_COLOR, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_COUTL), ATTR_FONT_CONTOUR, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CCROSS), ATTR_FONT_CROSSEDOUT,&getBooleanCppuType(), 0, MID_CROSSED_OUT }, + {MAP_CHAR_LEN(SC_UNONAME_CEMPHAS), ATTR_FONT_EMPHASISMARK,&getCppuType((sal_Int16*)0), 0, MID_EMPHASIS }, + {MAP_CHAR_LEN(SC_UNONAME_CFONT), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNONAME_CFCHARS), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFCHARS), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFCHARS), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNONAME_CFFAMIL), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFFAMIL), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFFAMIL), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNONAME_CFNAME), ATTR_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFNAME), ATTR_CJK_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFNAME), ATTR_CTL_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNONAME_CFPITCH), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFPITCH), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFPITCH), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNONAME_CFSTYLE), ATTR_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFSTYLE), ATTR_CJK_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFSTYLE), ATTR_CTL_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNONAME_CHEIGHT), ATTR_FONT_HEIGHT, &getCppuType((float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_CJK_CHEIGHT), ATTR_CJK_FONT_HEIGHT,&getCppuType((float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_CTL_CHEIGHT), ATTR_CTL_FONT_HEIGHT,&getCppuType((float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_CLOCAL), ATTR_FONT_LANGUAGE, &getCppuType((lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNO_CJK_CLOCAL), ATTR_CJK_FONT_LANGUAGE,&getCppuType((lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNO_CTL_CLOCAL), ATTR_CTL_FONT_LANGUAGE,&getCppuType((lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNONAME_COVER), ATTR_FONT_OVERLINE, &getCppuType((sal_Int16*)0), 0, MID_TL_STYLE }, + {MAP_CHAR_LEN(SC_UNONAME_COVRLCOL), ATTR_FONT_OVERLINE, &getCppuType((sal_Int32*)0), 0, MID_TL_COLOR }, + {MAP_CHAR_LEN(SC_UNONAME_COVRLHAS), ATTR_FONT_OVERLINE, &getBooleanCppuType(), 0, MID_TL_HASCOLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CPOST), ATTR_FONT_POSTURE, &getCppuType((awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNO_CJK_CPOST), ATTR_CJK_FONT_POSTURE,&getCppuType((awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNO_CTL_CPOST), ATTR_CTL_FONT_POSTURE,&getCppuType((awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNONAME_CRELIEF), ATTR_FONT_RELIEF, &getCppuType((sal_Int16*)0), 0, MID_RELIEF }, + {MAP_CHAR_LEN(SC_UNONAME_CSHADD), ATTR_FONT_SHADOWED, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CSTRIKE), ATTR_FONT_CROSSEDOUT,&getCppuType((sal_Int16*)0), 0, MID_CROSS_OUT }, + {MAP_CHAR_LEN(SC_UNONAME_CUNDER), ATTR_FONT_UNDERLINE,&getCppuType((sal_Int16*)0), 0, MID_TL_STYLE }, + {MAP_CHAR_LEN(SC_UNONAME_CUNDLCOL), ATTR_FONT_UNDERLINE,&getCppuType((sal_Int32*)0), 0, MID_TL_COLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CUNDLHAS), ATTR_FONT_UNDERLINE,&getBooleanCppuType(), 0, MID_TL_HASCOLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CWEIGHT), ATTR_FONT_WEIGHT, &getCppuType((float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNO_CJK_CWEIGHT), ATTR_CJK_FONT_WEIGHT,&getCppuType((float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNO_CTL_CWEIGHT), ATTR_CTL_FONT_WEIGHT,&getCppuType((float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNONAME_CWORDMOD), ATTR_FONT_WORDLINE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CHCOLHDR), SC_WID_UNO_CHCOLHDR,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CHROWHDR), SC_WID_UNO_CHROWHDR,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CONDFMT), SC_WID_UNO_CONDFMT, &getCppuType((uno::Reference<sheet::XSheetConditionalEntries>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CONDLOC), SC_WID_UNO_CONDLOC, &getCppuType((uno::Reference<sheet::XSheetConditionalEntries>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CONDXML), SC_WID_UNO_CONDXML, &getCppuType((uno::Reference<sheet::XSheetConditionalEntries>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_DIAGONAL_BLTR), ATTR_BORDER_BLTR, &::getCppuType((const table::BorderLine*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_DIAGONAL_TLBR), ATTR_BORDER_TLBR, &::getCppuType((const table::BorderLine*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_CELLHJUS), ATTR_HOR_JUSTIFY, &getCppuType((table::CellHoriJustify*)0), 0, MID_HORJUST_HORJUST }, + {MAP_CHAR_LEN(SC_UNONAME_CELLTRAN), ATTR_BACKGROUND, &getBooleanCppuType(), 0, MID_GRAPHIC_TRANSPARENT }, + {MAP_CHAR_LEN(SC_UNONAME_WRAP), ATTR_LINEBREAK, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_LEFTBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, LEFT_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_NUMFMT), ATTR_VALUE_FORMAT, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_NUMRULES), SC_WID_UNO_NUMRULES,&getCppuType((const uno::Reference<container::XIndexReplace>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLORI), ATTR_STACKED, &getCppuType((table::CellOrientation*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PADJUST), ATTR_HOR_JUSTIFY, &::getCppuType((const sal_Int16*)0), 0, MID_HORJUST_ADJUST }, + {MAP_CHAR_LEN(SC_UNONAME_PBMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PINDENT), ATTR_INDENT, &getCppuType((sal_Int16*)0), 0, 0 }, //! CONVERT_TWIPS + {MAP_CHAR_LEN(SC_UNONAME_PISCHDIST),ATTR_SCRIPTSPACE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PISFORBID),ATTR_FORBIDDEN_RULES,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PISHANG), ATTR_HANGPUNCTUATION,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PISHYPHEN),ATTR_HYPHENATE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PLASTADJ), ATTR_HOR_JUSTIFY, &::getCppuType((const sal_Int16*)0), 0, MID_HORJUST_ADJUST }, + {MAP_CHAR_LEN(SC_UNONAME_PLMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_L_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PRMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_R_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PTMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_RIGHTBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, RIGHT_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_ROTANG), ATTR_ROTATE_VALUE, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_ROTREF), ATTR_ROTATE_MODE, &getCppuType((table::CellVertJustify*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_SHADOW), ATTR_SHADOW, &getCppuType((table::ShadowFormat*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_SHRINK_TO_FIT), ATTR_SHRINKTOFIT, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_TBLBORD), SC_WID_UNO_TBLBORD, &getCppuType((table::TableBorder*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_TOPBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, TOP_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_USERDEF), ATTR_USERDEF, &getCppuType((uno::Reference<container::XNameContainer>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_VALIDAT), SC_WID_UNO_VALIDAT, &getCppuType((uno::Reference<beans::XPropertySet>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_VALILOC), SC_WID_UNO_VALILOC, &getCppuType((uno::Reference<beans::XPropertySet>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_VALIXML), SC_WID_UNO_VALIXML, &getCppuType((uno::Reference<beans::XPropertySet>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLVJUS), ATTR_VER_JUSTIFY, &getCppuType((table::CellVertJustify*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_WRITING), ATTR_WRITINGDIR, &getCppuType((sal_Int16*)0), 0, 0 }, + {0,0,0,0,0,0} + }; + static SfxItemPropertySet aCellsPropertySet( aCellsPropertyMap_Impl ); + return &aCellsPropertySet; +} + +// CellRange enthaelt alle Eintraege von Cells, zusaetzlich eigene Eintraege +// mit Which-ID 0 (werden nur fuer getPropertySetInfo benoetigt). + +const SfxItemPropertySet* lcl_GetRangePropertySet() +{ + static SfxItemPropertyMapEntry aRangePropertyMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_ABSNAME), SC_WID_UNO_ABSNAME, &getCppuType((rtl::OUString*)0), 0 | beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_ASIANVERT),ATTR_VERTICAL_ASIAN,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_BOTTBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, BOTTOM_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_CELLBACK), ATTR_BACKGROUND, &getCppuType((sal_Int32*)0), 0, MID_BACK_COLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CELLPRO), ATTR_PROTECTION, &getCppuType((util::CellProtection*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLSTYL), SC_WID_UNO_CELLSTYL,&getCppuType((rtl::OUString*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CCOLOR), ATTR_FONT_COLOR, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_COUTL), ATTR_FONT_CONTOUR, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CCROSS), ATTR_FONT_CROSSEDOUT,&getBooleanCppuType(), 0, MID_CROSSED_OUT }, + {MAP_CHAR_LEN(SC_UNONAME_CEMPHAS), ATTR_FONT_EMPHASISMARK,&getCppuType((sal_Int16*)0), 0, MID_EMPHASIS }, + {MAP_CHAR_LEN(SC_UNONAME_CFONT), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNONAME_CFCHARS), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFCHARS), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFCHARS), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNONAME_CFFAMIL), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFFAMIL), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFFAMIL), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNONAME_CFNAME), ATTR_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFNAME), ATTR_CJK_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFNAME), ATTR_CTL_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNONAME_CFPITCH), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFPITCH), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFPITCH), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNONAME_CFSTYLE), ATTR_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFSTYLE), ATTR_CJK_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFSTYLE), ATTR_CTL_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNONAME_CHEIGHT), ATTR_FONT_HEIGHT, &getCppuType((float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_CJK_CHEIGHT), ATTR_CJK_FONT_HEIGHT,&getCppuType((float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_CTL_CHEIGHT), ATTR_CTL_FONT_HEIGHT,&getCppuType((float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_CLOCAL), ATTR_FONT_LANGUAGE, &getCppuType((lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNO_CJK_CLOCAL), ATTR_CJK_FONT_LANGUAGE,&getCppuType((lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNO_CTL_CLOCAL), ATTR_CTL_FONT_LANGUAGE,&getCppuType((lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNONAME_COVER), ATTR_FONT_OVERLINE, &getCppuType((sal_Int16*)0), 0, MID_TL_STYLE }, + {MAP_CHAR_LEN(SC_UNONAME_COVRLCOL), ATTR_FONT_OVERLINE, &getCppuType((sal_Int32*)0), 0, MID_TL_COLOR }, + {MAP_CHAR_LEN(SC_UNONAME_COVRLHAS), ATTR_FONT_OVERLINE, &getBooleanCppuType(), 0, MID_TL_HASCOLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CPOST), ATTR_FONT_POSTURE, &getCppuType((awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNO_CJK_CPOST), ATTR_CJK_FONT_POSTURE,&getCppuType((awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNO_CTL_CPOST), ATTR_CTL_FONT_POSTURE,&getCppuType((awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNONAME_CRELIEF), ATTR_FONT_RELIEF, &getCppuType((sal_Int16*)0), 0, MID_RELIEF }, + {MAP_CHAR_LEN(SC_UNONAME_CSHADD), ATTR_FONT_SHADOWED, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CSTRIKE), ATTR_FONT_CROSSEDOUT,&getCppuType((sal_Int16*)0), 0, MID_CROSS_OUT }, + {MAP_CHAR_LEN(SC_UNONAME_CUNDER), ATTR_FONT_UNDERLINE,&getCppuType((sal_Int16*)0), 0, MID_TL_STYLE }, + {MAP_CHAR_LEN(SC_UNONAME_CUNDLCOL), ATTR_FONT_UNDERLINE,&getCppuType((sal_Int32*)0), 0, MID_TL_COLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CUNDLHAS), ATTR_FONT_UNDERLINE,&getBooleanCppuType(), 0, MID_TL_HASCOLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CWEIGHT), ATTR_FONT_WEIGHT, &getCppuType((float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNO_CJK_CWEIGHT), ATTR_CJK_FONT_WEIGHT,&getCppuType((float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNO_CTL_CWEIGHT), ATTR_CTL_FONT_WEIGHT,&getCppuType((float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNONAME_CWORDMOD), ATTR_FONT_WORDLINE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CHCOLHDR), SC_WID_UNO_CHCOLHDR,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CHROWHDR), SC_WID_UNO_CHROWHDR,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CONDFMT), SC_WID_UNO_CONDFMT, &getCppuType((uno::Reference<sheet::XSheetConditionalEntries>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CONDLOC), SC_WID_UNO_CONDLOC, &getCppuType((uno::Reference<sheet::XSheetConditionalEntries>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CONDXML), SC_WID_UNO_CONDXML, &getCppuType((uno::Reference<sheet::XSheetConditionalEntries>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_DIAGONAL_BLTR), ATTR_BORDER_BLTR, &::getCppuType((const table::BorderLine*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_DIAGONAL_TLBR), ATTR_BORDER_TLBR, &::getCppuType((const table::BorderLine*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_CELLHJUS), ATTR_HOR_JUSTIFY, &getCppuType((table::CellHoriJustify*)0), 0, MID_HORJUST_HORJUST }, + {MAP_CHAR_LEN(SC_UNONAME_CELLTRAN), ATTR_BACKGROUND, &getBooleanCppuType(), 0, MID_GRAPHIC_TRANSPARENT }, + {MAP_CHAR_LEN(SC_UNONAME_WRAP), ATTR_LINEBREAK, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_LEFTBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, LEFT_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_NUMFMT), ATTR_VALUE_FORMAT, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_NUMRULES), SC_WID_UNO_NUMRULES,&getCppuType((const uno::Reference<container::XIndexReplace>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLORI), ATTR_STACKED, &getCppuType((table::CellOrientation*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PADJUST), ATTR_HOR_JUSTIFY, &::getCppuType((const sal_Int16*)0), 0, MID_HORJUST_ADJUST }, + {MAP_CHAR_LEN(SC_UNONAME_PBMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PINDENT), ATTR_INDENT, &getCppuType((sal_Int16*)0), 0, 0 }, //! CONVERT_TWIPS + {MAP_CHAR_LEN(SC_UNONAME_PISCHDIST),ATTR_SCRIPTSPACE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PISFORBID),ATTR_FORBIDDEN_RULES,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PISHANG), ATTR_HANGPUNCTUATION,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PISHYPHEN),ATTR_HYPHENATE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PLASTADJ), ATTR_HOR_JUSTIFY, &::getCppuType((const sal_Int16*)0), 0, MID_HORJUST_ADJUST }, + {MAP_CHAR_LEN(SC_UNONAME_PLMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_L_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PRMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_R_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PTMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_POS), SC_WID_UNO_POS, &getCppuType((awt::Point*)0), 0 | beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_RIGHTBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, RIGHT_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_ROTANG), ATTR_ROTATE_VALUE, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_ROTREF), ATTR_ROTATE_MODE, &getCppuType((table::CellVertJustify*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_SHADOW), ATTR_SHADOW, &getCppuType((table::ShadowFormat*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_SHRINK_TO_FIT), ATTR_SHRINKTOFIT, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_SIZE), SC_WID_UNO_SIZE, &getCppuType((awt::Size*)0), 0 | beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_TBLBORD), SC_WID_UNO_TBLBORD, &getCppuType((table::TableBorder*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_TOPBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, TOP_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_USERDEF), ATTR_USERDEF, &getCppuType((uno::Reference<container::XNameContainer>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_VALIDAT), SC_WID_UNO_VALIDAT, &getCppuType((uno::Reference<beans::XPropertySet>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_VALILOC), SC_WID_UNO_VALILOC, &getCppuType((uno::Reference<beans::XPropertySet>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_VALIXML), SC_WID_UNO_VALIXML, &getCppuType((uno::Reference<beans::XPropertySet>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLVJUS), ATTR_VER_JUSTIFY, &getCppuType((table::CellVertJustify*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_WRITING), ATTR_WRITINGDIR, &getCppuType((sal_Int16*)0), 0, 0 }, + {0,0,0,0,0,0} + }; + static SfxItemPropertySet aRangePropertySet( aRangePropertyMap_Impl ); + return &aRangePropertySet; +} + +// Cell enthaelt alle Eintraege von CellRange, zusaetzlich eigene Eintraege +// mit Which-ID 0 (werden nur fuer getPropertySetInfo benoetigt). + +const SfxItemPropertySet* lcl_GetCellPropertySet() +{ + static SfxItemPropertyMapEntry aCellPropertyMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_ABSNAME), SC_WID_UNO_ABSNAME, &getCppuType((rtl::OUString*)0), 0 | beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_ASIANVERT),ATTR_VERTICAL_ASIAN,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_BOTTBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, BOTTOM_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_CELLBACK), ATTR_BACKGROUND, &getCppuType((sal_Int32*)0), 0, MID_BACK_COLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CELLPRO), ATTR_PROTECTION, &getCppuType((util::CellProtection*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLSTYL), SC_WID_UNO_CELLSTYL,&getCppuType((rtl::OUString*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CCOLOR), ATTR_FONT_COLOR, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_COUTL), ATTR_FONT_CONTOUR, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CCROSS), ATTR_FONT_CROSSEDOUT,&getBooleanCppuType(), 0, MID_CROSSED_OUT }, + {MAP_CHAR_LEN(SC_UNONAME_CEMPHAS), ATTR_FONT_EMPHASISMARK,&getCppuType((sal_Int16*)0), 0, MID_EMPHASIS }, + {MAP_CHAR_LEN(SC_UNONAME_CFONT), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNONAME_CFCHARS), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFCHARS), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFCHARS), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNONAME_CFFAMIL), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFFAMIL), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFFAMIL), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNONAME_CFNAME), ATTR_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFNAME), ATTR_CJK_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFNAME), ATTR_CTL_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNONAME_CFPITCH), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFPITCH), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFPITCH), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNONAME_CFSTYLE), ATTR_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFSTYLE), ATTR_CJK_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFSTYLE), ATTR_CTL_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNONAME_CHEIGHT), ATTR_FONT_HEIGHT, &getCppuType((float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_CJK_CHEIGHT), ATTR_CJK_FONT_HEIGHT,&getCppuType((float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_CTL_CHEIGHT), ATTR_CTL_FONT_HEIGHT,&getCppuType((float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_CLOCAL), ATTR_FONT_LANGUAGE, &getCppuType((lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNO_CJK_CLOCAL), ATTR_CJK_FONT_LANGUAGE,&getCppuType((lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNO_CTL_CLOCAL), ATTR_CTL_FONT_LANGUAGE,&getCppuType((lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNONAME_COVER), ATTR_FONT_OVERLINE, &getCppuType((sal_Int16*)0), 0, MID_TL_STYLE }, + {MAP_CHAR_LEN(SC_UNONAME_COVRLCOL), ATTR_FONT_OVERLINE, &getCppuType((sal_Int32*)0), 0, MID_TL_COLOR }, + {MAP_CHAR_LEN(SC_UNONAME_COVRLHAS), ATTR_FONT_OVERLINE, &getBooleanCppuType(), 0, MID_TL_HASCOLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CPOST), ATTR_FONT_POSTURE, &getCppuType((awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNO_CJK_CPOST), ATTR_CJK_FONT_POSTURE,&getCppuType((awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNO_CTL_CPOST), ATTR_CTL_FONT_POSTURE,&getCppuType((awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNONAME_CRELIEF), ATTR_FONT_RELIEF, &getCppuType((sal_Int16*)0), 0, MID_RELIEF }, + {MAP_CHAR_LEN(SC_UNONAME_CSHADD), ATTR_FONT_SHADOWED, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CSTRIKE), ATTR_FONT_CROSSEDOUT,&getCppuType((sal_Int16*)0), 0, MID_CROSS_OUT }, + {MAP_CHAR_LEN(SC_UNONAME_CUNDER), ATTR_FONT_UNDERLINE,&getCppuType((sal_Int16*)0), 0, MID_TL_STYLE }, + {MAP_CHAR_LEN(SC_UNONAME_CUNDLCOL), ATTR_FONT_UNDERLINE,&getCppuType((sal_Int32*)0), 0, MID_TL_COLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CUNDLHAS), ATTR_FONT_UNDERLINE,&getBooleanCppuType(), 0, MID_TL_HASCOLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CWEIGHT), ATTR_FONT_WEIGHT, &getCppuType((float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNO_CJK_CWEIGHT), ATTR_CJK_FONT_WEIGHT,&getCppuType((float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNO_CTL_CWEIGHT), ATTR_CTL_FONT_WEIGHT,&getCppuType((float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNONAME_CWORDMOD), ATTR_FONT_WORDLINE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CHCOLHDR), SC_WID_UNO_CHCOLHDR,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CHROWHDR), SC_WID_UNO_CHROWHDR,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CONDFMT), SC_WID_UNO_CONDFMT, &getCppuType((uno::Reference<sheet::XSheetConditionalEntries>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CONDLOC), SC_WID_UNO_CONDLOC, &getCppuType((uno::Reference<sheet::XSheetConditionalEntries>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CONDXML), SC_WID_UNO_CONDXML, &getCppuType((uno::Reference<sheet::XSheetConditionalEntries>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_DIAGONAL_BLTR), ATTR_BORDER_BLTR, &::getCppuType((const table::BorderLine*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_DIAGONAL_TLBR), ATTR_BORDER_TLBR, &::getCppuType((const table::BorderLine*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_FORMLOC), SC_WID_UNO_FORMLOC, &getCppuType((rtl::OUString*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_FORMRT), SC_WID_UNO_FORMRT, &getCppuType((table::CellContentType*)0), 0 | beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLHJUS), ATTR_HOR_JUSTIFY, &getCppuType((table::CellHoriJustify*)0), 0, MID_HORJUST_HORJUST }, + {MAP_CHAR_LEN(SC_UNONAME_CELLTRAN), ATTR_BACKGROUND, &getBooleanCppuType(), 0, MID_GRAPHIC_TRANSPARENT }, + {MAP_CHAR_LEN(SC_UNONAME_WRAP), ATTR_LINEBREAK, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_LEFTBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, LEFT_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_NUMFMT), ATTR_VALUE_FORMAT, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_NUMRULES), SC_WID_UNO_NUMRULES,&getCppuType((const uno::Reference<container::XIndexReplace>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLORI), ATTR_STACKED, &getCppuType((table::CellOrientation*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PADJUST), ATTR_HOR_JUSTIFY, &::getCppuType((const sal_Int16*)0), 0, MID_HORJUST_ADJUST }, + {MAP_CHAR_LEN(SC_UNONAME_PBMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PINDENT), ATTR_INDENT, &getCppuType((sal_Int16*)0), 0, 0 }, //! CONVERT_TWIPS + {MAP_CHAR_LEN(SC_UNONAME_PISCHDIST),ATTR_SCRIPTSPACE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PISFORBID),ATTR_FORBIDDEN_RULES,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PISHANG), ATTR_HANGPUNCTUATION,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PISHYPHEN),ATTR_HYPHENATE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PLASTADJ), ATTR_HOR_JUSTIFY, &::getCppuType((const sal_Int16*)0), 0, MID_HORJUST_ADJUST }, + {MAP_CHAR_LEN(SC_UNONAME_PLMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_L_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PRMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_R_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PTMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_POS), SC_WID_UNO_POS, &getCppuType((awt::Point*)0), 0 | beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_RIGHTBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, RIGHT_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_ROTANG), ATTR_ROTATE_VALUE, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_ROTREF), ATTR_ROTATE_MODE, &getCppuType((table::CellVertJustify*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_SHADOW), ATTR_SHADOW, &getCppuType((table::ShadowFormat*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_SHRINK_TO_FIT), ATTR_SHRINKTOFIT, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_SIZE), SC_WID_UNO_SIZE, &getCppuType((awt::Size*)0), 0 | beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_TBLBORD), SC_WID_UNO_TBLBORD, &getCppuType((table::TableBorder*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_TOPBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, TOP_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_USERDEF), ATTR_USERDEF, &getCppuType((uno::Reference<container::XNameContainer>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_VALIDAT), SC_WID_UNO_VALIDAT, &getCppuType((uno::Reference<beans::XPropertySet>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_VALILOC), SC_WID_UNO_VALILOC, &getCppuType((uno::Reference<beans::XPropertySet>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_VALIXML), SC_WID_UNO_VALIXML, &getCppuType((uno::Reference<beans::XPropertySet>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLVJUS), ATTR_VER_JUSTIFY, &getCppuType((table::CellVertJustify*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_WRITING), ATTR_WRITINGDIR, &getCppuType((sal_Int16*)0), 0, 0 }, + {0,0,0,0,0,0} + }; + static SfxItemPropertySet aCellPropertySet( aCellPropertyMap_Impl ); + return &aCellPropertySet; +} + +// Column und Row enthalten alle Eintraege von CellRange, zusaetzlich eigene Eintraege +// mit Which-ID 0 (werden nur fuer getPropertySetInfo benoetigt). + +const SfxItemPropertySet* lcl_GetColumnPropertySet() +{ + static SfxItemPropertyMapEntry aColumnPropertyMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_ABSNAME), SC_WID_UNO_ABSNAME, &getCppuType((rtl::OUString*)0), 0 | beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_ASIANVERT),ATTR_VERTICAL_ASIAN,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_BOTTBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, BOTTOM_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_CELLBACK), ATTR_BACKGROUND, &getCppuType((sal_Int32*)0), 0, MID_BACK_COLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CELLPRO), ATTR_PROTECTION, &getCppuType((util::CellProtection*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLSTYL), SC_WID_UNO_CELLSTYL,&getCppuType((rtl::OUString*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CCOLOR), ATTR_FONT_COLOR, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_COUTL), ATTR_FONT_CONTOUR, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CCROSS), ATTR_FONT_CROSSEDOUT,&getBooleanCppuType(), 0, MID_CROSSED_OUT }, + {MAP_CHAR_LEN(SC_UNONAME_CEMPHAS), ATTR_FONT_EMPHASISMARK,&getCppuType((sal_Int16*)0), 0, MID_EMPHASIS }, + {MAP_CHAR_LEN(SC_UNONAME_CFONT), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNONAME_CFCHARS), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFCHARS), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFCHARS), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNONAME_CFFAMIL), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFFAMIL), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFFAMIL), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNONAME_CFNAME), ATTR_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFNAME), ATTR_CJK_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFNAME), ATTR_CTL_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNONAME_CFPITCH), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFPITCH), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFPITCH), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNONAME_CFSTYLE), ATTR_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFSTYLE), ATTR_CJK_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFSTYLE), ATTR_CTL_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNONAME_CHEIGHT), ATTR_FONT_HEIGHT, &getCppuType((float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_CJK_CHEIGHT), ATTR_CJK_FONT_HEIGHT,&getCppuType((float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_CTL_CHEIGHT), ATTR_CTL_FONT_HEIGHT,&getCppuType((float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_CLOCAL), ATTR_FONT_LANGUAGE, &getCppuType((lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNO_CJK_CLOCAL), ATTR_CJK_FONT_LANGUAGE,&getCppuType((lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNO_CTL_CLOCAL), ATTR_CTL_FONT_LANGUAGE,&getCppuType((lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNONAME_COVER), ATTR_FONT_OVERLINE, &getCppuType((sal_Int16*)0), 0, MID_TL_STYLE }, + {MAP_CHAR_LEN(SC_UNONAME_COVRLCOL), ATTR_FONT_OVERLINE, &getCppuType((sal_Int32*)0), 0, MID_TL_COLOR }, + {MAP_CHAR_LEN(SC_UNONAME_COVRLHAS), ATTR_FONT_OVERLINE, &getBooleanCppuType(), 0, MID_TL_HASCOLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CPOST), ATTR_FONT_POSTURE, &getCppuType((awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNO_CJK_CPOST), ATTR_CJK_FONT_POSTURE,&getCppuType((awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNO_CTL_CPOST), ATTR_CTL_FONT_POSTURE,&getCppuType((awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNONAME_CRELIEF), ATTR_FONT_RELIEF, &getCppuType((sal_Int16*)0), 0, MID_RELIEF }, + {MAP_CHAR_LEN(SC_UNONAME_CSHADD), ATTR_FONT_SHADOWED, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CSTRIKE), ATTR_FONT_CROSSEDOUT,&getCppuType((sal_Int16*)0), 0, MID_CROSS_OUT }, + {MAP_CHAR_LEN(SC_UNONAME_CUNDER), ATTR_FONT_UNDERLINE,&getCppuType((sal_Int16*)0), 0, MID_TL_STYLE }, + {MAP_CHAR_LEN(SC_UNONAME_CUNDLCOL), ATTR_FONT_UNDERLINE,&getCppuType((sal_Int32*)0), 0, MID_TL_COLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CUNDLHAS), ATTR_FONT_UNDERLINE,&getBooleanCppuType(), 0, MID_TL_HASCOLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CWEIGHT), ATTR_FONT_WEIGHT, &getCppuType((float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNO_CJK_CWEIGHT), ATTR_CJK_FONT_WEIGHT,&getCppuType((float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNO_CTL_CWEIGHT), ATTR_CTL_FONT_WEIGHT,&getCppuType((float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNONAME_CWORDMOD), ATTR_FONT_WORDLINE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CHCOLHDR), SC_WID_UNO_CHCOLHDR,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CHROWHDR), SC_WID_UNO_CHROWHDR,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CONDFMT), SC_WID_UNO_CONDFMT, &getCppuType((uno::Reference<sheet::XSheetConditionalEntries>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CONDLOC), SC_WID_UNO_CONDLOC, &getCppuType((uno::Reference<sheet::XSheetConditionalEntries>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CONDXML), SC_WID_UNO_CONDXML, &getCppuType((uno::Reference<sheet::XSheetConditionalEntries>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_DIAGONAL_BLTR), ATTR_BORDER_BLTR, &::getCppuType((const table::BorderLine*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_DIAGONAL_TLBR), ATTR_BORDER_TLBR, &::getCppuType((const table::BorderLine*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_CELLHJUS), ATTR_HOR_JUSTIFY, &getCppuType((table::CellHoriJustify*)0), 0, MID_HORJUST_HORJUST }, + {MAP_CHAR_LEN(SC_UNONAME_CELLTRAN), ATTR_BACKGROUND, &getBooleanCppuType(), 0, MID_GRAPHIC_TRANSPARENT }, +// {MAP_CHAR_LEN(SC_UNONAME_CELLFILT), SC_WID_UNO_CELLFILT,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_MANPAGE), SC_WID_UNO_MANPAGE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_NEWPAGE), SC_WID_UNO_NEWPAGE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_WRAP), ATTR_LINEBREAK, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLVIS), SC_WID_UNO_CELLVIS, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_LEFTBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, LEFT_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_NUMFMT), ATTR_VALUE_FORMAT, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_NUMRULES), SC_WID_UNO_NUMRULES,&getCppuType((const uno::Reference<container::XIndexReplace>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_OWIDTH), SC_WID_UNO_OWIDTH, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLORI), ATTR_STACKED, &getCppuType((table::CellOrientation*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PADJUST), ATTR_HOR_JUSTIFY, &::getCppuType((const sal_Int16*)0), 0, MID_HORJUST_ADJUST }, + {MAP_CHAR_LEN(SC_UNONAME_PBMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PINDENT), ATTR_INDENT, &getCppuType((sal_Int16*)0), 0, 0 }, //! CONVERT_TWIPS + {MAP_CHAR_LEN(SC_UNONAME_PISCHDIST),ATTR_SCRIPTSPACE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PISFORBID),ATTR_FORBIDDEN_RULES,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PISHANG), ATTR_HANGPUNCTUATION,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PISHYPHEN),ATTR_HYPHENATE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PLASTADJ), ATTR_HOR_JUSTIFY, &::getCppuType((const sal_Int16*)0), 0, MID_HORJUST_ADJUST }, + {MAP_CHAR_LEN(SC_UNONAME_PLMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_L_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PRMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_R_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PTMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_POS), SC_WID_UNO_POS, &getCppuType((awt::Point*)0), 0 | beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_RIGHTBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, RIGHT_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_ROTANG), ATTR_ROTATE_VALUE, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_ROTREF), ATTR_ROTATE_MODE, &getCppuType((table::CellVertJustify*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_SHADOW), ATTR_SHADOW, &getCppuType((table::ShadowFormat*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_SHRINK_TO_FIT), ATTR_SHRINKTOFIT, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_SIZE), SC_WID_UNO_SIZE, &getCppuType((awt::Size*)0), 0 | beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_TBLBORD), SC_WID_UNO_TBLBORD, &getCppuType((table::TableBorder*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_TOPBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, TOP_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_USERDEF), ATTR_USERDEF, &getCppuType((uno::Reference<container::XNameContainer>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_VALIDAT), SC_WID_UNO_VALIDAT, &getCppuType((uno::Reference<beans::XPropertySet>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_VALILOC), SC_WID_UNO_VALILOC, &getCppuType((uno::Reference<beans::XPropertySet>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_VALIXML), SC_WID_UNO_VALIXML, &getCppuType((uno::Reference<beans::XPropertySet>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLVJUS), ATTR_VER_JUSTIFY, &getCppuType((table::CellVertJustify*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLWID), SC_WID_UNO_CELLWID, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_WRITING), ATTR_WRITINGDIR, &getCppuType((sal_Int16*)0), 0, 0 }, + {0,0,0,0,0,0} + }; + static SfxItemPropertySet aColumnPropertySet( aColumnPropertyMap_Impl ); + return &aColumnPropertySet; +} + +const SfxItemPropertySet* lcl_GetRowPropertySet() +{ + static SfxItemPropertyMapEntry aRowPropertyMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_ABSNAME), SC_WID_UNO_ABSNAME, &getCppuType((rtl::OUString*)0), 0 | beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_ASIANVERT),ATTR_VERTICAL_ASIAN,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_BOTTBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, BOTTOM_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_CELLBACK), ATTR_BACKGROUND, &getCppuType((sal_Int32*)0), 0, MID_BACK_COLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CELLPRO), ATTR_PROTECTION, &getCppuType((util::CellProtection*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLSTYL), SC_WID_UNO_CELLSTYL,&getCppuType((rtl::OUString*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CCOLOR), ATTR_FONT_COLOR, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_COUTL), ATTR_FONT_CONTOUR, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CCROSS), ATTR_FONT_CROSSEDOUT,&getBooleanCppuType(), 0, MID_CROSSED_OUT }, + {MAP_CHAR_LEN(SC_UNONAME_CEMPHAS), ATTR_FONT_EMPHASISMARK,&getCppuType((sal_Int16*)0), 0, MID_EMPHASIS }, + {MAP_CHAR_LEN(SC_UNONAME_CFONT), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNONAME_CFCHARS), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFCHARS), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFCHARS), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNONAME_CFFAMIL), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFFAMIL), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFFAMIL), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNONAME_CFNAME), ATTR_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFNAME), ATTR_CJK_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFNAME), ATTR_CTL_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNONAME_CFPITCH), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFPITCH), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFPITCH), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNONAME_CFSTYLE), ATTR_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFSTYLE), ATTR_CJK_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFSTYLE), ATTR_CTL_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNONAME_CHEIGHT), ATTR_FONT_HEIGHT, &getCppuType((float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_CJK_CHEIGHT), ATTR_CJK_FONT_HEIGHT,&getCppuType((float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_CTL_CHEIGHT), ATTR_CTL_FONT_HEIGHT,&getCppuType((float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_CLOCAL), ATTR_FONT_LANGUAGE, &getCppuType((lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNO_CJK_CLOCAL), ATTR_CJK_FONT_LANGUAGE,&getCppuType((lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNO_CTL_CLOCAL), ATTR_CTL_FONT_LANGUAGE,&getCppuType((lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNONAME_COVER), ATTR_FONT_OVERLINE, &getCppuType((sal_Int16*)0), 0, MID_TL_STYLE }, + {MAP_CHAR_LEN(SC_UNONAME_COVRLCOL), ATTR_FONT_OVERLINE, &getCppuType((sal_Int32*)0), 0, MID_TL_COLOR }, + {MAP_CHAR_LEN(SC_UNONAME_COVRLHAS), ATTR_FONT_OVERLINE, &getBooleanCppuType(), 0, MID_TL_HASCOLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CPOST), ATTR_FONT_POSTURE, &getCppuType((awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNO_CJK_CPOST), ATTR_CJK_FONT_POSTURE,&getCppuType((awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNO_CTL_CPOST), ATTR_CTL_FONT_POSTURE,&getCppuType((awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNONAME_CRELIEF), ATTR_FONT_RELIEF, &getCppuType((sal_Int16*)0), 0, MID_RELIEF }, + {MAP_CHAR_LEN(SC_UNONAME_CSHADD), ATTR_FONT_SHADOWED, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CSTRIKE), ATTR_FONT_CROSSEDOUT,&getCppuType((sal_Int16*)0), 0, MID_CROSS_OUT }, + {MAP_CHAR_LEN(SC_UNONAME_CUNDER), ATTR_FONT_UNDERLINE,&getCppuType((sal_Int16*)0), 0, MID_TL_STYLE }, + {MAP_CHAR_LEN(SC_UNONAME_CUNDLCOL), ATTR_FONT_UNDERLINE,&getCppuType((sal_Int32*)0), 0, MID_TL_COLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CUNDLHAS), ATTR_FONT_UNDERLINE,&getBooleanCppuType(), 0, MID_TL_HASCOLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CWEIGHT), ATTR_FONT_WEIGHT, &getCppuType((float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNO_CJK_CWEIGHT), ATTR_CJK_FONT_WEIGHT,&getCppuType((float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNO_CTL_CWEIGHT), ATTR_CTL_FONT_WEIGHT,&getCppuType((float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNONAME_CWORDMOD), ATTR_FONT_WORDLINE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CHCOLHDR), SC_WID_UNO_CHCOLHDR,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CHROWHDR), SC_WID_UNO_CHROWHDR,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CONDFMT), SC_WID_UNO_CONDFMT, &getCppuType((uno::Reference<sheet::XSheetConditionalEntries>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CONDLOC), SC_WID_UNO_CONDLOC, &getCppuType((uno::Reference<sheet::XSheetConditionalEntries>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CONDXML), SC_WID_UNO_CONDXML, &getCppuType((uno::Reference<sheet::XSheetConditionalEntries>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_DIAGONAL_BLTR), ATTR_BORDER_BLTR, &::getCppuType((const table::BorderLine*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_DIAGONAL_TLBR), ATTR_BORDER_TLBR, &::getCppuType((const table::BorderLine*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_CELLHGT), SC_WID_UNO_CELLHGT, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLHJUS), ATTR_HOR_JUSTIFY, &getCppuType((table::CellHoriJustify*)0), 0, MID_HORJUST_HORJUST }, + {MAP_CHAR_LEN(SC_UNONAME_CELLTRAN), ATTR_BACKGROUND, &getBooleanCppuType(), 0, MID_GRAPHIC_TRANSPARENT }, + {MAP_CHAR_LEN(SC_UNONAME_CELLFILT), SC_WID_UNO_CELLFILT,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_MANPAGE), SC_WID_UNO_MANPAGE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_NEWPAGE), SC_WID_UNO_NEWPAGE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_WRAP), ATTR_LINEBREAK, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLVIS), SC_WID_UNO_CELLVIS, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_LEFTBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, LEFT_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_NUMFMT), ATTR_VALUE_FORMAT, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_NUMRULES), SC_WID_UNO_NUMRULES,&getCppuType((const uno::Reference<container::XIndexReplace>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_OHEIGHT), SC_WID_UNO_OHEIGHT, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLORI), ATTR_STACKED, &getCppuType((table::CellOrientation*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PADJUST), ATTR_HOR_JUSTIFY, &::getCppuType((const sal_Int16*)0), 0, MID_HORJUST_ADJUST }, + {MAP_CHAR_LEN(SC_UNONAME_PBMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PINDENT), ATTR_INDENT, &getCppuType((sal_Int16*)0), 0, 0 }, //! CONVERT_TWIPS + {MAP_CHAR_LEN(SC_UNONAME_PISCHDIST),ATTR_SCRIPTSPACE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PISFORBID),ATTR_FORBIDDEN_RULES,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PISHANG), ATTR_HANGPUNCTUATION,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PISHYPHEN),ATTR_HYPHENATE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PLASTADJ), ATTR_HOR_JUSTIFY, &::getCppuType((const sal_Int16*)0), 0, MID_HORJUST_ADJUST }, + {MAP_CHAR_LEN(SC_UNONAME_PLMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_L_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PRMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_R_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PTMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_POS), SC_WID_UNO_POS, &getCppuType((awt::Point*)0), 0 | beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_RIGHTBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, RIGHT_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_ROTANG), ATTR_ROTATE_VALUE, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_ROTREF), ATTR_ROTATE_MODE, &getCppuType((table::CellVertJustify*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_SHADOW), ATTR_SHADOW, &getCppuType((table::ShadowFormat*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_SHRINK_TO_FIT), ATTR_SHRINKTOFIT, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_SIZE), SC_WID_UNO_SIZE, &getCppuType((awt::Size*)0), 0 | beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_TBLBORD), SC_WID_UNO_TBLBORD, &getCppuType((table::TableBorder*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_TOPBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, TOP_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_USERDEF), ATTR_USERDEF, &getCppuType((uno::Reference<container::XNameContainer>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_VALIDAT), SC_WID_UNO_VALIDAT, &getCppuType((uno::Reference<beans::XPropertySet>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_VALILOC), SC_WID_UNO_VALILOC, &getCppuType((uno::Reference<beans::XPropertySet>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_VALIXML), SC_WID_UNO_VALIXML, &getCppuType((uno::Reference<beans::XPropertySet>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLVJUS), ATTR_VER_JUSTIFY, &getCppuType((table::CellVertJustify*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_WRITING), ATTR_WRITINGDIR, &getCppuType((sal_Int16*)0), 0, 0 }, + {0,0,0,0,0,0} + }; + static SfxItemPropertySet aRowPropertySet( aRowPropertyMap_Impl ); + return &aRowPropertySet; +} + +const SfxItemPropertySet* lcl_GetSheetPropertySet() +{ + static SfxItemPropertyMapEntry aSheetPropertyMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_ABSNAME), SC_WID_UNO_ABSNAME, &getCppuType((rtl::OUString*)0), 0 | beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_ASIANVERT),ATTR_VERTICAL_ASIAN,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_AUTOPRINT),SC_WID_UNO_AUTOPRINT,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_BORDCOL), SC_WID_UNO_BORDCOL, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_BOTTBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, BOTTOM_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_CELLBACK), ATTR_BACKGROUND, &getCppuType((sal_Int32*)0), 0, MID_BACK_COLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CELLPRO), ATTR_PROTECTION, &getCppuType((util::CellProtection*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLSTYL), SC_WID_UNO_CELLSTYL,&getCppuType((rtl::OUString*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CCOLOR), ATTR_FONT_COLOR, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_COUTL), ATTR_FONT_CONTOUR, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CCROSS), ATTR_FONT_CROSSEDOUT,&getBooleanCppuType(), 0, MID_CROSSED_OUT }, + {MAP_CHAR_LEN(SC_UNONAME_CEMPHAS), ATTR_FONT_EMPHASISMARK,&getCppuType((sal_Int16*)0), 0, MID_EMPHASIS }, + {MAP_CHAR_LEN(SC_UNONAME_CFONT), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNONAME_CFCHARS), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFCHARS), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFCHARS), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNONAME_CFFAMIL), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFFAMIL), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFFAMIL), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNONAME_CFNAME), ATTR_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFNAME), ATTR_CJK_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFNAME), ATTR_CTL_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNONAME_CFPITCH), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFPITCH), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFPITCH), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNONAME_CFSTYLE), ATTR_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFSTYLE), ATTR_CJK_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFSTYLE), ATTR_CTL_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNONAME_CHEIGHT), ATTR_FONT_HEIGHT, &getCppuType((float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_CJK_CHEIGHT), ATTR_CJK_FONT_HEIGHT,&getCppuType((float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_CTL_CHEIGHT), ATTR_CTL_FONT_HEIGHT,&getCppuType((float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_CLOCAL), ATTR_FONT_LANGUAGE, &getCppuType((lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNO_CJK_CLOCAL), ATTR_CJK_FONT_LANGUAGE,&getCppuType((lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNO_CTL_CLOCAL), ATTR_CTL_FONT_LANGUAGE,&getCppuType((lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNONAME_COVER), ATTR_FONT_OVERLINE, &getCppuType((sal_Int16*)0), 0, MID_TL_STYLE }, + {MAP_CHAR_LEN(SC_UNONAME_COVRLCOL), ATTR_FONT_OVERLINE, &getCppuType((sal_Int32*)0), 0, MID_TL_COLOR }, + {MAP_CHAR_LEN(SC_UNONAME_COVRLHAS), ATTR_FONT_OVERLINE, &getBooleanCppuType(), 0, MID_TL_HASCOLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CPOST), ATTR_FONT_POSTURE, &getCppuType((awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNO_CJK_CPOST), ATTR_CJK_FONT_POSTURE,&getCppuType((awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNO_CTL_CPOST), ATTR_CTL_FONT_POSTURE,&getCppuType((awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNONAME_CRELIEF), ATTR_FONT_RELIEF, &getCppuType((sal_Int16*)0), 0, MID_RELIEF }, + {MAP_CHAR_LEN(SC_UNONAME_CSHADD), ATTR_FONT_SHADOWED, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CSTRIKE), ATTR_FONT_CROSSEDOUT,&getCppuType((sal_Int16*)0), 0, MID_CROSS_OUT }, + {MAP_CHAR_LEN(SC_UNONAME_CUNDER), ATTR_FONT_UNDERLINE,&getCppuType((sal_Int16*)0), 0, MID_TL_STYLE }, + {MAP_CHAR_LEN(SC_UNONAME_CUNDLCOL), ATTR_FONT_UNDERLINE,&getCppuType((sal_Int32*)0), 0, MID_TL_COLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CUNDLHAS), ATTR_FONT_UNDERLINE,&getBooleanCppuType(), 0, MID_TL_HASCOLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CWEIGHT), ATTR_FONT_WEIGHT, &getCppuType((float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNO_CJK_CWEIGHT), ATTR_CJK_FONT_WEIGHT,&getCppuType((float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNO_CTL_CWEIGHT), ATTR_CTL_FONT_WEIGHT,&getCppuType((float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNONAME_CWORDMOD), ATTR_FONT_WORDLINE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CHCOLHDR), SC_WID_UNO_CHCOLHDR,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CHROWHDR), SC_WID_UNO_CHROWHDR,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CONDFMT), SC_WID_UNO_CONDFMT, &getCppuType((uno::Reference<sheet::XSheetConditionalEntries>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CONDLOC), SC_WID_UNO_CONDLOC, &getCppuType((uno::Reference<sheet::XSheetConditionalEntries>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CONDXML), SC_WID_UNO_CONDXML, &getCppuType((uno::Reference<sheet::XSheetConditionalEntries>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_COPYBACK), SC_WID_UNO_COPYBACK,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_COPYFORM), SC_WID_UNO_COPYFORM,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_COPYSTYL), SC_WID_UNO_COPYSTYL,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_DIAGONAL_BLTR), ATTR_BORDER_BLTR, &::getCppuType((const table::BorderLine*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_DIAGONAL_TLBR), ATTR_BORDER_TLBR, &::getCppuType((const table::BorderLine*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_CELLHJUS), ATTR_HOR_JUSTIFY, &getCppuType((table::CellHoriJustify*)0), 0, MID_HORJUST_HORJUST }, + {MAP_CHAR_LEN(SC_UNONAME_ISACTIVE), SC_WID_UNO_ISACTIVE,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLTRAN), ATTR_BACKGROUND, &getBooleanCppuType(), 0, MID_GRAPHIC_TRANSPARENT }, + {MAP_CHAR_LEN(SC_UNONAME_WRAP), ATTR_LINEBREAK, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLVIS), SC_WID_UNO_CELLVIS, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_LEFTBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, LEFT_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_LINKDISPBIT), SC_WID_UNO_LINKDISPBIT,&getCppuType((uno::Reference<awt::XBitmap>*)0), 0 | beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNO_LINKDISPNAME), SC_WID_UNO_LINKDISPNAME,&getCppuType((rtl::OUString*)0), 0 | beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_NUMFMT), ATTR_VALUE_FORMAT, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_NUMRULES), SC_WID_UNO_NUMRULES,&getCppuType((const uno::Reference<container::XIndexReplace>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLORI), ATTR_STACKED, &getCppuType((table::CellOrientation*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PAGESTL), SC_WID_UNO_PAGESTL, &getCppuType((rtl::OUString*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PADJUST), ATTR_HOR_JUSTIFY, &::getCppuType((const sal_Int16*)0), 0, MID_HORJUST_ADJUST }, + {MAP_CHAR_LEN(SC_UNONAME_PBMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PINDENT), ATTR_INDENT, &getCppuType((sal_Int16*)0), 0, 0 }, //! CONVERT_TWIPS + {MAP_CHAR_LEN(SC_UNONAME_PISCHDIST),ATTR_SCRIPTSPACE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PISFORBID),ATTR_FORBIDDEN_RULES,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PISHANG), ATTR_HANGPUNCTUATION,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PISHYPHEN),ATTR_HYPHENATE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PLASTADJ), ATTR_HOR_JUSTIFY, &::getCppuType((const sal_Int16*)0), 0, MID_HORJUST_ADJUST }, + {MAP_CHAR_LEN(SC_UNONAME_PLMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_L_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PRMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_R_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PTMARGIN), ATTR_MARGIN, &getCppuType((sal_Int32*)0), 0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_POS), SC_WID_UNO_POS, &getCppuType((awt::Point*)0), 0 | beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PRINTBORD),SC_WID_UNO_PRINTBORD,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PROTECT), SC_WID_UNO_PROTECT, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_RIGHTBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, RIGHT_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_ROTANG), ATTR_ROTATE_VALUE, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_ROTREF), ATTR_ROTATE_MODE, &getCppuType((table::CellVertJustify*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_SHADOW), ATTR_SHADOW, &getCppuType((table::ShadowFormat*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_SHOWBORD), SC_WID_UNO_SHOWBORD,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_SHRINK_TO_FIT), ATTR_SHRINKTOFIT, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_SIZE), SC_WID_UNO_SIZE, &getCppuType((awt::Size*)0), 0 | beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_TBLBORD), SC_WID_UNO_TBLBORD, &getCppuType((table::TableBorder*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_TABLAYOUT),SC_WID_UNO_TABLAYOUT,&getCppuType((sal_Int16*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_TOPBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, TOP_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_USERDEF), ATTR_USERDEF, &getCppuType((uno::Reference<container::XNameContainer>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_VALIDAT), SC_WID_UNO_VALIDAT, &getCppuType((uno::Reference<beans::XPropertySet>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_VALILOC), SC_WID_UNO_VALILOC, &getCppuType((uno::Reference<beans::XPropertySet>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_VALIXML), SC_WID_UNO_VALIXML, &getCppuType((uno::Reference<beans::XPropertySet>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLVJUS), ATTR_VER_JUSTIFY, &getCppuType((table::CellVertJustify*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_WRITING), ATTR_WRITINGDIR, &getCppuType((sal_Int16*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_TABCOLOR), SC_WID_UNO_TABCOLOR, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_CODENAME), SC_WID_UNO_CODENAME, &getCppuType(static_cast< const rtl::OUString * >(0)), 0, 0}, + {0,0,0,0,0,0} + }; + static SfxItemPropertySet aSheetPropertySet( aSheetPropertyMap_Impl ); + return &aSheetPropertySet; +} + +const SfxItemPropertyMapEntry* lcl_GetEditPropertyMap() +{ + static SfxItemPropertyMapEntry aEditPropertyMap_Impl[] = + { + SVX_UNOEDIT_CHAR_PROPERTIES, + SVX_UNOEDIT_FONT_PROPERTIES, + SVX_UNOEDIT_PARA_PROPERTIES, + SVX_UNOEDIT_NUMBERING_PROPERTIE, // for completeness of service ParagraphProperties + {MAP_CHAR_LEN(SC_UNONAME_TEXTUSER), EE_CHAR_XMLATTRIBS, &getCppuType((const uno::Reference< container::XNameContainer >*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_USERDEF), EE_PARA_XMLATTRIBS, &getCppuType((const uno::Reference< container::XNameContainer >*)0), 0, 0}, + {0,0,0,0,0,0} + }; + return aEditPropertyMap_Impl; +} +const SvxItemPropertySet* lcl_GetEditPropertySet() +{ + static SvxItemPropertySet aEditPropertySet( lcl_GetEditPropertyMap(), SdrObject::GetGlobalDrawObjectItemPool() ); + return &aEditPropertySet; +} + + +//------------------------------------------------------------------------ + +//! diese Funktionen in einen allgemeinen Header verschieben +inline long TwipsToHMM(long nTwips) { return (nTwips * 127 + 36) / 72; } +inline long HMMToTwips(long nHMM) { return (nHMM * 72 + 63) / 127; } + +//------------------------------------------------------------------------ + +#define SCCHARPROPERTIES_SERVICE "com.sun.star.style.CharacterProperties" +#define SCPARAPROPERTIES_SERVICE "com.sun.star.style.ParagraphProperties" +#define SCCELLPROPERTIES_SERVICE "com.sun.star.table.CellProperties" +#define SCCELLRANGE_SERVICE "com.sun.star.table.CellRange" +#define SCCELL_SERVICE "com.sun.star.table.Cell" +#define SCSHEETCELLRANGES_SERVICE "com.sun.star.sheet.SheetCellRanges" +#define SCSHEETCELLRANGE_SERVICE "com.sun.star.sheet.SheetCellRange" +#define SCSPREADSHEET_SERVICE "com.sun.star.sheet.Spreadsheet" +#define SCSHEETCELL_SERVICE "com.sun.star.sheet.SheetCell" + +SC_SIMPLE_SERVICE_INFO( ScCellFormatsEnumeration, "ScCellFormatsEnumeration", "com.sun.star.sheet.CellFormatRangesEnumeration" ) +SC_SIMPLE_SERVICE_INFO( ScCellFormatsObj, "ScCellFormatsObj", "com.sun.star.sheet.CellFormatRanges" ) +SC_SIMPLE_SERVICE_INFO( ScUniqueCellFormatsEnumeration, "ScUniqueCellFormatsEnumeration", "com.sun.star.sheet.UniqueCellFormatRangesEnumeration" ) +SC_SIMPLE_SERVICE_INFO( ScUniqueCellFormatsObj, "ScUniqueCellFormatsObj", "com.sun.star.sheet.UniqueCellFormatRanges" ) +SC_SIMPLE_SERVICE_INFO( ScCellRangesBase, "ScCellRangesBase", "stardiv.unknown" ) +SC_SIMPLE_SERVICE_INFO( ScCellsEnumeration, "ScCellsEnumeration", "com.sun.star.sheet.CellsEnumeration" ) +SC_SIMPLE_SERVICE_INFO( ScCellsObj, "ScCellsObj", "com.sun.star.sheet.Cells" ) +SC_SIMPLE_SERVICE_INFO( ScTableColumnObj, "ScTableColumnObj", "com.sun.star.table.TableColumn" ) +SC_SIMPLE_SERVICE_INFO( ScTableRowObj, "ScTableRowObj", "com.sun.star.table.TableRow" ) + +//------------------------------------------------------------------------ + +SV_IMPL_PTRARR( XModifyListenerArr_Impl, XModifyListenerPtr ); +SV_IMPL_PTRARR( ScNamedEntryArr_Impl, ScNamedEntryPtr ); + +//------------------------------------------------------------------------ + +//! ScLinkListener in anderes File verschieben !!! + +ScLinkListener::~ScLinkListener() +{ +} + +void ScLinkListener::Notify( SvtBroadcaster&, const SfxHint& rHint ) +{ + aLink.Call( (SfxHint*)&rHint ); +} + +//------------------------------------------------------------------------ + +void lcl_CopyProperties( beans::XPropertySet& rDest, beans::XPropertySet& rSource ) +{ + uno::Reference<beans::XPropertySetInfo> xInfo(rSource.getPropertySetInfo()); + if (xInfo.is()) + { + uno::Sequence<beans::Property> aSeq(xInfo->getProperties()); + const beans::Property* pAry = aSeq.getConstArray(); + ULONG nCount = aSeq.getLength(); + for (ULONG i=0; i<nCount; i++) + { + rtl::OUString aName(pAry[i].Name); + rDest.setPropertyValue( aName, rSource.getPropertyValue( aName ) ); + } + } +} + +SCTAB lcl_FirstTab( const ScRangeList& rRanges ) +{ + DBG_ASSERT(rRanges.Count() >= 1, "was fuer Ranges ?!?!"); + const ScRange* pFirst = rRanges.GetObject(0); + if (pFirst) + return pFirst->aStart.Tab(); + + return 0; // soll nicht sein +} + +BOOL lcl_WholeSheet( const ScRangeList& rRanges ) +{ + if ( rRanges.Count() == 1 ) + { + ScRange* pRange = rRanges.GetObject(0); + if ( pRange && pRange->aStart.Col() == 0 && pRange->aEnd.Col() == MAXCOL && + pRange->aStart.Row() == 0 && pRange->aEnd.Row() == MAXROW ) + return TRUE; + } + return FALSE; +} + +//------------------------------------------------------------------------ + +ScSubTotalFunc lcl_SummaryToSubTotal( sheet::GeneralFunction eSummary ) +{ + ScSubTotalFunc eSubTotal; + switch (eSummary) + { + case sheet::GeneralFunction_SUM: + eSubTotal = SUBTOTAL_FUNC_SUM; + break; + case sheet::GeneralFunction_COUNT: + eSubTotal = SUBTOTAL_FUNC_CNT2; + break; + case sheet::GeneralFunction_AVERAGE: + eSubTotal = SUBTOTAL_FUNC_AVE; + break; + case sheet::GeneralFunction_MAX: + eSubTotal = SUBTOTAL_FUNC_MAX; + break; + case sheet::GeneralFunction_MIN: + eSubTotal = SUBTOTAL_FUNC_MIN; + break; + case sheet::GeneralFunction_PRODUCT: + eSubTotal = SUBTOTAL_FUNC_PROD; + break; + case sheet::GeneralFunction_COUNTNUMS: + eSubTotal = SUBTOTAL_FUNC_CNT; + break; + case sheet::GeneralFunction_STDEV: + eSubTotal = SUBTOTAL_FUNC_STD; + break; + case sheet::GeneralFunction_STDEVP: + eSubTotal = SUBTOTAL_FUNC_STDP; + break; + case sheet::GeneralFunction_VAR: + eSubTotal = SUBTOTAL_FUNC_VAR; + break; + case sheet::GeneralFunction_VARP: + eSubTotal = SUBTOTAL_FUNC_VARP; + break; + + case sheet::GeneralFunction_NONE: + case sheet::GeneralFunction_AUTO: + default: + eSubTotal = SUBTOTAL_FUNC_NONE; + break; + } + return eSubTotal; +} + +//------------------------------------------------------------------------ + +const SvxBorderLine* ScHelperFunctions::GetBorderLine( SvxBorderLine& rLine, const table::BorderLine& rStruct ) +{ + // Calc braucht Twips, im Uno-Struct sind 1/100mm + + rLine.SetOutWidth( (USHORT)HMMToTwips( rStruct.OuterLineWidth ) ); + rLine.SetInWidth( (USHORT)HMMToTwips( rStruct.InnerLineWidth ) ); + rLine.SetDistance( (USHORT)HMMToTwips( rStruct.LineDistance ) ); + rLine.SetColor( ColorData( rStruct.Color ) ); + + if ( rLine.GetOutWidth() || rLine.GetInWidth() || rLine.GetDistance() ) + return &rLine; + else + return NULL; +} + +void ScHelperFunctions::FillBoxItems( SvxBoxItem& rOuter, SvxBoxInfoItem& rInner, const table::TableBorder& rBorder ) +{ + SvxBorderLine aLine; + rOuter.SetDistance( (USHORT)HMMToTwips( rBorder.Distance ) ); + rOuter.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.TopLine ), BOX_LINE_TOP ); + rOuter.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.BottomLine ), BOX_LINE_BOTTOM ); + rOuter.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.LeftLine ), BOX_LINE_LEFT ); + rOuter.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.RightLine ), BOX_LINE_RIGHT ); + rInner.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.HorizontalLine ), BOXINFO_LINE_HORI ); + rInner.SetLine( ScHelperFunctions::GetBorderLine( aLine, rBorder.VerticalLine ), BOXINFO_LINE_VERT ); + rInner.SetValid( VALID_TOP, rBorder.IsTopLineValid ); + rInner.SetValid( VALID_BOTTOM, rBorder.IsBottomLineValid ); + rInner.SetValid( VALID_LEFT, rBorder.IsLeftLineValid ); + rInner.SetValid( VALID_RIGHT, rBorder.IsRightLineValid ); + rInner.SetValid( VALID_HORI, rBorder.IsHorizontalLineValid ); + rInner.SetValid( VALID_VERT, rBorder.IsVerticalLineValid ); + rInner.SetValid( VALID_DISTANCE, rBorder.IsDistanceValid ); + rInner.SetTable( TRUE ); +} + +void ScHelperFunctions::FillBorderLine( table::BorderLine& rStruct, const SvxBorderLine* pLine ) +{ + if (pLine) + { + rStruct.Color = pLine->GetColor().GetColor(); + rStruct.InnerLineWidth = (sal_Int16)TwipsToHMM( pLine->GetInWidth() ); + rStruct.OuterLineWidth = (sal_Int16)TwipsToHMM( pLine->GetOutWidth() ); + rStruct.LineDistance = (sal_Int16)TwipsToHMM( pLine->GetDistance() ); + } + else + rStruct.Color = rStruct.InnerLineWidth = + rStruct.OuterLineWidth = rStruct.LineDistance = 0; +} + +void ScHelperFunctions::FillTableBorder( table::TableBorder& rBorder, + const SvxBoxItem& rOuter, const SvxBoxInfoItem& rInner ) +{ + ScHelperFunctions::FillBorderLine( rBorder.TopLine, rOuter.GetTop() ); + ScHelperFunctions::FillBorderLine( rBorder.BottomLine, rOuter.GetBottom() ); + ScHelperFunctions::FillBorderLine( rBorder.LeftLine, rOuter.GetLeft() ); + ScHelperFunctions::FillBorderLine( rBorder.RightLine, rOuter.GetRight() ); + ScHelperFunctions::FillBorderLine( rBorder.HorizontalLine, rInner.GetHori() ); + ScHelperFunctions::FillBorderLine( rBorder.VerticalLine, rInner.GetVert() ); + + rBorder.Distance = rOuter.GetDistance(); + rBorder.IsTopLineValid = rInner.IsValid(VALID_TOP); + rBorder.IsBottomLineValid = rInner.IsValid(VALID_BOTTOM); + rBorder.IsLeftLineValid = rInner.IsValid(VALID_LEFT); + rBorder.IsRightLineValid = rInner.IsValid(VALID_RIGHT); + rBorder.IsHorizontalLineValid = rInner.IsValid(VALID_HORI); + rBorder.IsVerticalLineValid = rInner.IsValid(VALID_VERT); + rBorder.IsDistanceValid = rInner.IsValid(VALID_DISTANCE); +} + +//------------------------------------------------------------------------ + +//! lcl_ApplyBorder nach docfunc verschieben! + +void ScHelperFunctions::ApplyBorder( ScDocShell* pDocShell, const ScRangeList& rRanges, + const SvxBoxItem& rOuter, const SvxBoxInfoItem& rInner ) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + BOOL bUndo(pDoc->IsUndoEnabled()); + ScDocument* pUndoDoc = NULL; + if (bUndo) + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + ULONG nCount = rRanges.Count(); + ULONG i; + for (i=0; i<nCount; i++) + { + ScRange aRange(*rRanges.GetObject(i)); + SCTAB nTab = aRange.aStart.Tab(); + + if (bUndo) + { + if ( i==0 ) + pUndoDoc->InitUndo( pDoc, nTab, nTab ); + else + pUndoDoc->AddUndoTab( nTab, nTab ); + pDoc->CopyToDocument( aRange, IDF_ATTRIB, FALSE, pUndoDoc ); + } + + ScMarkData aMark; + aMark.SetMarkArea( aRange ); + aMark.SelectTable( nTab, TRUE ); + + pDoc->ApplySelectionFrame( aMark, &rOuter, &rInner ); + // RowHeight bei Umrandung alleine nicht noetig + } + + if (bUndo) + { + pDocShell->GetUndoManager()->AddUndoAction( + new ScUndoBorder( pDocShell, rRanges, pUndoDoc, rOuter, rInner ) ); + } + + for (i=0; i<nCount; i++) + pDocShell->PostPaint( *rRanges.GetObject(i), PAINT_GRID, SC_PF_LINES | SC_PF_TESTMERGE ); + + pDocShell->SetDocumentModified(); +} + +//! move lcl_PutDataArray to docfunc? +//! merge loop with ScFunctionAccess::callFunction + +BOOL lcl_PutDataArray( ScDocShell& rDocShell, const ScRange& rRange, + const uno::Sequence< uno::Sequence<uno::Any> >& aData ) +{ +// BOOL bApi = TRUE; + + ScDocument* pDoc = rDocShell.GetDocument(); + SCTAB nTab = rRange.aStart.Tab(); + SCCOL nStartCol = rRange.aStart.Col(); + SCROW nStartRow = rRange.aStart.Row(); + SCCOL nEndCol = rRange.aEnd.Col(); + SCROW nEndRow = rRange.aEnd.Row(); + BOOL bUndo(pDoc->IsUndoEnabled()); + + if ( !pDoc->IsBlockEditable( nTab, nStartCol,nStartRow, nEndCol,nEndRow ) ) + { + //! error message + return FALSE; + } + + long nCols = 0; + long nRows = aData.getLength(); + const uno::Sequence<uno::Any>* pArray = aData.getConstArray(); + if ( nRows ) + nCols = pArray[0].getLength(); + + if ( nCols != nEndCol-nStartCol+1 || nRows != nEndRow-nStartRow+1 ) + { + //! error message? + return FALSE; + } + + ScDocument* pUndoDoc = NULL; + if ( bUndo ) + { + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndo( pDoc, nTab, nTab ); + pDoc->CopyToDocument( rRange, IDF_CONTENTS|IDF_NOCAPTIONS, FALSE, pUndoDoc ); + } + + pDoc->DeleteAreaTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, IDF_CONTENTS ); + + BOOL bError = FALSE; + SCROW nDocRow = nStartRow; + for (long nRow=0; nRow<nRows; nRow++) + { + const uno::Sequence<uno::Any>& rColSeq = pArray[nRow]; + if ( rColSeq.getLength() == nCols ) + { + SCCOL nDocCol = nStartCol; + const uno::Any* pColArr = rColSeq.getConstArray(); + for (long nCol=0; nCol<nCols; nCol++) + { + const uno::Any& rElement = pColArr[nCol]; + uno::TypeClass eElemClass = rElement.getValueTypeClass(); + if ( eElemClass == uno::TypeClass_VOID ) + { + // void = "no value" + pDoc->SetError( nDocCol, nDocRow, nTab, NOTAVAILABLE ); + } + else if ( eElemClass == uno::TypeClass_BYTE || + eElemClass == uno::TypeClass_SHORT || + eElemClass == uno::TypeClass_UNSIGNED_SHORT || + eElemClass == uno::TypeClass_LONG || + eElemClass == uno::TypeClass_UNSIGNED_LONG || + eElemClass == uno::TypeClass_FLOAT || + eElemClass == uno::TypeClass_DOUBLE ) + { + // #87871# accept integer types because Basic passes a floating point + // variable as byte, short or long if it's an integer number. + double fVal(0.0); + rElement >>= fVal; + pDoc->SetValue( nDocCol, nDocRow, nTab, fVal ); + } + else if ( eElemClass == uno::TypeClass_STRING ) + { + rtl::OUString aUStr; + rElement >>= aUStr; + if ( aUStr.getLength() ) + pDoc->PutCell( nDocCol, nDocRow, nTab, new ScStringCell( aUStr ) ); + } + else + bError = TRUE; // invalid type + + ++nDocCol; + } + } + else + bError = TRUE; // wrong size + + ++nDocRow; + } + + BOOL bHeight = rDocShell.AdjustRowHeight( nStartRow, nEndRow, nTab ); + + if ( pUndoDoc ) + { + ScMarkData aDestMark; + aDestMark.SelectOneTable( nTab ); + rDocShell.GetUndoManager()->AddUndoAction( + new ScUndoPaste( &rDocShell, + nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, aDestMark, + pUndoDoc, NULL, IDF_CONTENTS, NULL,NULL,NULL,NULL, FALSE ) ); + } + + if (!bHeight) + rDocShell.PostPaint( rRange, PAINT_GRID ); // AdjustRowHeight may have painted already + + rDocShell.SetDocumentModified(); + + return !bError; +} + +BOOL lcl_PutFormulaArray( ScDocShell& rDocShell, const ScRange& rRange, + const uno::Sequence< uno::Sequence<rtl::OUString> >& aData, + const ::rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar ) +{ +// BOOL bApi = TRUE; + + ScDocument* pDoc = rDocShell.GetDocument(); + SCTAB nTab = rRange.aStart.Tab(); + SCCOL nStartCol = rRange.aStart.Col(); + SCROW nStartRow = rRange.aStart.Row(); + SCCOL nEndCol = rRange.aEnd.Col(); + SCROW nEndRow = rRange.aEnd.Row(); + BOOL bUndo(pDoc->IsUndoEnabled()); + + if ( !pDoc->IsBlockEditable( nTab, nStartCol,nStartRow, nEndCol,nEndRow ) ) + { + //! error message + return FALSE; + } + + long nCols = 0; + long nRows = aData.getLength(); + const uno::Sequence<rtl::OUString>* pArray = aData.getConstArray(); + if ( nRows ) + nCols = pArray[0].getLength(); + + if ( nCols != nEndCol-nStartCol+1 || nRows != nEndRow-nStartRow+1 ) + { + //! error message? + return FALSE; + } + + ScDocument* pUndoDoc = NULL; + if ( bUndo ) + { + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndo( pDoc, nTab, nTab ); + pDoc->CopyToDocument( rRange, IDF_CONTENTS, FALSE, pUndoDoc ); + } + + pDoc->DeleteAreaTab( nStartCol, nStartRow, nEndCol, nEndRow, nTab, IDF_CONTENTS ); + + ScDocFunc aFunc( rDocShell ); // for InterpretEnglishString + + BOOL bError = FALSE; + SCROW nDocRow = nStartRow; + for (long nRow=0; nRow<nRows; nRow++) + { + const uno::Sequence<rtl::OUString>& rColSeq = pArray[nRow]; + if ( rColSeq.getLength() == nCols ) + { + SCCOL nDocCol = nStartCol; + const rtl::OUString* pColArr = rColSeq.getConstArray(); + for (long nCol=0; nCol<nCols; nCol++) + { + String aText(pColArr[nCol]); + ScAddress aPos( nDocCol, nDocRow, nTab ); + ScBaseCell* pNewCell = aFunc.InterpretEnglishString( aPos, aText, rFormulaNmsp, eGrammar ); + pDoc->PutCell( aPos, pNewCell ); + + ++nDocCol; + } + } + else + bError = TRUE; // wrong size + + ++nDocRow; + } + + BOOL bHeight = rDocShell.AdjustRowHeight( nStartRow, nEndRow, nTab ); + + if ( pUndoDoc ) + { + ScMarkData aDestMark; + aDestMark.SelectOneTable( nTab ); + rDocShell.GetUndoManager()->AddUndoAction( + new ScUndoPaste( &rDocShell, + nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab, aDestMark, + pUndoDoc, NULL, IDF_CONTENTS, NULL,NULL,NULL,NULL, FALSE ) ); + } + + if (!bHeight) + rDocShell.PostPaint( rRange, PAINT_GRID ); // AdjustRowHeight may have painted already + + rDocShell.SetDocumentModified(); + + return !bError; +} + +// used in ScCellRangeObj::getFormulaArray and ScCellObj::GetInputString_Impl +String lcl_GetInputString( ScDocument* pDoc, const ScAddress& rPosition, BOOL bEnglish ) +{ + String aVal; + if ( pDoc ) + { + ScBaseCell* pCell = pDoc->GetCell( rPosition ); + if ( pCell && pCell->GetCellType() != CELLTYPE_NOTE ) + { + CellType eType = pCell->GetCellType(); + if ( eType == CELLTYPE_FORMULA ) + { + ScFormulaCell* pForm = (ScFormulaCell*)pCell; + pForm->GetFormula( aVal,formula::FormulaGrammar::mapAPItoGrammar( bEnglish, false)); + } + else + { + SvNumberFormatter* pFormatter = bEnglish ? ScGlobal::GetEnglishFormatter() : + pDoc->GetFormatTable(); + // Since the English formatter was constructed with + // LANGUAGE_ENGLISH_US the "General" format has index key 0, + // we don't have to query. + sal_uInt32 nNumFmt = bEnglish ? +// pFormatter->GetStandardIndex(LANGUAGE_ENGLISH_US) : + 0 : + pDoc->GetNumberFormat( rPosition ); + + if ( eType == CELLTYPE_EDIT ) + { + // GetString an der EditCell macht Leerzeichen aus Umbruechen, + // hier werden die Umbrueche aber gebraucht + const EditTextObject* pData = ((ScEditCell*)pCell)->GetData(); + if (pData) + { + EditEngine& rEngine = pDoc->GetEditEngine(); + rEngine.SetText( *pData ); + aVal = rEngine.GetText( LINEEND_LF ); + } + } + else + ScCellFormat::GetInputString( pCell, nNumFmt, aVal, *pFormatter ); + + // ggf. ein ' davorhaengen wie in ScTabViewShell::UpdateInputHandler + if ( eType == CELLTYPE_STRING || eType == CELLTYPE_EDIT ) + { + double fDummy; + sal_Bool bIsNumberFormat(pFormatter->IsNumberFormat(aVal, nNumFmt, fDummy)); + if ( bIsNumberFormat ) + aVal.Insert('\'',0); + else if ( aVal.Len() && aVal.GetChar(0) == '\'' ) + { + // if the string starts with a "'", add another one because setFormula + // strips one (like text input, except for "text" number formats) + if ( bEnglish || ( pFormatter->GetType(nNumFmt) != NUMBERFORMAT_TEXT ) ) + aVal.Insert('\'',0); + } + } + } + } + } + return aVal; +} + +//------------------------------------------------------------------------ + +// Default-ctor fuer SMART_REFLECTION Krempel +ScCellRangesBase::ScCellRangesBase() : + pPropSet(lcl_GetCellsPropertySet()), + pDocShell( NULL ), + pValueListener( NULL ), + pCurrentFlat( NULL ), + pCurrentDeep( NULL ), + pCurrentDataSet( NULL ), + pNoDfltCurrentDataSet( NULL ), + pMarkData( NULL ), + nObjectId( 0 ), + bChartColAsHdr( FALSE ), + bChartRowAsHdr( FALSE ), + bCursorOnly( FALSE ), + bGotDataChangedHint( FALSE ), + aValueListeners( 0 ) +{ +} + +ScCellRangesBase::ScCellRangesBase(ScDocShell* pDocSh, const ScRange& rR) : + pPropSet(lcl_GetCellsPropertySet()), + pDocShell( pDocSh ), + pValueListener( NULL ), + pCurrentFlat( NULL ), + pCurrentDeep( NULL ), + pCurrentDataSet( NULL ), + pNoDfltCurrentDataSet( NULL ), + pMarkData( NULL ), + nObjectId( 0 ), + bChartColAsHdr( FALSE ), + bChartRowAsHdr( FALSE ), + bCursorOnly( FALSE ), + bGotDataChangedHint( FALSE ), + aValueListeners( 0 ) +{ + ScRange aCellRange(rR); + aCellRange.Justify(); + aRanges.Append( aCellRange ); + + if (pDocShell) // Null if created with createInstance + { + ScDocument* pDoc = pDocShell->GetDocument(); + pDoc->AddUnoObject(*this); + nObjectId = pDoc->GetNewUnoId(); + } +} + +ScCellRangesBase::ScCellRangesBase(ScDocShell* pDocSh, const ScRangeList& rR) : + pPropSet(lcl_GetCellsPropertySet()), + pDocShell( pDocSh ), + pValueListener( NULL ), + pCurrentFlat( NULL ), + pCurrentDeep( NULL ), + pCurrentDataSet( NULL ), + pNoDfltCurrentDataSet( NULL ), + pMarkData( NULL ), + aRanges( rR ), + nObjectId( 0 ), + bChartColAsHdr( FALSE ), + bChartRowAsHdr( FALSE ), + bCursorOnly( FALSE ), + bGotDataChangedHint( FALSE ), + aValueListeners( 0 ) +{ + if (pDocShell) // Null if created with createInstance + { + ScDocument* pDoc = pDocShell->GetDocument(); + pDoc->AddUnoObject(*this); + nObjectId = pDoc->GetNewUnoId(); + } +} + +ScCellRangesBase::~ScCellRangesBase() +{ + // #107294# call RemoveUnoObject first, so no notification can happen + // during ForgetCurrentAttrs + + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); + + ForgetCurrentAttrs(); + ForgetMarkData(); + + delete pValueListener; + + //! XChartDataChangeEventListener abmelden ?? + //! (ChartCollection haelt dann auch dieses Objekt fest!) +} + +void ScCellRangesBase::ForgetCurrentAttrs() +{ + delete pCurrentFlat; + delete pCurrentDeep; + delete pCurrentDataSet; + delete pNoDfltCurrentDataSet; + pCurrentFlat = NULL; + pCurrentDeep = NULL; + pCurrentDataSet = NULL; + pNoDfltCurrentDataSet = NULL; + + // #i62483# pMarkData can remain unchanged, is deleted only if the range changes (RefChanged) +} + +void ScCellRangesBase::ForgetMarkData() +{ + delete pMarkData; + pMarkData = NULL; +} + +const ScPatternAttr* ScCellRangesBase::GetCurrentAttrsFlat() +{ + // get and cache direct cell attributes for this object's range + + if ( !pCurrentFlat && pDocShell ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + pCurrentFlat = pDoc->CreateSelectionPattern( *GetMarkData(), FALSE ); + } + return pCurrentFlat; +} + +const ScPatternAttr* ScCellRangesBase::GetCurrentAttrsDeep() +{ + // get and cache cell attributes (incl. styles) for this object's range + + if ( !pCurrentDeep && pDocShell ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + pCurrentDeep = pDoc->CreateSelectionPattern( *GetMarkData(), TRUE ); + } + return pCurrentDeep; +} + +SfxItemSet* ScCellRangesBase::GetCurrentDataSet(bool bNoDflt) +{ + if(!pCurrentDataSet) + { + const ScPatternAttr* pPattern = GetCurrentAttrsDeep(); + if ( pPattern ) + { + // Dontcare durch Default ersetzen, damit man immer eine Reflection hat + pCurrentDataSet = new SfxItemSet( pPattern->GetItemSet() ); + pNoDfltCurrentDataSet = new SfxItemSet( pPattern->GetItemSet() ); + pCurrentDataSet->ClearInvalidItems(); + } + } + return bNoDflt ? pNoDfltCurrentDataSet : pCurrentDataSet; +} + +const ScMarkData* ScCellRangesBase::GetMarkData() +{ + if (!pMarkData) + { + pMarkData = new ScMarkData(); + pMarkData->MarkFromRangeList( aRanges, FALSE ); + } + return pMarkData; +} + +void ScCellRangesBase::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( ScUpdateRefHint ) ) + { + const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint; + + ScDocument* pDoc = pDocShell->GetDocument(); + ScRangeList* pUndoRanges = NULL; + if ( pDoc->HasUnoRefUndo() ) + pUndoRanges = new ScRangeList( aRanges ); + + if ( aRanges.UpdateReference( rRef.GetMode(), pDoc, rRef.GetRange(), + rRef.GetDx(), rRef.GetDy(), rRef.GetDz() ) ) + { + if (rRef.GetMode() == URM_INSDEL && + aRanges.Count() == 1 && + ScTableSheetObj::getImplementation( (cppu::OWeakObject*)this )) + { + // #101755#; the range size of a sheet does not change + ScRange* pR = aRanges.First(); + if (pR) + { + pR->aStart.SetCol(0); + pR->aStart.SetRow(0); + pR->aEnd.SetCol(MAXCOL); + pR->aEnd.SetRow(MAXROW); + } + } + RefChanged(); + + // #129050# any change of the range address is broadcast to value (modify) listeners + if ( aValueListeners.Count() ) + bGotDataChangedHint = TRUE; + + if ( pUndoRanges ) + pDoc->AddUnoRefChange( nObjectId, *pUndoRanges ); + } + + delete pUndoRanges; + } + else if ( rHint.ISA( SfxSimpleHint ) ) + { + ULONG nId = ((const SfxSimpleHint&)rHint).GetId(); + if ( nId == SFX_HINT_DYING ) + { + ForgetCurrentAttrs(); + pDocShell = NULL; // invalid + + if ( aValueListeners.Count() != 0 ) + { + // dispose listeners + + lang::EventObject aEvent; + aEvent.Source.set(static_cast<cppu::OWeakObject*>(this)); + for ( USHORT n=0; n<aValueListeners.Count(); n++ ) + (*aValueListeners[n])->disposing( aEvent ); + + aValueListeners.DeleteAndDestroy( 0, aValueListeners.Count() ); + + // The listeners can't have the last ref to this, as it's still held + // by the DocShell. + } + } + else if ( nId == SFX_HINT_DATACHANGED ) + { + // document content changed -> forget cached attributes + ForgetCurrentAttrs(); + + if ( bGotDataChangedHint && pDocShell ) + { + // This object was notified of content changes, so one call + // for each listener is generated now. + // The calls can't be executed directly because the document's + // UNO broadcaster list must not be modified. + // Instead, add to the document's list of listener calls, + // which will be executed directly after the broadcast of + // SFX_HINT_DATACHANGED. + + lang::EventObject aEvent; + aEvent.Source.set((cppu::OWeakObject*)this); + + // the EventObject holds a Ref to this object until after the listener calls + + ScDocument* pDoc = pDocShell->GetDocument(); + for ( USHORT n=0; n<aValueListeners.Count(); n++ ) + pDoc->AddUnoListenerCall( *aValueListeners[n], aEvent ); + + bGotDataChangedHint = FALSE; + } + } + else if ( nId == SC_HINT_CALCALL ) + { + // broadcast from DoHardRecalc - set bGotDataChangedHint + // (SFX_HINT_DATACHANGED follows separately) + + if ( aValueListeners.Count() ) + bGotDataChangedHint = TRUE; + } + } + else if ( rHint.ISA( ScUnoRefUndoHint ) ) + { + const ScUnoRefUndoHint& rUndoHint = static_cast<const ScUnoRefUndoHint&>(rHint); + if ( rUndoHint.GetObjectId() == nObjectId ) + { + // restore ranges from hint + + aRanges = rUndoHint.GetRanges(); + + RefChanged(); + if ( aValueListeners.Count() ) + bGotDataChangedHint = TRUE; // need to broadcast the undo, too + } + } +} + +void ScCellRangesBase::RefChanged() +{ + //! adjust XChartDataChangeEventListener + + if ( pValueListener && aValueListeners.Count() != 0 ) + { + pValueListener->EndListeningAll(); + + ScDocument* pDoc = pDocShell->GetDocument(); + ULONG nCount = aRanges.Count(); + for (ULONG i=0; i<nCount; i++) + pDoc->StartListeningArea( *aRanges.GetObject(i), pValueListener ); + } + + ForgetCurrentAttrs(); + ForgetMarkData(); +} + +ScDocument* ScCellRangesBase::GetDocument() const +{ + if (pDocShell) + return pDocShell->GetDocument(); + else + return NULL; +} + +void ScCellRangesBase::InitInsertRange(ScDocShell* pDocSh, const ScRange& rR) +{ + if ( !pDocShell && pDocSh ) + { + pDocShell = pDocSh; + + ScRange aCellRange(rR); + aCellRange.Justify(); + aRanges.RemoveAll(); + aRanges.Append( aCellRange ); + + pDocShell->GetDocument()->AddUnoObject(*this); + + RefChanged(); // Range im Range-Objekt anpassen + } +} + +void ScCellRangesBase::AddRange(const ScRange& rRange, const sal_Bool bMergeRanges) +{ + if (bMergeRanges) + aRanges.Join(rRange); + else + aRanges.Append(rRange); + RefChanged(); +} + +void ScCellRangesBase::SetNewRange(const ScRange& rNew) +{ + ScRange aCellRange(rNew); + aCellRange.Justify(); + + aRanges.RemoveAll(); + aRanges.Append( aCellRange ); + RefChanged(); +} + +void ScCellRangesBase::SetNewRanges(const ScRangeList& rNew) +{ + aRanges = rNew; + RefChanged(); +} + +void ScCellRangesBase::SetCursorOnly( BOOL bSet ) +{ + // set for a selection object that is created from the cursor position + // without anything selected (may contain several sheets) + + bCursorOnly = bSet; +} + +uno::Any SAL_CALL ScCellRangesBase::queryInterface( const uno::Type& rType ) + throw(uno::RuntimeException) +{ + SC_QUERYINTERFACE( beans::XPropertySet ) + SC_QUERYINTERFACE( beans::XMultiPropertySet ) + SC_QUERYINTERFACE( beans::XTolerantMultiPropertySet ) + SC_QUERYINTERFACE( beans::XPropertyState ) + SC_QUERYINTERFACE( sheet::XSheetOperation ) + SC_QUERYINTERFACE( chart::XChartDataArray ) + SC_QUERYINTERFACE( chart::XChartData ) + SC_QUERYINTERFACE( util::XIndent ) + SC_QUERYINTERFACE( sheet::XCellRangesQuery ) + SC_QUERYINTERFACE( sheet::XFormulaQuery ) + SC_QUERYINTERFACE( util::XReplaceable ) + SC_QUERYINTERFACE( util::XSearchable ) + SC_QUERYINTERFACE( util::XModifyBroadcaster ) + SC_QUERYINTERFACE( lang::XServiceInfo ) + SC_QUERYINTERFACE( lang::XUnoTunnel ) + SC_QUERYINTERFACE( lang::XTypeProvider ) + + return OWeakObject::queryInterface( rType ); +} + +void SAL_CALL ScCellRangesBase::acquire() throw() +{ + OWeakObject::acquire(); +} + +void SAL_CALL ScCellRangesBase::release() throw() +{ + OWeakObject::release(); +} + +uno::Sequence<uno::Type> SAL_CALL ScCellRangesBase::getTypes() throw(uno::RuntimeException) +{ + static uno::Sequence<uno::Type> aTypes; + if ( aTypes.getLength() == 0 ) + { + aTypes.realloc(13); + uno::Type* pPtr = aTypes.getArray(); + pPtr[0] = getCppuType((const uno::Reference<beans::XPropertySet>*)0); + pPtr[1] = getCppuType((const uno::Reference<beans::XMultiPropertySet>*)0); + pPtr[2] = getCppuType((const uno::Reference<beans::XPropertyState>*)0); + pPtr[3] = getCppuType((const uno::Reference<sheet::XSheetOperation>*)0); + pPtr[4] = getCppuType((const uno::Reference<chart::XChartDataArray>*)0); + pPtr[5] = getCppuType((const uno::Reference<util::XIndent>*)0); + pPtr[6] = getCppuType((const uno::Reference<sheet::XCellRangesQuery>*)0); + pPtr[7] = getCppuType((const uno::Reference<sheet::XFormulaQuery>*)0); + pPtr[8] = getCppuType((const uno::Reference<util::XReplaceable>*)0); + pPtr[9] = getCppuType((const uno::Reference<util::XModifyBroadcaster>*)0); + pPtr[10]= getCppuType((const uno::Reference<lang::XServiceInfo>*)0); + pPtr[11]= getCppuType((const uno::Reference<lang::XUnoTunnel>*)0); + pPtr[12]= getCppuType((const uno::Reference<lang::XTypeProvider>*)0); + } + return aTypes; +} + +uno::Sequence<sal_Int8> SAL_CALL ScCellRangesBase::getImplementationId() + throw(uno::RuntimeException) +{ + static uno::Sequence< sal_Int8 > aId; + if( aId.getLength() == 0 ) + { + aId.realloc( 16 ); + rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True ); + } + return aId; +} + +// --- + +void ScCellRangesBase::PaintRanges_Impl( USHORT nPart ) +{ + ULONG nCount = aRanges.Count(); + for (ULONG i=0; i<nCount; i++) + pDocShell->PostPaint( *aRanges.GetObject(i), nPart ); +} + +// XSheetOperation + +double SAL_CALL ScCellRangesBase::computeFunction( sheet::GeneralFunction nFunction ) + throw(uno::Exception, uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScMarkData aMark(*GetMarkData()); + aMark.MarkToSimple(); + if (!aMark.IsMarked()) + aMark.SetMarkNegative(TRUE); // um Dummy Position angeben zu koennen + + ScAddress aDummy; // wenn nicht Marked, ignoriert wegen Negative + double fVal; + ScSubTotalFunc eFunc = lcl_SummaryToSubTotal( nFunction ); + ScDocument* pDoc = pDocShell->GetDocument(); + if ( !pDoc->GetSelectionFunction( eFunc, aDummy, aMark, fVal ) ) + { + throw uno::RuntimeException(); //! own exception? + } + + return fVal; +} + +void SAL_CALL ScCellRangesBase::clearContents( sal_Int32 nContentFlags ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( aRanges.Count() ) + { + // only for clearContents: EDITATTR is only used if no contents are deleted + USHORT nDelFlags = static_cast< USHORT >( nContentFlags & IDF_ALL ); + if ( ( nContentFlags & IDF_EDITATTR ) && ( nContentFlags & IDF_CONTENTS ) == 0 ) + nDelFlags |= IDF_EDITATTR; + + ScDocFunc aFunc(*pDocShell); + aFunc.DeleteContents( *GetMarkData(), nDelFlags, TRUE, TRUE ); + } + // sonst ist nichts zu tun +} + +// XPropertyState + +const SfxItemPropertyMap* ScCellRangesBase::GetItemPropertyMap() +{ + return pPropSet->getPropertyMap(); +} + +void lcl_GetPropertyWhich( const SfxItemPropertySimpleEntry* pEntry, + USHORT& rItemWhich ) +{ + // Which-ID des betroffenen Items, auch wenn das Item die Property + // nicht alleine behandeln kann + if ( pEntry ) + { + if ( IsScItemWid( pEntry->nWID ) ) + rItemWhich = pEntry->nWID; + else + switch ( pEntry->nWID ) + { + case SC_WID_UNO_TBLBORD: + rItemWhich = ATTR_BORDER; + break; + case SC_WID_UNO_CONDFMT: + case SC_WID_UNO_CONDLOC: + case SC_WID_UNO_CONDXML: + rItemWhich = ATTR_CONDITIONAL; + break; + case SC_WID_UNO_VALIDAT: + case SC_WID_UNO_VALILOC: + case SC_WID_UNO_VALIXML: + rItemWhich = ATTR_VALIDDATA; + break; + } + } + +} + +beans::PropertyState ScCellRangesBase::GetOnePropertyState( USHORT nItemWhich, const SfxItemPropertySimpleEntry* pEntry ) +{ + beans::PropertyState eRet = beans::PropertyState_DIRECT_VALUE; + if ( nItemWhich ) // item wid (from map or special case) + { + // For items that contain several properties (like background), + // "ambiguous" is returned too often here + + // for PropertyState, don't look at styles + const ScPatternAttr* pPattern = GetCurrentAttrsFlat(); + if ( pPattern ) + { + SfxItemState eState = pPattern->GetItemSet().GetItemState( nItemWhich, FALSE ); + +// // if no rotate value is set, look at orientation +// //! also for a fixed value of 0 (in case orientation is ambiguous)? +// if ( nItemWhich == ATTR_ROTATE_VALUE && eState == SFX_ITEM_DEFAULT ) +// eState = pPattern->GetItemSet().GetItemState( ATTR_ORIENTATION, FALSE ); + + if ( nItemWhich == ATTR_VALUE_FORMAT && eState == SFX_ITEM_DEFAULT ) + eState = pPattern->GetItemSet().GetItemState( ATTR_LANGUAGE_FORMAT, FALSE ); + + if ( eState == SFX_ITEM_SET ) + eRet = beans::PropertyState_DIRECT_VALUE; + else if ( eState == SFX_ITEM_DEFAULT ) + eRet = beans::PropertyState_DEFAULT_VALUE; + else if ( eState == SFX_ITEM_DONTCARE ) + eRet = beans::PropertyState_AMBIGUOUS_VALUE; + else + { + DBG_ERROR("unbekannter ItemState"); + } + } + } + else if ( pEntry ) + { + if ( pEntry->nWID == SC_WID_UNO_CHCOLHDR || pEntry->nWID == SC_WID_UNO_CHROWHDR || pEntry->nWID == SC_WID_UNO_ABSNAME ) + eRet = beans::PropertyState_DIRECT_VALUE; + else if ( pEntry->nWID == SC_WID_UNO_CELLSTYL ) + { + // a style is always set, there's no default state + const ScStyleSheet* pStyle = pDocShell->GetDocument()->GetSelectionStyle(*GetMarkData()); + if (pStyle) + eRet = beans::PropertyState_DIRECT_VALUE; + else + eRet = beans::PropertyState_AMBIGUOUS_VALUE; + } + else if ( pEntry->nWID == SC_WID_UNO_NUMRULES ) + eRet = beans::PropertyState_DEFAULT_VALUE; // numbering rules are always default + } + return eRet; +} + +beans::PropertyState SAL_CALL ScCellRangesBase::getPropertyState( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( aRanges.Count() == 0 ) + throw uno::RuntimeException(); + + const SfxItemPropertyMap* pMap = GetItemPropertyMap(); // from derived class + USHORT nItemWhich = 0; + const SfxItemPropertySimpleEntry* pEntry = pMap->getByName( aPropertyName ); + lcl_GetPropertyWhich( pEntry, nItemWhich ); + return GetOnePropertyState( nItemWhich, pEntry ); +} + +uno::Sequence<beans::PropertyState> SAL_CALL ScCellRangesBase::getPropertyStates( + const uno::Sequence<rtl::OUString>& aPropertyNames ) + throw(beans::UnknownPropertyException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + const SfxItemPropertyMap* pPropertyMap = GetItemPropertyMap(); // from derived class + + uno::Sequence<beans::PropertyState> aRet(aPropertyNames.getLength()); + beans::PropertyState* pStates = aRet.getArray(); + for(INT32 i = 0; i < aPropertyNames.getLength(); i++) + { + USHORT nItemWhich = 0; + const SfxItemPropertySimpleEntry* pEntry = pPropertyMap->getByName( aPropertyNames[i] ); + lcl_GetPropertyWhich( pEntry, nItemWhich ); + pStates[i] = GetOnePropertyState(nItemWhich, pEntry); + } + return aRet; +} + +void SAL_CALL ScCellRangesBase::setPropertyToDefault( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( pDocShell ) + { + const SfxItemPropertyMap* pPropertyMap = GetItemPropertyMap(); // from derived class + USHORT nItemWhich = 0; + const SfxItemPropertySimpleEntry* pEntry = pPropertyMap->getByName( aPropertyName ); + lcl_GetPropertyWhich( pEntry, nItemWhich ); + if ( nItemWhich ) // item wid (from map or special case) + { + if ( aRanges.Count() ) // leer = nichts zu tun + { + ScDocFunc aFunc(*pDocShell); + + //! Bei Items, die mehrere Properties enthalten (z.B. Hintergrund) + //! wird hier zuviel zurueckgesetzt + +// //! for ATTR_ROTATE_VALUE, also reset ATTR_ORIENTATION? + + USHORT aWIDs[3]; + aWIDs[0] = nItemWhich; + if ( nItemWhich == ATTR_VALUE_FORMAT ) + { + aWIDs[1] = ATTR_LANGUAGE_FORMAT; // #67847# language for number formats + aWIDs[2] = 0; + } + else + aWIDs[1] = 0; + aFunc.ClearItems( *GetMarkData(), aWIDs, TRUE ); + } + } + else if ( pEntry ) + { + if ( pEntry->nWID == SC_WID_UNO_CHCOLHDR ) + bChartColAsHdr = FALSE; + else if ( pEntry->nWID == SC_WID_UNO_CHROWHDR ) + bChartRowAsHdr = FALSE; + else if ( pEntry->nWID == SC_WID_UNO_CELLSTYL ) + { + ScDocFunc aFunc(*pDocShell); + aFunc.ApplyStyle( *GetMarkData(), ScGlobal::GetRscString(STR_STYLENAME_STANDARD), TRUE, TRUE ); + } + } + } +} + +uno::Any SAL_CALL ScCellRangesBase::getPropertyDefault( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + //! mit getPropertyValue zusammenfassen + + ScUnoGuard aGuard; + uno::Any aAny; + + if ( pDocShell ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + const SfxItemPropertyMap* pPropertyMap = GetItemPropertyMap(); // from derived class + const SfxItemPropertySimpleEntry* pEntry = pPropertyMap->getByName( aPropertyName ); + if ( pEntry ) + { + if ( IsScItemWid( pEntry->nWID ) ) + { + const ScPatternAttr* pPattern = pDoc->GetDefPattern(); + if ( pPattern ) + { + const SfxItemSet& rSet = pPattern->GetItemSet(); + + switch ( pEntry->nWID ) // fuer Item-Spezial-Behandlungen + { + case ATTR_VALUE_FORMAT: + // default has no language set + aAny <<= (sal_Int32)( ((const SfxUInt32Item&)rSet.Get(pEntry->nWID)).GetValue() ); + break; + case ATTR_INDENT: + aAny <<= (sal_Int16)( TwipsToHMM(((const SfxUInt16Item&) + rSet.Get(pEntry->nWID)).GetValue()) ); + break; + default: + pPropSet->getPropertyValue(aPropertyName, rSet, aAny); + } + } + } + else + switch ( pEntry->nWID ) + { + case SC_WID_UNO_CHCOLHDR: + case SC_WID_UNO_CHROWHDR: + ScUnoHelpFunctions::SetBoolInAny( aAny, FALSE ); + break; + case SC_WID_UNO_CELLSTYL: + aAny <<= rtl::OUString( ScStyleNameConversion::DisplayToProgrammaticName( + ScGlobal::GetRscString(STR_STYLENAME_STANDARD), SFX_STYLE_FAMILY_PARA ) ); + break; + case SC_WID_UNO_TBLBORD: + { + const ScPatternAttr* pPattern = pDoc->GetDefPattern(); + if ( pPattern ) + { + table::TableBorder aBorder; + ScHelperFunctions::FillTableBorder( aBorder, + (const SvxBoxItem&)pPattern->GetItem(ATTR_BORDER), + (const SvxBoxInfoItem&)pPattern->GetItem(ATTR_BORDER_INNER) ); + aAny <<= aBorder; + } + } + break; + case SC_WID_UNO_CONDFMT: + case SC_WID_UNO_CONDLOC: + case SC_WID_UNO_CONDXML: + { + BOOL bEnglish = ( pEntry->nWID != SC_WID_UNO_CONDLOC ); + BOOL bXML = ( pEntry->nWID == SC_WID_UNO_CONDXML ); + formula::FormulaGrammar::Grammar eGrammar = (bXML ? + pDoc->GetStorageGrammar() : + formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML)); + + aAny <<= uno::Reference<sheet::XSheetConditionalEntries>( + new ScTableConditionalFormat( pDoc, 0, eGrammar )); + } + break; + case SC_WID_UNO_VALIDAT: + case SC_WID_UNO_VALILOC: + case SC_WID_UNO_VALIXML: + { + BOOL bEnglish = ( pEntry->nWID != SC_WID_UNO_VALILOC ); + BOOL bXML = ( pEntry->nWID == SC_WID_UNO_VALIXML ); + formula::FormulaGrammar::Grammar eGrammar = (bXML ? + pDoc->GetStorageGrammar() : + formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML)); + + aAny <<= uno::Reference<beans::XPropertySet>( + new ScTableValidationObj( pDoc, 0, eGrammar )); + } + break; + case SC_WID_UNO_NUMRULES: + { + aAny <<= uno::Reference<container::XIndexReplace>(ScStyleObj::CreateEmptyNumberingRules()); + } + break; + } + } + } + + return aAny; +} + +// XPropertySet + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScCellRangesBase::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef( + new SfxItemPropertySetInfo( pPropSet->getPropertyMap() )); + return aRef; +} + + +void lcl_SetCellProperty( const SfxItemPropertySimpleEntry& rEntry, const uno::Any& rValue, + ScPatternAttr& rPattern, ScDocument* pDoc, + USHORT& rFirstItemId, USHORT& rSecondItemId ) +{ + rFirstItemId = rEntry.nWID; + rSecondItemId = 0; + + SfxItemSet& rSet = rPattern.GetItemSet(); + switch ( rEntry.nWID ) + { + case ATTR_VALUE_FORMAT: + { + // #67847# language for number formats + SvNumberFormatter* pFormatter = pDoc->GetFormatTable(); + ULONG nOldFormat = ((const SfxUInt32Item&)rSet.Get( ATTR_VALUE_FORMAT )).GetValue(); + LanguageType eOldLang = ((const SvxLanguageItem&)rSet.Get( ATTR_LANGUAGE_FORMAT )).GetLanguage(); + nOldFormat = pFormatter->GetFormatForLanguageIfBuiltIn( nOldFormat, eOldLang ); + + sal_Int32 nIntVal = 0; + if ( rValue >>= nIntVal ) + { + ULONG nNewFormat = (ULONG)nIntVal; + rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) ); + + const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewFormat ); + LanguageType eNewLang = + pNewEntry ? pNewEntry->GetLanguage() : LANGUAGE_DONTKNOW; + if ( eNewLang != eOldLang && eNewLang != LANGUAGE_DONTKNOW ) + { + rSet.Put( SvxLanguageItem( eNewLang, ATTR_LANGUAGE_FORMAT ) ); + + // #40606# if only language is changed, + // don't touch number format attribute + ULONG nNewMod = nNewFormat % SV_COUNTRY_LANGUAGE_OFFSET; + if ( nNewMod == ( nOldFormat % SV_COUNTRY_LANGUAGE_OFFSET ) && + nNewMod <= SV_MAX_ANZ_STANDARD_FORMATE ) + { + rFirstItemId = 0; // don't use ATTR_VALUE_FORMAT value + } + + rSecondItemId = ATTR_LANGUAGE_FORMAT; + } + } + else + throw lang::IllegalArgumentException(); + } + break; + case ATTR_INDENT: + { + sal_Int16 nIntVal = 0; + if ( rValue >>= nIntVal ) + rSet.Put( SfxUInt16Item( rEntry.nWID, (USHORT)HMMToTwips(nIntVal) ) ); + else + throw lang::IllegalArgumentException(); + } + break; + case ATTR_ROTATE_VALUE: + { + sal_Int32 nRotVal = 0; + if ( rValue >>= nRotVal ) + { + // stored value is always between 0 and 360 deg. + nRotVal %= 36000; + if ( nRotVal < 0 ) + nRotVal += 36000; + + rSet.Put( SfxInt32Item( ATTR_ROTATE_VALUE, nRotVal ) ); + } + else + throw lang::IllegalArgumentException(); + } + break; + case ATTR_STACKED: + { + table::CellOrientation eOrient; + if( rValue >>= eOrient ) + { + switch( eOrient ) + { + case table::CellOrientation_STANDARD: + rSet.Put( SfxBoolItem( ATTR_STACKED, FALSE ) ); + break; + case table::CellOrientation_TOPBOTTOM: + rSet.Put( SfxBoolItem( ATTR_STACKED, FALSE ) ); + rSet.Put( SfxInt32Item( ATTR_ROTATE_VALUE, 27000 ) ); + rSecondItemId = ATTR_ROTATE_VALUE; + break; + case table::CellOrientation_BOTTOMTOP: + rSet.Put( SfxBoolItem( ATTR_STACKED, FALSE ) ); + rSet.Put( SfxInt32Item( ATTR_ROTATE_VALUE, 9000 ) ); + rSecondItemId = ATTR_ROTATE_VALUE; + break; + case table::CellOrientation_STACKED: + rSet.Put( SfxBoolItem( ATTR_STACKED, TRUE ) ); + break; + default: + { + // added to avoid warnings + } + } + } + } + break; + default: + { + lcl_GetCellsPropertySet()->setPropertyValue(rEntry, rValue, rSet); + } + } +} + +void SAL_CALL ScCellRangesBase::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if ( !pDocShell || aRanges.Count() == 0 ) + throw uno::RuntimeException(); + + const SfxItemPropertyMap* pPropertyMap = GetItemPropertyMap(); // from derived class + const SfxItemPropertySimpleEntry* pEntry = pPropertyMap->getByName( aPropertyName ); + if ( !pEntry ) + throw beans::UnknownPropertyException(); + + SetOnePropertyValue( pEntry, aValue ); +} + +void ScCellRangesBase::SetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntry, const uno::Any& aValue ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + if ( pEntry ) + { + if ( IsScItemWid( pEntry->nWID ) ) + { + if ( aRanges.Count() ) // leer = nichts zu tun + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScDocFunc aFunc(*pDocShell); + + // Fuer Teile von zusammengesetzten Items mit mehreren Properties (z.B. Hintergrund) + // muss vorher das alte Item aus dem Dokument geholt werden + //! Das kann hier aber nicht erkannt werden + //! -> eigenes Flag im PropertyMap-Eintrag, oder was ??? + //! Item direkt von einzelner Position im Bereich holen? + // ClearInvalidItems, damit auf jeden Fall ein Item vom richtigen Typ da ist + + ScPatternAttr aPattern( *GetCurrentAttrsDeep() ); + SfxItemSet& rSet = aPattern.GetItemSet(); + rSet.ClearInvalidItems(); + + USHORT nFirstItem, nSecondItem; + lcl_SetCellProperty( *pEntry, aValue, aPattern, pDoc, nFirstItem, nSecondItem ); + + for (USHORT nWhich = ATTR_PATTERN_START; nWhich <= ATTR_PATTERN_END; nWhich++) + if ( nWhich != nFirstItem && nWhich != nSecondItem ) + rSet.ClearItem(nWhich); + + aFunc.ApplyAttributes( *GetMarkData(), aPattern, TRUE, TRUE ); + } + } + else // implemented here + switch ( pEntry->nWID ) + { + case SC_WID_UNO_CHCOLHDR: + // chart header flags are set for this object, not stored with document + bChartColAsHdr = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + break; + case SC_WID_UNO_CHROWHDR: + bChartRowAsHdr = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + break; + case SC_WID_UNO_CELLSTYL: + { + rtl::OUString aStrVal; + aValue >>= aStrVal; + String aString(ScStyleNameConversion::ProgrammaticToDisplayName( + aStrVal, SFX_STYLE_FAMILY_PARA )); + ScDocFunc aFunc(*pDocShell); + aFunc.ApplyStyle( *GetMarkData(), aString, TRUE, TRUE ); + } + break; + case SC_WID_UNO_TBLBORD: + { + table::TableBorder aBorder; + if ( aRanges.Count() && ( aValue >>= aBorder ) ) // empty = nothing to do + { + SvxBoxItem aOuter(ATTR_BORDER); + SvxBoxInfoItem aInner(ATTR_BORDER_INNER); + ScHelperFunctions::FillBoxItems( aOuter, aInner, aBorder ); + + ScHelperFunctions::ApplyBorder( pDocShell, aRanges, aOuter, aInner ); //! docfunc + } + } + break; + case SC_WID_UNO_CONDFMT: + case SC_WID_UNO_CONDLOC: + case SC_WID_UNO_CONDXML: + { + uno::Reference<sheet::XSheetConditionalEntries> xInterface(aValue, uno::UNO_QUERY); + if ( aRanges.Count() && xInterface.is() ) // leer = nichts zu tun + { + ScTableConditionalFormat* pFormat = + ScTableConditionalFormat::getImplementation( xInterface ); + if (pFormat) + { + ScDocument* pDoc = pDocShell->GetDocument(); + BOOL bEnglish = ( pEntry->nWID != SC_WID_UNO_CONDLOC ); + BOOL bXML = ( pEntry->nWID == SC_WID_UNO_CONDXML ); + formula::FormulaGrammar::Grammar eGrammar = (bXML ? + formula::FormulaGrammar::GRAM_UNSPECIFIED : + formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML)); + + ScConditionalFormat aNew( 0, pDoc ); // Index wird beim Einfuegen gesetzt + pFormat->FillFormat( aNew, pDoc, eGrammar ); + ULONG nIndex = pDoc->AddCondFormat( aNew ); + + ScDocFunc aFunc(*pDocShell); + + ScPatternAttr aPattern( pDoc->GetPool() ); + aPattern.GetItemSet().Put( SfxUInt32Item( ATTR_CONDITIONAL, nIndex ) ); + aFunc.ApplyAttributes( *GetMarkData(), aPattern, TRUE, TRUE ); + } + } + } + break; + case SC_WID_UNO_VALIDAT: + case SC_WID_UNO_VALILOC: + case SC_WID_UNO_VALIXML: + { + uno::Reference<beans::XPropertySet> xInterface(aValue, uno::UNO_QUERY); + if ( aRanges.Count() && xInterface.is() ) // leer = nichts zu tun + { + ScTableValidationObj* pValidObj = + ScTableValidationObj::getImplementation( xInterface ); + if (pValidObj) + { + ScDocument* pDoc = pDocShell->GetDocument(); + BOOL bEnglish = ( pEntry->nWID != SC_WID_UNO_VALILOC ); + BOOL bXML = ( pEntry->nWID == SC_WID_UNO_VALIXML ); + formula::FormulaGrammar::Grammar eGrammar = (bXML ? + formula::FormulaGrammar::GRAM_UNSPECIFIED : + formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML)); + + ScValidationData* pNewData = + pValidObj->CreateValidationData( pDoc, eGrammar ); + ULONG nIndex = pDoc->AddValidationEntry( *pNewData ); + delete pNewData; + + ScDocFunc aFunc(*pDocShell); + + ScPatternAttr aPattern( pDoc->GetPool() ); + aPattern.GetItemSet().Put( SfxUInt32Item( ATTR_VALIDDATA, nIndex ) ); + aFunc.ApplyAttributes( *GetMarkData(), aPattern, TRUE, TRUE ); + } + } + } + break; + // SC_WID_UNO_NUMRULES is ignored... + } + } +} + +uno::Any SAL_CALL ScCellRangesBase::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if ( !pDocShell || aRanges.Count() == 0 ) + throw uno::RuntimeException(); + + const SfxItemPropertyMap* pPropertyMap = GetItemPropertyMap(); // from derived class + const SfxItemPropertySimpleEntry* pEntry = pPropertyMap->getByName( aPropertyName ); + if ( !pEntry ) + throw beans::UnknownPropertyException(); + + uno::Any aAny; + GetOnePropertyValue( pEntry, aAny ); + return aAny; +} + +void ScCellRangesBase::GetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntry, + uno::Any& rAny ) + throw(uno::RuntimeException) +{ + if ( pEntry ) + { + if ( IsScItemWid( pEntry->nWID ) ) + { + SfxItemSet* pDataSet = GetCurrentDataSet(); + if ( pDataSet ) + { + switch ( pEntry->nWID ) // fuer Item-Spezial-Behandlungen + { + case ATTR_VALUE_FORMAT: + { + ScDocument* pDoc = pDocShell->GetDocument(); + + ULONG nOldFormat = ((const SfxUInt32Item&) + pDataSet->Get( ATTR_VALUE_FORMAT )).GetValue(); + LanguageType eOldLang = ((const SvxLanguageItem&) + pDataSet->Get( ATTR_LANGUAGE_FORMAT )).GetLanguage(); + nOldFormat = pDoc->GetFormatTable()-> + GetFormatForLanguageIfBuiltIn( nOldFormat, eOldLang ); + rAny <<= (sal_Int32)( nOldFormat ); + } + break; + case ATTR_INDENT: + rAny <<= (sal_Int16)( TwipsToHMM(((const SfxUInt16Item&) + pDataSet->Get(pEntry->nWID)).GetValue()) ); + break; + case ATTR_STACKED: + { + sal_Int32 nRot = ((const SfxInt32Item&)pDataSet->Get(ATTR_ROTATE_VALUE)).GetValue(); + BOOL bStacked = ((const SfxBoolItem&)pDataSet->Get(pEntry->nWID)).GetValue(); + SvxOrientationItem( nRot, bStacked, 0 ).QueryValue( rAny ); + } + break; + default: + pPropSet->getPropertyValue(*pEntry, *pDataSet, rAny); + } + } + } + else // implemented here + switch ( pEntry->nWID ) + { + case SC_WID_UNO_CHCOLHDR: + ScUnoHelpFunctions::SetBoolInAny( rAny, bChartColAsHdr ); + break; + case SC_WID_UNO_CHROWHDR: + ScUnoHelpFunctions::SetBoolInAny( rAny, bChartRowAsHdr ); + break; + case SC_WID_UNO_CELLSTYL: + { + String aStyleName; + const ScStyleSheet* pStyle = pDocShell->GetDocument()->GetSelectionStyle(*GetMarkData()); + if (pStyle) + aStyleName = pStyle->GetName(); + rAny <<= rtl::OUString( ScStyleNameConversion::DisplayToProgrammaticName( + aStyleName, SFX_STYLE_FAMILY_PARA ) ); + } + break; + case SC_WID_UNO_TBLBORD: + { + //! loop throgh all ranges + const ScRange* pFirst = aRanges.GetObject(0); + if (pFirst) + { + SvxBoxItem aOuter(ATTR_BORDER); + SvxBoxInfoItem aInner(ATTR_BORDER_INNER); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScMarkData aMark; + aMark.SetMarkArea( *pFirst ); + aMark.SelectTable( pFirst->aStart.Tab(), TRUE ); + pDoc->GetSelectionFrame( aMark, aOuter, aInner ); + + table::TableBorder aBorder; + ScHelperFunctions::FillTableBorder( aBorder, aOuter, aInner ); + rAny <<= aBorder; + } + } + break; + case SC_WID_UNO_CONDFMT: + case SC_WID_UNO_CONDLOC: + case SC_WID_UNO_CONDXML: + { + const ScPatternAttr* pPattern = GetCurrentAttrsDeep(); + if ( pPattern ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + BOOL bEnglish = ( pEntry->nWID != SC_WID_UNO_CONDLOC ); + BOOL bXML = ( pEntry->nWID == SC_WID_UNO_CONDXML ); + formula::FormulaGrammar::Grammar eGrammar = (bXML ? + pDoc->GetStorageGrammar() : + formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML)); + ULONG nIndex = ((const SfxUInt32Item&) + pPattern->GetItem(ATTR_CONDITIONAL)).GetValue(); + rAny <<= uno::Reference<sheet::XSheetConditionalEntries>( + new ScTableConditionalFormat( pDoc, nIndex, eGrammar )); + } + } + break; + case SC_WID_UNO_VALIDAT: + case SC_WID_UNO_VALILOC: + case SC_WID_UNO_VALIXML: + { + const ScPatternAttr* pPattern = GetCurrentAttrsDeep(); + if ( pPattern ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + BOOL bEnglish = ( pEntry->nWID != SC_WID_UNO_VALILOC ); + BOOL bXML = ( pEntry->nWID == SC_WID_UNO_VALIXML ); + formula::FormulaGrammar::Grammar eGrammar = (bXML ? + pDoc->GetStorageGrammar() : + formula::FormulaGrammar::mapAPItoGrammar( bEnglish, bXML)); + ULONG nIndex = ((const SfxUInt32Item&) + pPattern->GetItem(ATTR_VALIDDATA)).GetValue(); + rAny <<= uno::Reference<beans::XPropertySet>( + new ScTableValidationObj( pDoc, nIndex, eGrammar )); + } + } + break; + case SC_WID_UNO_NUMRULES: + { + // always return empty numbering rules object + rAny <<= uno::Reference<container::XIndexReplace>(ScStyleObj::CreateEmptyNumberingRules()); + } + break; + case SC_WID_UNO_ABSNAME: + { + String sRet; + aRanges.Format(sRet, SCR_ABS_3D, pDocShell->GetDocument()); + rAny <<= rtl::OUString(sRet); + } + } + } +} + +void SAL_CALL ScCellRangesBase::addPropertyChangeListener( const rtl::OUString& /* aPropertyName */, + const uno::Reference<beans::XPropertyChangeListener>& /* aListener */) + throw(beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( aRanges.Count() == 0 ) + throw uno::RuntimeException(); + + DBG_ERROR("not implemented"); +} + +void SAL_CALL ScCellRangesBase::removePropertyChangeListener( const rtl::OUString& /* aPropertyName */, + const uno::Reference<beans::XPropertyChangeListener>& /* aListener */) + throw(beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( aRanges.Count() == 0 ) + throw uno::RuntimeException(); + + DBG_ERROR("not implemented"); +} + +void SAL_CALL ScCellRangesBase::addVetoableChangeListener( const rtl::OUString&, + const uno::Reference<beans::XVetoableChangeListener>&) + throw(beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + DBG_ERROR("not implemented"); +} + +void SAL_CALL ScCellRangesBase::removeVetoableChangeListener( const rtl::OUString&, + const uno::Reference<beans::XVetoableChangeListener>&) + throw(beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + DBG_ERROR("not implemented"); +} + +// XMultiPropertySet + +void SAL_CALL ScCellRangesBase::setPropertyValues( const uno::Sequence< rtl::OUString >& aPropertyNames, + const uno::Sequence< uno::Any >& aValues ) + throw (beans::PropertyVetoException, + lang::IllegalArgumentException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + + sal_Int32 nCount(aPropertyNames.getLength()); + sal_Int32 nValues(aValues.getLength()); + if (nCount != nValues) + throw lang::IllegalArgumentException(); + + if ( pDocShell && nCount ) + { + const SfxItemPropertyMap* pPropertyMap = GetItemPropertyMap(); // from derived class + const rtl::OUString* pNames = aPropertyNames.getConstArray(); + const uno::Any* pValues = aValues.getConstArray(); + + const SfxItemPropertySimpleEntry** pEntryArray = new const SfxItemPropertySimpleEntry*[nCount]; + + sal_Int32 i; + for(i = 0; i < nCount; i++) + { + // first loop: find all properties in map, but handle only CellStyle + // (CellStyle must be set before any other cell properties) + + const SfxItemPropertySimpleEntry* pEntry = pPropertyMap->getByName( pNames[i] ); + pEntryArray[i] = pEntry; + if (pEntry) + { + if ( pEntry->nWID == SC_WID_UNO_CELLSTYL ) + { + try + { + SetOnePropertyValue( pEntry, pValues[i] ); + } + catch ( lang::IllegalArgumentException& ) + { + DBG_ERROR("exception when setting cell style"); // not supposed to happen + } + } + } + } + + ScDocument* pDoc = pDocShell->GetDocument(); + ScPatternAttr* pOldPattern = NULL; + ScPatternAttr* pNewPattern = NULL; + + for(i = 0; i < nCount; i++) + { + // second loop: handle other properties + + const SfxItemPropertySimpleEntry* pEntry = pEntryArray[i]; + if ( pEntry ) + { + if ( IsScItemWid( pEntry->nWID ) ) // can be handled by SfxItemPropertySet + { + if ( !pOldPattern ) + { + pOldPattern = new ScPatternAttr( *GetCurrentAttrsDeep() ); + pOldPattern->GetItemSet().ClearInvalidItems(); + pNewPattern = new ScPatternAttr( pDoc->GetPool() ); + } + + // collect items in pNewPattern, apply with one call after the loop + + USHORT nFirstItem, nSecondItem; + lcl_SetCellProperty( *pEntry, pValues[i], *pOldPattern, pDoc, nFirstItem, nSecondItem ); + + // put only affected items into new set + if ( nFirstItem ) + pNewPattern->GetItemSet().Put( pOldPattern->GetItemSet().Get( nFirstItem ) ); + if ( nSecondItem ) + pNewPattern->GetItemSet().Put( pOldPattern->GetItemSet().Get( nSecondItem ) ); + } + else if ( pEntry->nWID != SC_WID_UNO_CELLSTYL ) // CellStyle is handled above + { + // call virtual method to set a single property + SetOnePropertyValue( pEntry, pValues[i] ); + } + } + } + + if ( pNewPattern && aRanges.Count() ) + { + ScDocFunc aFunc(*pDocShell); + aFunc.ApplyAttributes( *GetMarkData(), *pNewPattern, TRUE, TRUE ); + } + + delete pNewPattern; + delete pOldPattern; + delete[] pEntryArray; + } +} + +uno::Sequence<uno::Any> SAL_CALL ScCellRangesBase::getPropertyValues( + const uno::Sequence< rtl::OUString >& aPropertyNames ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + + const SfxItemPropertyMap* pPropertyMap = GetItemPropertyMap(); // from derived class + + uno::Sequence<uno::Any> aRet(aPropertyNames.getLength()); + uno::Any* pProperties = aRet.getArray(); + for(INT32 i = 0; i < aPropertyNames.getLength(); i++) + { + const SfxItemPropertySimpleEntry* pEntry = pPropertyMap->getByName( aPropertyNames[i] ); + GetOnePropertyValue( pEntry, pProperties[i] ); + } + return aRet; +} + +void SAL_CALL ScCellRangesBase::addPropertiesChangeListener( const uno::Sequence< rtl::OUString >& /* aPropertyNames */, + const uno::Reference< beans::XPropertiesChangeListener >& /* xListener */ ) + throw (uno::RuntimeException) +{ + DBG_ERROR("not implemented"); +} + +void SAL_CALL ScCellRangesBase::removePropertiesChangeListener( const uno::Reference< beans::XPropertiesChangeListener >& /* xListener */ ) + throw (uno::RuntimeException) +{ + DBG_ERROR("not implemented"); +} + +void SAL_CALL ScCellRangesBase::firePropertiesChangeEvent( const uno::Sequence< rtl::OUString >& /* aPropertyNames */, + const uno::Reference< beans::XPropertiesChangeListener >& /* xListener */ ) + throw (uno::RuntimeException) +{ + DBG_ERROR("not implemented"); +} + +IMPL_LINK( ScCellRangesBase, ValueListenerHdl, SfxHint*, pHint ) +{ + if ( pDocShell && pHint && pHint->ISA( SfxSimpleHint ) && + ((const SfxSimpleHint*)pHint)->GetId() & (SC_HINT_DATACHANGED | SC_HINT_DYING) ) + { + // This may be called several times for a single change, if several formulas + // in the range are notified. So only a flag is set that is checked when + // SFX_HINT_DATACHANGED is received. + + bGotDataChangedHint = TRUE; + } + return 0; +} + +// XTolerantMultiPropertySet +uno::Sequence< beans::SetPropertyTolerantFailed > SAL_CALL ScCellRangesBase::setPropertyValuesTolerant( const uno::Sequence< ::rtl::OUString >& aPropertyNames, + const uno::Sequence< uno::Any >& aValues ) + throw (lang::IllegalArgumentException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + sal_Int32 nCount(aPropertyNames.getLength()); + sal_Int32 nValues(aValues.getLength()); + if (nCount != nValues) + throw lang::IllegalArgumentException(); + + if ( pDocShell && nCount ) + { + uno::Sequence < beans::SetPropertyTolerantFailed > aReturns(nCount); + beans::SetPropertyTolerantFailed* pReturns = aReturns.getArray(); + + const SfxItemPropertyMap* pPropertyMap = GetItemPropertyMap(); // from derived class + const rtl::OUString* pNames = aPropertyNames.getConstArray(); + const uno::Any* pValues = aValues.getConstArray(); + + const SfxItemPropertySimpleEntry** pMapArray = new const SfxItemPropertySimpleEntry*[nCount]; + + sal_Int32 i; + for(i = 0; i < nCount; i++) + { + // first loop: find all properties in map, but handle only CellStyle + // (CellStyle must be set before any other cell properties) + + const SfxItemPropertySimpleEntry* pEntry = pPropertyMap->getByName( pNames[i] ); + pMapArray[i] = pEntry; + if (pEntry) + { + if ( pEntry->nWID == SC_WID_UNO_CELLSTYL ) + { + try + { + SetOnePropertyValue( pEntry, pValues[i] ); + } + catch ( lang::IllegalArgumentException& ) + { + DBG_ERROR("exception when setting cell style"); // not supposed to happen + } + } + } + } + + ScDocument* pDoc = pDocShell->GetDocument(); + ScPatternAttr* pOldPattern = NULL; + ScPatternAttr* pNewPattern = NULL; + + sal_Int32 nFailed(0); + for(i = 0; i < nCount; i++) + { + // second loop: handle other properties + + const SfxItemPropertySimpleEntry* pEntry = pMapArray[i]; + if ( pEntry && ((pEntry->nFlags & beans::PropertyAttribute::READONLY) == 0)) + { + if ( IsScItemWid( pEntry->nWID ) ) // can be handled by SfxItemPropertySet + { + if ( !pOldPattern ) + { + pOldPattern = new ScPatternAttr( *GetCurrentAttrsDeep() ); + pOldPattern->GetItemSet().ClearInvalidItems(); + pNewPattern = new ScPatternAttr( pDoc->GetPool() ); + } + + // collect items in pNewPattern, apply with one call after the loop + + USHORT nFirstItem, nSecondItem; + try + { + lcl_SetCellProperty( *pEntry, pValues[i], *pOldPattern, pDoc, nFirstItem, nSecondItem ); + + // put only affected items into new set + if ( nFirstItem ) + pNewPattern->GetItemSet().Put( pOldPattern->GetItemSet().Get( nFirstItem ) ); + if ( nSecondItem ) + pNewPattern->GetItemSet().Put( pOldPattern->GetItemSet().Get( nSecondItem ) ); + } + catch ( lang::IllegalArgumentException& ) + { + pReturns[nFailed].Name = pNames[i]; + pReturns[nFailed++].Result = beans::TolerantPropertySetResultType::ILLEGAL_ARGUMENT; + } + } + else if ( pEntry->nWID != SC_WID_UNO_CELLSTYL ) // CellStyle is handled above + { + // call virtual method to set a single property + try + { + SetOnePropertyValue( pEntry, pValues[i] ); + } + catch ( lang::IllegalArgumentException& ) + { + pReturns[nFailed].Name = pNames[i]; + pReturns[nFailed++].Result = beans::TolerantPropertySetResultType::ILLEGAL_ARGUMENT; + } + } + } + else + { + pReturns[nFailed].Name = pNames[i]; + if (pEntry) + pReturns[nFailed++].Result = beans::TolerantPropertySetResultType::PROPERTY_VETO; + else + pReturns[nFailed++].Result = beans::TolerantPropertySetResultType::UNKNOWN_PROPERTY; + } + } + + if ( pNewPattern && aRanges.Count() ) + { + ScDocFunc aFunc(*pDocShell); + aFunc.ApplyAttributes( *GetMarkData(), *pNewPattern, TRUE, TRUE ); + } + + delete pNewPattern; + delete pOldPattern; + delete[] pMapArray; + + aReturns.realloc(nFailed); + + return aReturns; + } + return uno::Sequence < beans::SetPropertyTolerantFailed >(); +} + +uno::Sequence< beans::GetPropertyTolerantResult > SAL_CALL ScCellRangesBase::getPropertyValuesTolerant( const uno::Sequence< ::rtl::OUString >& aPropertyNames ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + + sal_Int32 nCount(aPropertyNames.getLength()); + uno::Sequence < beans::GetPropertyTolerantResult > aReturns(nCount); + beans::GetPropertyTolerantResult* pReturns = aReturns.getArray(); + + const SfxItemPropertyMap* pPropertyMap = GetItemPropertyMap(); // from derived class + + for(INT32 i = 0; i < nCount; i++) + { + const SfxItemPropertySimpleEntry* pEntry = pPropertyMap->getByName( aPropertyNames[i] ); + if (!pEntry) + { + pReturns[i].Result = beans::TolerantPropertySetResultType::UNKNOWN_PROPERTY; + } + else + { + USHORT nItemWhich = 0; + lcl_GetPropertyWhich( pEntry, nItemWhich ); + pReturns[i].State = GetOnePropertyState( nItemWhich, pEntry ); + GetOnePropertyValue( pEntry, pReturns[i].Value ); + pReturns[i].Result = beans::TolerantPropertySetResultType::SUCCESS; + } + } + return aReturns; +} + +uno::Sequence< beans::GetDirectPropertyTolerantResult > SAL_CALL ScCellRangesBase::getDirectPropertyValuesTolerant( const uno::Sequence< ::rtl::OUString >& aPropertyNames ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + + sal_Int32 nCount(aPropertyNames.getLength()); + uno::Sequence < beans::GetDirectPropertyTolerantResult > aReturns(nCount); + beans::GetDirectPropertyTolerantResult* pReturns = aReturns.getArray(); + + const SfxItemPropertyMap* pPropertyMap = GetItemPropertyMap(); // from derived class + + INT32 j = 0; + for(INT32 i = 0; i < nCount; i++) + { + const SfxItemPropertySimpleEntry* pEntry = pPropertyMap->getByName( aPropertyNames[i] ); + if (!pEntry) + { + pReturns[i].Result = beans::TolerantPropertySetResultType::UNKNOWN_PROPERTY; + } + else + { + USHORT nItemWhich = 0; + lcl_GetPropertyWhich( pEntry, nItemWhich ); + pReturns[j].State = GetOnePropertyState( nItemWhich, pEntry ); + if (pReturns[j].State == beans::PropertyState_DIRECT_VALUE) + { + GetOnePropertyValue( pEntry, pReturns[j].Value ); + pReturns[j].Result = beans::TolerantPropertySetResultType::SUCCESS; + pReturns[j].Name = aPropertyNames[i]; + ++j; + } + } + } + if (j < nCount) + aReturns.realloc(j); + return aReturns; +} + +// XIndent + +void SAL_CALL ScCellRangesBase::decrementIndent() throw(::com::sun::star::uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( pDocShell && aRanges.Count() ) // leer = nichts zu tun + { + ScDocFunc aFunc(*pDocShell); + //#97041#; put only MultiMarked ScMarkData in ChangeIndent + ScMarkData aMarkData(*GetMarkData()); + aMarkData.MarkToMulti(); + aFunc.ChangeIndent( aMarkData, FALSE, TRUE ); + } +} + +void SAL_CALL ScCellRangesBase::incrementIndent() throw(::com::sun::star::uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( pDocShell && aRanges.Count() ) // leer = nichts zu tun + { + ScDocFunc aFunc(*pDocShell); + //#97041#; put only MultiMarked ScMarkData in ChangeIndent + ScMarkData aMarkData(*GetMarkData()); + aMarkData.MarkToMulti(); + aFunc.ChangeIndent( aMarkData, TRUE, TRUE ); + } +} + +// XChartData + +ScMemChart* ScCellRangesBase::CreateMemChart_Impl() const +{ + if ( pDocShell && aRanges.Count() ) + { + ScRangeListRef xChartRanges; + if ( aRanges.Count() == 1 ) + { + // ganze Tabelle sinnvoll begrenzen (auf belegten Datenbereich) + // (nur hier, Listener werden auf den ganzen Bereich angemeldet) + //! direkt testen, ob es ein ScTableSheetObj ist? + + ScRange* pRange = aRanges.GetObject(0); + if ( pRange->aStart.Col() == 0 && pRange->aEnd.Col() == MAXCOL && + pRange->aStart.Row() == 0 && pRange->aEnd.Row() == MAXROW ) + { + SCTAB nTab = pRange->aStart.Tab(); + + SCCOL nStartX; + SCROW nStartY; // Anfang holen + if (!pDocShell->GetDocument()->GetDataStart( nTab, nStartX, nStartY )) + { + nStartX = 0; + nStartY = 0; + } + + SCCOL nEndX; + SCROW nEndY; // Ende holen + if (!pDocShell->GetDocument()->GetTableArea( nTab, nEndX, nEndY )) + { + nEndX = 0; + nEndY = 0; + } + + xChartRanges = new ScRangeList; + xChartRanges->Append( ScRange( nStartX, nStartY, nTab, nEndX, nEndY, nTab ) ); + } + } + if (!xChartRanges.Is()) // sonst Ranges direkt uebernehmen + xChartRanges = new ScRangeList(aRanges); + ScChartArray aArr( pDocShell->GetDocument(), xChartRanges, String() ); + + // RowAsHdr = ColHeaders und umgekehrt + aArr.SetHeaders( bChartRowAsHdr, bChartColAsHdr ); + + return aArr.CreateMemChart(); + } + return NULL; +} + +uno::Sequence< uno::Sequence<double> > SAL_CALL ScCellRangesBase::getData() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScMemChart* pMemChart = CreateMemChart_Impl(); + if ( pMemChart ) + { + sal_Int32 nColCount = pMemChart->GetColCount(); + sal_Int32 nRowCount = static_cast<sal_Int32>(pMemChart->GetRowCount()); + + uno::Sequence< uno::Sequence<double> > aRowSeq( nRowCount ); + uno::Sequence<double>* pRowAry = aRowSeq.getArray(); + for (sal_Int32 nRow = 0; nRow < nRowCount; nRow++) + { + uno::Sequence<double> aColSeq( nColCount ); + double* pColAry = aColSeq.getArray(); + for (sal_Int32 nCol = 0; nCol < nColCount; nCol++) + pColAry[nCol] = pMemChart->GetData( static_cast<short>(nCol), static_cast<short>(nRow) ); + + pRowAry[nRow] = aColSeq; + } + + delete pMemChart; + return aRowSeq; + } + + return uno::Sequence< uno::Sequence<double> >(0); +} + +ScRangeListRef ScCellRangesBase::GetLimitedChartRanges_Impl( long nDataColumns, long nDataRows ) const +{ + if ( aRanges.Count() == 1 ) + { + ScRange* pRange = aRanges.GetObject(0); + if ( pRange->aStart.Col() == 0 && pRange->aEnd.Col() == MAXCOL && + pRange->aStart.Row() == 0 && pRange->aEnd.Row() == MAXROW ) + { + // if aRanges is a complete sheet, limit to given size + + SCTAB nTab = pRange->aStart.Tab(); + + long nEndColumn = nDataColumns - 1 + ( bChartColAsHdr ? 1 : 0 ); + if ( nEndColumn < 0 ) + nEndColumn = 0; + if ( nEndColumn > MAXCOL ) + nEndColumn = MAXCOL; + + long nEndRow = nDataRows - 1 + ( bChartRowAsHdr ? 1 : 0 ); + if ( nEndRow < 0 ) + nEndRow = 0; + if ( nEndRow > MAXROW ) + nEndRow = MAXROW; + + ScRangeListRef xChartRanges = new ScRangeList; + xChartRanges->Append( ScRange( 0, 0, nTab, (SCCOL)nEndColumn, (SCROW)nEndRow, nTab ) ); + return xChartRanges; + } + } + + return new ScRangeList(aRanges); // as-is +} + +void SAL_CALL ScCellRangesBase::setData( const uno::Sequence< uno::Sequence<double> >& aData ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + BOOL bDone = FALSE; + long nRowCount = aData.getLength(); + long nColCount = nRowCount ? aData[0].getLength() : 0; + ScRangeListRef xChartRanges = GetLimitedChartRanges_Impl( nColCount, nRowCount ); + if ( pDocShell && xChartRanges.Is() ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScChartArray aArr( pDoc, xChartRanges, String() ); + aArr.SetHeaders( bChartRowAsHdr, bChartColAsHdr ); // RowAsHdr = ColHeaders + const ScChartPositionMap* pPosMap = aArr.GetPositionMap(); + if (pPosMap) + { + if ( pPosMap->GetColCount() == static_cast<SCCOL>(nColCount) && + pPosMap->GetRowCount() == static_cast<SCROW>(nRowCount) ) + { + for (long nRow=0; nRow<nRowCount; nRow++) + { + const uno::Sequence<double>& rRowSeq = aData[nRow]; + const double* pArray = rRowSeq.getConstArray(); + nColCount = rRowSeq.getLength(); + for (long nCol=0; nCol<nColCount; nCol++) + { + const ScAddress* pPos = pPosMap->GetPosition( + sal::static_int_cast<SCCOL>(nCol), + sal::static_int_cast<SCROW>(nRow) ); + if (pPos) + { + double fVal = pArray[nCol]; + if ( fVal == DBL_MIN ) + pDoc->PutCell( *pPos, NULL ); // empty cell + else + pDoc->SetValue( pPos->Col(), pPos->Row(), pPos->Tab(), pArray[nCol] ); + } + } + } + + //! undo + PaintRanges_Impl( PAINT_GRID ); + pDocShell->SetDocumentModified(); + ForceChartListener_Impl(); // call listeners for this object synchronously + bDone = TRUE; + } + } + } + + if (!bDone) + throw uno::RuntimeException(); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScCellRangesBase::getRowDescriptions() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScMemChart* pMemChart = CreateMemChart_Impl(); + if ( pMemChart ) + { + sal_Int32 nRowCount = static_cast<sal_Int32>(pMemChart->GetRowCount()); + uno::Sequence<rtl::OUString> aSeq( nRowCount ); + rtl::OUString* pAry = aSeq.getArray(); + for (sal_Int32 nRow = 0; nRow < nRowCount; nRow++) + pAry[nRow] = pMemChart->GetRowText(static_cast<short>(nRow)); + + delete pMemChart; + return aSeq; + } + return uno::Sequence<rtl::OUString>(0); +} + +void SAL_CALL ScCellRangesBase::setRowDescriptions( + const uno::Sequence<rtl::OUString>& aRowDescriptions ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + BOOL bDone = FALSE; + if ( bChartColAsHdr ) + { + long nRowCount = aRowDescriptions.getLength(); + ScRangeListRef xChartRanges = GetLimitedChartRanges_Impl( 1, nRowCount ); + if ( pDocShell && xChartRanges.Is() ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScChartArray aArr( pDoc, xChartRanges, String() ); + aArr.SetHeaders( bChartRowAsHdr, bChartColAsHdr ); // RowAsHdr = ColHeaders + const ScChartPositionMap* pPosMap = aArr.GetPositionMap(); + if (pPosMap) + { + if ( pPosMap->GetRowCount() == static_cast<SCROW>(nRowCount) ) + { + const rtl::OUString* pArray = aRowDescriptions.getConstArray(); + for (long nRow=0; nRow<nRowCount; nRow++) + { + const ScAddress* pPos = pPosMap->GetRowHeaderPosition( + static_cast<SCSIZE>(nRow) ); + if (pPos) + { + String aStr = pArray[nRow]; + if ( aStr.Len() ) + pDoc->PutCell( *pPos, new ScStringCell( aStr ) ); + else + pDoc->PutCell( *pPos, NULL ); // empty cell + } + } + + //! undo + PaintRanges_Impl( PAINT_GRID ); + pDocShell->SetDocumentModified(); + ForceChartListener_Impl(); // call listeners for this object synchronously + bDone = TRUE; + } + } + } + } + + if (!bDone) + throw uno::RuntimeException(); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScCellRangesBase::getColumnDescriptions() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScMemChart* pMemChart = CreateMemChart_Impl(); + if ( pMemChart ) + { + sal_Int32 nColCount = pMemChart->GetColCount(); + uno::Sequence<rtl::OUString> aSeq( nColCount ); + rtl::OUString* pAry = aSeq.getArray(); + for (sal_Int32 nCol = 0; nCol < nColCount; nCol++) + pAry[nCol] = pMemChart->GetColText(static_cast<short>(nCol)); + + delete pMemChart; + return aSeq; + } + return uno::Sequence<rtl::OUString>(0); +} + +void SAL_CALL ScCellRangesBase::setColumnDescriptions( + const uno::Sequence<rtl::OUString>& aColumnDescriptions ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + BOOL bDone = FALSE; + if ( bChartRowAsHdr ) + { + long nColCount = aColumnDescriptions.getLength(); + ScRangeListRef xChartRanges = GetLimitedChartRanges_Impl( nColCount, 1 ); + if ( pDocShell && xChartRanges.Is() ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScChartArray aArr( pDoc, xChartRanges, String() ); + aArr.SetHeaders( bChartRowAsHdr, bChartColAsHdr ); // RowAsHdr = ColHeaders + const ScChartPositionMap* pPosMap = aArr.GetPositionMap(); + if (pPosMap) + { + if ( pPosMap->GetColCount() == static_cast<SCCOL>(nColCount) ) + { + const rtl::OUString* pArray = aColumnDescriptions.getConstArray(); + for (long nCol=0; nCol<nColCount; nCol++) + { + const ScAddress* pPos = pPosMap->GetColHeaderPosition( + sal::static_int_cast<SCCOL>(nCol) ); + if (pPos) + { + String aStr(pArray[nCol]); + if ( aStr.Len() ) + pDoc->PutCell( *pPos, new ScStringCell( aStr ) ); + else + pDoc->PutCell( *pPos, NULL ); // empty cell + } + } + + //! undo + PaintRanges_Impl( PAINT_GRID ); + pDocShell->SetDocumentModified(); + ForceChartListener_Impl(); // call listeners for this object synchronously + bDone = TRUE; + } + } + } + } + + if (!bDone) + throw uno::RuntimeException(); +} + +void ScCellRangesBase::ForceChartListener_Impl() +{ + // call Update immediately so the caller to setData etc. can + // regognize the listener call + + if ( pDocShell ) + { + ScChartListenerCollection* pColl = pDocShell->GetDocument()->GetChartListenerCollection(); + if ( pColl ) + { + USHORT nCollCount = pColl->GetCount(); + for ( USHORT nIndex = 0; nIndex < nCollCount; nIndex++ ) + { + ScChartListener* pChartListener = (ScChartListener*)pColl->At(nIndex); + if ( pChartListener && + pChartListener->GetUnoSource() == static_cast<chart::XChartData*>(this) && + pChartListener->IsDirty() ) + pChartListener->Update(); + } + } + } +} + +String lcl_UniqueName( ScStrCollection& rColl, const String& rPrefix ) +{ + long nNumber = 1; + USHORT nCollCount = rColl.GetCount(); + while (TRUE) + { + String aName(rPrefix); + aName += String::CreateFromInt32( nNumber ); + BOOL bFound = FALSE; + for (USHORT i=0; i<nCollCount; i++) + if ( rColl[i]->GetString() == aName ) + { + bFound = TRUE; + break; + } + if (!bFound) + return aName; + ++nNumber; + } +} + +void SAL_CALL ScCellRangesBase::addChartDataChangeEventListener( const uno::Reference< + chart::XChartDataChangeEventListener >& aListener ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( pDocShell && aRanges.Count() ) + { + //! auf doppelte testen? + + ScDocument* pDoc = pDocShell->GetDocument(); + ScRangeListRef aRangesRef( new ScRangeList(aRanges) ); + ScChartListenerCollection* pColl = pDoc->GetChartListenerCollection(); + String aName(lcl_UniqueName( *pColl, + String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM("__Uno")) )); + ScChartListener* pListener = new ScChartListener( aName, pDoc, aRangesRef ); + pListener->SetUno( aListener, this ); + pColl->Insert( pListener ); + pListener->StartListeningTo(); + } +} + +void SAL_CALL ScCellRangesBase::removeChartDataChangeEventListener( const uno::Reference< + chart::XChartDataChangeEventListener >& aListener ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( pDocShell && aRanges.Count() ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScChartListenerCollection* pColl = pDoc->GetChartListenerCollection(); + pColl->FreeUno( aListener, this ); + } +} + +double SAL_CALL ScCellRangesBase::getNotANumber() throw(::com::sun::star::uno::RuntimeException) +{ + // im ScChartArray wird DBL_MIN verwendet, weil das Chart es so will + return DBL_MIN; +} + +sal_Bool SAL_CALL ScCellRangesBase::isNotANumber( double nNumber ) throw(uno::RuntimeException) +{ + // im ScChartArray wird DBL_MIN verwendet, weil das Chart es so will + return (nNumber == DBL_MIN); +} + +// XModifyBroadcaster + +void SAL_CALL ScCellRangesBase::addModifyListener( const uno::Reference<util::XModifyListener>& aListener ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( aRanges.Count() == 0 ) + throw uno::RuntimeException(); + + uno::Reference<util::XModifyListener> *pObj = + new uno::Reference<util::XModifyListener>( aListener ); + aValueListeners.Insert( pObj, aValueListeners.Count() ); + + if ( aValueListeners.Count() == 1 ) + { + if (!pValueListener) + pValueListener = new ScLinkListener( LINK( this, ScCellRangesBase, ValueListenerHdl ) ); + + ScDocument* pDoc = pDocShell->GetDocument(); + ULONG nCount = aRanges.Count(); + for (ULONG i=0; i<nCount; i++) + pDoc->StartListeningArea( *aRanges.GetObject(i), pValueListener ); + + acquire(); // don't lose this object (one ref for all listeners) + } +} + +void SAL_CALL ScCellRangesBase::removeModifyListener( const uno::Reference<util::XModifyListener>& aListener ) + throw(uno::RuntimeException) +{ + + ScUnoGuard aGuard; + if ( aRanges.Count() == 0 ) + throw uno::RuntimeException(); + + acquire(); // in case the listeners have the last ref - released below + + USHORT nCount = aValueListeners.Count(); + for ( USHORT n=nCount; n--; ) + { + uno::Reference<util::XModifyListener> *pObj = aValueListeners[n]; + if ( *pObj == aListener ) + { + aValueListeners.DeleteAndDestroy( n ); + + if ( aValueListeners.Count() == 0 ) + { + if (pValueListener) + pValueListener->EndListeningAll(); + + release(); // release the ref for the listeners + } + + break; + } + } + + release(); // might delete this object +} + +// XCellRangesQuery + +uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryVisibleCells() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + //! fuer alle Tabellen getrennt, wenn Markierungen pro Tabelle getrennt sind! + SCTAB nTab = lcl_FirstTab(aRanges); + + ScMarkData aMarkData(*GetMarkData()); + + ScDocument* pDoc = pDocShell->GetDocument(); + SCCOL nCol = 0, nLastCol; + while (nCol <= MAXCOL) + { + if (pDoc->ColHidden(nCol, nTab, nLastCol)) + // hidden columns. Unselect them. + aMarkData.SetMultiMarkArea(ScRange(nCol, 0, nTab, nLastCol, MAXROW, nTab), false); + + nCol = nLastCol + 1; + } + + SCROW nRow = 0, nLastRow; + while (nRow <= MAXROW) + { + if (pDoc->RowHidden(nRow, nTab, nLastRow)) + // These rows are hidden. Unselect them. + aMarkData.SetMultiMarkArea(ScRange(0, nRow, nTab, MAXCOL, nLastRow, nTab), false); + + nRow = nLastRow + 1; + } + + ScRangeList aNewRanges; + aMarkData.FillRangeListWithMarks( &aNewRanges, FALSE ); + return new ScCellRangesObj( pDocShell, aNewRanges ); + } + + return NULL; +} + +uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryEmptyCells() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + + ScMarkData aMarkData(*GetMarkData()); + + // belegte Zellen wegmarkieren + ULONG nCount = aRanges.Count(); + for (ULONG i=0; i<nCount; i++) + { + ScRange aRange = *aRanges.GetObject(i); + + ScCellIterator aIter( pDoc, aRange ); + ScBaseCell* pCell = aIter.GetFirst(); + while (pCell) + { + // Notizen zaehlen als nicht-leer + if ( !pCell->IsBlank() ) + aMarkData.SetMultiMarkArea( + ScRange( aIter.GetCol(), aIter.GetRow(), aIter.GetTab() ), + FALSE ); + + pCell = aIter.GetNext(); + } + } + + ScRangeList aNewRanges; + // IsMultiMarked reicht hier nicht (wird beim deselektieren nicht zurueckgesetzt) + if (aMarkData.HasAnyMultiMarks()) + aMarkData.FillRangeListWithMarks( &aNewRanges, FALSE ); + + return new ScCellRangesObj( pDocShell, aNewRanges ); // aNewRanges kann leer sein + } + + return NULL; +} + +uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryContentCells( + sal_Int16 nContentFlags ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + + ScMarkData aMarkData; + + // passende Zellen selektieren + ULONG nCount = aRanges.Count(); + for (ULONG i=0; i<nCount; i++) + { + ScRange aRange = *aRanges.GetObject(i); + + ScCellIterator aIter( pDoc, aRange ); + ScBaseCell* pCell = aIter.GetFirst(); + while (pCell) + { + BOOL bAdd = FALSE; + if ( pCell->HasNote() && ( nContentFlags & sheet::CellFlags::ANNOTATION ) ) + bAdd = TRUE; + else + switch ( pCell->GetCellType() ) + { + case CELLTYPE_STRING: + if ( nContentFlags & sheet::CellFlags::STRING ) + bAdd = TRUE; + break; + case CELLTYPE_EDIT: + if ( (nContentFlags & sheet::CellFlags::STRING) || (nContentFlags & sheet::CellFlags::FORMATTED) ) + bAdd = TRUE; + break; + case CELLTYPE_FORMULA: + if ( nContentFlags & sheet::CellFlags::FORMULA ) + bAdd = TRUE; + break; + case CELLTYPE_VALUE: + if ( (nContentFlags & (sheet::CellFlags::VALUE|sheet::CellFlags::DATETIME)) + == (sheet::CellFlags::VALUE|sheet::CellFlags::DATETIME) ) + bAdd = TRUE; + else + { + // Date/Time Erkennung + + ULONG nIndex = (ULONG)((SfxUInt32Item*)pDoc->GetAttr( + aIter.GetCol(), aIter.GetRow(), aIter.GetTab(), + ATTR_VALUE_FORMAT ))->GetValue(); + short nTyp = pDoc->GetFormatTable()->GetType(nIndex); + if ((nTyp == NUMBERFORMAT_DATE) || (nTyp == NUMBERFORMAT_TIME) || + (nTyp == NUMBERFORMAT_DATETIME)) + { + if ( nContentFlags & sheet::CellFlags::DATETIME ) + bAdd = TRUE; + } + else + { + if ( nContentFlags & sheet::CellFlags::VALUE ) + bAdd = TRUE; + } + } + break; + default: + { + // added to avoid warnings + } + } + + if (bAdd) + aMarkData.SetMultiMarkArea( + ScRange( aIter.GetCol(), aIter.GetRow(), aIter.GetTab() ), + TRUE ); + + pCell = aIter.GetNext(); + } + } + + ScRangeList aNewRanges; + if (aMarkData.IsMultiMarked()) + aMarkData.FillRangeListWithMarks( &aNewRanges, FALSE ); + + return new ScCellRangesObj( pDocShell, aNewRanges ); // aNewRanges kann leer sein + } + + return NULL; +} + +uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryFormulaCells( + sal_Int32 nResultFlags ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + + ScMarkData aMarkData; + + // passende Zellen selektieren + ULONG nCount = aRanges.Count(); + for (ULONG i=0; i<nCount; i++) + { + ScRange aRange = *aRanges.GetObject(i); + + ScCellIterator aIter( pDoc, aRange ); + ScBaseCell* pCell = aIter.GetFirst(); + while (pCell) + { + if (pCell->GetCellType() == CELLTYPE_FORMULA) + { + ScFormulaCell* pFCell = (ScFormulaCell*)pCell; + BOOL bAdd = FALSE; + if (pFCell->GetErrCode()) + { + if ( nResultFlags & sheet::FormulaResult::ERROR ) + bAdd = TRUE; + } + else if (pFCell->IsValue()) + { + if ( nResultFlags & sheet::FormulaResult::VALUE ) + bAdd = TRUE; + } + else // String + { + if ( nResultFlags & sheet::FormulaResult::STRING ) + bAdd = TRUE; + } + + if (bAdd) + aMarkData.SetMultiMarkArea( + ScRange( aIter.GetCol(), aIter.GetRow(), aIter.GetTab() ), + TRUE ); + } + + pCell = aIter.GetNext(); + } + } + + ScRangeList aNewRanges; + if (aMarkData.IsMultiMarked()) + aMarkData.FillRangeListWithMarks( &aNewRanges, FALSE ); + + return new ScCellRangesObj( pDocShell, aNewRanges ); // aNewRanges kann leer sein + } + + return NULL; +} + +uno::Reference<sheet::XSheetCellRanges> ScCellRangesBase::QueryDifferences_Impl( + const table::CellAddress& aCompare, BOOL bColumnDiff) +{ + if (pDocShell) + { + ULONG nRangeCount = aRanges.Count(); + ULONG i; + ScDocument* pDoc = pDocShell->GetDocument(); + ScMarkData aMarkData; + + SCCOLROW nCmpPos = bColumnDiff ? (SCCOLROW)aCompare.Row : (SCCOLROW)aCompare.Column; + + // zuerst alles selektieren, wo ueberhaupt etwas in der Vergleichsspalte steht + // (fuer gleiche Zellen wird die Selektion im zweiten Schritt aufgehoben) + + SCTAB nTab = lcl_FirstTab(aRanges); //! fuer alle Tabellen, wenn Markierungen pro Tabelle! + ScRange aCmpRange, aCellRange; + if (bColumnDiff) + aCmpRange = ScRange( 0,nCmpPos,nTab, MAXCOL,nCmpPos,nTab ); + else + aCmpRange = ScRange( static_cast<SCCOL>(nCmpPos),0,nTab, static_cast<SCCOL>(nCmpPos),MAXROW,nTab ); + ScCellIterator aCmpIter( pDoc, aCmpRange ); + ScBaseCell* pCmpCell = aCmpIter.GetFirst(); + while (pCmpCell) + { + if (pCmpCell->GetCellType() != CELLTYPE_NOTE) + { + SCCOLROW nCellPos = bColumnDiff ? static_cast<SCCOLROW>(aCmpIter.GetCol()) : static_cast<SCCOLROW>(aCmpIter.GetRow()); + if (bColumnDiff) + aCellRange = ScRange( static_cast<SCCOL>(nCellPos),0,nTab, + static_cast<SCCOL>(nCellPos),MAXROW,nTab ); + else + aCellRange = ScRange( 0,nCellPos,nTab, MAXCOL,nCellPos,nTab ); + + for (i=0; i<nRangeCount; i++) + { + ScRange aRange(*aRanges.GetObject(i)); + if ( aRange.Intersects( aCellRange ) ) + { + if (bColumnDiff) + { + aRange.aStart.SetCol(static_cast<SCCOL>(nCellPos)); + aRange.aEnd.SetCol(static_cast<SCCOL>(nCellPos)); + } + else + { + aRange.aStart.SetRow(nCellPos); + aRange.aEnd.SetRow(nCellPos); + } + aMarkData.SetMultiMarkArea( aRange ); + } + } + } + pCmpCell = aCmpIter.GetNext(); + } + + // alle nichtleeren Zellen mit der Vergleichsspalte vergleichen und entsprechend + // selektieren oder aufheben + + ScAddress aCmpAddr; + for (i=0; i<nRangeCount; i++) + { + ScRange aRange(*aRanges.GetObject(i)); + + ScCellIterator aIter( pDoc, aRange ); + ScBaseCell* pCell = aIter.GetFirst(); + while (pCell) + { + if (bColumnDiff) + aCmpAddr = ScAddress( aIter.GetCol(), nCmpPos, aIter.GetTab() ); + else + aCmpAddr = ScAddress( static_cast<SCCOL>(nCmpPos), aIter.GetRow(), aIter.GetTab() ); + const ScBaseCell* pOtherCell = pDoc->GetCell( aCmpAddr ); + + ScRange aOneRange( aIter.GetCol(), aIter.GetRow(), aIter.GetTab() ); + if ( !ScBaseCell::CellEqual( pCell, pOtherCell ) ) + aMarkData.SetMultiMarkArea( aOneRange ); + else + aMarkData.SetMultiMarkArea( aOneRange, FALSE ); // deselect + + pCell = aIter.GetNext(); + } + } + + ScRangeList aNewRanges; + if (aMarkData.IsMultiMarked()) + aMarkData.FillRangeListWithMarks( &aNewRanges, FALSE ); + + return new ScCellRangesObj( pDocShell, aNewRanges ); // aNewRanges kann leer sein + } + return NULL; +} + +uno::Reference<sheet::XSheetCellRanges > SAL_CALL ScCellRangesBase::queryColumnDifferences( + const table::CellAddress& aCompare ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return QueryDifferences_Impl( aCompare, TRUE ); +} + +uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryRowDifferences( + const table::CellAddress& aCompare ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return QueryDifferences_Impl( aCompare, FALSE ); +} + +uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryIntersection( + const table::CellRangeAddress& aRange ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScRange aMask( (SCCOL)aRange.StartColumn, (SCROW)aRange.StartRow, aRange.Sheet, + (SCCOL)aRange.EndColumn, (SCROW)aRange.EndRow, aRange.Sheet ); + + ScRangeList aNew; + ULONG nCount = aRanges.Count(); + for (ULONG i=0; i<nCount; i++) + { + ScRange aTemp(*aRanges.GetObject(i)); + if ( aTemp.Intersects( aMask ) ) + aNew.Join( ScRange( Max( aTemp.aStart.Col(), aMask.aStart.Col() ), + Max( aTemp.aStart.Row(), aMask.aStart.Row() ), + Max( aTemp.aStart.Tab(), aMask.aStart.Tab() ), + Min( aTemp.aEnd.Col(), aMask.aEnd.Col() ), + Min( aTemp.aEnd.Row(), aMask.aEnd.Row() ), + Min( aTemp.aEnd.Tab(), aMask.aEnd.Tab() ) ) ); + } + + return new ScCellRangesObj( pDocShell, aNew ); // kann leer sein +} + +// XFormulaQuery + +uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryPrecedents( + sal_Bool bRecursive ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( pDocShell ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + + ScRangeList aNewRanges(aRanges); + BOOL bFound; + do + { + bFound = FALSE; + + // #97205# aMarkData uses aNewRanges, not aRanges, so GetMarkData can't be used + ScMarkData aMarkData; + aMarkData.MarkFromRangeList( aNewRanges, FALSE ); + aMarkData.MarkToMulti(); // needed for IsAllMarked + + ULONG nCount = aNewRanges.Count(); + for (ULONG nR=0; nR<nCount; nR++) + { + ScRange aRange(*aNewRanges.GetObject(nR)); + ScCellIterator aIter( pDoc, aRange ); + ScBaseCell* pCell = aIter.GetFirst(); + while (pCell) + { + if ( pCell->GetCellType() == CELLTYPE_FORMULA ) + { + ScFormulaCell* pFCell = (ScFormulaCell*) pCell; + + ScDetectiveRefIter aRefIter( pFCell ); + ScRange aRefRange; + while ( aRefIter.GetNextRef( aRefRange) ) + { + if ( bRecursive && !bFound && !aMarkData.IsAllMarked( aRefRange ) ) + bFound = TRUE; + aMarkData.SetMultiMarkArea( aRefRange, TRUE ); + } + } + pCell = aIter.GetNext(); + } + } + + aMarkData.FillRangeListWithMarks( &aNewRanges, TRUE ); + } + while ( bRecursive && bFound ); + + return new ScCellRangesObj( pDocShell, aNewRanges ); + } + + return NULL; +} + +uno::Reference<sheet::XSheetCellRanges> SAL_CALL ScCellRangesBase::queryDependents( + sal_Bool bRecursive ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( pDocShell ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + + ScRangeList aNewRanges(aRanges); + BOOL bFound; + do + { + bFound = FALSE; + ULONG nRangesCount = aNewRanges.Count(); + + // #97205# aMarkData uses aNewRanges, not aRanges, so GetMarkData can't be used + ScMarkData aMarkData; + aMarkData.MarkFromRangeList( aNewRanges, FALSE ); + aMarkData.MarkToMulti(); // needed for IsAllMarked + + SCTAB nTab = lcl_FirstTab(aNewRanges); //! alle Tabellen + + ScCellIterator aCellIter( pDoc, 0,0, nTab, MAXCOL,MAXROW, nTab ); + ScBaseCell* pCell = aCellIter.GetFirst(); + while (pCell) + { + if (pCell->GetCellType() == CELLTYPE_FORMULA) + { + BOOL bMark = FALSE; + ScDetectiveRefIter aIter( (ScFormulaCell*) pCell ); + ScRange aRefRange; + while ( aIter.GetNextRef( aRefRange) ) + { + for (ULONG nR=0; nR<nRangesCount; nR++) + { + ScRange aRange(*aNewRanges.GetObject(nR)); + if (aRange.Intersects(aRefRange)) + bMark = TRUE; // von Teil des Ranges abhaengig + } + } + if (bMark) + { + ScRange aCellRange( aCellIter.GetCol(), + aCellIter.GetRow(), + aCellIter.GetTab() ); + if ( bRecursive && !bFound && !aMarkData.IsAllMarked( aCellRange ) ) + bFound = TRUE; + aMarkData.SetMultiMarkArea( aCellRange, TRUE ); + } + } + pCell = aCellIter.GetNext(); + } + + aMarkData.FillRangeListWithMarks( &aNewRanges, TRUE ); + } + while ( bRecursive && bFound ); + + return new ScCellRangesObj( pDocShell, aNewRanges ); + } + + return NULL; +} + +// XSearchable + +uno::Reference<util::XSearchDescriptor> SAL_CALL ScCellRangesBase::createSearchDescriptor() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScCellSearchObj; +} + +uno::Reference<container::XIndexAccess> SAL_CALL ScCellRangesBase::findAll( + const uno::Reference<util::XSearchDescriptor>& xDesc ) + throw(uno::RuntimeException) +{ + // Wenn nichts gefunden wird, soll Null zurueckgegeben werden (?) + uno::Reference<container::XIndexAccess> xRet; + if ( pDocShell && xDesc.is() ) + { + ScCellSearchObj* pSearch = ScCellSearchObj::getImplementation( xDesc ); + if (pSearch) + { + SvxSearchItem* pSearchItem = pSearch->GetSearchItem(); + if (pSearchItem) + { + ScDocument* pDoc = pDocShell->GetDocument(); + pSearchItem->SetCommand( SVX_SEARCHCMD_FIND_ALL ); + // immer nur innerhalb dieses Objekts + pSearchItem->SetSelection( !lcl_WholeSheet(aRanges) ); + + ScMarkData aMark(*GetMarkData()); + + String aDummyUndo; + SCCOL nCol = 0; + SCROW nRow = 0; + SCTAB nTab = 0; + BOOL bFound = pDoc->SearchAndReplace( *pSearchItem, nCol, nRow, nTab, + aMark, aDummyUndo, NULL ); + if (bFound) + { + ScRangeList aNewRanges; + aMark.FillRangeListWithMarks( &aNewRanges, TRUE ); + // bei findAll immer CellRanges, egal wieviel gefunden wurde + xRet.set(new ScCellRangesObj( pDocShell, aNewRanges )); + } + } + } + } + return xRet; +} + +uno::Reference<uno::XInterface> ScCellRangesBase::Find_Impl( + const uno::Reference<util::XSearchDescriptor>& xDesc, + const ScAddress* pLastPos ) +{ + uno::Reference<uno::XInterface> xRet; + if ( pDocShell && xDesc.is() ) + { + ScCellSearchObj* pSearch = ScCellSearchObj::getImplementation( xDesc ); + if (pSearch) + { + SvxSearchItem* pSearchItem = pSearch->GetSearchItem(); + if (pSearchItem) + { + ScDocument* pDoc = pDocShell->GetDocument(); + pSearchItem->SetCommand( SVX_SEARCHCMD_FIND ); + // immer nur innerhalb dieses Objekts + pSearchItem->SetSelection( !lcl_WholeSheet(aRanges) ); + + ScMarkData aMark(*GetMarkData()); + + SCCOL nCol; + SCROW nRow; + SCTAB nTab; + if (pLastPos) + pLastPos->GetVars( nCol, nRow, nTab ); + else + { + nTab = lcl_FirstTab(aRanges); //! mehrere Tabellen? + ScDocument::GetSearchAndReplaceStart( *pSearchItem, nCol, nRow ); + } + + String aDummyUndo; + BOOL bFound = pDoc->SearchAndReplace( *pSearchItem, nCol, nRow, nTab, + aMark, aDummyUndo, NULL ); + if (bFound) + { + ScAddress aFoundPos( nCol, nRow, nTab ); + xRet.set((cppu::OWeakObject*) new ScCellObj( pDocShell, aFoundPos )); + } + } + } + } + return xRet; +} + +uno::Reference<uno::XInterface> SAL_CALL ScCellRangesBase::findFirst( + const uno::Reference<util::XSearchDescriptor>& xDesc ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return Find_Impl( xDesc, NULL ); +} + +uno::Reference<uno::XInterface> SAL_CALL ScCellRangesBase::findNext( + const uno::Reference<uno::XInterface>& xStartAt, + const uno::Reference<util::XSearchDescriptor >& xDesc ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( xStartAt.is() ) + { + ScCellRangesBase* pRangesImp = ScCellRangesBase::getImplementation( xStartAt ); + if ( pRangesImp && pRangesImp->GetDocShell() == pDocShell ) + { + const ScRangeList& rStartRanges = pRangesImp->GetRangeList(); + if ( rStartRanges.Count() == 1 ) + { + ScAddress aStartPos = rStartRanges.GetObject(0)->aStart; + return Find_Impl( xDesc, &aStartPos ); + } + } + } + return NULL; +} + +// XReplaceable + +uno::Reference<util::XReplaceDescriptor> SAL_CALL ScCellRangesBase::createReplaceDescriptor() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScCellSearchObj; +} + +sal_Int32 SAL_CALL ScCellRangesBase::replaceAll( const uno::Reference<util::XSearchDescriptor>& xDesc ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + INT32 nReplaced = 0; + if ( pDocShell && xDesc.is() ) + { + ScCellSearchObj* pSearch = ScCellSearchObj::getImplementation( xDesc ); + if (pSearch) + { + SvxSearchItem* pSearchItem = pSearch->GetSearchItem(); + if (pSearchItem) + { + ScDocument* pDoc = pDocShell->GetDocument(); + BOOL bUndo(pDoc->IsUndoEnabled()); + pSearchItem->SetCommand( SVX_SEARCHCMD_REPLACE_ALL ); + // immer nur innerhalb dieses Objekts + pSearchItem->SetSelection( !lcl_WholeSheet(aRanges) ); + + ScMarkData aMark(*GetMarkData()); + + SCTAB nTabCount = pDoc->GetTableCount(); + BOOL bProtected = !pDocShell->IsEditable(); + for (SCTAB i=0; i<nTabCount; i++) + if ( aMark.GetTableSelect(i) && pDoc->IsTabProtected(i) ) + bProtected = TRUE; + if (bProtected) + { + //! Exception, oder was? + } + else + { + SCTAB nTab = aMark.GetFirstSelected(); // bei SearchAndReplace nicht benutzt + SCCOL nCol = 0; + SCROW nRow = 0; + + String aUndoStr; + ScDocument* pUndoDoc = NULL; + if (bUndo) + { + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndo( pDoc, nTab, nTab ); + } + for (SCTAB i=0; i<nTabCount; i++) + if ( aMark.GetTableSelect(i) && i != nTab && bUndo) + pUndoDoc->AddUndoTab( i, i ); + ScMarkData* pUndoMark = NULL; + if (bUndo) + pUndoMark = new ScMarkData(aMark); + + BOOL bFound(FALSE); + if (bUndo) + bFound = pDoc->SearchAndReplace( *pSearchItem, nCol, nRow, nTab, + aMark, aUndoStr, pUndoDoc ); + if (bFound) + { + nReplaced = pUndoDoc->GetCellCount(); + + pDocShell->GetUndoManager()->AddUndoAction( + new ScUndoReplace( pDocShell, *pUndoMark, nCol, nRow, nTab, + aUndoStr, pUndoDoc, pSearchItem ) ); + + pDocShell->PostPaintGridAll(); + pDocShell->SetDocumentModified(); + } + else + { + delete pUndoDoc; + delete pUndoMark; + // nReplaced bleibt 0 + } + } + } + } + } + return nReplaced; +} + +// XUnoTunnel + +sal_Int64 SAL_CALL ScCellRangesBase::getSomething( + const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); + } + return 0; +} + +// static +const uno::Sequence<sal_Int8>& ScCellRangesBase::getUnoTunnelId() +{ + static uno::Sequence<sal_Int8> * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +// static +ScCellRangesBase* ScCellRangesBase::getImplementation( const uno::Reference<uno::XInterface> xObj ) +{ + ScCellRangesBase* pRet = NULL; + uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); + if (xUT.is()) + pRet = reinterpret_cast<ScCellRangesBase*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId()))); + return pRet; +} + +//------------------------------------------------------------------------ + +ScCellRangesObj::ScCellRangesObj(ScDocShell* pDocSh, const ScRangeList& rR) : + ScCellRangesBase( pDocSh, rR ) +{ +} + +ScCellRangesObj::~ScCellRangesObj() +{ +} + +void ScCellRangesObj::RefChanged() +{ + ScCellRangesBase::RefChanged(); + + // nix weiter... +} + +uno::Any SAL_CALL ScCellRangesObj::queryInterface( const uno::Type& rType ) + throw(uno::RuntimeException) +{ + SC_QUERYINTERFACE( sheet::XSheetCellRangeContainer ) + SC_QUERYINTERFACE( sheet::XSheetCellRanges ) + SC_QUERYINTERFACE( container::XIndexAccess ) + SC_QUERY_MULTIPLE( container::XElementAccess, container::XIndexAccess ) + SC_QUERYINTERFACE( container::XEnumerationAccess ) + SC_QUERYINTERFACE( container::XNameContainer ) + SC_QUERYINTERFACE( container::XNameReplace ) + SC_QUERYINTERFACE( container::XNameAccess ) + + return ScCellRangesBase::queryInterface( rType ); +} + +void SAL_CALL ScCellRangesObj::acquire() throw() +{ + ScCellRangesBase::acquire(); +} + +void SAL_CALL ScCellRangesObj::release() throw() +{ + ScCellRangesBase::release(); +} + +uno::Sequence<uno::Type> SAL_CALL ScCellRangesObj::getTypes() throw(uno::RuntimeException) +{ + static uno::Sequence<uno::Type> aTypes; + if ( aTypes.getLength() == 0 ) + { + uno::Sequence<uno::Type> aParentTypes(ScCellRangesBase::getTypes()); + long nParentLen = aParentTypes.getLength(); + const uno::Type* pParentPtr = aParentTypes.getConstArray(); + + aTypes.realloc( nParentLen + 3 ); + uno::Type* pPtr = aTypes.getArray(); + pPtr[nParentLen + 0] = getCppuType((const uno::Reference<sheet::XSheetCellRangeContainer>*)0); + pPtr[nParentLen + 1] = getCppuType((const uno::Reference<container::XNameContainer>*)0); + pPtr[nParentLen + 2] = getCppuType((const uno::Reference<container::XEnumerationAccess>*)0); + + for (long i=0; i<nParentLen; i++) + pPtr[i] = pParentPtr[i]; // parent types first + } + return aTypes; +} + +uno::Sequence<sal_Int8> SAL_CALL ScCellRangesObj::getImplementationId() + throw(uno::RuntimeException) +{ + static uno::Sequence< sal_Int8 > aId; + if( aId.getLength() == 0 ) + { + aId.realloc( 16 ); + rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True ); + } + return aId; +} + +// XCellRanges + +ScCellRangeObj* ScCellRangesObj::GetObjectByIndex_Impl(sal_Int32 nIndex) const +{ + ScDocShell* pDocSh = GetDocShell(); + const ScRangeList& rRanges = GetRangeList(); + if ( pDocSh && nIndex >= 0 && nIndex < sal::static_int_cast<sal_Int32>(rRanges.Count()) ) + { + ScRange aRange(*rRanges.GetObject(nIndex)); + if ( aRange.aStart == aRange.aEnd ) + return new ScCellObj( pDocSh, aRange.aStart ); + else + return new ScCellRangeObj( pDocSh, aRange ); + } + + return NULL; // keine DocShell oder falscher Index +} + +uno::Sequence<table::CellRangeAddress> SAL_CALL ScCellRangesObj::getRangeAddresses() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + const ScRangeList& rRanges = GetRangeList(); + ULONG nCount = rRanges.Count(); + if ( pDocSh && nCount ) + { + table::CellRangeAddress aRangeAddress; + uno::Sequence<table::CellRangeAddress> aSeq(nCount); + table::CellRangeAddress* pAry = aSeq.getArray(); + for (sal_uInt32 i=0; i<nCount; i++) + { + ScUnoConversion::FillApiRange( aRangeAddress, *rRanges.GetObject(i) ); + pAry[i] = aRangeAddress; + } + return aSeq; + } + + return uno::Sequence<table::CellRangeAddress>(0); // leer ist moeglich +} + +uno::Reference<container::XEnumerationAccess> SAL_CALL ScCellRangesObj::getCells() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + // getCells with empty range list is possible (no exception), + // the resulting enumeration just has no elements + // (same behaviour as a valid range with no cells) + // This is handled in ScCellsEnumeration ctor. + + const ScRangeList& rRanges = GetRangeList(); + ScDocShell* pDocSh = GetDocShell(); + if (pDocSh) + return new ScCellsObj( pDocSh, rRanges ); + return NULL; +} + +rtl::OUString SAL_CALL ScCellRangesObj::getRangeAddressesAsString() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aString; + ScDocShell* pDocSh = GetDocShell(); + const ScRangeList& rRanges = GetRangeList(); + if (pDocSh) + rRanges.Format( aString, SCA_VALID | SCA_TAB_3D, pDocSh->GetDocument() ); + return aString; +} + +// XSheetCellRangeContainer + +void SAL_CALL ScCellRangesObj::addRangeAddress( const table::CellRangeAddress& rRange, + sal_Bool bMergeRanges ) + throw(::com::sun::star::uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScRange aRange(static_cast<SCCOL>(rRange.StartColumn), + static_cast<SCROW>(rRange.StartRow), + static_cast<SCTAB>(rRange.Sheet), + static_cast<SCCOL>(rRange.EndColumn), + static_cast<SCROW>(rRange.EndRow), + static_cast<SCTAB>(rRange.Sheet)); + AddRange(aRange, bMergeRanges); +} + +void lcl_RemoveNamedEntry( ScNamedEntryArr_Impl& rNamedEntries, const ScRange& rRange ) +{ + USHORT nCount = rNamedEntries.Count(); + for ( USHORT n=nCount; n--; ) + if ( rNamedEntries[n]->GetRange() == rRange ) + rNamedEntries.DeleteAndDestroy( n ); +} + +void SAL_CALL ScCellRangesObj::removeRangeAddress( const table::CellRangeAddress& rRange ) + throw(::com::sun::star::container::NoSuchElementException, + ::com::sun::star::uno::RuntimeException) +{ + ScUnoGuard aGuard; + const ScRangeList& rRanges = GetRangeList(); + + ScRangeList aSheetRanges; + ScRangeList aNotSheetRanges; + for (sal_uInt32 i = 0; i < rRanges.Count(); ++i) + { + if (rRanges.GetObject(i)->aStart.Tab() == rRange.Sheet) + { + aSheetRanges.Append(*rRanges.GetObject(i)); + } + else + { + aNotSheetRanges.Append(*rRanges.GetObject(i)); + } + } + ScMarkData aMarkData; + aMarkData.MarkFromRangeList( aSheetRanges, FALSE ); + ScRange aRange(static_cast<SCCOL>(rRange.StartColumn), + static_cast<SCROW>(rRange.StartRow), + static_cast<SCTAB>(rRange.Sheet), + static_cast<SCCOL>(rRange.EndColumn), + static_cast<SCROW>(rRange.EndRow), + static_cast<SCTAB>(rRange.Sheet)); + if (aMarkData.GetTableSelect( aRange.aStart.Tab() )) + { + aMarkData.MarkToMulti(); + if (aMarkData.IsAllMarked( aRange ) ) + { + aMarkData.SetMultiMarkArea( aRange, FALSE ); + lcl_RemoveNamedEntry(aNamedEntries, aRange); + } + else + throw container::NoSuchElementException(); + } + SetNewRanges(aNotSheetRanges); + ScRangeList aNew; + aMarkData.FillRangeListWithMarks( &aNew, FALSE ); + for (sal_uInt32 j = 0; j < aNew.Count(); ++j) + { + AddRange(*aNew.GetObject(j), sal_False); + } +} + +void SAL_CALL ScCellRangesObj::addRangeAddresses( const uno::Sequence<table::CellRangeAddress >& rRanges, + sal_Bool bMergeRanges ) + throw(::com::sun::star::uno::RuntimeException) +{ + ScUnoGuard aGuard; + sal_Int32 nCount(rRanges.getLength()); + if (nCount) + { + const table::CellRangeAddress* pRanges = rRanges.getConstArray(); + for (sal_Int32 i = 0; i < rRanges.getLength(); i++, pRanges++) + { + ScRange aRange(static_cast<SCCOL>(pRanges->StartColumn), + static_cast<SCROW>(pRanges->StartRow), + static_cast<SCTAB>(pRanges->Sheet), + static_cast<SCCOL>(pRanges->EndColumn), + static_cast<SCROW>(pRanges->EndRow), + static_cast<SCTAB>(pRanges->Sheet)); + AddRange(aRange, bMergeRanges); + } + } +} + +void SAL_CALL ScCellRangesObj::removeRangeAddresses( const uno::Sequence<table::CellRangeAddress >& rRangeSeq ) + throw(::com::sun::star::container::NoSuchElementException, + ::com::sun::star::uno::RuntimeException) +{ + // with this implementation not needed +// ScUnoGuard aGuard; + + + // use sometimes a better/faster implementation + sal_uInt32 nCount(rRangeSeq.getLength()); + if (nCount) + { + const table::CellRangeAddress* pRanges = rRangeSeq.getConstArray(); + for (sal_uInt32 i=0; i < nCount; ++i, ++pRanges) + { + removeRangeAddress(*pRanges); + } + } +} + +// XNameContainer + +void lcl_RemoveNamedEntry( ScNamedEntryArr_Impl& rNamedEntries, const String& rName ) +{ + USHORT nCount = rNamedEntries.Count(); + for ( USHORT n=nCount; n--; ) + if ( rNamedEntries[n]->GetName() == rName ) + rNamedEntries.DeleteAndDestroy( n ); +} + +void SAL_CALL ScCellRangesObj::insertByName( const rtl::OUString& aName, const uno::Any& aElement ) + throw(lang::IllegalArgumentException, container::ElementExistException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + BOOL bDone = FALSE; + + //! Type of aElement can be some specific interface instead of XInterface + + uno::Reference<uno::XInterface> xInterface(aElement, uno::UNO_QUERY); + if ( pDocSh && xInterface.is() ) + { + ScCellRangesBase* pRangesImp = ScCellRangesBase::getImplementation( xInterface ); + if ( pRangesImp && pRangesImp->GetDocShell() == pDocSh ) + { + // if explicit name is given and already existing, throw exception + + String aNamStr(aName); + if ( aNamStr.Len() ) + { + USHORT nNamedCount = aNamedEntries.Count(); + for (USHORT n=0; n<nNamedCount; n++) + if ( aNamedEntries[n]->GetName() == aNamStr ) + throw container::ElementExistException(); + } + + ScRangeList aNew(GetRangeList()); + const ScRangeList& rAddRanges = pRangesImp->GetRangeList(); + ULONG nAddCount = rAddRanges.Count(); + for (ULONG i=0; i<nAddCount; i++) + aNew.Join( *rAddRanges.GetObject(i) ); + SetNewRanges(aNew); + bDone = TRUE; + + if ( aName.getLength() && nAddCount == 1 ) + { + // if a name is given, also insert into list of named entries + // (only possible for a single range) + // name is not in aNamedEntries (tested above) + + ScNamedEntry* pEntry = new ScNamedEntry( aNamStr, *rAddRanges.GetObject(0) ); + aNamedEntries.Insert( pEntry, aNamedEntries.Count() ); + } + } + } + + if (!bDone) + { + // invalid element - double names are handled above + throw lang::IllegalArgumentException(); + } +} + +BOOL lcl_FindRangeByName( const ScRangeList& rRanges, ScDocShell* pDocSh, + const String& rName, ULONG& rIndex ) +{ + if (pDocSh) + { + String aRangeStr; + ScDocument* pDoc = pDocSh->GetDocument(); + ULONG nCount = rRanges.Count(); + for (ULONG i=0; i<nCount; i++) + { + rRanges.GetObject(i)->Format( aRangeStr, SCA_VALID | SCA_TAB_3D, pDoc ); + if ( aRangeStr == rName ) + { + rIndex = i; + return TRUE; + } + } + } + return FALSE; // nicht gefunden +} + +BOOL lcl_FindRangeOrEntry( const ScNamedEntryArr_Impl& rNamedEntries, + const ScRangeList& rRanges, ScDocShell* pDocSh, + const String& rName, ScRange& rFound ) +{ + // exact range in list? + + ULONG nIndex = 0; + if ( lcl_FindRangeByName( rRanges, pDocSh, rName, nIndex ) ) + { + rFound = *rRanges.GetObject(nIndex); + return TRUE; + } + + // range contained in selection? (sheet must be specified) + + ScRange aCellRange; + USHORT nParse = aCellRange.ParseAny( rName, pDocSh->GetDocument() ); + if ( ( nParse & ( SCA_VALID | SCA_TAB_3D ) ) == ( SCA_VALID | SCA_TAB_3D ) ) + { + ScMarkData aMarkData; + aMarkData.MarkFromRangeList( rRanges, FALSE ); + aMarkData.MarkToMulti(); // needed for IsAllMarked + if ( aMarkData.IsAllMarked( aCellRange ) ) + { + rFound = aCellRange; + return TRUE; + } + } + + // named entry in this object? + + if ( rNamedEntries.Count() ) + { + for ( USHORT n=0; n<rNamedEntries.Count(); n++ ) + if ( rNamedEntries[n]->GetName() == rName ) + { + // test if named entry is contained in rRanges + + const ScRange& rComp = rNamedEntries[n]->GetRange(); + ScMarkData aMarkData; + aMarkData.MarkFromRangeList( rRanges, FALSE ); + aMarkData.MarkToMulti(); // needed for IsAllMarked + if ( aMarkData.IsAllMarked( rComp ) ) + { + rFound = rComp; + return TRUE; + } + } + } + + return FALSE; // not found +} + +void SAL_CALL ScCellRangesObj::removeByName( const rtl::OUString& aName ) + throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + BOOL bDone = FALSE; + String aNameStr(aName); + ScDocShell* pDocSh = GetDocShell(); + const ScRangeList& rRanges = GetRangeList(); + ULONG nIndex = 0; + if ( lcl_FindRangeByName( rRanges, pDocSh, aNameStr, nIndex ) ) + { + // einzelnen Range weglassen + ScRangeList aNew; + ULONG nCount = rRanges.Count(); + for (ULONG i=0; i<nCount; i++) + if (i != nIndex) + aNew.Append( *rRanges.GetObject(i) ); + SetNewRanges(aNew); + bDone = TRUE; + } + else if (pDocSh) + { + // deselect any ranges (parsed or named entry) + ScRangeList aDiff; + BOOL bValid = ( aDiff.Parse( aNameStr, pDocSh->GetDocument() ) & SCA_VALID ) != 0; + if ( !bValid && aNamedEntries.Count() ) + { + USHORT nCount = aNamedEntries.Count(); + for (USHORT n=0; n<nCount && !bValid; n++) + if (aNamedEntries[n]->GetName() == aNameStr) + { + aDiff.RemoveAll(); + aDiff.Append( aNamedEntries[n]->GetRange() ); + bValid = TRUE; + } + } + if ( bValid ) + { + ScMarkData aMarkData; + aMarkData.MarkFromRangeList( rRanges, FALSE ); + + ULONG nDiffCount = aDiff.Count(); + for (ULONG i=0; i<nDiffCount; i++) + { + ScRange* pDiffRange = aDiff.GetObject(i); + if (aMarkData.GetTableSelect( pDiffRange->aStart.Tab() )) + aMarkData.SetMultiMarkArea( *pDiffRange, FALSE ); + } + + ScRangeList aNew; + aMarkData.FillRangeListWithMarks( &aNew, FALSE ); + SetNewRanges(aNew); + + bDone = TRUE; //! error if range was not selected before? + } + } + + if (aNamedEntries.Count()) + lcl_RemoveNamedEntry( aNamedEntries, aNameStr ); // remove named entry + + if (!bDone) + throw container::NoSuchElementException(); // not found +} + +// XNameReplace + +void SAL_CALL ScCellRangesObj::replaceByName( const rtl::OUString& aName, const uno::Any& aElement ) + throw(lang::IllegalArgumentException, container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + //! zusammenfassen? + removeByName( aName ); + insertByName( aName, aElement ); +} + +// XNameAccess + +uno::Any SAL_CALL ScCellRangesObj::getByName( const rtl::OUString& aName ) + throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Any aRet; + + String aNameStr(aName); + ScDocShell* pDocSh = GetDocShell(); + const ScRangeList& rRanges = GetRangeList(); + ScRange aRange; + if ( lcl_FindRangeOrEntry( aNamedEntries, rRanges, pDocSh, aNameStr, aRange ) ) + { + uno::Reference<table::XCellRange> xRange; + if ( aRange.aStart == aRange.aEnd ) + xRange.set(new ScCellObj( pDocSh, aRange.aStart )); + else + xRange.set(new ScCellRangeObj( pDocSh, aRange )); + aRet <<= xRange; + } + else + throw container::NoSuchElementException(); + return aRet; +} + +BOOL lcl_FindEntryName( const ScNamedEntryArr_Impl& rNamedEntries, + const ScRange& rRange, String& rName ) +{ + USHORT nCount = rNamedEntries.Count(); + for (USHORT i=0; i<nCount; i++) + if (rNamedEntries[i]->GetRange() == rRange) + { + rName = rNamedEntries[i]->GetName(); + return TRUE; + } + return FALSE; +} + +uno::Sequence<rtl::OUString> SAL_CALL ScCellRangesObj::getElementNames() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + ScDocShell* pDocSh = GetDocShell(); + const ScRangeList& rRanges = GetRangeList(); + if (pDocSh) + { + String aRangeStr; + ScDocument* pDoc = pDocSh->GetDocument(); + ULONG nCount = rRanges.Count(); + + uno::Sequence<rtl::OUString> aSeq(nCount); + rtl::OUString* pAry = aSeq.getArray(); + for (ULONG i=0; i<nCount; i++) + { + // use given name if for exactly this range, otherwise just format + ScRange aRange = *rRanges.GetObject(i); + if ( !aNamedEntries.Count() || !lcl_FindEntryName( aNamedEntries, aRange, aRangeStr ) ) + aRange.Format( aRangeStr, SCA_VALID | SCA_TAB_3D, pDoc ); + pAry[i] = aRangeStr; + } + return aSeq; + } + return uno::Sequence<rtl::OUString>(0); +} + +sal_Bool SAL_CALL ScCellRangesObj::hasByName( const rtl::OUString& aName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aNameStr(aName); + ScDocShell* pDocSh = GetDocShell(); + const ScRangeList& rRanges = GetRangeList(); + ScRange aRange; + return lcl_FindRangeOrEntry( aNamedEntries, rRanges, pDocSh, aNameStr, aRange ); +} + +// XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScCellRangesObj::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.SheetCellRangesEnumeration"))); +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScCellRangesObj::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + const ScRangeList& rRanges = GetRangeList(); + return rRanges.Count(); +} + +uno::Any SAL_CALL ScCellRangesObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<table::XCellRange> xRange(GetObjectByIndex_Impl(nIndex)); + if (xRange.is()) + return uno::makeAny(xRange); + else + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +uno::Type SAL_CALL ScCellRangesObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((uno::Reference<table::XCellRange>*)0); +} + +sal_Bool SAL_CALL ScCellRangesObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + const ScRangeList& rRanges = GetRangeList(); + return rRanges.Count() != 0; +} + +// XServiceInfo + +rtl::OUString SAL_CALL ScCellRangesObj::getImplementationName() throw(uno::RuntimeException) +{ + return rtl::OUString::createFromAscii( "ScCellRangesObj" ); +} + +sal_Bool SAL_CALL ScCellRangesObj::supportsService( const rtl::OUString& rServiceName ) + throw(uno::RuntimeException) +{ + String aServiceStr(rServiceName); + return aServiceStr.EqualsAscii( SCSHEETCELLRANGES_SERVICE ) || + aServiceStr.EqualsAscii( SCCELLPROPERTIES_SERVICE ) || + aServiceStr.EqualsAscii( SCCHARPROPERTIES_SERVICE ) || + aServiceStr.EqualsAscii( SCPARAPROPERTIES_SERVICE ); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScCellRangesObj::getSupportedServiceNames() + throw(uno::RuntimeException) +{ + uno::Sequence<rtl::OUString> aRet(4); + rtl::OUString* pArray = aRet.getArray(); + pArray[0] = rtl::OUString::createFromAscii( SCSHEETCELLRANGES_SERVICE ); + pArray[1] = rtl::OUString::createFromAscii( SCCELLPROPERTIES_SERVICE ); + pArray[2] = rtl::OUString::createFromAscii( SCCHARPROPERTIES_SERVICE ); + pArray[3] = rtl::OUString::createFromAscii( SCPARAPROPERTIES_SERVICE ); + return aRet; +} + +//------------------------------------------------------------------------ + +// static +uno::Reference<table::XCellRange> ScCellRangeObj::CreateRangeFromDoc( ScDocument* pDoc, const ScRange& rR ) +{ + SfxObjectShell* pObjSh = pDoc->GetDocumentShell(); + if ( pObjSh && pObjSh->ISA(ScDocShell) ) + return new ScCellRangeObj( (ScDocShell*) pObjSh, rR ); + return NULL; +} + +//------------------------------------------------------------------------ + +ScCellRangeObj::ScCellRangeObj(ScDocShell* pDocSh, const ScRange& rR) : + ScCellRangesBase( pDocSh, rR ), + pRangePropSet( lcl_GetRangePropertySet() ), + aRange( rR ) +{ + aRange.Justify(); // Anfang / Ende richtig +} + +ScCellRangeObj::~ScCellRangeObj() +{ +} + +void ScCellRangeObj::RefChanged() +{ + ScCellRangesBase::RefChanged(); + + const ScRangeList& rRanges = GetRangeList(); + DBG_ASSERT(rRanges.Count() == 1, "was fuer Ranges ?!?!"); + const ScRange* pFirst = rRanges.GetObject(0); + if (pFirst) + { + aRange = *pFirst; + aRange.Justify(); + } +} + +uno::Any SAL_CALL ScCellRangeObj::queryInterface( const uno::Type& rType ) + throw(uno::RuntimeException) +{ + SC_QUERYINTERFACE( sheet::XCellRangeAddressable ) + SC_QUERYINTERFACE( table::XCellRange ) + SC_QUERYINTERFACE( sheet::XSheetCellRange ) + SC_QUERYINTERFACE( sheet::XArrayFormulaRange ) + SC_QUERYINTERFACE( sheet::XArrayFormulaTokens ) + SC_QUERYINTERFACE( sheet::XCellRangeData ) + SC_QUERYINTERFACE( sheet::XCellRangeFormula ) + SC_QUERYINTERFACE( sheet::XMultipleOperation ) + SC_QUERYINTERFACE( util::XMergeable ) + SC_QUERYINTERFACE( sheet::XCellSeries ) + SC_QUERYINTERFACE( table::XAutoFormattable ) + SC_QUERYINTERFACE( util::XSortable ) + SC_QUERYINTERFACE( sheet::XSheetFilterableEx ) + SC_QUERYINTERFACE( sheet::XSheetFilterable ) + SC_QUERYINTERFACE( sheet::XSubTotalCalculatable ) + SC_QUERYINTERFACE( table::XColumnRowRange ) + SC_QUERYINTERFACE( util::XImportable ) + SC_QUERYINTERFACE( sheet::XCellFormatRangesSupplier ) + SC_QUERYINTERFACE( sheet::XUniqueCellFormatRangesSupplier ) + + return ScCellRangesBase::queryInterface( rType ); +} + +void SAL_CALL ScCellRangeObj::acquire() throw() +{ + ScCellRangesBase::acquire(); +} + +void SAL_CALL ScCellRangeObj::release() throw() +{ + ScCellRangesBase::release(); +} + +uno::Sequence<uno::Type> SAL_CALL ScCellRangeObj::getTypes() throw(uno::RuntimeException) +{ + static uno::Sequence<uno::Type> aTypes; + if ( aTypes.getLength() == 0 ) + { + uno::Sequence<uno::Type> aParentTypes(ScCellRangesBase::getTypes()); + long nParentLen = aParentTypes.getLength(); + const uno::Type* pParentPtr = aParentTypes.getConstArray(); + + aTypes.realloc( nParentLen + 17 ); + uno::Type* pPtr = aTypes.getArray(); + pPtr[nParentLen + 0] = getCppuType((const uno::Reference<sheet::XCellRangeAddressable>*)0); + pPtr[nParentLen + 1] = getCppuType((const uno::Reference<sheet::XSheetCellRange>*)0); + pPtr[nParentLen + 2] = getCppuType((const uno::Reference<sheet::XArrayFormulaRange>*)0); + pPtr[nParentLen + 3] = getCppuType((const uno::Reference<sheet::XArrayFormulaTokens>*)0); + pPtr[nParentLen + 4] = getCppuType((const uno::Reference<sheet::XCellRangeData>*)0); + pPtr[nParentLen + 5] = getCppuType((const uno::Reference<sheet::XCellRangeFormula>*)0); + pPtr[nParentLen + 6] = getCppuType((const uno::Reference<sheet::XMultipleOperation>*)0); + pPtr[nParentLen + 7] = getCppuType((const uno::Reference<util::XMergeable>*)0); + pPtr[nParentLen + 8] = getCppuType((const uno::Reference<sheet::XCellSeries>*)0); + pPtr[nParentLen + 9] = getCppuType((const uno::Reference<table::XAutoFormattable>*)0); + pPtr[nParentLen +10] = getCppuType((const uno::Reference<util::XSortable>*)0); + pPtr[nParentLen +11] = getCppuType((const uno::Reference<sheet::XSheetFilterableEx>*)0); + pPtr[nParentLen +12] = getCppuType((const uno::Reference<sheet::XSubTotalCalculatable>*)0); + pPtr[nParentLen +13] = getCppuType((const uno::Reference<table::XColumnRowRange>*)0); + pPtr[nParentLen +14] = getCppuType((const uno::Reference<util::XImportable>*)0); + pPtr[nParentLen +15] = getCppuType((const uno::Reference<sheet::XCellFormatRangesSupplier>*)0); + pPtr[nParentLen +16] = getCppuType((const uno::Reference<sheet::XUniqueCellFormatRangesSupplier>*)0); + + for (long i=0; i<nParentLen; i++) + pPtr[i] = pParentPtr[i]; // parent types first + } + return aTypes; +} + +uno::Sequence<sal_Int8> SAL_CALL ScCellRangeObj::getImplementationId() + throw(uno::RuntimeException) +{ + static uno::Sequence< sal_Int8 > aId; + if( aId.getLength() == 0 ) + { + aId.realloc( 16 ); + rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True ); + } + return aId; +} + +// XCellRange + +// ColumnCount / RowCount sind weggefallen +//! werden im Writer fuer Tabellen noch gebraucht ??? + +uno::Reference<table::XCell> ScCellRangeObj::GetCellByPosition_Impl( + sal_Int32 nColumn, sal_Int32 nRow ) + throw(lang::IndexOutOfBoundsException, uno::RuntimeException) +{ + ScDocShell* pDocSh = GetDocShell(); + if (!pDocSh) + throw uno::RuntimeException(); + + if ( nColumn >= 0 && nRow >= 0 ) + { + sal_Int32 nPosX = aRange.aStart.Col() + nColumn; + sal_Int32 nPosY = aRange.aStart.Row() + nRow; + + if ( nPosX <= aRange.aEnd.Col() && nPosY <= aRange.aEnd.Row() ) + { + ScAddress aNew( (SCCOL)nPosX, (SCROW)nPosY, aRange.aStart.Tab() ); + return new ScCellObj( pDocSh, aNew ); + } + } + + throw lang::IndexOutOfBoundsException(); +// return NULL; +} + +uno::Reference<table::XCell> SAL_CALL ScCellRangeObj::getCellByPosition( + sal_Int32 nColumn, sal_Int32 nRow ) + throw(lang::IndexOutOfBoundsException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + return GetCellByPosition_Impl(nColumn, nRow); +} + +uno::Reference<table::XCellRange> SAL_CALL ScCellRangeObj::getCellRangeByPosition( + sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom ) + throw(lang::IndexOutOfBoundsException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + ScDocShell* pDocSh = GetDocShell(); + if (!pDocSh) + throw uno::RuntimeException(); + + if ( nLeft >= 0 && nTop >= 0 && nRight >= 0 && nBottom >= 0 ) + { + sal_Int32 nStartX = aRange.aStart.Col() + nLeft; + sal_Int32 nStartY = aRange.aStart.Row() + nTop; + sal_Int32 nEndX = aRange.aStart.Col() + nRight; + sal_Int32 nEndY = aRange.aStart.Row() + nBottom; + + if ( nStartX <= nEndX && nEndX <= aRange.aEnd.Col() && + nStartY <= nEndY && nEndY <= aRange.aEnd.Row() ) + { + ScRange aNew( (SCCOL)nStartX, (SCROW)nStartY, aRange.aStart.Tab(), + (SCCOL)nEndX, (SCROW)nEndY, aRange.aEnd.Tab() ); + return new ScCellRangeObj( pDocSh, aNew ); + } + } + + throw lang::IndexOutOfBoundsException(); +// return NULL; +} + + +uno::Reference<table::XCellRange> SAL_CALL ScCellRangeObj::getCellRangeByName( + const rtl::OUString& aName ) throw(uno::RuntimeException) +{ + return getCellRangeByName( aName, ScAddress::detailsOOOa1 ); +} + +uno::Reference<table::XCellRange> ScCellRangeObj::getCellRangeByName( + const rtl::OUString& aName, const ScAddress::Details& rDetails ) throw(uno::RuntimeException) +{ + // name refers to the whole document (with the range's table as default), + // valid only if the range is within this range + + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = aRange.aStart.Tab(); + + ScRange aCellRange; + BOOL bFound = FALSE; + String aString(aName); + USHORT nParse = aCellRange.ParseAny( aString, pDoc, rDetails ); + if ( nParse & SCA_VALID ) + { + if ( !(nParse & SCA_TAB_3D) ) // keine Tabelle angegeben -> auf dieser Tabelle + { + aCellRange.aStart.SetTab(nTab); + aCellRange.aEnd.SetTab(nTab); + } + bFound = TRUE; + } + else + { + ScRangeUtil aRangeUtil; + if ( aRangeUtil.MakeRangeFromName( aString, pDoc, nTab, aCellRange, RUTL_NAMES ) || + aRangeUtil.MakeRangeFromName( aString, pDoc, nTab, aCellRange, RUTL_DBASE ) ) + bFound = TRUE; + } + + if (bFound) // valid only if within this object's range + { + if (!aRange.In(aCellRange)) + bFound = FALSE; + } + + if (bFound) + { + if ( aCellRange.aStart == aCellRange.aEnd ) + return new ScCellObj( pDocSh, aCellRange.aStart ); + else + return new ScCellRangeObj( pDocSh, aCellRange ); + } + } + + throw uno::RuntimeException(); +// return NULL; +} + +// XColumnRowRange + +uno::Reference<table::XTableColumns> SAL_CALL ScCellRangeObj::getColumns() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if (pDocSh) + return new ScTableColumnsObj( pDocSh, aRange.aStart.Tab(), + aRange.aStart.Col(), aRange.aEnd.Col() ); + + DBG_ERROR("Dokument ungueltig"); + return NULL; +} + +uno::Reference<table::XTableRows> SAL_CALL ScCellRangeObj::getRows() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if (pDocSh) + return new ScTableRowsObj( pDocSh, aRange.aStart.Tab(), + aRange.aStart.Row(), aRange.aEnd.Row() ); + + DBG_ERROR("Dokument ungueltig"); + return NULL; +} + +// XAddressableCellRange + +table::CellRangeAddress SAL_CALL ScCellRangeObj::getRangeAddress() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + table::CellRangeAddress aRet; + ScUnoConversion::FillApiRange( aRet, aRange ); + return aRet; +} + +// XSheetCellRange + +uno::Reference<sheet::XSpreadsheet> SAL_CALL ScCellRangeObj::getSpreadsheet() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if (pDocSh) + return new ScTableSheetObj( pDocSh, aRange.aStart.Tab() ); + + DBG_ERROR("Dokument ungueltig"); + return NULL; +} + +// XArrayFormulaRange + +rtl::OUString SAL_CALL ScCellRangeObj::getArrayFormula() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + // Matrix-Formel, wenn eindeutig Teil einer Matrix, + // also wenn Anfang und Ende des Blocks zur selben Matrix gehoeren. + // Sonst Leerstring. + + String aFormula; + ScDocShell* pDocSh = GetDocShell(); + if (pDocSh) + { + ScDocument* pDoc = pDocSh->GetDocument(); + const ScBaseCell* pCell1 = pDoc->GetCell( aRange.aStart ); + const ScBaseCell* pCell2 = pDoc->GetCell( aRange.aEnd ); + if ( pCell1 && pCell2 && pCell1->GetCellType() == CELLTYPE_FORMULA && + pCell2->GetCellType() == CELLTYPE_FORMULA ) + { + const ScFormulaCell* pFCell1 = (const ScFormulaCell*)pCell1; + const ScFormulaCell* pFCell2 = (const ScFormulaCell*)pCell2; + ScAddress aStart1; + ScAddress aStart2; + if ( pFCell1->GetMatrixOrigin( aStart1 ) && pFCell2->GetMatrixOrigin( aStart2 ) ) + { + if ( aStart1 == aStart2 ) // beides dieselbe Matrix + pFCell1->GetFormula( aFormula ); // egal, von welcher Zelle + } + } + } + return aFormula; +} + +void ScCellRangeObj::SetArrayFormula_Impl( const rtl::OUString& rFormula, + const rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar ) throw(uno::RuntimeException) +{ + ScDocShell* pDocSh = GetDocShell(); + if (pDocSh) + { + ScDocFunc aFunc(*pDocSh); + if ( rFormula.getLength() ) + { + if ( ScTableSheetObj::getImplementation( (cppu::OWeakObject*)this ) ) + { + // #74681# don't set array formula for sheet object + throw uno::RuntimeException(); + } + + aFunc.EnterMatrix( aRange, NULL, NULL, rFormula, TRUE, TRUE, rFormulaNmsp, eGrammar ); + } + else + { + // empty string -> erase array formula + ScMarkData aMark; + aMark.SetMarkArea( aRange ); + aMark.SelectTable( aRange.aStart.Tab(), TRUE ); + aFunc.DeleteContents( aMark, IDF_CONTENTS, TRUE, TRUE ); + } + } +} + +void SAL_CALL ScCellRangeObj::setArrayFormula( const rtl::OUString& aFormula ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + // GRAM_PODF_A1 for API compatibility. + SetArrayFormula_Impl( aFormula, ::rtl::OUString(), formula::FormulaGrammar::GRAM_PODF_A1); +} + +void ScCellRangeObj::SetArrayFormulaWithGrammar( const rtl::OUString& rFormula, + const rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + SetArrayFormula_Impl( rFormula, rFormulaNmsp, eGrammar); +} + +// XArrayFormulaTokens + +uno::Sequence<sheet::FormulaToken> SAL_CALL ScCellRangeObj::getArrayTokens() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + // same cell logic as in getArrayFormula + + uno::Sequence<sheet::FormulaToken> aSequence; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + const ScBaseCell* pCell1 = pDoc->GetCell( aRange.aStart ); + const ScBaseCell* pCell2 = pDoc->GetCell( aRange.aEnd ); + if ( pCell1 && pCell2 && pCell1->GetCellType() == CELLTYPE_FORMULA && + pCell2->GetCellType() == CELLTYPE_FORMULA ) + { + const ScFormulaCell* pFCell1 = (const ScFormulaCell*)pCell1; + const ScFormulaCell* pFCell2 = (const ScFormulaCell*)pCell2; + ScAddress aStart1; + ScAddress aStart2; + if ( pFCell1->GetMatrixOrigin( aStart1 ) && pFCell2->GetMatrixOrigin( aStart2 ) ) + { + if ( aStart1 == aStart2 ) + { + ScTokenArray* pTokenArray = pFCell1->GetCode(); + if ( pTokenArray ) + (void)ScTokenConversion::ConvertToTokenSequence( *pDoc, aSequence, *pTokenArray ); + } + } + } + } + return aSequence; +} + +void SAL_CALL ScCellRangeObj::setArrayTokens( const uno::Sequence<sheet::FormulaToken>& rTokens ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocFunc aFunc(*pDocSh); + if ( rTokens.getLength() ) + { + if ( ScTableSheetObj::getImplementation( (cppu::OWeakObject*)this ) ) + { + throw uno::RuntimeException(); + } + + ScDocument* pDoc = pDocSh->GetDocument(); + ScTokenArray aTokenArray; + (void)ScTokenConversion::ConvertToTokenArray( *pDoc, aTokenArray, rTokens ); + + // Actually GRAM_PODF_A1 is a don't-care here because of the token + // array being set, it fits with other API compatibility grammars + // though. + aFunc.EnterMatrix( aRange, NULL, &aTokenArray, EMPTY_STRING, TRUE, TRUE, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 ); + } + else + { + // empty sequence -> erase array formula + ScMarkData aMark; + aMark.SetMarkArea( aRange ); + aMark.SelectTable( aRange.aStart.Tab(), TRUE ); + aFunc.DeleteContents( aMark, IDF_CONTENTS, TRUE, TRUE ); + } + } +} + +// XCellRangeData + +uno::Sequence< uno::Sequence<uno::Any> > SAL_CALL ScCellRangeObj::getDataArray() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if ( ScTableSheetObj::getImplementation( (cppu::OWeakObject*)this ) ) + { + // don't create a data array for the sheet + throw uno::RuntimeException(); + } + + ScDocShell* pDocSh = GetDocShell(); + if (pDocSh) + { + uno::Any aAny; + // bAllowNV = TRUE: errors as void + if ( ScRangeToSequence::FillMixedArray( aAny, pDocSh->GetDocument(), aRange, TRUE ) ) + { + uno::Sequence< uno::Sequence<uno::Any> > aSeq; + if ( aAny >>= aSeq ) + return aSeq; // success + } + } + + throw uno::RuntimeException(); // no other exceptions specified +// return uno::Sequence< uno::Sequence<uno::Any> >(0); +} + +void SAL_CALL ScCellRangeObj::setDataArray( + const uno::Sequence< uno::Sequence<uno::Any> >& aArray ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + BOOL bDone = FALSE; + ScDocShell* pDocSh = GetDocShell(); + if (pDocSh) + { + //! move lcl_PutDataArray to docfunc? + bDone = lcl_PutDataArray( *pDocSh, aRange, aArray ); + } + + if (!bDone) + throw uno::RuntimeException(); // no other exceptions specified +} + +// XCellRangeFormula + +uno::Sequence< uno::Sequence<rtl::OUString> > SAL_CALL ScCellRangeObj::getFormulaArray() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if ( ScTableSheetObj::getImplementation( (cppu::OWeakObject*)this ) ) + { + // don't create a data array for the sheet + throw uno::RuntimeException(); + } + + ScDocShell* pDocSh = GetDocShell(); + if (pDocSh) + { + SCCOL nStartCol = aRange.aStart.Col(); + SCROW nStartRow = aRange.aStart.Row(); + SCCOL nEndCol = aRange.aEnd.Col(); + SCROW nEndRow = aRange.aEnd.Row(); + SCCOL nColCount = nEndCol + 1 - nStartCol; + SCROW nRowCount = nEndRow + 1 - nStartRow; + SCTAB nTab = aRange.aStart.Tab(); + + uno::Sequence< uno::Sequence<rtl::OUString> > aRowSeq( nRowCount ); + uno::Sequence<rtl::OUString>* pRowAry = aRowSeq.getArray(); + for (SCROW nRowIndex = 0; nRowIndex < nRowCount; nRowIndex++) + { + uno::Sequence<rtl::OUString> aColSeq( nColCount ); + rtl::OUString* pColAry = aColSeq.getArray(); + for (SCCOL nColIndex = 0; nColIndex < nColCount; nColIndex++) + pColAry[nColIndex] = lcl_GetInputString( pDocSh->GetDocument(), + ScAddress( nStartCol+nColIndex, nStartRow+nRowIndex, nTab ), TRUE ); + + pRowAry[nRowIndex] = aColSeq; + } + + return aRowSeq; + } + + throw uno::RuntimeException(); // no other exceptions specified +// return uno::Sequence< uno::Sequence<rtl::OUString> >(0); +} + +void SAL_CALL ScCellRangeObj::setFormulaArray( + const uno::Sequence< uno::Sequence<rtl::OUString> >& aArray ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + BOOL bDone = FALSE; + ScDocShell* pDocSh = GetDocShell(); + if (pDocSh) + { + ScExternalRefManager::ApiGuard aExtRefGuard(pDocSh->GetDocument()); + + // GRAM_PODF_A1 for API compatibility. + bDone = lcl_PutFormulaArray( *pDocSh, aRange, aArray, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 ); + } + + if (!bDone) + throw uno::RuntimeException(); // no other exceptions specified +} + +// XMultipleOperation + +void SAL_CALL ScCellRangeObj::setTableOperation( const table::CellRangeAddress& aFormulaRange, + sheet::TableOperationMode nMode, + const table::CellAddress& aColumnCell, + const table::CellAddress& aRowCell ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if (pDocSh) + { + BOOL bError = FALSE; + ScTabOpParam aParam; + aParam.aRefFormulaCell = ScRefAddress( (SCCOL)aFormulaRange.StartColumn, + (SCROW)aFormulaRange.StartRow, aFormulaRange.Sheet, + FALSE, FALSE, FALSE ); + aParam.aRefFormulaEnd = ScRefAddress( (SCCOL)aFormulaRange.EndColumn, + (SCROW)aFormulaRange.EndRow, aFormulaRange.Sheet, + FALSE, FALSE, FALSE ); + aParam.aRefRowCell = ScRefAddress( (SCCOL)aRowCell.Column, + (SCROW)aRowCell.Row, aRowCell.Sheet, + FALSE, FALSE, FALSE ); + aParam.aRefColCell = ScRefAddress( (SCCOL)aColumnCell.Column, + (SCROW)aColumnCell.Row, aColumnCell.Sheet, + FALSE, FALSE, FALSE ); + switch (nMode) + { + case sheet::TableOperationMode_COLUMN: + aParam.nMode = 0; + break; + case sheet::TableOperationMode_ROW: + aParam.nMode = 1; + break; + case sheet::TableOperationMode_BOTH: + aParam.nMode = 2; + break; + default: + bError = TRUE; + } + + if (!bError) + { + ScDocFunc aFunc(*pDocSh); + aFunc.TabOp( aRange, NULL, aParam, TRUE, TRUE ); + } + } +} + +// XMergeable + +void SAL_CALL ScCellRangeObj::merge( sal_Bool bMerge ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocFunc aFunc(*pDocSh); + if ( bMerge ) + aFunc.MergeCells( aRange, FALSE, TRUE, TRUE ); + else + aFunc.UnmergeCells( aRange, TRUE, TRUE ); + + //! Fehler abfangen? + } +} + +sal_Bool SAL_CALL ScCellRangeObj::getIsMerged() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + return pDocSh && pDocSh->GetDocument()->HasAttrib( aRange, HASATTR_MERGED ); +} + +// XCellSeries + +void SAL_CALL ScCellRangeObj::fillSeries( sheet::FillDirection nFillDirection, + sheet::FillMode nFillMode, sheet::FillDateMode nFillDateMode, + double fStep, double fEndValue ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + BOOL bError = FALSE; + + FillDir eDir = FILL_TO_BOTTOM; + switch (nFillDirection) + { + case sheet::FillDirection_TO_BOTTOM: + eDir = FILL_TO_BOTTOM; + break; + case sheet::FillDirection_TO_RIGHT: + eDir = FILL_TO_RIGHT; + break; + case sheet::FillDirection_TO_TOP: + eDir = FILL_TO_TOP; + break; + case sheet::FillDirection_TO_LEFT: + eDir = FILL_TO_LEFT; + break; + default: + bError = TRUE; + } + + FillCmd eCmd = FILL_SIMPLE; + switch ( nFillMode ) + { + case sheet::FillMode_SIMPLE: + eCmd = FILL_SIMPLE; + break; + case sheet::FillMode_LINEAR: + eCmd = FILL_LINEAR; + break; + case sheet::FillMode_GROWTH: + eCmd = FILL_GROWTH; + break; + case sheet::FillMode_DATE: + eCmd = FILL_DATE; + break; + case sheet::FillMode_AUTO: + eCmd = FILL_AUTO; + break; + default: + bError = TRUE; + } + + FillDateCmd eDateCmd = FILL_DAY; + switch ( nFillDateMode ) + { + case sheet::FillDateMode_FILL_DATE_DAY: + eDateCmd = FILL_DAY; + break; + case sheet::FillDateMode_FILL_DATE_WEEKDAY: + eDateCmd = FILL_WEEKDAY; + break; + case sheet::FillDateMode_FILL_DATE_MONTH: + eDateCmd = FILL_MONTH; + break; + case sheet::FillDateMode_FILL_DATE_YEAR: + eDateCmd = FILL_YEAR; + break; + default: + bError = TRUE; + } + + if (!bError) + { + ScDocFunc aFunc(*pDocSh); + aFunc.FillSeries( aRange, NULL, eDir, eCmd, eDateCmd, + MAXDOUBLE, fStep, fEndValue, TRUE, TRUE ); + } + } +} + +void SAL_CALL ScCellRangeObj::fillAuto( sheet::FillDirection nFillDirection, + sal_Int32 nSourceCount ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh && nSourceCount ) + { + ScRange aSourceRange(aRange); + SCsCOLROW nCount = 0; // "Dest-Count" + FillDir eDir = FILL_TO_BOTTOM; + BOOL bError = FALSE; + switch (nFillDirection) + { + case sheet::FillDirection_TO_BOTTOM: + aSourceRange.aEnd.SetRow( static_cast<SCROW>( aSourceRange.aStart.Row() + nSourceCount - 1 ) ); + nCount = aRange.aEnd.Row() - aSourceRange.aEnd.Row(); + eDir = FILL_TO_BOTTOM; + break; + case sheet::FillDirection_TO_RIGHT: + aSourceRange.aEnd.SetCol( static_cast<SCCOL>( aSourceRange.aStart.Col() + nSourceCount - 1 ) ); + nCount = aRange.aEnd.Col() - aSourceRange.aEnd.Col(); + eDir = FILL_TO_RIGHT; + break; + case sheet::FillDirection_TO_TOP: + aSourceRange.aStart.SetRow( static_cast<SCROW>( aSourceRange.aEnd.Row() - nSourceCount + 1 ) ); + nCount = aSourceRange.aStart.Row() - aRange.aStart.Row(); + eDir = FILL_TO_TOP; + break; + case sheet::FillDirection_TO_LEFT: + aSourceRange.aStart.SetCol( static_cast<SCCOL>( aSourceRange.aEnd.Col() - nSourceCount + 1 ) ); + nCount = aSourceRange.aStart.Col() - aRange.aStart.Col(); + eDir = FILL_TO_LEFT; + break; + default: + bError = TRUE; + } + if (nCount < 0 || nCount > MAXROW) // overflow + bError = TRUE; + + if (!bError) + { + ScDocFunc aFunc(*pDocSh); + aFunc.FillAuto( aSourceRange, NULL, eDir, nCount, TRUE, TRUE ); + } + } +} + +// XAutoFormattable + +void SAL_CALL ScCellRangeObj::autoFormat( const rtl::OUString& aName ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScAutoFormat* pAutoFormat = ScGlobal::GetAutoFormat(); + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh && pAutoFormat ) + { + String aNameString(aName); + USHORT nCount = pAutoFormat->GetCount(); + USHORT nIndex; + String aCompare; + for (nIndex=0; nIndex<nCount; nIndex++) + { + (*pAutoFormat)[nIndex]->GetName(aCompare); + if ( aCompare == aNameString ) //! Case-insensitiv ??? + break; + } + if (nIndex<nCount) + { + ScDocFunc aFunc(*pDocSh); + aFunc.AutoFormat( aRange, NULL, nIndex, TRUE, TRUE ); + } + else + throw lang::IllegalArgumentException(); + } +} + +// XSortable + +uno::Sequence<beans::PropertyValue> SAL_CALL ScCellRangeObj::createSortDescriptor() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScSortParam aParam; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + // DB-Bereich anlegen erst beim Ausfuehren, per API immer genau den Bereich + ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_OLD, SC_DBSEL_FORCE_MARK ); + if (pData) + { + pData->GetSortParam(aParam); + + // im SortDescriptor sind die Fields innerhalb des Bereichs gezaehlt + ScRange aDBRange; + pData->GetArea(aDBRange); + SCCOLROW nFieldStart = aParam.bByRow ? + static_cast<SCCOLROW>(aDBRange.aStart.Col()) : + static_cast<SCCOLROW>(aDBRange.aStart.Row()); + for (USHORT i=0; i<MAXSORT; i++) + if ( aParam.bDoSort[i] && aParam.nField[i] >= nFieldStart ) + aParam.nField[i] -= nFieldStart; + } + } + + uno::Sequence<beans::PropertyValue> aSeq( ScSortDescriptor::GetPropertyCount() ); + ScSortDescriptor::FillProperties( aSeq, aParam ); + return aSeq; +} + +void SAL_CALL ScCellRangeObj::sort( const uno::Sequence<beans::PropertyValue>& aDescriptor ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if (pDocSh) + { + USHORT i; + ScSortParam aParam; + ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_MAKE, SC_DBSEL_FORCE_MARK ); // ggf. Bereich anlegen + if (pData) + { + // alten Einstellungen holen, falls nicht alles neu gesetzt wird + pData->GetSortParam(aParam); + SCCOLROW nOldStart = aParam.bByRow ? + static_cast<SCCOLROW>(aRange.aStart.Col()) : + static_cast<SCCOLROW>(aRange.aStart.Row()); + for (i=0; i<MAXSORT; i++) + if ( aParam.bDoSort[i] && aParam.nField[i] >= nOldStart ) + aParam.nField[i] -= nOldStart; + } + + ScSortDescriptor::FillSortParam( aParam, aDescriptor ); + + // im SortDescriptor sind die Fields innerhalb des Bereichs gezaehlt + // ByRow kann bei FillSortParam umgesetzt worden sein + SCCOLROW nFieldStart = aParam.bByRow ? + static_cast<SCCOLROW>(aRange.aStart.Col()) : + static_cast<SCCOLROW>(aRange.aStart.Row()); + for (i=0; i<MAXSORT; i++) + aParam.nField[i] += nFieldStart; + + SCTAB nTab = aRange.aStart.Tab(); + aParam.nCol1 = aRange.aStart.Col(); + aParam.nRow1 = aRange.aStart.Row(); + aParam.nCol2 = aRange.aEnd.Col(); + aParam.nRow2 = aRange.aEnd.Row(); + + pDocSh->GetDBData( aRange, SC_DB_MAKE, SC_DBSEL_FORCE_MARK ); // ggf. Bereich anlegen + + ScDBDocFunc aFunc(*pDocSh); // Bereich muss angelegt sein + aFunc.Sort( nTab, aParam, TRUE, TRUE, TRUE ); + } +} + +// XFilterable + +uno::Reference<sheet::XSheetFilterDescriptor> SAL_CALL ScCellRangeObj::createFilterDescriptor( + sal_Bool bEmpty ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + ScFilterDescriptor* pNew = new ScFilterDescriptor(pDocSh); + if ( !bEmpty && pDocSh ) + { + // DB-Bereich anlegen erst beim Ausfuehren, per API immer genau den Bereich + ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_OLD, SC_DBSEL_FORCE_MARK ); + if (pData) + { + ScQueryParam aParam; + pData->GetQueryParam(aParam); + // im FilterDescriptor sind die Fields innerhalb des Bereichs gezaehlt + ScRange aDBRange; + pData->GetArea(aDBRange); + SCCOLROW nFieldStart = aParam.bByRow ? + static_cast<SCCOLROW>(aDBRange.aStart.Col()) : + static_cast<SCCOLROW>(aDBRange.aStart.Row()); + SCSIZE nCount = aParam.GetEntryCount(); + for (SCSIZE i=0; i<nCount; i++) + { + ScQueryEntry& rEntry = aParam.GetEntry(i); + if (rEntry.bDoQuery && rEntry.nField >= nFieldStart) + rEntry.nField -= nFieldStart; + } + pNew->SetParam(aParam); + } + } + return pNew; +} + +void SAL_CALL ScCellRangeObj::filter( const uno::Reference<sheet::XSheetFilterDescriptor>& xDescriptor ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + // das koennte theoretisch ein fremdes Objekt sein, also nur das + // oeffentliche XSheetFilterDescriptor Interface benutzen, um + // die Daten in ein ScFilterDescriptor Objekt zu kopieren: + //! wenn es schon ein ScFilterDescriptor ist, direkt per getImplementation? + + ScDocShell* pDocSh = GetDocShell(); + ScFilterDescriptor aImpl(pDocSh); + uno::Reference< sheet::XSheetFilterDescriptor2 > xDescriptor2( xDescriptor, uno::UNO_QUERY ); + if ( xDescriptor2.is() ) + { + aImpl.setFilterFields2( xDescriptor2->getFilterFields2() ); + } + else + { + aImpl.setFilterFields( xDescriptor->getFilterFields() ); + } + // Rest sind jetzt Properties... + + uno::Reference<beans::XPropertySet> xPropSet( xDescriptor, uno::UNO_QUERY ); + if (xPropSet.is()) + lcl_CopyProperties( aImpl, *(beans::XPropertySet*)xPropSet.get() ); + + // + // ausfuehren... + // + + if (pDocSh) + { + ScQueryParam aParam = aImpl.GetParam(); + // im FilterDescriptor sind die Fields innerhalb des Bereichs gezaehlt + SCCOLROW nFieldStart = aParam.bByRow ? + static_cast<SCCOLROW>(aRange.aStart.Col()) : + static_cast<SCCOLROW>(aRange.aStart.Row()); + SCSIZE nCount = aParam.GetEntryCount(); + for (SCSIZE i=0; i<nCount; i++) + { + ScQueryEntry& rEntry = aParam.GetEntry(i); + if (rEntry.bDoQuery) + { + rEntry.nField += nFieldStart; + // Im Dialog wird immer der String angezeigt -> muss zum Wert passen + if ( !rEntry.bQueryByString ) + pDocSh->GetDocument()->GetFormatTable()-> + GetInputLineString( rEntry.nVal, 0, *rEntry.pStr ); + } + } + + SCTAB nTab = aRange.aStart.Tab(); + aParam.nCol1 = aRange.aStart.Col(); + aParam.nRow1 = aRange.aStart.Row(); + aParam.nCol2 = aRange.aEnd.Col(); + aParam.nRow2 = aRange.aEnd.Row(); + + pDocSh->GetDBData( aRange, SC_DB_MAKE, SC_DBSEL_FORCE_MARK ); // ggf. Bereich anlegen + + //! keep source range in filter descriptor + //! if created by createFilterDescriptorByObject ??? + + ScDBDocFunc aFunc(*pDocSh); + aFunc.Query( nTab, aParam, NULL, TRUE, TRUE ); // Bereich muss angelegt sein + } +} + +//! get/setAutoFilter als Properties!!! + +// XAdvancedFilterSource + +uno::Reference<sheet::XSheetFilterDescriptor> SAL_CALL ScCellRangeObj::createFilterDescriptorByObject( + const uno::Reference<sheet::XSheetFilterable>& xObject ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + // this ist hier nicht der Bereich, der gefiltert wird, sondern der + // Bereich mit der Abfrage... + + uno::Reference<sheet::XCellRangeAddressable> xAddr( xObject, uno::UNO_QUERY ); + + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh && xAddr.is() ) + { + //! Test, ob xObject im selben Dokument ist + + ScFilterDescriptor* pNew = new ScFilterDescriptor(pDocSh); //! stattdessen vom Objekt? + //XSheetFilterDescriptorRef xNew = xObject->createFilterDescriptor(TRUE); + + ScQueryParam aParam = pNew->GetParam(); + aParam.bHasHeader = TRUE; + + table::CellRangeAddress aDataAddress(xAddr->getRangeAddress()); + aParam.nCol1 = (SCCOL)aDataAddress.StartColumn; + aParam.nRow1 = (SCROW)aDataAddress.StartRow; + aParam.nCol2 = (SCCOL)aDataAddress.EndColumn; + aParam.nRow2 = (SCROW)aDataAddress.EndRow; + aParam.nTab = aDataAddress.Sheet; + + ScDocument* pDoc = pDocSh->GetDocument(); + BOOL bOk = pDoc->CreateQueryParam( + aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aEnd.Row(), + aRange.aStart.Tab(), aParam ); + if ( bOk ) + { + // im FilterDescriptor sind die Fields innerhalb des Bereichs gezaehlt + SCCOLROW nFieldStart = aParam.bByRow ? + static_cast<SCCOLROW>(aDataAddress.StartColumn) : + static_cast<SCCOLROW>(aDataAddress.StartRow); + SCSIZE nCount = aParam.GetEntryCount(); + for (SCSIZE i=0; i<nCount; i++) + { + ScQueryEntry& rEntry = aParam.GetEntry(i); + if (rEntry.bDoQuery && rEntry.nField >= nFieldStart) + rEntry.nField -= nFieldStart; + } + + pNew->SetParam( aParam ); + return pNew; + } + else + { + delete pNew; + return NULL; // ungueltig -> null + } + } + + DBG_ERROR("kein Dokument oder kein Bereich"); + return NULL; +} + +// XSubTotalSource + +uno::Reference<sheet::XSubTotalDescriptor> SAL_CALL ScCellRangeObj::createSubTotalDescriptor( + sal_Bool bEmpty ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScSubTotalDescriptor* pNew = new ScSubTotalDescriptor; + ScDocShell* pDocSh = GetDocShell(); + if ( !bEmpty && pDocSh ) + { + // DB-Bereich anlegen erst beim Ausfuehren, per API immer genau den Bereich + ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_OLD, SC_DBSEL_FORCE_MARK ); + if (pData) + { + ScSubTotalParam aParam; + pData->GetSubTotalParam(aParam); + // im SubTotalDescriptor sind die Fields innerhalb des Bereichs gezaehlt + ScRange aDBRange; + pData->GetArea(aDBRange); + SCCOL nFieldStart = aDBRange.aStart.Col(); + for (USHORT i=0; i<MAXSUBTOTAL; i++) + { + if ( aParam.bGroupActive[i] ) + { + if ( aParam.nField[i] >= nFieldStart ) + aParam.nField[i] = sal::static_int_cast<SCCOL>( aParam.nField[i] - nFieldStart ); + for (SCCOL j=0; j<aParam.nSubTotals[i]; j++) + if ( aParam.pSubTotals[i][j] >= nFieldStart ) + aParam.pSubTotals[i][j] = sal::static_int_cast<SCCOL>( aParam.pSubTotals[i][j] - nFieldStart ); + } + } + pNew->SetParam(aParam); + } + } + return pNew; +} + +void SAL_CALL ScCellRangeObj::applySubTotals( + const uno::Reference<sheet::XSubTotalDescriptor>& xDescriptor, + sal_Bool bReplace ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if (!xDescriptor.is()) return; + + ScDocShell* pDocSh = GetDocShell(); + ScSubTotalDescriptorBase* pImp = + ScSubTotalDescriptorBase::getImplementation( xDescriptor ); + + if (pDocSh && pImp) + { + ScSubTotalParam aParam; + pImp->GetData(aParam); // virtuelle Methode der Basisklasse + + // im SubTotalDescriptor sind die Fields innerhalb des Bereichs gezaehlt + SCCOL nFieldStart = aRange.aStart.Col(); + for (USHORT i=0; i<MAXSUBTOTAL; i++) + { + if ( aParam.bGroupActive[i] ) + { + aParam.nField[i] = sal::static_int_cast<SCCOL>( aParam.nField[i] + nFieldStart ); + for (SCCOL j=0; j<aParam.nSubTotals[i]; j++) + aParam.pSubTotals[i][j] = sal::static_int_cast<SCCOL>( aParam.pSubTotals[i][j] + nFieldStart ); + } + } + + aParam.bReplace = bReplace; + + SCTAB nTab = aRange.aStart.Tab(); + aParam.nCol1 = aRange.aStart.Col(); + aParam.nRow1 = aRange.aStart.Row(); + aParam.nCol2 = aRange.aEnd.Col(); + aParam.nRow2 = aRange.aEnd.Row(); + + pDocSh->GetDBData( aRange, SC_DB_MAKE, SC_DBSEL_FORCE_MARK ); // ggf. Bereich anlegen + + ScDBDocFunc aFunc(*pDocSh); + aFunc.DoSubTotals( nTab, aParam, NULL, TRUE, TRUE ); // Bereich muss angelegt sein + } +} + +void SAL_CALL ScCellRangeObj::removeSubTotals() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + ScDocShell* pDocSh = GetDocShell(); + if (pDocSh) + { + ScSubTotalParam aParam; + ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_OLD, SC_DBSEL_FORCE_MARK ); + if (pData) + pData->GetSubTotalParam(aParam); // auch bei Remove die Feld-Eintraege behalten + + aParam.bRemoveOnly = TRUE; + + SCTAB nTab = aRange.aStart.Tab(); + aParam.nCol1 = aRange.aStart.Col(); + aParam.nRow1 = aRange.aStart.Row(); + aParam.nCol2 = aRange.aEnd.Col(); + aParam.nRow2 = aRange.aEnd.Row(); + + pDocSh->GetDBData( aRange, SC_DB_MAKE, SC_DBSEL_FORCE_MARK ); // ggf. Bereich anlegen + + ScDBDocFunc aFunc(*pDocSh); + aFunc.DoSubTotals( nTab, aParam, NULL, TRUE, TRUE ); // Bereich muss angelegt sein + } +} + +uno::Sequence<beans::PropertyValue> SAL_CALL ScCellRangeObj::createImportDescriptor( sal_Bool bEmpty ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScImportParam aParam; + ScDocShell* pDocSh = GetDocShell(); + if ( !bEmpty && pDocSh ) + { + // DB-Bereich anlegen erst beim Ausfuehren, per API immer genau den Bereich + ScDBData* pData = pDocSh->GetDBData( aRange, SC_DB_OLD, SC_DBSEL_FORCE_MARK ); + if (pData) + pData->GetImportParam(aParam); + } + + uno::Sequence<beans::PropertyValue> aSeq( ScImportDescriptor::GetPropertyCount() ); + ScImportDescriptor::FillProperties( aSeq, aParam ); + return aSeq; +} + +void SAL_CALL ScCellRangeObj::doImport( const uno::Sequence<beans::PropertyValue>& aDescriptor ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if (pDocSh) + { + ScImportParam aParam; + ScImportDescriptor::FillImportParam( aParam, aDescriptor ); + + SCTAB nTab = aRange.aStart.Tab(); + aParam.nCol1 = aRange.aStart.Col(); + aParam.nRow1 = aRange.aStart.Row(); + aParam.nCol2 = aRange.aEnd.Col(); + aParam.nRow2 = aRange.aEnd.Row(); + + //! TODO: could we get passed a valid result set by any means? + uno::Reference< sdbc::XResultSet > xResultSet; + + pDocSh->GetDBData( aRange, SC_DB_MAKE, SC_DBSEL_FORCE_MARK ); // ggf. Bereich anlegen + + ScDBDocFunc aFunc(*pDocSh); // Bereich muss angelegt sein + aFunc.DoImport( nTab, aParam, xResultSet, NULL, TRUE, FALSE ); //! Api-Flag als Parameter + } +} + +// XCellFormatRangesSupplier + +uno::Reference<container::XIndexAccess> SAL_CALL ScCellRangeObj::getCellFormatRanges() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + return new ScCellFormatsObj( pDocSh, aRange ); + return NULL; +} + +// XUniqueCellFormatRangesSupplier + +uno::Reference<container::XIndexAccess> SAL_CALL ScCellRangeObj::getUniqueCellFormatRanges() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + return new ScUniqueCellFormatsObj( pDocSh, aRange ); + return NULL; +} + +// XPropertySet erweitert fuer Range-Properties + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScCellRangeObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef( + new SfxItemPropertySetInfo( pRangePropSet->getPropertyMap() )); + return aRef; +} + +void ScCellRangeObj::SetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntry, const uno::Any& aValue ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + // Range has only Position and Size in addition to ScCellRangesBase, both are ReadOnly + // -> nothing to do here + + ScCellRangesBase::SetOnePropertyValue( pEntry, aValue ); +} + +void ScCellRangeObj::GetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntry, + uno::Any& rAny ) + throw(uno::RuntimeException) +{ + if ( pEntry ) + { + if ( pEntry->nWID == SC_WID_UNO_POS ) + { + ScDocShell* pDocSh = GetDocShell(); + if (pDocSh) + { + // GetMMRect converts using HMM_PER_TWIPS, like the DrawingLayer + Rectangle aMMRect(pDocSh->GetDocument()->GetMMRect( + aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab() )); + awt::Point aPos( aMMRect.Left(), aMMRect.Top() ); + rAny <<= aPos; + } + } + else if ( pEntry->nWID == SC_WID_UNO_SIZE ) + { + ScDocShell* pDocSh = GetDocShell(); + if (pDocSh) + { + // GetMMRect converts using HMM_PER_TWIPS, like the DrawingLayer + Rectangle aMMRect = pDocSh->GetDocument()->GetMMRect( + aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab() ); + Size aSize(aMMRect.GetSize()); + awt::Size aAwtSize( aSize.Width(), aSize.Height() ); + rAny <<= aAwtSize; + } + } + else + ScCellRangesBase::GetOnePropertyValue( pEntry, rAny ); + + } +} + +const SfxItemPropertyMap* ScCellRangeObj::GetItemPropertyMap() +{ + return pRangePropSet->getPropertyMap(); +} + +// XServiceInfo + +rtl::OUString SAL_CALL ScCellRangeObj::getImplementationName() throw(uno::RuntimeException) +{ + return rtl::OUString::createFromAscii( "ScCellRangeObj" ); +} + +sal_Bool SAL_CALL ScCellRangeObj::supportsService( const rtl::OUString& rServiceName ) + throw(uno::RuntimeException) +{ + String aServiceStr( rServiceName ); + return aServiceStr.EqualsAscii( SCSHEETCELLRANGE_SERVICE ) || + aServiceStr.EqualsAscii( SCCELLRANGE_SERVICE ) || + aServiceStr.EqualsAscii( SCCELLPROPERTIES_SERVICE ) || + aServiceStr.EqualsAscii( SCCHARPROPERTIES_SERVICE ) || + aServiceStr.EqualsAscii( SCPARAPROPERTIES_SERVICE ); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScCellRangeObj::getSupportedServiceNames() + throw(uno::RuntimeException) +{ + uno::Sequence<rtl::OUString> aRet(5); + rtl::OUString* pArray = aRet.getArray(); + pArray[0] = rtl::OUString::createFromAscii( SCSHEETCELLRANGE_SERVICE ); + pArray[1] = rtl::OUString::createFromAscii( SCCELLRANGE_SERVICE ); + pArray[2] = rtl::OUString::createFromAscii( SCCELLPROPERTIES_SERVICE ); + pArray[3] = rtl::OUString::createFromAscii( SCCHARPROPERTIES_SERVICE ); + pArray[4] = rtl::OUString::createFromAscii( SCPARAPROPERTIES_SERVICE ); + return aRet; +} + +//------------------------------------------------------------------------ + +const SvxItemPropertySet* ScCellObj::GetEditPropertySet() // static +{ + return lcl_GetEditPropertySet(); +} +const SfxItemPropertyMap* ScCellObj::GetCellPropertyMap() +{ + return lcl_GetCellPropertySet()->getPropertyMap(); +} + +ScCellObj::ScCellObj(ScDocShell* pDocSh, const ScAddress& rP) : + ScCellRangeObj( pDocSh, ScRange(rP,rP) ), + pUnoText( NULL ), + pCellPropSet( lcl_GetCellPropertySet() ), + aCellPos( rP ), + nActionLockCount( 0 ) +{ + // pUnoText is allocated on demand (GetUnoText) + // can't be aggregated because getString/setString is handled here +} + +SvxUnoText& ScCellObj::GetUnoText() +{ + if (!pUnoText) + { + pUnoText = new ScCellTextObj( GetDocShell(), aCellPos ); + pUnoText->acquire(); + if (nActionLockCount) + { + ScSharedCellEditSource* pEditSource = + static_cast<ScSharedCellEditSource*> (pUnoText->GetEditSource()); + if (pEditSource) + pEditSource->SetDoUpdateData(sal_False); + } + } + return *pUnoText; +} + +ScCellObj::~ScCellObj() +{ + if (pUnoText) + pUnoText->release(); +} + +void ScCellObj::RefChanged() +{ + ScCellRangeObj::RefChanged(); + + const ScRangeList& rRanges = GetRangeList(); + DBG_ASSERT(rRanges.Count() == 1, "was fuer Ranges ?!?!"); + const ScRange* pFirst = rRanges.GetObject(0); + if (pFirst) + aCellPos = pFirst->aStart; +} + +uno::Any SAL_CALL ScCellObj::queryInterface( const uno::Type& rType ) throw(uno::RuntimeException) +{ + SC_QUERYINTERFACE( table::XCell ) + SC_QUERYINTERFACE( sheet::XFormulaTokens ) + SC_QUERYINTERFACE( sheet::XCellAddressable ) + SC_QUERYINTERFACE( text::XText ) + SC_QUERYINTERFACE( text::XSimpleText ) + SC_QUERYINTERFACE( text::XTextRange ) + SC_QUERYINTERFACE( container::XEnumerationAccess ) + SC_QUERYINTERFACE( container::XElementAccess ) + SC_QUERYINTERFACE( sheet::XSheetAnnotationAnchor ) + SC_QUERYINTERFACE( text::XTextFieldsSupplier ) + SC_QUERYINTERFACE( document::XActionLockable ) + + return ScCellRangeObj::queryInterface( rType ); +} + +void SAL_CALL ScCellObj::acquire() throw() +{ + ScCellRangeObj::acquire(); +} + +void SAL_CALL ScCellObj::release() throw() +{ + ScCellRangeObj::release(); +} + +uno::Sequence<uno::Type> SAL_CALL ScCellObj::getTypes() throw(uno::RuntimeException) +{ + static uno::Sequence<uno::Type> aTypes; + if ( aTypes.getLength() == 0 ) + { + uno::Sequence<uno::Type> aParentTypes(ScCellRangeObj::getTypes()); + long nParentLen = aParentTypes.getLength(); + const uno::Type* pParentPtr = aParentTypes.getConstArray(); + + aTypes.realloc( nParentLen + 8 ); + uno::Type* pPtr = aTypes.getArray(); + pPtr[nParentLen + 0] = getCppuType((const uno::Reference<table::XCell>*)0); + pPtr[nParentLen + 1] = getCppuType((const uno::Reference<sheet::XCellAddressable>*)0); + pPtr[nParentLen + 2] = getCppuType((const uno::Reference<text::XText>*)0); + pPtr[nParentLen + 3] = getCppuType((const uno::Reference<container::XEnumerationAccess>*)0); + pPtr[nParentLen + 4] = getCppuType((const uno::Reference<sheet::XSheetAnnotationAnchor>*)0); + pPtr[nParentLen + 5] = getCppuType((const uno::Reference<text::XTextFieldsSupplier>*)0); + pPtr[nParentLen + 6] = getCppuType((const uno::Reference<document::XActionLockable>*)0); + pPtr[nParentLen + 7] = getCppuType((const uno::Reference<sheet::XFormulaTokens>*)0); + + for (long i=0; i<nParentLen; i++) + pPtr[i] = pParentPtr[i]; // parent types first + } + return aTypes; +} + +uno::Sequence<sal_Int8> SAL_CALL ScCellObj::getImplementationId() throw(uno::RuntimeException) +{ + static uno::Sequence< sal_Int8 > aId; + if( aId.getLength() == 0 ) + { + aId.realloc( 16 ); + rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True ); + } + return aId; +} + +// Hilfsfunktionen + +String ScCellObj::GetInputString_Impl(BOOL bEnglish) const // fuer getFormula / FormulaLocal +{ + if (GetDocShell()) + return lcl_GetInputString( GetDocShell()->GetDocument(), aCellPos, bEnglish ); + return String(); +} + +String ScCellObj::GetOutputString_Impl(ScDocument* pDoc, const ScAddress& aCellPos) +{ + String aVal; + if ( pDoc ) + { + ScBaseCell* pCell = pDoc->GetCell( aCellPos ); + if ( pCell && pCell->GetCellType() != CELLTYPE_NOTE ) + { + if ( pCell->GetCellType() == CELLTYPE_EDIT ) + { + // GetString an der EditCell macht Leerzeichen aus Umbruechen, + // hier werden die Umbrueche aber gebraucht + const EditTextObject* pData = ((ScEditCell*)pCell)->GetData(); + if (pData) + { + EditEngine& rEngine = pDoc->GetEditEngine(); + rEngine.SetText( *pData ); + aVal = rEngine.GetText( LINEEND_LF ); + } + // Edit-Zellen auch nicht per NumberFormatter formatieren + // (passend zur Ausgabe) + } + else + { + // wie in GetString am Dokument (column) + Color* pColor; + ULONG nNumFmt = pDoc->GetNumberFormat( aCellPos ); + ScCellFormat::GetString( pCell, nNumFmt, aVal, &pColor, *pDoc->GetFormatTable() ); + } + } + } + return aVal; +} + +String ScCellObj::GetOutputString_Impl() const +{ + ScDocShell* pDocSh = GetDocShell(); + String aVal; + if ( pDocSh ) + aVal = GetOutputString_Impl(pDocSh->GetDocument(), aCellPos); + return aVal; +} + +void ScCellObj::SetString_Impl(const String& rString, BOOL bInterpret, BOOL bEnglish) +{ + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocFunc aFunc(*pDocSh); + // GRAM_PODF_A1 for API compatibility. + (void)aFunc.SetCellText( aCellPos, rString, bInterpret, bEnglish, TRUE, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 ); + } +} + +double ScCellObj::GetValue_Impl() const +{ + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + return pDocSh->GetDocument()->GetValue( aCellPos ); + + return 0.0; +} + +void ScCellObj::SetValue_Impl(double fValue) +{ + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocFunc aFunc(*pDocSh); + (void)aFunc.PutCell( aCellPos, new ScValueCell(fValue), TRUE ); + } +} + +// only for XML import + +void ScCellObj::SetFormulaResultString( const ::rtl::OUString& rResult ) +{ + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScBaseCell* pCell = pDocSh->GetDocument()->GetCell( aCellPos ); + if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA ) + ((ScFormulaCell*)pCell)->SetHybridString( rResult ); + } +} + +void ScCellObj::SetFormulaResultDouble( double fResult ) +{ + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScBaseCell* pCell = pDocSh->GetDocument()->GetCell( aCellPos ); + if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA ) + ((ScFormulaCell*)pCell)->SetHybridDouble( fResult ); + } +} + +void ScCellObj::SetFormulaWithGrammar( const ::rtl::OUString& rFormula, + const ::rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar ) +{ + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocFunc aFunc(*pDocSh); + aFunc.SetCellText( aCellPos, rFormula, TRUE, TRUE, TRUE, rFormulaNmsp, eGrammar); + } +} + +// XText + +uno::Reference<text::XTextCursor> SAL_CALL ScCellObj::createTextCursor() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScCellTextCursor( *this ); +} + +uno::Reference<text::XTextCursor> SAL_CALL ScCellObj::createTextCursorByRange( + const uno::Reference<text::XTextRange>& aTextPosition ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + SvxUnoTextCursor* pCursor = new ScCellTextCursor( *this ); + uno::Reference<text::XTextCursor> xCursor(pCursor); + + SvxUnoTextRangeBase* pRange = SvxUnoTextRangeBase::getImplementation( aTextPosition ); + if(pRange) + pCursor->SetSelection( pRange->GetSelection() ); + else + { + ScCellTextCursor* pOther = ScCellTextCursor::getImplementation( aTextPosition ); + if(pOther) + pCursor->SetSelection( pOther->GetSelection() ); + else + throw uno::RuntimeException(); + } + + return xCursor; +} + +rtl::OUString SAL_CALL ScCellObj::getString() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return GetOutputString_Impl(); +} + +void SAL_CALL ScCellObj::setString( const rtl::OUString& aText ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aString(aText); + SetString_Impl(aString, FALSE, FALSE); // immer Text + + // don't create pUnoText here if not there + if (pUnoText) + pUnoText->SetSelection(ESelection( 0,0, 0,aString.Len() )); +} + +void SAL_CALL ScCellObj::insertString( const uno::Reference<text::XTextRange>& xRange, + const rtl::OUString& aString, sal_Bool bAbsorb ) + throw(uno::RuntimeException) +{ + // special handling for ScCellTextCursor is no longer needed, + // SvxUnoText::insertString checks for SvxUnoTextRangeBase instead of SvxUnoTextRange + + ScUnoGuard aGuard; + GetUnoText().insertString(xRange, aString, bAbsorb); +} + +void SAL_CALL ScCellObj::insertControlCharacter( const uno::Reference<text::XTextRange>& xRange, + sal_Int16 nControlCharacter, sal_Bool bAbsorb ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + GetUnoText().insertControlCharacter(xRange, nControlCharacter, bAbsorb); +} + +void SAL_CALL ScCellObj::insertTextContent( const uno::Reference<text::XTextRange >& xRange, + const uno::Reference<text::XTextContent >& xContent, + sal_Bool bAbsorb ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh && xContent.is() ) + { + ScCellFieldObj* pCellField = ScCellFieldObj::getImplementation( xContent ); + SvxUnoTextRangeBase* pTextRange = ScCellTextCursor::getImplementation( xRange ); + +#if 0 + if (!pTextRange) + pTextRange = SvxUnoTextRangeBase::getImplementation( xRange ); + + //! bei SvxUnoTextRange testen, ob in passendem Objekt !!! +#endif + + if ( pCellField && !pCellField->IsInserted() && pTextRange ) + { + SvxEditSource* pEditSource = pTextRange->GetEditSource(); + ESelection aSelection(pTextRange->GetSelection()); + + if (!bAbsorb) + { + // nicht ersetzen -> hinten anhaengen + aSelection.Adjust(); + aSelection.nStartPara = aSelection.nEndPara; + aSelection.nStartPos = aSelection.nEndPos; + } + + SvxFieldItem aItem(pCellField->CreateFieldItem()); + + SvxTextForwarder* pForwarder = pEditSource->GetTextForwarder(); + pForwarder->QuickInsertField( aItem, aSelection ); + pEditSource->UpdateData(); + + // neue Selektion: ein Zeichen + aSelection.Adjust(); + aSelection.nEndPara = aSelection.nStartPara; + aSelection.nEndPos = aSelection.nStartPos + 1; + pCellField->InitDoc( pDocSh, aCellPos, aSelection ); + + // #91431# for bAbsorb=FALSE, the new selection must be behind the inserted content + // (the xml filter relies on this) + if (!bAbsorb) + aSelection.nStartPos = aSelection.nEndPos; + + pTextRange->SetSelection( aSelection ); + + return; + } + } + GetUnoText().insertTextContent(xRange, xContent, bAbsorb); +} + +void SAL_CALL ScCellObj::removeTextContent( const uno::Reference<text::XTextContent>& xContent ) + throw(container::NoSuchElementException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( xContent.is() ) + { + ScCellFieldObj* pCellField = ScCellFieldObj::getImplementation( xContent ); + if ( pCellField && pCellField->IsInserted() ) + { + //! Testen, ob das Feld in dieser Zelle ist + pCellField->DeleteField(); + return; + } + } + GetUnoText().removeTextContent(xContent); +} + +uno::Reference<text::XText> SAL_CALL ScCellObj::getText() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return this; +} + +uno::Reference<text::XTextRange> SAL_CALL ScCellObj::getStart() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return GetUnoText().getStart(); +} + +uno::Reference<text::XTextRange> SAL_CALL ScCellObj::getEnd() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return GetUnoText().getEnd(); +} + +uno::Reference<container::XEnumeration> SAL_CALL ScCellObj::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return GetUnoText().createEnumeration(); +} + +uno::Type SAL_CALL ScCellObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return GetUnoText().getElementType(); +} + +sal_Bool SAL_CALL ScCellObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return GetUnoText().hasElements(); +} + +// XCell + +rtl::OUString SAL_CALL ScCellObj::getFormula() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + // TRUE = englisch + return GetInputString_Impl(TRUE); +} + +void SAL_CALL ScCellObj::setFormula( const rtl::OUString& aFormula ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aString(aFormula); + SetString_Impl(aString, TRUE, TRUE); // englisch interpretieren +} + +double SAL_CALL ScCellObj::getValue() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return GetValue_Impl(); +} + +void SAL_CALL ScCellObj::setValue( double nValue ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + SetValue_Impl(nValue); +} + +table::CellContentType SAL_CALL ScCellObj::getType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + table::CellContentType eRet = table::CellContentType_EMPTY; + ScDocShell* pDocSh = GetDocShell(); + if (pDocSh) + { + CellType eCalcType = pDocSh->GetDocument()->GetCellType( aCellPos ); + switch (eCalcType) + { + case CELLTYPE_VALUE: + eRet = table::CellContentType_VALUE; + break; + case CELLTYPE_STRING: + case CELLTYPE_EDIT: + eRet = table::CellContentType_TEXT; + break; + case CELLTYPE_FORMULA: + eRet = table::CellContentType_FORMULA; + break; + default: + eRet = table::CellContentType_EMPTY; + } + } + else + { + DBG_ERROR("keine DocShell"); //! Exception oder so? + } + + return eRet; +} + +table::CellContentType ScCellObj::GetResultType_Impl() +{ + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScBaseCell* pCell = pDocSh->GetDocument()->GetCell(aCellPos); + if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA ) + { + BOOL bValue = ((ScFormulaCell*)pCell)->IsValue(); + return bValue ? table::CellContentType_VALUE : table::CellContentType_TEXT; + } + } + return getType(); // wenn keine Formel +} + +sal_Int32 SAL_CALL ScCellObj::getError() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + USHORT nError = 0; + ScDocShell* pDocSh = GetDocShell(); + if (pDocSh) + { + ScBaseCell* pCell = pDocSh->GetDocument()->GetCell( aCellPos ); + if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA ) + nError = ((ScFormulaCell*)pCell)->GetErrCode(); + // sonst bleibt's bei 0 + } + else + { + DBG_ERROR("keine DocShell"); //! Exception oder so? + } + + return nError; +} + +// XFormulaTokens + +uno::Sequence<sheet::FormulaToken> SAL_CALL ScCellObj::getTokens() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Sequence<sheet::FormulaToken> aSequence; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + ScBaseCell* pCell = pDoc->GetCell( aCellPos ); + if ( pCell && pCell->GetCellType() == CELLTYPE_FORMULA ) + { + ScTokenArray* pTokenArray = static_cast<ScFormulaCell*>(pCell)->GetCode(); + if ( pTokenArray ) + (void)ScTokenConversion::ConvertToTokenSequence( *pDoc, aSequence, *pTokenArray ); + } + } + return aSequence; +} + +void SAL_CALL ScCellObj::setTokens( const uno::Sequence<sheet::FormulaToken>& rTokens ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + ScTokenArray aTokenArray; + (void)ScTokenConversion::ConvertToTokenArray( *pDoc, aTokenArray, rTokens ); + + ScDocFunc aFunc( *pDocSh ); + ScBaseCell* pNewCell = new ScFormulaCell( pDoc, aCellPos, &aTokenArray ); + (void)aFunc.PutCell( aCellPos, pNewCell, TRUE ); + } +} + +// XCellAddressable + +table::CellAddress SAL_CALL ScCellObj::getCellAddress() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + table::CellAddress aAdr; + aAdr.Sheet = aCellPos.Tab(); + aAdr.Column = aCellPos.Col(); + aAdr.Row = aCellPos.Row(); + return aAdr; +} + +// XSheetAnnotationAnchor + +uno::Reference<sheet::XSheetAnnotation> SAL_CALL ScCellObj::getAnnotation() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + return new ScAnnotationObj( pDocSh, aCellPos ); + + DBG_ERROR("getAnnotation ohne DocShell"); + return NULL; +} + +// XFieldTypesSupplier + +uno::Reference<container::XEnumerationAccess> SAL_CALL ScCellObj::getTextFields() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + return new ScCellFieldsObj( pDocSh, aCellPos ); + + return NULL; +} + +uno::Reference<container::XNameAccess> SAL_CALL ScCellObj::getTextFieldMasters() + throw(uno::RuntimeException) +{ + // sowas gibts nicht im Calc (?) + return NULL; +} + +// XPropertySet erweitert fuer Zell-Properties + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScCellObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef( + new SfxItemPropertySetInfo( pCellPropSet->getPropertyMap() )); + return aRef; +} + +void ScCellObj::SetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntry, const uno::Any& aValue ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + if ( pEntry ) + { + if ( pEntry->nWID == SC_WID_UNO_FORMLOC ) + { + rtl::OUString aStrVal; + aValue >>= aStrVal; + String aString(aStrVal); + SetString_Impl(aString, TRUE, FALSE); // lokal interpretieren + } + else if ( pEntry->nWID == SC_WID_UNO_FORMRT ) + { + // Read-Only + //! Exception oder so... + } + else + ScCellRangeObj::SetOnePropertyValue( pEntry, aValue ); + } +} + +void ScCellObj::GetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntry, + uno::Any& rAny ) + throw(uno::RuntimeException) +{ + if ( pEntry ) + { + if ( pEntry->nWID == SC_WID_UNO_FORMLOC ) + { + // FALSE = lokal + rAny <<= rtl::OUString( GetInputString_Impl(FALSE) ); + } + else if ( pEntry->nWID == SC_WID_UNO_FORMRT ) + { + table::CellContentType eType = GetResultType_Impl(); + rAny <<= eType; + } + else + ScCellRangeObj::GetOnePropertyValue(pEntry, rAny); + } +} + +const SfxItemPropertyMap* ScCellObj::GetItemPropertyMap() +{ + return pCellPropSet->getPropertyMap(); +} + +// XServiceInfo + +rtl::OUString SAL_CALL ScCellObj::getImplementationName() throw(uno::RuntimeException) +{ + return rtl::OUString::createFromAscii( "ScCellObj" ); +} + +sal_Bool SAL_CALL ScCellObj::supportsService( const rtl::OUString& rServiceName ) + throw(uno::RuntimeException) +{ + // CellRange/SheetCellRange are not in SheetCell service description, + // but ScCellObj is used instead of ScCellRangeObj in CellRanges collections, + // so it must support them + + String aServiceStr(rServiceName); + return aServiceStr.EqualsAscii( SCSHEETCELL_SERVICE ) || + aServiceStr.EqualsAscii( SCCELL_SERVICE ) || + aServiceStr.EqualsAscii( SCCELLPROPERTIES_SERVICE ) || + aServiceStr.EqualsAscii( SCCHARPROPERTIES_SERVICE ) || + aServiceStr.EqualsAscii( SCPARAPROPERTIES_SERVICE ) || + aServiceStr.EqualsAscii( SCSHEETCELLRANGE_SERVICE ) || + aServiceStr.EqualsAscii( SCCELLRANGE_SERVICE ); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScCellObj::getSupportedServiceNames() + throw(uno::RuntimeException) +{ + uno::Sequence<rtl::OUString> aRet(7); + rtl::OUString* pArray = aRet.getArray(); + pArray[0] = rtl::OUString::createFromAscii( SCSHEETCELL_SERVICE ); + pArray[1] = rtl::OUString::createFromAscii( SCCELL_SERVICE ); + pArray[2] = rtl::OUString::createFromAscii( SCCELLPROPERTIES_SERVICE ); + pArray[3] = rtl::OUString::createFromAscii( SCCHARPROPERTIES_SERVICE ); + pArray[4] = rtl::OUString::createFromAscii( SCPARAPROPERTIES_SERVICE ); + pArray[5] = rtl::OUString::createFromAscii( SCSHEETCELLRANGE_SERVICE ); + pArray[6] = rtl::OUString::createFromAscii( SCCELLRANGE_SERVICE ); + return aRet; +} + +// XActionLockable + +sal_Bool SAL_CALL ScCellObj::isActionLocked() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return nActionLockCount != 0; +} + +void SAL_CALL ScCellObj::addActionLock() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (!nActionLockCount) + { + if (pUnoText) + { + ScSharedCellEditSource* pEditSource = + static_cast<ScSharedCellEditSource*> (pUnoText->GetEditSource()); + if (pEditSource) + pEditSource->SetDoUpdateData(sal_False); + } + } + nActionLockCount++; +} + +void SAL_CALL ScCellObj::removeActionLock() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (nActionLockCount > 0) + { + nActionLockCount--; + if (!nActionLockCount) + { + if (pUnoText) + { + ScSharedCellEditSource* pEditSource = + static_cast<ScSharedCellEditSource*> (pUnoText->GetEditSource()); + if (pEditSource) + { + pEditSource->SetDoUpdateData(sal_True); + if (pEditSource->IsDirty()) + pEditSource->UpdateData(); + } + } + } + } +} + +void SAL_CALL ScCellObj::setActionLocks( sal_Int16 nLock ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pUnoText) + { + ScSharedCellEditSource* pEditSource = + static_cast<ScSharedCellEditSource*> (pUnoText->GetEditSource()); + if (pEditSource) + { + pEditSource->SetDoUpdateData(nLock == 0); + if ((nActionLockCount > 0) && (nLock == 0) && pEditSource->IsDirty()) + pEditSource->UpdateData(); + } + } + nActionLockCount = nLock; +} + +sal_Int16 SAL_CALL ScCellObj::resetActionLocks() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + USHORT nRet(nActionLockCount); + if (pUnoText) + { + ScSharedCellEditSource* pEditSource = + static_cast<ScSharedCellEditSource*> (pUnoText->GetEditSource()); + if (pEditSource) + { + pEditSource->SetDoUpdateData(sal_True); + if (pEditSource->IsDirty()) + pEditSource->UpdateData(); + } + } + nActionLockCount = 0; + return nRet; +} + +//------------------------------------------------------------------------ + +ScTableSheetObj::ScTableSheetObj( ScDocShell* pDocSh, SCTAB nTab ) : + ScCellRangeObj( pDocSh, ScRange(0,0,nTab, MAXCOL,MAXROW,nTab) ), + pSheetPropSet(lcl_GetSheetPropertySet()) +{ +} + +ScTableSheetObj::~ScTableSheetObj() +{ +} + +void ScTableSheetObj::InitInsertSheet(ScDocShell* pDocSh, SCTAB nTab) +{ + InitInsertRange( pDocSh, ScRange(0,0,nTab, MAXCOL,MAXROW,nTab) ); +} + +uno::Any SAL_CALL ScTableSheetObj::queryInterface( const uno::Type& rType ) throw(uno::RuntimeException) +{ + SC_QUERYINTERFACE( sheet::XSpreadsheet ) + SC_QUERYINTERFACE( container::XNamed ) + SC_QUERYINTERFACE( sheet::XSheetPageBreak ) + SC_QUERYINTERFACE( sheet::XCellRangeMovement ) + SC_QUERYINTERFACE( table::XTableChartsSupplier ) + SC_QUERYINTERFACE( sheet::XDataPilotTablesSupplier ) + SC_QUERYINTERFACE( sheet::XScenariosSupplier ) + SC_QUERYINTERFACE( sheet::XSheetAnnotationsSupplier ) + SC_QUERYINTERFACE( drawing::XDrawPageSupplier ) + SC_QUERYINTERFACE( sheet::XPrintAreas ) + SC_QUERYINTERFACE( sheet::XSheetAuditing ) + SC_QUERYINTERFACE( sheet::XSheetOutline ) + SC_QUERYINTERFACE( util::XProtectable ) + SC_QUERYINTERFACE( sheet::XScenario ) + SC_QUERYINTERFACE( sheet::XScenarioEnhanced ) + SC_QUERYINTERFACE( sheet::XSheetLinkable ) + SC_QUERYINTERFACE( sheet::XExternalSheetName ) + SC_QUERYINTERFACE( document::XEventsSupplier ) + + return ScCellRangeObj::queryInterface( rType ); +} + +void SAL_CALL ScTableSheetObj::acquire() throw() +{ + ScCellRangeObj::acquire(); +} + +void SAL_CALL ScTableSheetObj::release() throw() +{ + ScCellRangeObj::release(); +} + +uno::Sequence<uno::Type> SAL_CALL ScTableSheetObj::getTypes() throw(uno::RuntimeException) +{ + static uno::Sequence<uno::Type> aTypes; + if ( aTypes.getLength() == 0 ) + { + uno::Sequence<uno::Type> aParentTypes = ScCellRangeObj::getTypes(); + long nParentLen = aParentTypes.getLength(); + const uno::Type* pParentPtr = aParentTypes.getConstArray(); + + aTypes.realloc( nParentLen + 18 ); + uno::Type* pPtr = aTypes.getArray(); + pPtr[nParentLen + 0] = getCppuType((const uno::Reference<sheet::XSpreadsheet>*)0); + pPtr[nParentLen + 1] = getCppuType((const uno::Reference<container::XNamed>*)0); + pPtr[nParentLen + 2] = getCppuType((const uno::Reference<sheet::XSheetPageBreak>*)0); + pPtr[nParentLen + 3] = getCppuType((const uno::Reference<sheet::XCellRangeMovement>*)0); + pPtr[nParentLen + 4] = getCppuType((const uno::Reference<table::XTableChartsSupplier>*)0); + pPtr[nParentLen + 5] = getCppuType((const uno::Reference<sheet::XDataPilotTablesSupplier>*)0); + pPtr[nParentLen + 6] = getCppuType((const uno::Reference<sheet::XScenariosSupplier>*)0); + pPtr[nParentLen + 7] = getCppuType((const uno::Reference<sheet::XSheetAnnotationsSupplier>*)0); + pPtr[nParentLen + 8] = getCppuType((const uno::Reference<drawing::XDrawPageSupplier>*)0); + pPtr[nParentLen + 9] = getCppuType((const uno::Reference<sheet::XPrintAreas>*)0); + pPtr[nParentLen +10] = getCppuType((const uno::Reference<sheet::XSheetAuditing>*)0); + pPtr[nParentLen +11] = getCppuType((const uno::Reference<sheet::XSheetOutline>*)0); + pPtr[nParentLen +12] = getCppuType((const uno::Reference<util::XProtectable>*)0); + pPtr[nParentLen +13] = getCppuType((const uno::Reference<sheet::XScenario>*)0); + pPtr[nParentLen +14] = getCppuType((const uno::Reference<sheet::XScenarioEnhanced>*)0); + pPtr[nParentLen +15] = getCppuType((const uno::Reference<sheet::XSheetLinkable>*)0); + pPtr[nParentLen +16] = getCppuType((const uno::Reference<sheet::XExternalSheetName>*)0); + pPtr[nParentLen +17] = getCppuType((const uno::Reference<document::XEventsSupplier>*)0); + + for (long i=0; i<nParentLen; i++) + pPtr[i] = pParentPtr[i]; // parent types first + } + return aTypes; +} + +uno::Sequence<sal_Int8> SAL_CALL ScTableSheetObj::getImplementationId() throw(uno::RuntimeException) +{ + static uno::Sequence< sal_Int8 > aId; + if( aId.getLength() == 0 ) + { + aId.realloc( 16 ); + rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True ); + } + return aId; +} + +// Hilfsfunktionen + +SCTAB ScTableSheetObj::GetTab_Impl() const +{ + const ScRangeList& rRanges = GetRangeList(); + DBG_ASSERT(rRanges.Count() == 1, "was fuer Ranges ?!?!"); + const ScRange* pFirst = rRanges.GetObject(0); + if (pFirst) + return pFirst->aStart.Tab(); + + return 0; // soll nicht sein +} + +// former XSheet + +uno::Reference<table::XTableCharts> SAL_CALL ScTableSheetObj::getCharts() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + return new ScChartsObj( pDocSh, GetTab_Impl() ); + + DBG_ERROR("kein Dokument"); + return NULL; +} + +uno::Reference<sheet::XDataPilotTables> SAL_CALL ScTableSheetObj::getDataPilotTables() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + return new ScDataPilotTablesObj( pDocSh, GetTab_Impl() ); + + DBG_ERROR("kein Dokument"); + return NULL; +} + +uno::Reference<sheet::XScenarios> SAL_CALL ScTableSheetObj::getScenarios() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + + if ( pDocSh ) + return new ScScenariosObj( pDocSh, GetTab_Impl() ); + + DBG_ERROR("kein Dokument"); + return NULL; +} + +uno::Reference<sheet::XSheetAnnotations> SAL_CALL ScTableSheetObj::getAnnotations() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + + if ( pDocSh ) + return new ScAnnotationsObj( pDocSh, GetTab_Impl() ); + + DBG_ERROR("kein Dokument"); + return NULL; +} + +uno::Reference<table::XCellRange> SAL_CALL ScTableSheetObj::getCellRangeByName( + const rtl::OUString& rRange ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ScCellRangeObj::getCellRangeByName( rRange ); +} + +uno::Reference<sheet::XSheetCellCursor> SAL_CALL ScTableSheetObj::createCursor() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + //! einzelne Zelle oder ganze Tabelle??????? + SCTAB nTab = GetTab_Impl(); + return new ScCellCursorObj( pDocSh, ScRange( 0,0,nTab, MAXCOL,MAXROW,nTab ) ); + } + return NULL; +} + +uno::Reference<sheet::XSheetCellCursor> SAL_CALL ScTableSheetObj::createCursorByRange( + const uno::Reference<sheet::XSheetCellRange>& xCellRange ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh && xCellRange.is() ) + { + ScCellRangesBase* pRangesImp = ScCellRangesBase::getImplementation( xCellRange ); + if (pRangesImp) + { + const ScRangeList& rRanges = pRangesImp->GetRangeList(); + DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); + return new ScCellCursorObj( pDocSh, *rRanges.GetObject(0) ); + } + } + return NULL; +} + +// XSheetCellRange + +uno::Reference<sheet::XSpreadsheet> SAL_CALL ScTableSheetObj::getSpreadsheet() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return this; //!??? +} + +// XCellRange + +uno::Reference<table::XCell> SAL_CALL ScTableSheetObj::getCellByPosition( + sal_Int32 nColumn, sal_Int32 nRow ) + throw(lang::IndexOutOfBoundsException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ScCellRangeObj::GetCellByPosition_Impl(nColumn, nRow); +} + +uno::Reference<table::XCellRange> SAL_CALL ScTableSheetObj::getCellRangeByPosition( + sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom ) + throw(lang::IndexOutOfBoundsException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ScCellRangeObj::getCellRangeByPosition(nLeft,nTop,nRight,nBottom); +} + +uno::Sequence<sheet::TablePageBreakData> SAL_CALL ScTableSheetObj::getColumnPageBreaks() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetTab_Impl(); + + Size aSize(pDoc->GetPageSize( nTab )); + if (aSize.Width() && aSize.Height()) // effektive Groesse schon gesetzt? + pDoc->UpdatePageBreaks( nTab ); + else + { + // Umbrueche updaten wie in ScDocShell::PageStyleModified: + ScPrintFunc aPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab ); + aPrintFunc.UpdatePages(); + } + + SCCOL nCount = 0; + SCCOL nCol; + for (nCol=0; nCol<=MAXCOL; nCol++) + if (pDoc->HasColBreak(nCol, nTab)) + ++nCount; + + sheet::TablePageBreakData aData; + uno::Sequence<sheet::TablePageBreakData> aSeq(nCount); + sheet::TablePageBreakData* pAry = aSeq.getArray(); + USHORT nPos = 0; + for (nCol=0; nCol<=MAXCOL; nCol++) + { + ScBreakType nBreak = pDoc->HasColBreak(nCol, nTab); + if (nBreak) + { + aData.Position = nCol; + aData.ManualBreak = (nBreak & BREAK_MANUAL); + pAry[nPos] = aData; + ++nPos; + } + } + return aSeq; + } + return uno::Sequence<sheet::TablePageBreakData>(0); +} + +uno::Sequence<sheet::TablePageBreakData> SAL_CALL ScTableSheetObj::getRowPageBreaks() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetTab_Impl(); + + Size aSize(pDoc->GetPageSize( nTab )); + if (aSize.Width() && aSize.Height()) // effektive Groesse schon gesetzt? + pDoc->UpdatePageBreaks( nTab ); + else + { + // Umbrueche updaten wie in ScDocShell::PageStyleModified: + ScPrintFunc aPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab ); + aPrintFunc.UpdatePages(); + } + return pDoc->GetRowBreakData(nTab); + } + return uno::Sequence<sheet::TablePageBreakData>(0); +} + +void SAL_CALL ScTableSheetObj::removeAllManualPageBreaks() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + //! docfunc Funktion, auch fuer ScViewFunc::RemoveManualBreaks + + ScDocument* pDoc = pDocSh->GetDocument(); + BOOL bUndo (pDoc->IsUndoEnabled()); + SCTAB nTab = GetTab_Impl(); + + if (bUndo) + { + ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + pUndoDoc->InitUndo( pDoc, nTab, nTab, TRUE, TRUE ); + pDoc->CopyToDocument( 0,0,nTab, MAXCOL,MAXROW,nTab, IDF_NONE, FALSE, pUndoDoc ); + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoRemoveBreaks( pDocSh, nTab, pUndoDoc ) ); + } + + pDoc->RemoveManualBreaks(nTab); + pDoc->UpdatePageBreaks(nTab); + + //? UpdatePageBreakData( TRUE ); + pDocSh->SetDocumentModified(); + pDocSh->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID ); + } +} + +// XNamed + +rtl::OUString SAL_CALL ScTableSheetObj::getName() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aName; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + pDocSh->GetDocument()->GetName( GetTab_Impl(), aName ); + return aName; +} + +void SAL_CALL ScTableSheetObj::setName( const rtl::OUString& aNewName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + String aString(aNewName); + ScDocFunc aFunc( *pDocSh ); + aFunc.RenameTable( GetTab_Impl(), aString, TRUE, TRUE ); + } +} + +// XDrawPageSupplier + +uno::Reference<drawing::XDrawPage> SAL_CALL ScTableSheetObj::getDrawPage() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDrawLayer* pDrawLayer = pDocSh->MakeDrawLayer(); + DBG_ASSERT(pDrawLayer,"kann Draw-Layer nicht anlegen"); + + SCTAB nTab = GetTab_Impl(); + SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab)); + DBG_ASSERT(pPage,"Draw-Page nicht gefunden"); + if (pPage) + return uno::Reference<drawing::XDrawPage> (pPage->getUnoPage(), uno::UNO_QUERY); + + // Das DrawPage-Objekt meldet sich als Listener am SdrModel an + // und sollte von dort alle Aktionen mitbekommen + } + return NULL; +} + +// XCellMovement + +void SAL_CALL ScTableSheetObj::insertCells( const table::CellRangeAddress& rRangeAddress, + sheet::CellInsertMode nMode ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + BOOL bDo = TRUE; + InsCellCmd eCmd = INS_NONE; + switch (nMode) + { + case sheet::CellInsertMode_NONE: bDo = FALSE; break; + case sheet::CellInsertMode_DOWN: eCmd = INS_CELLSDOWN; break; + case sheet::CellInsertMode_RIGHT: eCmd = INS_CELLSRIGHT; break; + case sheet::CellInsertMode_ROWS: eCmd = INS_INSROWS; break; + case sheet::CellInsertMode_COLUMNS: eCmd = INS_INSCOLS; break; + default: + DBG_ERROR("insertCells: falscher Mode"); + bDo = FALSE; + } + + if (bDo) + { + DBG_ASSERT( rRangeAddress.Sheet == GetTab_Impl(), "falsche Tabelle in CellRangeAddress" ); + ScRange aScRange; + ScUnoConversion::FillScRange( aScRange, rRangeAddress ); + ScDocFunc aFunc(*pDocSh); + aFunc.InsertCells( aScRange, NULL, eCmd, TRUE, TRUE ); + } + } +} + +void SAL_CALL ScTableSheetObj::removeRange( const table::CellRangeAddress& rRangeAddress, + sheet::CellDeleteMode nMode ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + BOOL bDo = TRUE; + DelCellCmd eCmd = DEL_NONE; + switch (nMode) + { + case sheet::CellDeleteMode_NONE: bDo = FALSE; break; + case sheet::CellDeleteMode_UP: eCmd = DEL_CELLSUP; break; + case sheet::CellDeleteMode_LEFT: eCmd = DEL_CELLSLEFT; break; + case sheet::CellDeleteMode_ROWS: eCmd = DEL_DELROWS; break; + case sheet::CellDeleteMode_COLUMNS: eCmd = DEL_DELCOLS; break; + default: + DBG_ERROR("deleteCells: falscher Mode"); + bDo = FALSE; + } + + if (bDo) + { + DBG_ASSERT( rRangeAddress.Sheet == GetTab_Impl(), "falsche Tabelle in CellRangeAddress" ); + ScRange aScRange; + ScUnoConversion::FillScRange( aScRange, rRangeAddress ); + ScDocFunc aFunc(*pDocSh); + aFunc.DeleteCells( aScRange, NULL, eCmd, TRUE, TRUE ); + } + } +} + +void SAL_CALL ScTableSheetObj::moveRange( const table::CellAddress& aDestination, + const table::CellRangeAddress& aSource ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + DBG_ASSERT( aSource.Sheet == GetTab_Impl(), "falsche Tabelle in CellRangeAddress" ); + ScRange aSourceRange; + ScUnoConversion::FillScRange( aSourceRange, aSource ); + ScAddress aDestPos( (SCCOL)aDestination.Column, (SCROW)aDestination.Row, aDestination.Sheet ); + ScDocFunc aFunc(*pDocSh); + aFunc.MoveBlock( aSourceRange, aDestPos, TRUE, TRUE, TRUE, TRUE ); + } +} + +void SAL_CALL ScTableSheetObj::copyRange( const table::CellAddress& aDestination, + const table::CellRangeAddress& aSource ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + DBG_ASSERT( aSource.Sheet == GetTab_Impl(), "falsche Tabelle in CellRangeAddress" ); + ScRange aSourceRange; + ScUnoConversion::FillScRange( aSourceRange, aSource ); + ScAddress aDestPos( (SCCOL)aDestination.Column, (SCROW)aDestination.Row, aDestination.Sheet ); + ScDocFunc aFunc(*pDocSh); + aFunc.MoveBlock( aSourceRange, aDestPos, FALSE, TRUE, TRUE, TRUE ); + } +} + +// XPrintAreas + +void ScTableSheetObj::PrintAreaUndo_Impl( ScPrintRangeSaver* pOldRanges ) +{ + // Umbrueche und Undo + + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + BOOL bUndo(pDoc->IsUndoEnabled()); + SCTAB nTab = GetTab_Impl(); + + ScPrintRangeSaver* pNewRanges = pDoc->CreatePrintRangeSaver(); + if (bUndo) + { + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoPrintRange( pDocSh, nTab, pOldRanges, pNewRanges ) ); + } + + ScPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab ).UpdatePages(); + + SfxBindings* pBindings = pDocSh->GetViewBindings(); + if (pBindings) + pBindings->Invalidate( SID_DELETE_PRINTAREA ); + + pDocSh->SetDocumentModified(); + } + else + delete pOldRanges; +} + +uno::Sequence<table::CellRangeAddress> SAL_CALL ScTableSheetObj::getPrintAreas() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetTab_Impl(); + USHORT nCount = pDoc->GetPrintRangeCount( nTab ); + + table::CellRangeAddress aRangeAddress; + uno::Sequence<table::CellRangeAddress> aSeq(nCount); + table::CellRangeAddress* pAry = aSeq.getArray(); + for (USHORT i=0; i<nCount; i++) + { + const ScRange* pRange = pDoc->GetPrintRange( nTab, i ); + DBG_ASSERT(pRange,"wo ist der Druckbereich"); + if (pRange) + { + ScUnoConversion::FillApiRange( aRangeAddress, *pRange ); + aRangeAddress.Sheet = nTab; // core does not care about sheet index + pAry[i] = aRangeAddress; + } + } + return aSeq; + } + return uno::Sequence<table::CellRangeAddress>(); +} + +void SAL_CALL ScTableSheetObj::setPrintAreas( + const uno::Sequence<table::CellRangeAddress>& aPrintAreas ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetTab_Impl(); + + ScPrintRangeSaver* pOldRanges = pDoc->CreatePrintRangeSaver(); + + USHORT nCount = (USHORT) aPrintAreas.getLength(); + pDoc->ClearPrintRanges( nTab ); + if (nCount) + { + ScRange aPrintRange; + const table::CellRangeAddress* pAry = aPrintAreas.getConstArray(); + for (USHORT i=0; i<nCount; i++) + { + ScUnoConversion::FillScRange( aPrintRange, pAry[i] ); + pDoc->AddPrintRange( nTab, aPrintRange ); + } + } + + PrintAreaUndo_Impl( pOldRanges ); // Undo, Umbrueche, Modified etc. + } +} + +sal_Bool SAL_CALL ScTableSheetObj::getPrintTitleColumns() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetTab_Impl(); + return ( pDoc->GetRepeatColRange(nTab) != NULL ); + } + return FALSE; +} + +void SAL_CALL ScTableSheetObj::setPrintTitleColumns( sal_Bool bPrintTitleColumns ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetTab_Impl(); + + ScPrintRangeSaver* pOldRanges = pDoc->CreatePrintRangeSaver(); + + if ( bPrintTitleColumns ) + { + if ( !pDoc->GetRepeatColRange( nTab ) ) // keinen bestehenden Bereich veraendern + { + ScRange aNew( 0, 0, nTab, 0, 0, nTab ); // Default + pDoc->SetRepeatColRange( nTab, &aNew ); // einschalten + } + } + else + pDoc->SetRepeatColRange( nTab, NULL ); // abschalten + + PrintAreaUndo_Impl( pOldRanges ); // Undo, Umbrueche, Modified etc. + + //! zuletzt gesetzten Bereich beim Abschalten merken und beim Einschalten wiederherstellen ??? + } +} + +table::CellRangeAddress SAL_CALL ScTableSheetObj::getTitleColumns() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + table::CellRangeAddress aRet; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetTab_Impl(); + const ScRange* pRange = pDoc->GetRepeatColRange(nTab); + if (pRange) + { + ScUnoConversion::FillApiRange( aRet, *pRange ); + aRet.Sheet = nTab; // core does not care about sheet index + } + } + return aRet; +} + +void SAL_CALL ScTableSheetObj::setTitleColumns( const table::CellRangeAddress& aTitleColumns ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetTab_Impl(); + + ScPrintRangeSaver* pOldRanges = pDoc->CreatePrintRangeSaver(); + + ScRange aNew; + ScUnoConversion::FillScRange( aNew, aTitleColumns ); + pDoc->SetRepeatColRange( nTab, &aNew ); // immer auch einschalten + + PrintAreaUndo_Impl( pOldRanges ); // Undo, Umbrueche, Modified etc. + } +} + +sal_Bool SAL_CALL ScTableSheetObj::getPrintTitleRows() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetTab_Impl(); + return ( pDoc->GetRepeatRowRange(nTab) != NULL ); + } + return FALSE; +} + +void SAL_CALL ScTableSheetObj::setPrintTitleRows( sal_Bool bPrintTitleRows ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetTab_Impl(); + + ScPrintRangeSaver* pOldRanges = pDoc->CreatePrintRangeSaver(); + + if ( bPrintTitleRows ) + { + if ( !pDoc->GetRepeatRowRange( nTab ) ) // keinen bestehenden Bereich veraendern + { + ScRange aNew( 0, 0, nTab, 0, 0, nTab ); // Default + pDoc->SetRepeatRowRange( nTab, &aNew ); // einschalten + } + } + else + pDoc->SetRepeatRowRange( nTab, NULL ); // abschalten + + PrintAreaUndo_Impl( pOldRanges ); // Undo, Umbrueche, Modified etc. + + //! zuletzt gesetzten Bereich beim Abschalten merken und beim Einschalten wiederherstellen ??? + } +} + +table::CellRangeAddress SAL_CALL ScTableSheetObj::getTitleRows() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + table::CellRangeAddress aRet; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetTab_Impl(); + const ScRange* pRange = pDoc->GetRepeatRowRange(nTab); + if (pRange) + { + ScUnoConversion::FillApiRange( aRet, *pRange ); + aRet.Sheet = nTab; // core does not care about sheet index + } + } + return aRet; +} + +void SAL_CALL ScTableSheetObj::setTitleRows( const table::CellRangeAddress& aTitleRows ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetTab_Impl(); + + ScPrintRangeSaver* pOldRanges = pDoc->CreatePrintRangeSaver(); + + ScRange aNew; + ScUnoConversion::FillScRange( aNew, aTitleRows ); + pDoc->SetRepeatRowRange( nTab, &aNew ); // immer auch einschalten + + PrintAreaUndo_Impl( pOldRanges ); // Undo, Umbrueche, Modified etc. + } +} + +// XSheetLinkable + +sheet::SheetLinkMode SAL_CALL ScTableSheetObj::getLinkMode() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + sheet::SheetLinkMode eRet = sheet::SheetLinkMode_NONE; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + BYTE nMode = pDocSh->GetDocument()->GetLinkMode( GetTab_Impl() ); + if ( nMode == SC_LINK_NORMAL ) + eRet = sheet::SheetLinkMode_NORMAL; + else if ( nMode == SC_LINK_VALUE ) + eRet = sheet::SheetLinkMode_VALUE; + } + return eRet; +} + +void SAL_CALL ScTableSheetObj::setLinkMode( sheet::SheetLinkMode nLinkMode ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + //! Filter und Options aus altem Link suchen + + rtl::OUString aUrl(getLinkUrl()); + rtl::OUString aSheet(getLinkSheetName()); + + rtl::OUString aEmpty; + link( aUrl, aSheet, aEmpty, aEmpty, nLinkMode ); +} + +rtl::OUString SAL_CALL ScTableSheetObj::getLinkUrl() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aFile; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + aFile = pDocSh->GetDocument()->GetLinkDoc( GetTab_Impl() ); + return aFile; +} + +void SAL_CALL ScTableSheetObj::setLinkUrl( const rtl::OUString& aLinkUrl ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + //! Filter und Options aus altem Link suchen + + sheet::SheetLinkMode eMode = getLinkMode(); + rtl::OUString aSheet(getLinkSheetName()); + + rtl::OUString aEmpty; + link( aLinkUrl, aSheet, aEmpty, aEmpty, eMode ); +} + +rtl::OUString SAL_CALL ScTableSheetObj::getLinkSheetName() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aSheet; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + aSheet = pDocSh->GetDocument()->GetLinkTab( GetTab_Impl() ); + return aSheet; +} + +void SAL_CALL ScTableSheetObj::setLinkSheetName( const rtl::OUString& aLinkSheetName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + //! Filter und Options aus altem Link suchen + + sheet::SheetLinkMode eMode = getLinkMode(); + rtl::OUString aUrl(getLinkUrl()); + + rtl::OUString aEmpty; + link( aUrl, aLinkSheetName, aEmpty, aEmpty, eMode ); +} + +void SAL_CALL ScTableSheetObj::link( const rtl::OUString& aUrl, const rtl::OUString& aSheetName, + const rtl::OUString& aFilterName, const rtl::OUString& aFilterOptions, + sheet::SheetLinkMode nMode ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetTab_Impl(); + + String aFileString (aUrl); + String aFilterString (aFilterName); + String aOptString (aFilterOptions); + String aSheetString (aSheetName); + + aFileString = ScGlobal::GetAbsDocName( aFileString, pDocSh ); + if ( !aFilterString.Len() ) + ScDocumentLoader::GetFilterName( aFileString, aFilterString, aOptString, TRUE, FALSE ); + + // remove application prefix from filter name here, so the filter options + // aren't reset when the filter name is changed in ScTableLink::DataChanged + ScDocumentLoader::RemoveAppPrefix( aFilterString ); + + BYTE nLinkMode = SC_LINK_NONE; + if ( nMode == sheet::SheetLinkMode_NORMAL ) + nLinkMode = SC_LINK_NORMAL; + else if ( nMode == sheet::SheetLinkMode_VALUE ) + nLinkMode = SC_LINK_VALUE; + + ULONG nRefresh = 0; + pDoc->SetLink( nTab, nLinkMode, aFileString, aFilterString, aOptString, aSheetString, nRefresh ); + + pDocSh->UpdateLinks(); // ggf. Link eintragen oder loeschen + SfxBindings* pBindings = pDocSh->GetViewBindings(); + if (pBindings) + pBindings->Invalidate(SID_LINKS); + + //! Undo fuer Link-Daten an der Table + + if ( nLinkMode != SC_LINK_NONE && pDoc->IsExecuteLinkEnabled() ) // Link updaten + { + // Update immer, auch wenn der Link schon da war + //! Update nur fuer die betroffene Tabelle??? + + sfx2::LinkManager* pLinkManager = pDoc->GetLinkManager(); + USHORT nCount = pLinkManager->GetLinks().Count(); + for ( USHORT i=0; i<nCount; i++ ) + { + ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[i]; + if (pBase->ISA(ScTableLink)) + { + ScTableLink* pTabLink = (ScTableLink*)pBase; + if ( pTabLink->GetFileName() == aFileString ) + pTabLink->Update(); // inkl. Paint&Undo + + //! Der Dateiname sollte nur einmal vorkommen (?) + } + } + } + + //! Notify fuer ScSheetLinkObj Objekte!!! + } +} + +// XSheetAuditing + +sal_Bool SAL_CALL ScTableSheetObj::hideDependents( const table::CellAddress& aPosition ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + SCTAB nTab = GetTab_Impl(); + DBG_ASSERT( aPosition.Sheet == nTab, "falsche Tabelle in CellAddress" ); + ScAddress aPos( (SCCOL)aPosition.Column, (SCROW)aPosition.Row, nTab ); + ScDocFunc aFunc(*pDocSh); + return aFunc.DetectiveDelSucc( aPos ); + } + return FALSE; +} + +sal_Bool SAL_CALL ScTableSheetObj::hidePrecedents( const table::CellAddress& aPosition ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + SCTAB nTab = GetTab_Impl(); + DBG_ASSERT( aPosition.Sheet == nTab, "falsche Tabelle in CellAddress" ); + ScAddress aPos( (SCCOL)aPosition.Column, (SCROW)aPosition.Row, nTab ); + ScDocFunc aFunc(*pDocSh); + return aFunc.DetectiveDelPred( aPos ); + } + return FALSE; +} + +sal_Bool SAL_CALL ScTableSheetObj::showDependents( const table::CellAddress& aPosition ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + SCTAB nTab = GetTab_Impl(); + DBG_ASSERT( aPosition.Sheet == nTab, "falsche Tabelle in CellAddress" ); + ScAddress aPos( (SCCOL)aPosition.Column, (SCROW)aPosition.Row, nTab ); + ScDocFunc aFunc(*pDocSh); + return aFunc.DetectiveAddSucc( aPos ); + } + return FALSE; +} + +sal_Bool SAL_CALL ScTableSheetObj::showPrecedents( const table::CellAddress& aPosition ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + SCTAB nTab = GetTab_Impl(); + DBG_ASSERT( aPosition.Sheet == nTab, "falsche Tabelle in CellAddress" ); + ScAddress aPos( (SCCOL)aPosition.Column, (SCROW)aPosition.Row, nTab ); + ScDocFunc aFunc(*pDocSh); + return aFunc.DetectiveAddPred( aPos ); + } + return FALSE; +} + +sal_Bool SAL_CALL ScTableSheetObj::showErrors( const table::CellAddress& aPosition ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + SCTAB nTab = GetTab_Impl(); + DBG_ASSERT( aPosition.Sheet == nTab, "falsche Tabelle in CellAddress" ); + ScAddress aPos( (SCCOL)aPosition.Column, (SCROW)aPosition.Row, nTab ); + ScDocFunc aFunc(*pDocSh); + return aFunc.DetectiveAddError( aPos ); + } + return FALSE; +} + +sal_Bool SAL_CALL ScTableSheetObj::showInvalid() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocFunc aFunc(*pDocSh); + return aFunc.DetectiveMarkInvalid( GetTab_Impl() ); + } + return FALSE; +} + +void SAL_CALL ScTableSheetObj::clearArrows() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocFunc aFunc(*pDocSh); + aFunc.DetectiveDelAll( GetTab_Impl() ); + } +} + +// XSheetOutline + +void SAL_CALL ScTableSheetObj::group( const table::CellRangeAddress& rGroupRange, + table::TableOrientation nOrientation ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + BOOL bColumns = ( nOrientation == table::TableOrientation_COLUMNS ); + ScRange aGroupRange; + ScUnoConversion::FillScRange( aGroupRange, rGroupRange ); + ScOutlineDocFunc aFunc(*pDocSh); + aFunc.MakeOutline( aGroupRange, bColumns, TRUE, TRUE ); + } +} + +void SAL_CALL ScTableSheetObj::ungroup( const table::CellRangeAddress& rGroupRange, + table::TableOrientation nOrientation ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + BOOL bColumns = ( nOrientation == table::TableOrientation_COLUMNS ); + ScRange aGroupRange; + ScUnoConversion::FillScRange( aGroupRange, rGroupRange ); + ScOutlineDocFunc aFunc(*pDocSh); + aFunc.RemoveOutline( aGroupRange, bColumns, TRUE, TRUE ); + } +} + +void SAL_CALL ScTableSheetObj::autoOutline( const table::CellRangeAddress& rCellRange ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScRange aFormulaRange; + ScUnoConversion::FillScRange( aFormulaRange, rCellRange ); + ScOutlineDocFunc aFunc(*pDocSh); + aFunc.AutoOutline( aFormulaRange, TRUE, TRUE ); + } +} + +void SAL_CALL ScTableSheetObj::clearOutline() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + SCTAB nTab = GetTab_Impl(); + ScOutlineDocFunc aFunc(*pDocSh); + aFunc.RemoveAllOutlines( nTab, TRUE, TRUE ); + } +} + +void SAL_CALL ScTableSheetObj::hideDetail( const table::CellRangeAddress& rCellRange ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScRange aMarkRange; + ScUnoConversion::FillScRange( aMarkRange, rCellRange ); + ScOutlineDocFunc aFunc(*pDocSh); + aFunc.HideMarkedOutlines( aMarkRange, TRUE, TRUE ); + } +} + +void SAL_CALL ScTableSheetObj::showDetail( const table::CellRangeAddress& rCellRange ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScRange aMarkRange; + ScUnoConversion::FillScRange( aMarkRange, rCellRange ); + ScOutlineDocFunc aFunc(*pDocSh); + aFunc.ShowMarkedOutlines( aMarkRange, TRUE, TRUE ); + } +} + +void SAL_CALL ScTableSheetObj::showLevel( sal_Int16 nLevel, table::TableOrientation nOrientation ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + BOOL bColumns = ( nOrientation == table::TableOrientation_COLUMNS ); + SCTAB nTab = GetTab_Impl(); + ScOutlineDocFunc aFunc(*pDocSh); + aFunc.SelectLevel( nTab, bColumns, nLevel, TRUE, TRUE, TRUE ); + } +} + +// XProtectable + +void SAL_CALL ScTableSheetObj::protect( const rtl::OUString& aPassword ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + // #i108245# if already protected, don't change anything + if ( pDocSh && !pDocSh->GetDocument()->IsTabProtected( GetTab_Impl() ) ) + { + String aString(aPassword); + ScDocFunc aFunc(*pDocSh); + aFunc.Protect( GetTab_Impl(), aString, TRUE ); + } +} + +void SAL_CALL ScTableSheetObj::unprotect( const rtl::OUString& aPassword ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + String aString(aPassword); + ScDocFunc aFunc(*pDocSh); + BOOL bDone = aFunc.Unprotect( GetTab_Impl(), aString, TRUE ); + if (!bDone) + throw lang::IllegalArgumentException(); + } +} + +sal_Bool SAL_CALL ScTableSheetObj::isProtected() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + return pDocSh->GetDocument()->IsTabProtected( GetTab_Impl() ); + + DBG_ERROR("keine DocShell"); //! Exception oder so? + return FALSE; +} + +// XScenario + +sal_Bool SAL_CALL ScTableSheetObj::getIsScenario() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + return pDocSh->GetDocument()->IsScenario( GetTab_Impl() ); + + return FALSE; +} + +rtl::OUString SAL_CALL ScTableSheetObj::getScenarioComment() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + String aComment; + Color aColor; + USHORT nFlags; + pDocSh->GetDocument()->GetScenarioData( GetTab_Impl(), aComment, aColor, nFlags ); + return aComment; + } + return rtl::OUString(); +} + +void SAL_CALL ScTableSheetObj::setScenarioComment( const rtl::OUString& aScenarioComment ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetTab_Impl(); + + String aName; + String aComment; + Color aColor; + USHORT nFlags; + pDoc->GetName( nTab, aName ); + pDoc->GetScenarioData( nTab, aComment, aColor, nFlags ); + + aComment = String( aScenarioComment ); + + pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags ); + } +} + +void SAL_CALL ScTableSheetObj::addRanges( const uno::Sequence<table::CellRangeAddress>& rScenRanges ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetTab_Impl(); + + if (pDoc->IsScenario(nTab)) + { + ScMarkData aMarkData; + aMarkData.SelectTable( nTab, TRUE ); + + USHORT nRangeCount = (USHORT)rScenRanges.getLength(); + if (nRangeCount) + { + const table::CellRangeAddress* pAry = rScenRanges.getConstArray(); + for (USHORT i=0; i<nRangeCount; i++) + { + DBG_ASSERT( pAry[i].Sheet == nTab, "addRanges mit falscher Tab" ); + ScRange aOneRange( (SCCOL)pAry[i].StartColumn, (SCROW)pAry[i].StartRow, nTab, + (SCCOL)pAry[i].EndColumn, (SCROW)pAry[i].EndRow, nTab ); + + aMarkData.SetMultiMarkArea( aOneRange ); + } + } + + // Szenario-Ranges sind durch Attribut gekennzeichnet + ScPatternAttr aPattern( pDoc->GetPool() ); + aPattern.GetItemSet().Put( ScMergeFlagAttr( SC_MF_SCENARIO ) ); + aPattern.GetItemSet().Put( ScProtectionAttr( TRUE ) ); + ScDocFunc aFunc(*pDocSh); + aFunc.ApplyAttributes( aMarkData, aPattern, TRUE, TRUE ); + } + + // don't use. We should use therefor a private interface, so we can also set the flags. +/* else if (nTab > 0 && pDoc->IsImportingXML()) // make this sheet as an scenario and only if it is not the first sheet and only if it is ImportingXML, + // because than no UNDO and repaint is necessary. + { + USHORT nRangeCount = (USHORT)rScenRanges.getLength(); + if (nRangeCount) + { + pDoc->SetScenario( nTab, TRUE ); + + // default flags + Color aColor( COL_LIGHTGRAY ); // Default + USHORT nFlags = SC_SCENARIO_SHOWFRAME | SC_SCENARIO_PRINTFRAME | SC_SCENARIO_TWOWAY; + String aComment; + + pDoc->SetScenarioData( nTab, aComment, aColor, nFlags ); + const table::CellRangeAddress* pAry = rScenRanges.getConstArray(); + for (USHORT i=0; i<nRangeCount; i++) + { + DBG_ASSERT( pAry[i].Sheet == nTab, "addRanges mit falscher Tab" ); + pDoc->ApplyFlagsTab( (USHORT)pAry[i].StartColumn, (USHORT)pAry[i].StartRow, + (USHORT)pAry[i].EndColumn, (USHORT)pAry[i].EndRow, nTab, SC_MF_SCENARIO ); + } + pDoc->SetActiveScenario( nTab, TRUE ); + + // set to next visible tab + USHORT j = nTab - 1; + BOOL bFinished = FALSE; + while (j < nTab && !bFinished) + { + if (pDoc->IsVisible(j)) + { + pDoc->SetVisibleTab(j); + bFinished = TRUE; + } + else + --j; + } + + ScDocFunc aFunc(*pDocSh); + aFunc.SetTableVisible( nTab, FALSE, TRUE ); + } + }*/ + } +} + +void SAL_CALL ScTableSheetObj::apply() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetTab_Impl(); + String aName; + pDoc->GetName( nTab, aName ); // Name dieses Szenarios + + SCTAB nDestTab = nTab; + while ( nDestTab > 0 && pDoc->IsScenario(nDestTab) ) + --nDestTab; + + if ( !pDoc->IsScenario(nDestTab) ) + pDocSh->UseScenario( nDestTab, aName ); + + //! sonst Fehler oder so + } +} + +// XScenarioEnhanced + +uno::Sequence< table::CellRangeAddress > SAL_CALL ScTableSheetObj::getRanges( ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetTab_Impl(); + const ScRangeList* pRangeList = pDoc->GetScenarioRanges(nTab); + if (pRangeList) + { + sal_Int32 nCount = pRangeList->Count(); + uno::Sequence< table::CellRangeAddress > aRetRanges(nCount); + table::CellRangeAddress* pAry = aRetRanges.getArray(); + for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ ) + { + const ScRange* pRange = pRangeList->GetObject( nIndex ); + pAry->StartColumn = pRange->aStart.Col(); + pAry->StartRow = pRange->aStart.Row(); + pAry->EndColumn = pRange->aEnd.Col(); + pAry->EndRow = pRange->aEnd.Row(); + pAry->Sheet = pRange->aStart.Tab(); + ++pAry; + } + return aRetRanges; + } + } + return uno::Sequence< table::CellRangeAddress > (); +} + +// XExternalSheetName + +void ScTableSheetObj::setExternalName( const ::rtl::OUString& aUrl, const ::rtl::OUString& aSheetName ) + throw (container::ElementExistException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + if ( pDoc ) + { + const SCTAB nTab = GetTab_Impl(); + const String aAbsDocName( ScGlobal::GetAbsDocName( aUrl, pDocSh ) ); + const String aDocTabName( ScGlobal::GetDocTabName( aAbsDocName, aSheetName ) ); + if ( !pDoc->RenameTab( nTab, aDocTabName, FALSE /*bUpdateRef*/, TRUE /*bExternalDocument*/ ) ) + { + throw container::ElementExistException( ::rtl::OUString(), *this ); + } + } + } +} + +// XEventsSupplier + +uno::Reference<container::XNameReplace> SAL_CALL ScTableSheetObj::getEvents() throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + return new ScSheetEventsObj( pDocSh, GetTab_Impl() ); + + return NULL; +} + +// XPropertySet erweitert fuer Sheet-Properties + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTableSheetObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef( + new SfxItemPropertySetInfo( pSheetPropSet->getPropertyMap() )); + return aRef; +} + +void ScTableSheetObj::SetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntry, const uno::Any& aValue ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + if ( pEntry ) + { + if ( IsScItemWid( pEntry->nWID ) ) + { + // for Item WIDs, call ScCellRangesBase directly + ScCellRangesBase::SetOnePropertyValue(pEntry, aValue); + return; + } + + // own properties + + ScDocShell* pDocSh = GetDocShell(); + if (!pDocSh) + return; //! Exception oder so? + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetTab_Impl(); + ScDocFunc aFunc(*pDocSh); + + if ( pEntry->nWID == SC_WID_UNO_PAGESTL ) + { + rtl::OUString aStrVal; + aValue >>= aStrVal; + String aNewStr(ScStyleNameConversion::ProgrammaticToDisplayName( + aStrVal, SFX_STYLE_FAMILY_PAGE )); + + //! Undo? (auch bei SID_STYLE_APPLY an der View) + + if ( pDoc->GetPageStyle( nTab ) != aNewStr ) + { + pDoc->SetPageStyle( nTab, aNewStr ); + if (!pDoc->IsImportingXML()) + { + ScPrintFunc( pDocSh, pDocSh->GetPrinter(), nTab ).UpdatePages(); + + SfxBindings* pBindings = pDocSh->GetViewBindings(); + if (pBindings) + { + pBindings->Invalidate( SID_STYLE_FAMILY4 ); + pBindings->Invalidate( SID_STATUS_PAGESTYLE ); + pBindings->Invalidate( FID_RESET_PRINTZOOM ); + pBindings->Invalidate( SID_ATTR_PARA_LEFT_TO_RIGHT ); + pBindings->Invalidate( SID_ATTR_PARA_RIGHT_TO_LEFT ); + } + } + pDocSh->SetDocumentModified(); + } + } + else if ( pEntry->nWID == SC_WID_UNO_CELLVIS ) + { + BOOL bVis = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + aFunc.SetTableVisible( nTab, bVis, TRUE ); + } + else if ( pEntry->nWID == SC_WID_UNO_ISACTIVE ) + { + if (pDoc->IsScenario(nTab)) + pDoc->SetActiveScenario( nTab, ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + } + else if ( pEntry->nWID == SC_WID_UNO_BORDCOL ) + { + if (pDoc->IsScenario(nTab)) + { + sal_Int32 nNewColor = 0; + if (aValue >>= nNewColor) + { + String aName; + String aComment; + Color aColor; + USHORT nFlags; + pDoc->GetName( nTab, aName ); + pDoc->GetScenarioData( nTab, aComment, aColor, nFlags ); + + aColor = Color(static_cast<sal_uInt32>(nNewColor)); + + pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags ); + } + } + } + else if ( pEntry->nWID == SC_WID_UNO_PROTECT ) + { + if (pDoc->IsScenario(nTab)) + { + String aName; + String aComment; + Color aColor; + USHORT nFlags; + pDoc->GetName( nTab, aName ); + pDoc->GetScenarioData( nTab, aComment, aColor, nFlags ); + sal_Bool bModify(sal_False); + + if (ScUnoHelpFunctions::GetBoolFromAny( aValue )) + { + if (!(nFlags & SC_SCENARIO_PROTECT)) + { + nFlags |= SC_SCENARIO_PROTECT; + bModify = sal_True; + } + } + else + { + if (nFlags & SC_SCENARIO_PROTECT) + { + nFlags -= SC_SCENARIO_PROTECT; + bModify = sal_True; + } + } + + if (bModify) + pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags ); + } + } + else if ( pEntry->nWID == SC_WID_UNO_SHOWBORD ) + { + if (pDoc->IsScenario(nTab)) + { + String aName; + String aComment; + Color aColor; + USHORT nFlags; + pDoc->GetName( nTab, aName ); + pDoc->GetScenarioData( nTab, aComment, aColor, nFlags ); + sal_Bool bModify(sal_False); + + if (ScUnoHelpFunctions::GetBoolFromAny( aValue )) + { + if (!(nFlags & SC_SCENARIO_SHOWFRAME)) + { + nFlags |= SC_SCENARIO_SHOWFRAME; + bModify = sal_True; + } + } + else + { + if (nFlags & SC_SCENARIO_SHOWFRAME) + { + nFlags -= SC_SCENARIO_SHOWFRAME; + bModify = sal_True; + } + } + + if (bModify) + pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags ); + } + } + else if ( pEntry->nWID == SC_WID_UNO_PRINTBORD ) + { + if (pDoc->IsScenario(nTab)) + { + String aName; + String aComment; + Color aColor; + USHORT nFlags; + pDoc->GetName( nTab, aName ); + pDoc->GetScenarioData( nTab, aComment, aColor, nFlags ); + sal_Bool bModify(sal_False); + + if (ScUnoHelpFunctions::GetBoolFromAny( aValue )) + { + if (!(nFlags & SC_SCENARIO_PRINTFRAME)) + { + nFlags |= SC_SCENARIO_PRINTFRAME; + bModify = sal_True; + } + } + else + { + if (nFlags & SC_SCENARIO_PRINTFRAME) + { + nFlags -= SC_SCENARIO_PRINTFRAME; + bModify = sal_True; + } + } + + if (bModify) + pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags ); + } + } + else if ( pEntry->nWID == SC_WID_UNO_COPYBACK ) + { + if (pDoc->IsScenario(nTab)) + { + String aName; + String aComment; + Color aColor; + USHORT nFlags; + pDoc->GetName( nTab, aName ); + pDoc->GetScenarioData( nTab, aComment, aColor, nFlags ); + sal_Bool bModify(sal_False); + + if (ScUnoHelpFunctions::GetBoolFromAny( aValue )) + { + if (!(nFlags & SC_SCENARIO_TWOWAY)) + { + nFlags |= SC_SCENARIO_TWOWAY; + bModify = sal_True; + } + } + else + { + if (nFlags & SC_SCENARIO_TWOWAY) + { + nFlags -= SC_SCENARIO_TWOWAY; + bModify = sal_True; + } + } + + if (bModify) + pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags ); + } + } + else if ( pEntry->nWID == SC_WID_UNO_COPYSTYL ) + { + if (pDoc->IsScenario(nTab)) + { + String aName; + String aComment; + Color aColor; + USHORT nFlags; + pDoc->GetName( nTab, aName ); + pDoc->GetScenarioData( nTab, aComment, aColor, nFlags ); + sal_Bool bModify(sal_False); + + if (ScUnoHelpFunctions::GetBoolFromAny( aValue )) + { + if (!(nFlags & SC_SCENARIO_ATTRIB)) + { + nFlags |= SC_SCENARIO_ATTRIB; + bModify = sal_True; + } + } + else + { + if (nFlags & SC_SCENARIO_ATTRIB) + { + nFlags -= SC_SCENARIO_ATTRIB; + bModify = sal_True; + } + } + + if (bModify) + pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags ); + } + } + else if ( pEntry->nWID == SC_WID_UNO_COPYFORM ) + { + if (pDoc->IsScenario(nTab)) + { + String aName; + String aComment; + Color aColor; + USHORT nFlags; + pDoc->GetName( nTab, aName ); + pDoc->GetScenarioData( nTab, aComment, aColor, nFlags ); + sal_Bool bModify(sal_False); + + if (ScUnoHelpFunctions::GetBoolFromAny( aValue )) + { + if (nFlags & SC_SCENARIO_VALUE) + { + nFlags -= SC_SCENARIO_VALUE; + bModify = sal_True; + } + } + else + { + if (!(nFlags & SC_SCENARIO_VALUE)) + { + nFlags |= SC_SCENARIO_VALUE; + bModify = sal_True; + } + } + + if (bModify) + pDocSh->ModifyScenario( nTab, aName, aComment, aColor, nFlags ); + } + } + else if ( pEntry->nWID == SC_WID_UNO_TABLAYOUT ) + { + sal_Int16 nValue = 0; + if (aValue >>= nValue) + { + if (nValue == com::sun::star::text::WritingMode2::RL_TB) + aFunc.SetLayoutRTL(nTab, sal_True, sal_True); + else + aFunc.SetLayoutRTL(nTab, sal_False, sal_True); + } + } + else if ( pEntry->nWID == SC_WID_UNO_AUTOPRINT ) + { + BOOL bAutoPrint = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + if (bAutoPrint) + pDoc->SetPrintEntireSheet( nTab ); // clears all print ranges + else + { + if (pDoc->IsPrintEntireSheet( nTab )) + pDoc->ClearPrintRanges( nTab ); // if this flag is true, there are no PrintRanges, so Clear clears only the flag. + } + } + else if ( pEntry->nWID == SC_WID_UNO_TABCOLOR ) + { + sal_Int32 nColor = COL_AUTO; + if (aValue >>= nColor) + { + if (static_cast<ColorData>(nColor) != COL_AUTO) + pDoc->SetTabBgColor(nTab, Color(static_cast<ColorData>(nColor))); + } + } + else if ( pEntry->nWID == SC_WID_UNO_CODENAME ) + { + rtl::OUString aCodeName; + if ( pDocSh && ( aValue >>= aCodeName ) ) + { + String sNewName( aCodeName ); + pDocSh->GetDocument()->SetCodeName( GetTab_Impl(), sNewName ); + } + } + else + ScCellRangeObj::SetOnePropertyValue(pEntry, aValue); // base class, no Item WID + } +} + +void ScTableSheetObj::GetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntry, + uno::Any& rAny ) + throw(uno::RuntimeException) +{ + if ( pEntry ) + { + ScDocShell* pDocSh = GetDocShell(); + if (!pDocSh) + throw uno::RuntimeException(); + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = GetTab_Impl(); + + if ( pEntry->nWID == SC_WID_UNO_PAGESTL ) + { + rAny <<= rtl::OUString( ScStyleNameConversion::DisplayToProgrammaticName( + pDoc->GetPageStyle( nTab ), SFX_STYLE_FAMILY_PAGE ) ); + } + else if ( pEntry->nWID == SC_WID_UNO_CELLVIS ) + { + BOOL bVis = pDoc->IsVisible( nTab ); + ScUnoHelpFunctions::SetBoolInAny( rAny, bVis ); + } + else if ( pEntry->nWID == SC_WID_UNO_LINKDISPBIT ) + { + // no target bitmaps for individual entries (would be all equal) + // ScLinkTargetTypeObj::SetLinkTargetBitmap( aAny, SC_LINKTARGETTYPE_SHEET ); + } + else if ( pEntry->nWID == SC_WID_UNO_LINKDISPNAME ) + { + // LinkDisplayName for hyperlink dialog + rAny <<= getName(); // sheet name + } + else if ( pEntry->nWID == SC_WID_UNO_ISACTIVE ) + { + if (pDoc->IsScenario(nTab)) + ScUnoHelpFunctions::SetBoolInAny( rAny, pDoc->IsActiveScenario( nTab )); + } + else if ( pEntry->nWID == SC_WID_UNO_BORDCOL ) + { + if (pDoc->IsScenario(nTab)) + { + String aComment; + Color aColor; + USHORT nFlags; + pDoc->GetScenarioData( nTab, aComment, aColor, nFlags ); + + rAny <<= static_cast<sal_Int32>(aColor.GetColor()); + } + } + else if ( pEntry->nWID == SC_WID_UNO_PROTECT ) + { + if (pDoc->IsScenario(nTab)) + { + String aComment; + Color aColor; + USHORT nFlags; + pDoc->GetScenarioData( nTab, aComment, aColor, nFlags ); + + ScUnoHelpFunctions::SetBoolInAny( rAny, (nFlags & SC_SCENARIO_PROTECT) != 0 ); + } + } + else if ( pEntry->nWID == SC_WID_UNO_SHOWBORD ) + { + if (pDoc->IsScenario(nTab)) + { + String aComment; + Color aColor; + USHORT nFlags; + pDoc->GetScenarioData( nTab, aComment, aColor, nFlags ); + + ScUnoHelpFunctions::SetBoolInAny( rAny, (nFlags & SC_SCENARIO_SHOWFRAME) != 0 ); + } + } + else if ( pEntry->nWID == SC_WID_UNO_PRINTBORD ) + { + if (pDoc->IsScenario(nTab)) + { + String aComment; + Color aColor; + USHORT nFlags; + pDoc->GetScenarioData( nTab, aComment, aColor, nFlags ); + + ScUnoHelpFunctions::SetBoolInAny( rAny, (nFlags & SC_SCENARIO_PRINTFRAME) != 0 ); + } + } + else if ( pEntry->nWID == SC_WID_UNO_COPYBACK ) + { + if (pDoc->IsScenario(nTab)) + { + String aComment; + Color aColor; + USHORT nFlags; + pDoc->GetScenarioData( nTab, aComment, aColor, nFlags ); + + ScUnoHelpFunctions::SetBoolInAny( rAny, (nFlags & SC_SCENARIO_TWOWAY) != 0 ); + } + } + else if ( pEntry->nWID == SC_WID_UNO_COPYSTYL ) + { + if (pDoc->IsScenario(nTab)) + { + String aComment; + Color aColor; + USHORT nFlags; + pDoc->GetScenarioData( nTab, aComment, aColor, nFlags ); + + ScUnoHelpFunctions::SetBoolInAny( rAny, (nFlags & SC_SCENARIO_ATTRIB) != 0 ); + } + } + else if ( pEntry->nWID == SC_WID_UNO_COPYFORM ) + { + if (pDoc->IsScenario(nTab)) + { + String aComment; + Color aColor; + USHORT nFlags; + pDoc->GetScenarioData( nTab, aComment, aColor, nFlags ); + + ScUnoHelpFunctions::SetBoolInAny( rAny, !(nFlags & SC_SCENARIO_VALUE)); + } + } + else if ( pEntry->nWID == SC_WID_UNO_TABLAYOUT ) + { + if (pDoc->IsLayoutRTL(nTab)) + rAny <<= sal_Int16(com::sun::star::text::WritingMode2::RL_TB); + else + rAny <<= sal_Int16(com::sun::star::text::WritingMode2::LR_TB); + } + else if ( pEntry->nWID == SC_WID_UNO_AUTOPRINT ) + { + BOOL bAutoPrint = pDoc->IsPrintEntireSheet( nTab ); + ScUnoHelpFunctions::SetBoolInAny( rAny, bAutoPrint ); + } + else if ( pEntry->nWID == SC_WID_UNO_TABCOLOR ) + { + rAny <<= sal_Int32(pDoc->GetTabBgColor(nTab).GetColor()); + } + else if ( pEntry->nWID == SC_WID_UNO_CODENAME ) + { + String aCodeName; + if ( pDocSh ) + pDocSh->GetDocument()->GetCodeName( GetTab_Impl(), aCodeName ); + rAny <<= rtl::OUString( aCodeName ); + } + else + ScCellRangeObj::GetOnePropertyValue(pEntry, rAny); + } +} + +const SfxItemPropertyMap* ScTableSheetObj::GetItemPropertyMap() +{ + return pSheetPropSet->getPropertyMap(); +} + +// XServiceInfo + +rtl::OUString SAL_CALL ScTableSheetObj::getImplementationName() throw(uno::RuntimeException) +{ + return rtl::OUString::createFromAscii( "ScTableSheetObj" ); +} + +sal_Bool SAL_CALL ScTableSheetObj::supportsService( const rtl::OUString& rServiceName ) + throw(uno::RuntimeException) +{ + String aServiceStr( rServiceName ); + return aServiceStr.EqualsAscii( SCSPREADSHEET_SERVICE ) || + aServiceStr.EqualsAscii( SCSHEETCELLRANGE_SERVICE ) || + aServiceStr.EqualsAscii( SCCELLRANGE_SERVICE ) || + aServiceStr.EqualsAscii( SCCELLPROPERTIES_SERVICE ) || + aServiceStr.EqualsAscii( SCCHARPROPERTIES_SERVICE ) || + aServiceStr.EqualsAscii( SCPARAPROPERTIES_SERVICE ) || + aServiceStr.EqualsAscii( SCLINKTARGET_SERVICE ); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScTableSheetObj::getSupportedServiceNames() + throw(uno::RuntimeException) +{ + uno::Sequence<rtl::OUString> aRet(7); + rtl::OUString* pArray = aRet.getArray(); + pArray[0] = rtl::OUString::createFromAscii( SCSPREADSHEET_SERVICE ); + pArray[1] = rtl::OUString::createFromAscii( SCSHEETCELLRANGE_SERVICE ); + pArray[2] = rtl::OUString::createFromAscii( SCCELLRANGE_SERVICE ); + pArray[3] = rtl::OUString::createFromAscii( SCCELLPROPERTIES_SERVICE ); + pArray[4] = rtl::OUString::createFromAscii( SCCHARPROPERTIES_SERVICE ); + pArray[5] = rtl::OUString::createFromAscii( SCPARAPROPERTIES_SERVICE ); + pArray[6] = rtl::OUString::createFromAscii( SCLINKTARGET_SERVICE ); + return aRet; +} + +// XUnoTunnel + +sal_Int64 SAL_CALL ScTableSheetObj::getSomething( + const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); + } + + return ScCellRangeObj::getSomething( rId ); +} + +// static +const uno::Sequence<sal_Int8>& ScTableSheetObj::getUnoTunnelId() +{ + static uno::Sequence<sal_Int8> * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +// static +ScTableSheetObj* ScTableSheetObj::getImplementation( const uno::Reference<uno::XInterface> xObj ) +{ + ScTableSheetObj* pRet = NULL; + uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); + if (xUT.is()) + pRet = reinterpret_cast<ScTableSheetObj*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId()))); + return pRet; +} + +//------------------------------------------------------------------------ + +ScTableColumnObj::ScTableColumnObj( ScDocShell* pDocSh, SCCOL nCol, SCTAB nTab ) : + ScCellRangeObj( pDocSh, ScRange(nCol,0,nTab, nCol,MAXROW,nTab) ), + pColPropSet(lcl_GetColumnPropertySet()) +{ +} + +ScTableColumnObj::~ScTableColumnObj() +{ +} + +uno::Any SAL_CALL ScTableColumnObj::queryInterface( const uno::Type& rType ) throw(uno::RuntimeException) +{ + SC_QUERYINTERFACE( container::XNamed ) + + return ScCellRangeObj::queryInterface( rType ); +} + +void SAL_CALL ScTableColumnObj::acquire() throw() +{ + ScCellRangeObj::acquire(); +} + +void SAL_CALL ScTableColumnObj::release() throw() +{ + ScCellRangeObj::release(); +} + +uno::Sequence<uno::Type> SAL_CALL ScTableColumnObj::getTypes() throw(uno::RuntimeException) +{ + static uno::Sequence<uno::Type> aTypes; + if ( aTypes.getLength() == 0 ) + { + uno::Sequence<uno::Type> aParentTypes(ScCellRangeObj::getTypes()); + long nParentLen = aParentTypes.getLength(); + const uno::Type* pParentPtr = aParentTypes.getConstArray(); + + aTypes.realloc( nParentLen + 1 ); + uno::Type* pPtr = aTypes.getArray(); + pPtr[nParentLen + 0] = getCppuType((const uno::Reference<container::XNamed>*)0); + + for (long i=0; i<nParentLen; i++) + pPtr[i] = pParentPtr[i]; // parent types first + } + return aTypes; +} + +uno::Sequence<sal_Int8> SAL_CALL ScTableColumnObj::getImplementationId() throw(uno::RuntimeException) +{ + static uno::Sequence< sal_Int8 > aId; + if( aId.getLength() == 0 ) + { + aId.realloc( 16 ); + rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True ); + } + return aId; +} + +// XNamed + +rtl::OUString SAL_CALL ScTableColumnObj::getName() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + const ScRange& rRange = GetRange(); + DBG_ASSERT(rRange.aStart.Col() == rRange.aEnd.Col(), "too many columns"); + SCCOL nCol = rRange.aStart.Col(); + + return ScColToAlpha( nCol ); // from global.hxx +} + +void SAL_CALL ScTableColumnObj::setName( const rtl::OUString& /* aNewName */ ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + throw uno::RuntimeException(); // read-only +} + +// XPropertySet erweitert fuer Spalten-Properties + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTableColumnObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef( + new SfxItemPropertySetInfo( pColPropSet->getPropertyMap() )); + return aRef; +} + +void ScTableColumnObj::SetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntry, const uno::Any& aValue ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + if ( pEntry ) + { + if ( IsScItemWid( pEntry->nWID ) ) + { + // for Item WIDs, call ScCellRangesBase directly + ScCellRangesBase::SetOnePropertyValue(pEntry, aValue); + return; + } + + // own properties + + ScDocShell* pDocSh = GetDocShell(); + if (!pDocSh) + return; //! Exception oder so? + const ScRange& rRange = GetRange(); + DBG_ASSERT(rRange.aStart.Col() == rRange.aEnd.Col(), "zuviele Spalten"); + SCCOL nCol = rRange.aStart.Col(); + SCTAB nTab = rRange.aStart.Tab(); + ScDocFunc aFunc(*pDocSh); + + SCCOLROW nColArr[2]; + nColArr[0] = nColArr[1] = nCol; + + if ( pEntry->nWID == SC_WID_UNO_CELLWID ) + { + sal_Int32 nNewWidth = 0; + if ( aValue >>= nNewWidth ) + { + // property is 1/100mm, column width is twips + nNewWidth = HMMToTwips(nNewWidth); + aFunc.SetWidthOrHeight( TRUE, 1, nColArr, nTab, SC_SIZE_ORIGINAL, + (USHORT)nNewWidth, TRUE, TRUE ); + } + } + else if ( pEntry->nWID == SC_WID_UNO_CELLVIS ) + { + BOOL bVis = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + ScSizeMode eMode = bVis ? SC_SIZE_SHOW : SC_SIZE_DIRECT; + aFunc.SetWidthOrHeight( TRUE, 1, nColArr, nTab, eMode, 0, TRUE, TRUE ); + // SC_SIZE_DIRECT mit Groesse 0 blendet aus + } + else if ( pEntry->nWID == SC_WID_UNO_OWIDTH ) + { + BOOL bOpt = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + if (bOpt) + aFunc.SetWidthOrHeight( TRUE, 1, nColArr, nTab, + SC_SIZE_OPTIMAL, STD_EXTRA_WIDTH, TRUE, TRUE ); + // FALSE bei Spalten momentan ohne Auswirkung + } + else if ( pEntry->nWID == SC_WID_UNO_NEWPAGE || pEntry->nWID == SC_WID_UNO_MANPAGE ) + { + BOOL bSet = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + if (bSet) + aFunc.InsertPageBreak( TRUE, rRange.aStart, TRUE, TRUE, TRUE ); + else + aFunc.RemovePageBreak( TRUE, rRange.aStart, TRUE, TRUE, TRUE ); + } + else + ScCellRangeObj::SetOnePropertyValue(pEntry, aValue); // base class, no Item WID + } +} + +void ScTableColumnObj::GetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntry, + uno::Any& rAny ) + throw(uno::RuntimeException) +{ + if ( pEntry ) + { + ScDocShell* pDocSh = GetDocShell(); + if (!pDocSh) + throw uno::RuntimeException(); + + ScDocument* pDoc = pDocSh->GetDocument(); + const ScRange& rRange = GetRange(); + DBG_ASSERT(rRange.aStart.Col() == rRange.aEnd.Col(), "zuviele Spalten"); + SCCOL nCol = rRange.aStart.Col(); + SCTAB nTab = rRange.aStart.Tab(); + + if ( pEntry->nWID == SC_WID_UNO_CELLWID ) + { + // for hidden column, return original height + USHORT nWidth = pDoc->GetOriginalWidth( nCol, nTab ); + // property is 1/100mm, column width is twips + nWidth = (USHORT) TwipsToHMM(nWidth); + rAny <<= (sal_Int32)( nWidth ); + } + else if ( pEntry->nWID == SC_WID_UNO_CELLVIS ) + { + SCCOL nDummy; + bool bHidden = pDoc->ColHidden(nCol, nTab, nDummy); + ScUnoHelpFunctions::SetBoolInAny( rAny, !bHidden ); + } + else if ( pEntry->nWID == SC_WID_UNO_OWIDTH ) + { + //! momentan immer gesetzt ??!?! + BOOL bOpt = !(pDoc->GetColFlags( nCol, nTab ) & CR_MANUALSIZE); + ScUnoHelpFunctions::SetBoolInAny( rAny, bOpt ); + } + else if ( pEntry->nWID == SC_WID_UNO_NEWPAGE ) + { + ScBreakType nBreak = pDoc->HasColBreak(nCol, nTab); + ScUnoHelpFunctions::SetBoolInAny( rAny, nBreak ); + } + else if ( pEntry->nWID == SC_WID_UNO_MANPAGE ) + { + ScBreakType nBreak = pDoc->HasColBreak(nCol, nTab); + ScUnoHelpFunctions::SetBoolInAny(rAny, (nBreak & BREAK_MANUAL)); + } + else + ScCellRangeObj::GetOnePropertyValue(pEntry, rAny); + } +} + +const SfxItemPropertyMap* ScTableColumnObj::GetItemPropertyMap() +{ + return pColPropSet->getPropertyMap(); +} + +//------------------------------------------------------------------------ + +ScTableRowObj::ScTableRowObj(ScDocShell* pDocSh, SCROW nRow, SCTAB nTab) : + ScCellRangeObj( pDocSh, ScRange(0,nRow,nTab, MAXCOL,nRow,nTab) ), + pRowPropSet(lcl_GetRowPropertySet()) +{ +} + +ScTableRowObj::~ScTableRowObj() +{ +} + +// XPropertySet erweitert fuer Zeilen-Properties + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTableRowObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef( + new SfxItemPropertySetInfo( pRowPropSet->getPropertyMap() )); + return aRef; +} + +void ScTableRowObj::SetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntry, const uno::Any& aValue ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + if ( pEntry ) + { + if ( IsScItemWid( pEntry->nWID ) ) + { + // for Item WIDs, call ScCellRangesBase directly + ScCellRangesBase::SetOnePropertyValue(pEntry, aValue); + return; + } + + // own properties + + ScDocShell* pDocSh = GetDocShell(); + if (!pDocSh) + return; //! Exception oder so? + ScDocument* pDoc = pDocSh->GetDocument(); + const ScRange& rRange = GetRange(); + DBG_ASSERT(rRange.aStart.Row() == rRange.aEnd.Row(), "zuviele Zeilen"); + SCROW nRow = rRange.aStart.Row(); + SCTAB nTab = rRange.aStart.Tab(); + ScDocFunc aFunc(*pDocSh); + + SCCOLROW nRowArr[2]; + nRowArr[0] = nRowArr[1] = nRow; + + if ( pEntry->nWID == SC_WID_UNO_CELLHGT ) + { + sal_Int32 nNewHeight = 0; + if ( aValue >>= nNewHeight ) + { + // property is 1/100mm, row height is twips + nNewHeight = HMMToTwips(nNewHeight); + aFunc.SetWidthOrHeight( FALSE, 1, nRowArr, nTab, SC_SIZE_ORIGINAL, + (USHORT)nNewHeight, TRUE, TRUE ); + } + } + else if ( pEntry->nWID == SC_WID_UNO_CELLVIS ) + { + BOOL bVis = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + ScSizeMode eMode = bVis ? SC_SIZE_SHOW : SC_SIZE_DIRECT; + aFunc.SetWidthOrHeight( FALSE, 1, nRowArr, nTab, eMode, 0, TRUE, TRUE ); + // SC_SIZE_DIRECT mit Groesse 0 blendet aus + } + else if ( pEntry->nWID == SC_WID_UNO_CELLFILT ) + { + BOOL bFil = ScUnoHelpFunctions::GetBoolFromAny( aValue ); +// ScSizeMode eMode = bVis ? SC_SIZE_SHOW : SC_SIZE_DIRECT; +// aFunc.SetWidthOrHeight( FALSE, 1, nRowArr, nTab, eMode, 0, TRUE, TRUE ); + // SC_SIZE_DIRECT mit Groesse 0 blendet aus + pDoc->SetRowFiltered(nRow, nRow, nTab, bFil); + } + else if ( pEntry->nWID == SC_WID_UNO_OHEIGHT ) + { + BOOL bOpt = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + if (bOpt) + aFunc.SetWidthOrHeight( FALSE, 1, nRowArr, nTab, SC_SIZE_OPTIMAL, 0, TRUE, TRUE ); + else + { + // set current height again manually + USHORT nHeight = pDoc->GetOriginalHeight( nRow, nTab ); + aFunc.SetWidthOrHeight( FALSE, 1, nRowArr, nTab, SC_SIZE_ORIGINAL, nHeight, TRUE, TRUE ); + } + } + else if ( pEntry->nWID == SC_WID_UNO_NEWPAGE || pEntry->nWID == SC_WID_UNO_MANPAGE ) + { + BOOL bSet = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + if (bSet) + aFunc.InsertPageBreak( FALSE, rRange.aStart, TRUE, TRUE, TRUE ); + else + aFunc.RemovePageBreak( FALSE, rRange.aStart, TRUE, TRUE, TRUE ); + } + else + ScCellRangeObj::SetOnePropertyValue(pEntry, aValue); // base class, no Item WID + } +} + +void ScTableRowObj::GetOnePropertyValue( const SfxItemPropertySimpleEntry* pEntry, + uno::Any& rAny ) + throw(uno::RuntimeException) +{ + if ( pEntry ) + { + ScDocShell* pDocSh = GetDocShell(); + if (!pDocSh) + throw uno::RuntimeException(); + ScDocument* pDoc = pDocSh->GetDocument(); + const ScRange& rRange = GetRange(); + DBG_ASSERT(rRange.aStart.Row() == rRange.aEnd.Row(), "zuviele Zeilen"); + SCROW nRow = rRange.aStart.Row(); + SCTAB nTab = rRange.aStart.Tab(); + + if ( pEntry->nWID == SC_WID_UNO_CELLHGT ) + { + // for hidden row, return original height + USHORT nHeight = pDoc->GetOriginalHeight( nRow, nTab ); + // property is 1/100mm, row height is twips + nHeight = (USHORT) TwipsToHMM(nHeight); + rAny <<= (sal_Int32)( nHeight ); + } + else if ( pEntry->nWID == SC_WID_UNO_CELLVIS ) + { + SCROW nDummy; + bool bHidden = pDoc->RowHidden(nRow, nTab, nDummy); + ScUnoHelpFunctions::SetBoolInAny( rAny, !bHidden ); + } + else if ( pEntry->nWID == SC_WID_UNO_CELLFILT ) + { + bool bVis = pDoc->RowFiltered(nRow, nTab); + ScUnoHelpFunctions::SetBoolInAny( rAny, bVis ); + } + else if ( pEntry->nWID == SC_WID_UNO_OHEIGHT ) + { + BOOL bOpt = !(pDoc->GetRowFlags( nRow, nTab ) & CR_MANUALSIZE); + ScUnoHelpFunctions::SetBoolInAny( rAny, bOpt ); + } + else if ( pEntry->nWID == SC_WID_UNO_NEWPAGE ) + { + ScBreakType nBreak = pDoc->HasRowBreak(nRow, nTab); + ScUnoHelpFunctions::SetBoolInAny( rAny, nBreak ); + } + else if ( pEntry->nWID == SC_WID_UNO_MANPAGE ) + { + ScBreakType nBreak = (pDoc->HasRowBreak(nRow, nTab) & BREAK_MANUAL); + ScUnoHelpFunctions::SetBoolInAny( rAny, nBreak ); + } + else + ScCellRangeObj::GetOnePropertyValue(pEntry, rAny); + } +} + +const SfxItemPropertyMap* ScTableRowObj::GetItemPropertyMap() +{ + return pRowPropSet->getPropertyMap(); +} + +//------------------------------------------------------------------------ + +ScCellsObj::ScCellsObj(ScDocShell* pDocSh, const ScRangeList& rR) : + pDocShell( pDocSh ), + aRanges( rR ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScCellsObj::~ScCellsObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScCellsObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( ScUpdateRefHint ) ) + { + const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint; + aRanges.UpdateReference( rRef.GetMode(), pDocShell->GetDocument(), rRef.GetRange(), + rRef.GetDx(), rRef.GetDy(), rRef.GetDz() ); + } + else if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +// XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScCellsObj::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + return new ScCellsEnumeration( pDocShell, aRanges ); + return NULL; +} + +uno::Type SAL_CALL ScCellsObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((uno::Reference<table::XCell>*)0); +} + +sal_Bool SAL_CALL ScCellsObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + BOOL bHas = FALSE; + if ( pDocShell ) + { + //! schneller selber testen? + + uno::Reference<container::XEnumeration> xEnum(new ScCellsEnumeration( pDocShell, aRanges )); + bHas = xEnum->hasMoreElements(); + } + return bHas; +} + +//------------------------------------------------------------------------ + +ScCellsEnumeration::ScCellsEnumeration(ScDocShell* pDocSh, const ScRangeList& rR) : + pDocShell( pDocSh ), + aRanges( rR ), + pMark( NULL ), + bAtEnd( FALSE ) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + pDoc->AddUnoObject(*this); + + if ( aRanges.Count() == 0 ) + bAtEnd = TRUE; + else + { + SCTAB nTab = 0; + const ScRange* pFirst = aRanges.GetObject(0); + if (pFirst) + nTab = pFirst->aStart.Tab(); + aPos = ScAddress(0,0,nTab); + CheckPos_Impl(); // aPos auf erste passende Zelle setzen + } +} + +void ScCellsEnumeration::CheckPos_Impl() +{ + if (pDocShell) + { + BOOL bFound = FALSE; + ScDocument* pDoc = pDocShell->GetDocument(); + ScBaseCell* pCell = pDoc->GetCell(aPos); + if ( pCell && pCell->GetCellType() != CELLTYPE_NOTE ) + { + if (!pMark) + { + pMark = new ScMarkData; + pMark->MarkFromRangeList( aRanges, FALSE ); + pMark->MarkToMulti(); // needed for GetNextMarkedCell + } + bFound = pMark->IsCellMarked( aPos.Col(), aPos.Row() ); + } + if (!bFound) + Advance_Impl(); + } +} + +ScCellsEnumeration::~ScCellsEnumeration() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); + delete pMark; +} + +void ScCellsEnumeration::Advance_Impl() +{ + DBG_ASSERT(!bAtEnd,"zuviel Advance_Impl"); + if (!pMark) + { + pMark = new ScMarkData; + pMark->MarkFromRangeList( aRanges, FALSE ); + pMark->MarkToMulti(); // needed for GetNextMarkedCell + } + + SCCOL nCol = aPos.Col(); + SCROW nRow = aPos.Row(); + SCTAB nTab = aPos.Tab(); + BOOL bFound = pDocShell->GetDocument()->GetNextMarkedCell( nCol, nRow, nTab, *pMark ); + if (bFound) + aPos.Set( nCol, nRow, nTab ); + else + bAtEnd = TRUE; // kommt nix mehr +} + +void ScCellsEnumeration::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( ScUpdateRefHint ) ) + { + if (pDocShell) + { + const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint; + aRanges.UpdateReference( rRef.GetMode(), pDocShell->GetDocument(), rRef.GetRange(), + rRef.GetDx(), rRef.GetDy(), rRef.GetDz() ); + + delete pMark; // aus verschobenen Bereichen neu erzeugen + pMark = NULL; + + if (!bAtEnd) // aPos anpassen + { + ScRangeList aNew; + aNew.Append(ScRange(aPos)); + aNew.UpdateReference( rRef.GetMode(), pDocShell->GetDocument(), rRef.GetRange(), + rRef.GetDx(), rRef.GetDy(), rRef.GetDz() ); + if (aNew.Count()==1) + { + aPos = aNew.GetObject(0)->aStart; + CheckPos_Impl(); + } + } + } + } + else if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +// XEnumeration + +sal_Bool SAL_CALL ScCellsEnumeration::hasMoreElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return !bAtEnd; +} + +uno::Any SAL_CALL ScCellsEnumeration::nextElement() throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell && !bAtEnd) + { + // Interface-Typ muss zu ScCellsObj::getElementType passen + + ScAddress aTempPos(aPos); + Advance_Impl(); + return uno::makeAny(uno::Reference<table::XCell>(new ScCellObj( pDocShell, aTempPos ))); + } + + throw container::NoSuchElementException(); // no more elements +// return uno::Any(); +} + +//------------------------------------------------------------------------ + +ScCellFormatsObj::ScCellFormatsObj(ScDocShell* pDocSh, const ScRange& rRange) : + pDocShell( pDocSh ), + aTotalRange( rRange ) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + pDoc->AddUnoObject(*this); + + DBG_ASSERT( aTotalRange.aStart.Tab() == aTotalRange.aEnd.Tab(), "unterschiedliche Tabellen" ); +} + +ScCellFormatsObj::~ScCellFormatsObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScCellFormatsObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( ScUpdateRefHint ) ) + { + //! aTotalRange... + } + else if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +ScCellRangeObj* ScCellFormatsObj::GetObjectByIndex_Impl(long nIndex) const +{ + //! direkt auf die AttrArrays zugreifen !!!! + + ScCellRangeObj* pRet = NULL; + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + long nPos = 0; + ScAttrRectIterator aIter( pDoc, aTotalRange.aStart.Tab(), + aTotalRange.aStart.Col(), aTotalRange.aStart.Row(), + aTotalRange.aEnd.Col(), aTotalRange.aEnd.Row() ); + SCCOL nCol1, nCol2; + SCROW nRow1, nRow2; + while ( aIter.GetNext( nCol1, nCol2, nRow1, nRow2 ) ) + { + if ( nPos == nIndex ) + { + SCTAB nTab = aTotalRange.aStart.Tab(); + ScRange aNext( nCol1, nRow1, nTab, nCol2, nRow2, nTab ); + + if ( aNext.aStart == aNext.aEnd ) + pRet = new ScCellObj( pDocShell, aNext.aStart ); + else + pRet = new ScCellRangeObj( pDocShell, aNext ); + } + ++nPos; + } + } + return pRet; +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScCellFormatsObj::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + //! direkt auf die AttrArrays zugreifen !!!! + + long nCount = 0; + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScAttrRectIterator aIter( pDoc, aTotalRange.aStart.Tab(), + aTotalRange.aStart.Col(), aTotalRange.aStart.Row(), + aTotalRange.aEnd.Col(), aTotalRange.aEnd.Row() ); + SCCOL nCol1, nCol2; + SCROW nRow1, nRow2; + while ( aIter.GetNext( nCol1, nCol2, nRow1, nRow2 ) ) + ++nCount; + } + return nCount; +} + +uno::Any SAL_CALL ScCellFormatsObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + uno::Reference<table::XCellRange> xRange(GetObjectByIndex_Impl(nIndex)); + if (xRange.is()) + return uno::makeAny(xRange); + else + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +uno::Type SAL_CALL ScCellFormatsObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((uno::Reference<table::XCellRange>*)0); +} + +sal_Bool SAL_CALL ScCellFormatsObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); //! immer groesser 0 ?? +} + +// XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScCellFormatsObj::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + return new ScCellFormatsEnumeration( pDocShell, aTotalRange ); + return NULL; +} + +//------------------------------------------------------------------------ + +ScCellFormatsEnumeration::ScCellFormatsEnumeration(ScDocShell* pDocSh, const ScRange& rRange) : + pDocShell( pDocSh ), + nTab( rRange.aStart.Tab() ), + pIter( NULL ), + bAtEnd( FALSE ), + bDirty( FALSE ) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + pDoc->AddUnoObject(*this); + + DBG_ASSERT( rRange.aStart.Tab() == rRange.aEnd.Tab(), + "CellFormatsEnumeration: unterschiedliche Tabellen" ); + + pIter = new ScAttrRectIterator( pDoc, nTab, + rRange.aStart.Col(), rRange.aStart.Row(), + rRange.aEnd.Col(), rRange.aEnd.Row() ); + Advance_Impl(); +} + +ScCellFormatsEnumeration::~ScCellFormatsEnumeration() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); + delete pIter; +} + +void ScCellFormatsEnumeration::Advance_Impl() +{ + DBG_ASSERT(!bAtEnd,"zuviel Advance_Impl"); + + if ( pIter ) + { + if ( bDirty ) + { + pIter->DataChanged(); // AttrArray-Index neu suchen + bDirty = FALSE; + } + + SCCOL nCol1, nCol2; + SCROW nRow1, nRow2; + if ( pIter->GetNext( nCol1, nCol2, nRow1, nRow2 ) ) + aNext = ScRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab ); + else + bAtEnd = TRUE; // kommt nix mehr + } + else + bAtEnd = TRUE; // Dok weggekommen oder so +} + +ScCellRangeObj* ScCellFormatsEnumeration::NextObject_Impl() +{ + ScCellRangeObj* pRet = NULL; + if (pDocShell && !bAtEnd) + { + if ( aNext.aStart == aNext.aEnd ) + pRet = new ScCellObj( pDocShell, aNext.aStart ); + else + pRet = new ScCellRangeObj( pDocShell, aNext ); + Advance_Impl(); + } + return pRet; +} + +void ScCellFormatsEnumeration::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( ScUpdateRefHint ) ) + { + //! und nun ??? + } + else if ( rHint.ISA( SfxSimpleHint ) ) + { + ULONG nId = ((const SfxSimpleHint&)rHint).GetId(); + if ( nId == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + delete pIter; + pIter = NULL; + } + else if ( nId == SFX_HINT_DATACHANGED ) + { + bDirty = TRUE; // AttrArray-Index evtl. ungueltig geworden + } + } +} + +// XEnumeration + +sal_Bool SAL_CALL ScCellFormatsEnumeration::hasMoreElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return !bAtEnd; +} + +uno::Any SAL_CALL ScCellFormatsEnumeration::nextElement() throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if ( bAtEnd || !pDocShell ) + throw container::NoSuchElementException(); // no more elements + + // Interface-Typ muss zu ScCellFormatsObj::getElementType passen + + return uno::makeAny(uno::Reference<table::XCellRange> (NextObject_Impl())); +} + +//------------------------------------------------------------------------ + +ScUniqueCellFormatsObj::ScUniqueCellFormatsObj(ScDocShell* pDocSh, const ScRange& rRange) : + pDocShell( pDocSh ), + aTotalRange( rRange ), + aRangeLists() +{ + pDocShell->GetDocument()->AddUnoObject(*this); + + DBG_ASSERT( aTotalRange.aStart.Tab() == aTotalRange.aEnd.Tab(), "unterschiedliche Tabellen" ); + + GetObjects_Impl(); +} + +ScUniqueCellFormatsObj::~ScUniqueCellFormatsObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScUniqueCellFormatsObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( ScUpdateRefHint ) ) + { + //! aTotalRange... + } + else if ( rHint.ISA( SfxSimpleHint ) ) + { + ULONG nId = ((const SfxSimpleHint&)rHint).GetId(); + if ( nId == SFX_HINT_DYING ) + pDocShell = NULL; // ungueltig geworden + } +} + +// +// Fill the list of formats from the document +// + +// hash code to access the range lists by ScPatternAttr pointer +struct ScPatternHashCode +{ + size_t operator()( const ScPatternAttr* pPattern ) const + { + return reinterpret_cast<size_t>(pPattern); + } +}; + +// Hash map to find a range by its start row +typedef ::std::hash_map< SCROW, ScRange > ScRowRangeHashMap; + +typedef ::std::vector<ScRange> ScRangeVector; + +// Hash map entry. +// The Join method depends on the column-wise order of ScAttrRectIterator +class ScUniqueFormatsEntry +{ + enum EntryState { STATE_EMPTY, STATE_SINGLE, STATE_COMPLEX }; + + EntryState eState; + ScRange aSingleRange; + ScRowRangeHashMap aJoinedRanges; // "active" ranges to be merged + ScRangeVector aCompletedRanges; // ranges that will no longer be touched + ScRangeListRef aReturnRanges; // result as ScRangeList for further use + +public: + ScUniqueFormatsEntry() : eState( STATE_EMPTY ) {} + ScUniqueFormatsEntry( const ScUniqueFormatsEntry& r ) : + eState( r.eState ), + aSingleRange( r.aSingleRange ), + aJoinedRanges( r.aJoinedRanges ), + aCompletedRanges( r.aCompletedRanges ), + aReturnRanges( r.aReturnRanges ) {} + ~ScUniqueFormatsEntry() {} + + void Join( const ScRange& rNewRange ); + const ScRangeList& GetRanges(); + void Clear() { aReturnRanges.Clear(); } // aJoinedRanges and aCompletedRanges are cleared in GetRanges +}; + +void ScUniqueFormatsEntry::Join( const ScRange& rNewRange ) +{ + // Special-case handling for single range + + if ( eState == STATE_EMPTY ) + { + aSingleRange = rNewRange; + eState = STATE_SINGLE; + return; + } + if ( eState == STATE_SINGLE ) + { + if ( aSingleRange.aStart.Row() == rNewRange.aStart.Row() && + aSingleRange.aEnd.Row() == rNewRange.aEnd.Row() && + aSingleRange.aEnd.Col() + 1 == rNewRange.aStart.Col() ) + { + aSingleRange.aEnd.SetCol( rNewRange.aEnd.Col() ); + return; // still a single range + } + + SCROW nSingleRow = aSingleRange.aStart.Row(); + aJoinedRanges.insert( ScRowRangeHashMap::value_type( nSingleRow, aSingleRange ) ); + eState = STATE_COMPLEX; + // continue normally + } + + // This is called in the order of ScAttrRectIterator results. + // rNewRange can only be joined with an existing entry if it's the same rows, starting in the next column. + // If the old entry for the start row extends to a different end row, or ends in a different column, it + // can be moved to aCompletedRanges because it can't be joined with following iterator results. + // Everything happens within one sheet, so Tab can be ignored. + + SCROW nStartRow = rNewRange.aStart.Row(); + ScRowRangeHashMap::iterator aIter( aJoinedRanges.find( nStartRow ) ); // find the active entry for the start row + if ( aIter != aJoinedRanges.end() ) + { + ScRange& rOldRange = aIter->second; + if ( rOldRange.aEnd.Row() == rNewRange.aEnd.Row() && + rOldRange.aEnd.Col() + 1 == rNewRange.aStart.Col() ) + { + // extend existing range + rOldRange.aEnd.SetCol( rNewRange.aEnd.Col() ); + } + else + { + // move old range to aCompletedRanges, keep rNewRange for joining + aCompletedRanges.push_back( rOldRange ); + rOldRange = rNewRange; // replace in hash map + } + } + else + { + // keep rNewRange for joining + aJoinedRanges.insert( ScRowRangeHashMap::value_type( nStartRow, rNewRange ) ); + } +} + +const ScRangeList& ScUniqueFormatsEntry::GetRanges() +{ + if ( eState == STATE_SINGLE ) + { + aReturnRanges = new ScRangeList; + aReturnRanges->Append( aSingleRange ); + return *aReturnRanges; + } + + // move remaining entries from aJoinedRanges to aCompletedRanges + + ScRowRangeHashMap::const_iterator aJoinedEnd = aJoinedRanges.end(); + for ( ScRowRangeHashMap::const_iterator aJoinedIter = aJoinedRanges.begin(); aJoinedIter != aJoinedEnd; ++aJoinedIter ) + aCompletedRanges.push_back( aJoinedIter->second ); + aJoinedRanges.clear(); + + // sort all ranges for a predictable API result + + std::sort( aCompletedRanges.begin(), aCompletedRanges.end() ); + + // fill and return ScRangeList + + aReturnRanges = new ScRangeList; + ScRangeVector::const_iterator aCompEnd( aCompletedRanges.end() ); + for ( ScRangeVector::const_iterator aCompIter( aCompletedRanges.begin() ); aCompIter != aCompEnd; ++aCompIter ) + aReturnRanges->Append( *aCompIter ); + aCompletedRanges.clear(); + + return *aReturnRanges; +} + +typedef ::std::hash_map< const ScPatternAttr*, ScUniqueFormatsEntry, ScPatternHashCode > ScUniqueFormatsHashMap; + +// function object to sort the range lists by start of first range +struct ScUniqueFormatsOrder +{ + bool operator()( const ScRangeList& rList1, const ScRangeList& rList2 ) const + { + // all range lists have at least one entry + DBG_ASSERT( rList1.Count() > 0 && rList2.Count() > 0, "ScUniqueFormatsOrder: empty list" ); + + // compare start positions using ScAddress comparison operator + return ( rList1.GetObject(0)->aStart < rList2.GetObject(0)->aStart ); + } +}; + +void ScUniqueCellFormatsObj::GetObjects_Impl() +{ + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB nTab = aTotalRange.aStart.Tab(); + ScAttrRectIterator aIter( pDoc, nTab, + aTotalRange.aStart.Col(), aTotalRange.aStart.Row(), + aTotalRange.aEnd.Col(), aTotalRange.aEnd.Row() ); + SCCOL nCol1, nCol2; + SCROW nRow1, nRow2; + + // Collect the ranges for each format in a hash map, to avoid nested loops + + ScUniqueFormatsHashMap aHashMap; + while (aIter.GetNext( nCol1, nCol2, nRow1, nRow2 ) ) + { + ScRange aRange( nCol1, nRow1, nTab, nCol2, nRow2, nTab ); + const ScPatternAttr* pPattern = pDoc->GetPattern(nCol1, nRow1, nTab); + aHashMap[pPattern].Join( aRange ); + } + + // Fill the vector aRangeLists with the range lists from the hash map + + aRangeLists.reserve( aHashMap.size() ); + ScUniqueFormatsHashMap::iterator aMapIter( aHashMap.begin() ); + ScUniqueFormatsHashMap::iterator aMapEnd( aHashMap.end() ); + while ( aMapIter != aMapEnd ) + { + ScUniqueFormatsEntry& rEntry = aMapIter->second; + const ScRangeList& rRanges = rEntry.GetRanges(); + aRangeLists.push_back( rRanges ); // copy ScRangeList + rEntry.Clear(); // free memory, don't hold both copies of all ranges + ++aMapIter; + } + + // Sort the vector by first range's start position, to avoid random shuffling + // due to using the ScPatterAttr pointers + + ScUniqueFormatsOrder aComp; + ::std::sort( aRangeLists.begin(), aRangeLists.end(), aComp ); + } +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScUniqueCellFormatsObj::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + return aRangeLists.size(); +} + +uno::Any SAL_CALL ScUniqueCellFormatsObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if(static_cast<sal_uInt32>(nIndex) < aRangeLists.size()) + return uno::makeAny(uno::Reference<sheet::XSheetCellRangeContainer>(new ScCellRangesObj(pDocShell, aRangeLists[nIndex]))); + else + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +uno::Type SAL_CALL ScUniqueCellFormatsObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((uno::Reference<sheet::XSheetCellRangeContainer>*)0); +} + +sal_Bool SAL_CALL ScUniqueCellFormatsObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( aRangeLists.size() != 0 ); +} + +// XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScUniqueCellFormatsObj::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + return new ScUniqueCellFormatsEnumeration( pDocShell, aRangeLists ); + return NULL; +} + +//------------------------------------------------------------------------ + +ScUniqueCellFormatsEnumeration::ScUniqueCellFormatsEnumeration(ScDocShell* pDocSh, const ScMyRangeLists& rRangeLists) : + aRangeLists(rRangeLists), + pDocShell( pDocSh ), + nCurrentPosition(0) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScUniqueCellFormatsEnumeration::~ScUniqueCellFormatsEnumeration() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScUniqueCellFormatsEnumeration::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( ScUpdateRefHint ) ) + { + //! und nun ??? + } + else if ( rHint.ISA( SfxSimpleHint ) ) + { + ULONG nId = ((const SfxSimpleHint&)rHint).GetId(); + if ( nId == SFX_HINT_DYING ) + pDocShell = NULL; // ungueltig geworden + } +} + +// XEnumeration + +sal_Bool SAL_CALL ScUniqueCellFormatsEnumeration::hasMoreElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return static_cast<sal_uInt32>(nCurrentPosition) < aRangeLists.size(); +} + +uno::Any SAL_CALL ScUniqueCellFormatsEnumeration::nextElement() throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if ( !hasMoreElements() || !pDocShell ) + throw container::NoSuchElementException(); // no more elements + + // Interface-Typ muss zu ScCellFormatsObj::getElementType passen + + return uno::makeAny(uno::Reference<sheet::XSheetCellRangeContainer>(new ScCellRangesObj(pDocShell, aRangeLists[nCurrentPosition++]))); +} + + diff --git a/sc/source/ui/unoobj/cellvaluebinding.cxx b/sc/source/ui/unoobj/cellvaluebinding.cxx new file mode 100644 index 000000000000..3b806ccf80b7 --- /dev/null +++ b/sc/source/ui/unoobj/cellvaluebinding.cxx @@ -0,0 +1,663 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" +#include "cellvaluebinding.hxx" +#include <tools/debug.hxx> +#include <rtl/math.hxx> +#include <com/sun/star/table/XCellRange.hpp> +#include <com/sun/star/sheet/XCellAddressable.hpp> +#include <com/sun/star/sheet/XCellRangeData.hpp> +#include <com/sun/star/container/XIndexAccess.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <com/sun/star/util/XNumberFormatsSupplier.hpp> +#include <com/sun/star/util/XNumberFormatTypes.hpp> +#include <com/sun/star/util/NumberFormat.hpp> + +//......................................................................... +namespace calc +{ +//......................................................................... + +#define PROP_HANDLE_BOUND_CELL 1 + + using namespace ::com::sun::star::uno; + using namespace ::com::sun::star::lang; + using namespace ::com::sun::star::table; + using namespace ::com::sun::star::text; + using namespace ::com::sun::star::sheet; + using namespace ::com::sun::star::container; + using namespace ::com::sun::star::beans; + using namespace ::com::sun::star::util; + using namespace ::com::sun::star::form::binding; + + //===================================================================== + //= OCellValueBinding + //===================================================================== + DBG_NAME( OCellValueBinding ) + //--------------------------------------------------------------------- +#ifdef DBG_UTIL + const char* OCellValueBinding::checkConsistency_static( const void* _pThis ) + { + return static_cast< const OCellValueBinding* >( _pThis )->checkConsistency( ); + } + + const char* OCellValueBinding::checkConsistency( ) const + { + const char* pAssertion = NULL; + if ( m_xCellText.is() && !m_xCell.is() ) + // there are places (e.g. getSupportedTypes) which rely on the fact + // that m_xCellText.is() implies m_xCell.is() + pAssertion = "cell references inconsistent!"; + + // TODO: place any additional checks here to ensure consistency of this instance + return pAssertion; + } +#endif + + //--------------------------------------------------------------------- + OCellValueBinding::OCellValueBinding( const Reference< XSpreadsheetDocument >& _rxDocument, sal_Bool _bListPos ) + :OCellValueBinding_Base( m_aMutex ) + ,OCellValueBinding_PBase( OCellValueBinding_Base::rBHelper ) + ,m_xDocument( _rxDocument ) + ,m_aModifyListeners( m_aMutex ) + ,m_bInitialized( sal_False ) + ,m_bListPos( _bListPos ) + { + DBG_CTOR( OCellValueBinding, checkConsistency_static ); + + // register our property at the base class + CellAddress aInitialPropValue; + registerPropertyNoMember( + ::rtl::OUString::createFromAscii( "BoundCell" ), + PROP_HANDLE_BOUND_CELL, + PropertyAttribute::BOUND | PropertyAttribute::READONLY, + ::getCppuType( &aInitialPropValue ), + &aInitialPropValue + ); + + // TODO: implement a ReadOnly property as required by the service, + // which probably maps to the cell being locked + } + + //--------------------------------------------------------------------- + OCellValueBinding::~OCellValueBinding( ) + { + if ( !OCellValueBinding_Base::rBHelper.bDisposed ) + { + acquire(); // prevent duplicate dtor + dispose(); + } + + DBG_DTOR( OCellValueBinding, checkConsistency_static ); + } + + //-------------------------------------------------------------------- + IMPLEMENT_FORWARD_XINTERFACE2( OCellValueBinding, OCellValueBinding_Base, OCellValueBinding_PBase ) + + //-------------------------------------------------------------------- + IMPLEMENT_FORWARD_XTYPEPROVIDER2( OCellValueBinding, OCellValueBinding_Base, OCellValueBinding_PBase ) + + //-------------------------------------------------------------------- + void SAL_CALL OCellValueBinding::disposing() + { + DBG_CHKTHIS( OCellValueBinding, checkConsistency_static ); + + Reference<XModifyBroadcaster> xBroadcaster( m_xCell, UNO_QUERY ); + if ( xBroadcaster.is() ) + { + xBroadcaster->removeModifyListener( this ); + } + +// OCellValueBinding_Base::disposing(); + WeakAggComponentImplHelperBase::disposing(); + + // TODO: clean up here whatever you need to clean up (e.g. deregister as XEventListener + // for the cell) + } + + //-------------------------------------------------------------------- + Reference< XPropertySetInfo > SAL_CALL OCellValueBinding::getPropertySetInfo( ) throw(RuntimeException) + { + DBG_CHKTHIS( OCellValueBinding, checkConsistency_static ); + return createPropertySetInfo( getInfoHelper() ) ; + } + + //-------------------------------------------------------------------- + ::cppu::IPropertyArrayHelper& SAL_CALL OCellValueBinding::getInfoHelper() + { + return *OCellValueBinding_PABase::getArrayHelper(); + } + + //-------------------------------------------------------------------- + ::cppu::IPropertyArrayHelper* OCellValueBinding::createArrayHelper( ) const + { + Sequence< Property > aProps; + describeProperties( aProps ); + return new ::cppu::OPropertyArrayHelper(aProps); + } + + //-------------------------------------------------------------------- + void SAL_CALL OCellValueBinding::getFastPropertyValue( Any& _rValue, sal_Int32 _nHandle ) const + { + DBG_CHKTHIS( OCellValueBinding, checkConsistency_static ); + DBG_ASSERT( _nHandle == PROP_HANDLE_BOUND_CELL, "OCellValueBinding::getFastPropertyValue: invalid handle!" ); + // we only have this one property .... + (void)_nHandle; // avoid warning in product version + + _rValue.clear(); + Reference< XCellAddressable > xCellAddress( m_xCell, UNO_QUERY ); + if ( xCellAddress.is() ) + _rValue <<= xCellAddress->getCellAddress( ); + } + + //-------------------------------------------------------------------- + Sequence< Type > SAL_CALL OCellValueBinding::getSupportedValueTypes( ) throw (RuntimeException) + { + DBG_CHKTHIS( OCellValueBinding, checkConsistency_static ); + checkDisposed( ); + checkInitialized( ); + + sal_Int32 nCount = m_xCellText.is() ? 3 : m_xCell.is() ? 1 : 0; + if ( m_bListPos ) + ++nCount; + + Sequence< Type > aTypes( nCount ); + if ( m_xCell.is() ) + { + // an XCell can be used to set/get "double" values + aTypes[0] = ::getCppuType( static_cast< double* >( NULL ) ); + if ( m_xCellText.is() ) + { + // an XTextRange can be used to set/get "string" values + aTypes[1] = ::getCppuType( static_cast< ::rtl::OUString* >( NULL ) ); + // and additionally, we use it to handle booleans + aTypes[2] = ::getCppuType( static_cast< sal_Bool* >( NULL ) ); + } + + // add sal_Int32 only if constructed as ListPositionCellBinding + if ( m_bListPos ) + aTypes[nCount-1] = ::getCppuType( static_cast< sal_Int32* >( NULL ) ); + } + + return aTypes; + } + + //-------------------------------------------------------------------- + sal_Bool SAL_CALL OCellValueBinding::supportsType( const Type& aType ) throw (RuntimeException) + { + DBG_CHKTHIS( OCellValueBinding, checkConsistency_static ); + checkDisposed( ); + checkInitialized( ); + + // look up in our sequence + Sequence< Type > aSupportedTypes( getSupportedValueTypes() ); + const Type* pTypes = aSupportedTypes.getConstArray(); + const Type* pTypesEnd = aSupportedTypes.getConstArray() + aSupportedTypes.getLength(); + while ( pTypes != pTypesEnd ) + if ( aType.equals( *pTypes++ ) ) + return sal_True; + + return sal_False; + } + + //-------------------------------------------------------------------- + Any SAL_CALL OCellValueBinding::getValue( const Type& aType ) throw (IncompatibleTypesException, RuntimeException) + { + DBG_CHKTHIS( OCellValueBinding, checkConsistency_static ); + checkDisposed( ); + checkInitialized( ); + checkValueType( aType ); + + Any aReturn; + switch ( aType.getTypeClass() ) + { + case TypeClass_STRING: + DBG_ASSERT( m_xCellText.is(), "OCellValueBinding::getValue: don't have a text!" ); + if ( m_xCellText.is() ) + aReturn <<= m_xCellText->getString(); + else + aReturn <<= ::rtl::OUString(); + break; + + case TypeClass_BOOLEAN: + DBG_ASSERT( m_xCell.is(), "OCellValueBinding::getValue: don't have a double value supplier!" ); + if ( m_xCell.is() ) + { + // check if the cell has a numeric value (this might go into a helper function): + + sal_Bool bHasValue = sal_False; + CellContentType eCellType = m_xCell->getType(); + if ( eCellType == CellContentType_VALUE ) + bHasValue = sal_True; + else if ( eCellType == CellContentType_FORMULA ) + { + // check if the formula result is a value + if ( m_xCell->getError() == 0 ) + { + Reference<XPropertySet> xProp( m_xCell, UNO_QUERY ); + if ( xProp.is() ) + { + CellContentType eResultType; + if ( (xProp->getPropertyValue(::rtl::OUString::createFromAscii( "FormulaResultType" ) ) >>= eResultType) && eResultType == CellContentType_VALUE ) + bHasValue = sal_True; + } + } + } + + if ( bHasValue ) + { + // 0 is "unchecked", any other value is "checked", regardless of number format + double nCellValue = m_xCell->getValue(); + sal_Bool bBoolValue = ( nCellValue != 0.0 ); + aReturn <<= bBoolValue; + } + // empty cells, text cells and text or error formula results: leave return value empty + } + break; + + case TypeClass_DOUBLE: + DBG_ASSERT( m_xCell.is(), "OCellValueBinding::getValue: don't have a double value supplier!" ); + if ( m_xCell.is() ) + aReturn <<= m_xCell->getValue(); + else + aReturn <<= (double)0; + break; + + case TypeClass_LONG: + DBG_ASSERT( m_xCell.is(), "OCellValueBinding::getValue: don't have a double value supplier!" ); + if ( m_xCell.is() ) + { + // The list position value in the cell is 1-based. + // We subtract 1 from any cell value (no special handling for 0 or negative values). + + sal_Int32 nValue = (sal_Int32) rtl::math::approxFloor( m_xCell->getValue() ); + --nValue; + + aReturn <<= nValue; + } + else + aReturn <<= (sal_Int32)0; + break; + + default: + DBG_ERROR( "OCellValueBinding::getValue: unreachable code!" ); + // a type other than double and string should never have survived the checkValueType + // above + } + return aReturn; + } + + //-------------------------------------------------------------------- + void SAL_CALL OCellValueBinding::setValue( const Any& aValue ) throw (IncompatibleTypesException, NoSupportException, RuntimeException) + { + DBG_CHKTHIS( OCellValueBinding, checkConsistency_static ); + checkDisposed( ); + checkInitialized( ); + if ( aValue.hasValue() ) + checkValueType( aValue.getValueType() ); + + switch ( aValue.getValueType().getTypeClass() ) + { + case TypeClass_STRING: + { + DBG_ASSERT( m_xCellText.is(), "OCellValueBinding::setValue: don't have a text!" ); + + ::rtl::OUString sText; + aValue >>= sText; + if ( m_xCellText.is() ) + m_xCellText->setString( sText ); + } + break; + + case TypeClass_BOOLEAN: + { + DBG_ASSERT( m_xCell.is(), "OCellValueBinding::setValue: don't have a double value supplier!" ); + + // boolean is stored as values 0 or 1 + // TODO: set the number format to boolean if no format is set? + + sal_Bool bValue( sal_False ); + aValue >>= bValue; + double nCellValue = bValue ? 1.0 : 0.0; + + if ( m_xCell.is() ) + m_xCell->setValue( nCellValue ); + + setBooleanFormat(); + } + break; + + case TypeClass_DOUBLE: + { + DBG_ASSERT( m_xCell.is(), "OCellValueBinding::setValue: don't have a double value supplier!" ); + + double nValue = 0; + aValue >>= nValue; + if ( m_xCell.is() ) + m_xCell->setValue( nValue ); + } + break; + + case TypeClass_LONG: + { + DBG_ASSERT( m_xCell.is(), "OCellValueBinding::setValue: don't have a double value supplier!" ); + + sal_Int32 nValue = 0; + aValue >>= nValue; // list index from control layer (0-based) + ++nValue; // the list position value in the cell is 1-based + if ( m_xCell.is() ) + m_xCell->setValue( nValue ); + } + break; + + case TypeClass_VOID: + { + // #N/A error value can only be set using XCellRangeData + + Reference<XCellRangeData> xData( m_xCell, UNO_QUERY ); + DBG_ASSERT( xData.is(), "OCellValueBinding::setValue: don't have XCellRangeData!" ); + if ( xData.is() ) + { + Sequence<Any> aInner(1); // one empty element + Sequence< Sequence<Any> > aOuter( &aInner, 1 ); // one row + xData->setDataArray( aOuter ); + } + } + break; + + default: + DBG_ERROR( "OCellValueBinding::setValue: unreachable code!" ); + // a type other than double and string should never have survived the checkValueType + // above + } + } + //-------------------------------------------------------------------- + void OCellValueBinding::setBooleanFormat() + { + // set boolean number format if not already set + + ::rtl::OUString sPropName( ::rtl::OUString::createFromAscii( "NumberFormat" ) ); + Reference<XPropertySet> xCellProp( m_xCell, UNO_QUERY ); + Reference<XNumberFormatsSupplier> xSupplier( m_xDocument, UNO_QUERY ); + if ( xSupplier.is() && xCellProp.is() ) + { + Reference<XNumberFormats> xFormats(xSupplier->getNumberFormats()); + Reference<XNumberFormatTypes> xTypes( xFormats, UNO_QUERY ); + if ( xTypes.is() ) + { + Locale aLocale; + sal_Bool bWasBoolean = sal_False; + + sal_Int32 nOldIndex = ::comphelper::getINT32( xCellProp->getPropertyValue( sPropName ) ); + Reference<XPropertySet> xOldFormat; + try + { + xOldFormat.set(xFormats->getByKey( nOldIndex )); + } + catch ( Exception& ) + { + // non-existing format - can happen, use defaults + } + if ( xOldFormat.is() ) + { + // use the locale of the existing format + xOldFormat->getPropertyValue( ::rtl::OUString::createFromAscii( "Locale" ) ) >>= aLocale; + + sal_Int16 nOldType = ::comphelper::getINT16( + xOldFormat->getPropertyValue( ::rtl::OUString::createFromAscii( "Type" ) ) ); + if ( nOldType & NumberFormat::LOGICAL ) + bWasBoolean = sal_True; + } + + if ( !bWasBoolean ) + { + sal_Int32 nNewIndex = xTypes->getStandardFormat( NumberFormat::LOGICAL, aLocale ); + xCellProp->setPropertyValue( sPropName, makeAny( nNewIndex ) ); + } + } + } + } + + //-------------------------------------------------------------------- + void OCellValueBinding::checkDisposed( ) const SAL_THROW( ( DisposedException ) ) + { + if ( OCellValueBinding_Base::rBHelper.bInDispose || OCellValueBinding_Base::rBHelper.bDisposed ) + throw DisposedException(); + // TODO: is it worth having an error message here? + } + + //-------------------------------------------------------------------- + void OCellValueBinding::checkInitialized() SAL_THROW( ( RuntimeException ) ) + { + if ( !m_bInitialized ) + throw RuntimeException(); + // TODO: error message + } + + //-------------------------------------------------------------------- + void OCellValueBinding::checkValueType( const Type& _rType ) const SAL_THROW( ( IncompatibleTypesException ) ) + { + OCellValueBinding* pNonConstThis = const_cast< OCellValueBinding* >( this ); + if ( !pNonConstThis->supportsType( _rType ) ) + { + ::rtl::OUString sMessage( RTL_CONSTASCII_USTRINGPARAM( "The given type (" ) ); + sMessage += _rType.getTypeName(); + sMessage += ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( ") is not supported by this binding." ) ); + // TODO: localize this error message + + throw IncompatibleTypesException( sMessage, *pNonConstThis ); + // TODO: alternatively use a type converter service for this? + } + } + + //-------------------------------------------------------------------- + ::rtl::OUString SAL_CALL OCellValueBinding::getImplementationName( ) throw (RuntimeException) + { + DBG_CHKTHIS( OCellValueBinding, checkConsistency_static ); + + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.sheet.OCellValueBinding" ) ); + } + + //-------------------------------------------------------------------- + sal_Bool SAL_CALL OCellValueBinding::supportsService( const ::rtl::OUString& _rServiceName ) throw (RuntimeException) + { + DBG_CHKTHIS( OCellValueBinding, checkConsistency_static ); + + Sequence< ::rtl::OUString > aSupportedServices( getSupportedServiceNames() ); + const ::rtl::OUString* pLookup = aSupportedServices.getConstArray(); + const ::rtl::OUString* pLookupEnd = aSupportedServices.getConstArray() + aSupportedServices.getLength(); + while ( pLookup != pLookupEnd ) + if ( *pLookup++ == _rServiceName ) + return sal_True; + + return sal_False; + } + + //-------------------------------------------------------------------- + Sequence< ::rtl::OUString > SAL_CALL OCellValueBinding::getSupportedServiceNames( ) throw (RuntimeException) + { + DBG_CHKTHIS( OCellValueBinding, checkConsistency_static ); + + Sequence< ::rtl::OUString > aServices( m_bListPos ? 3 : 2 ); + aServices[ 0 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.table.CellValueBinding" ) ); + aServices[ 1 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.form.binding.ValueBinding" ) ); + if ( m_bListPos ) + aServices[ 2 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.table.ListPositionCellBinding" ) ); + return aServices; + } + + //-------------------------------------------------------------------- + void SAL_CALL OCellValueBinding::addModifyListener( const Reference< XModifyListener >& _rxListener ) throw (RuntimeException) + { + if ( _rxListener.is() ) + m_aModifyListeners.addInterface( _rxListener ); + } + + //-------------------------------------------------------------------- + void SAL_CALL OCellValueBinding::removeModifyListener( const Reference< XModifyListener >& _rxListener ) throw (RuntimeException) + { + if ( _rxListener.is() ) + m_aModifyListeners.removeInterface( _rxListener ); + } + + //-------------------------------------------------------------------- + void OCellValueBinding::notifyModified() + { + EventObject aEvent; + aEvent.Source.set(*this); + + ::cppu::OInterfaceIteratorHelper aIter( m_aModifyListeners ); + while ( aIter.hasMoreElements() ) + { + try + { + static_cast< XModifyListener* >( aIter.next() )->modified( aEvent ); + } + catch( const RuntimeException& ) + { + // silent this + } + catch( const Exception& ) + { + DBG_ERROR( "OCellValueBinding::notifyModified: caught a (non-runtime) exception!" ); + } + } + } + + //-------------------------------------------------------------------- + void SAL_CALL OCellValueBinding::modified( const EventObject& /* aEvent */ ) throw (RuntimeException) + { + DBG_CHKTHIS( OCellValueBinding, checkConsistency_static ); + + notifyModified(); + } + + //-------------------------------------------------------------------- + void SAL_CALL OCellValueBinding::disposing( const EventObject& aEvent ) throw (RuntimeException) + { + DBG_CHKTHIS( OCellValueBinding, checkConsistency_static ); + + Reference<XInterface> xCellInt( m_xCell, UNO_QUERY ); + if ( xCellInt == aEvent.Source ) + { + // release references to cell object + m_xCell.clear(); + m_xCellText.clear(); + } + } + + //-------------------------------------------------------------------- + void SAL_CALL OCellValueBinding::initialize( const Sequence< Any >& _rArguments ) throw (Exception, RuntimeException) + { + if ( m_bInitialized ) + throw Exception(); + // TODO: error message + + // get the cell address + CellAddress aAddress; + sal_Bool bFoundAddress = sal_False; + + const Any* pLoop = _rArguments.getConstArray(); + const Any* pLoopEnd = _rArguments.getConstArray() + _rArguments.getLength(); + for ( ; ( pLoop != pLoopEnd ) && !bFoundAddress; ++pLoop ) + { + NamedValue aValue; + if ( *pLoop >>= aValue ) + { + if ( aValue.Name.equalsAscii( "BoundCell" ) ) + { + if ( aValue.Value >>= aAddress ) + bFoundAddress = sal_True; + } + } + } + + if ( !bFoundAddress ) + // TODO: error message + throw Exception(); + + // get the cell object + try + { + // first the sheets collection + Reference< XIndexAccess > xSheets; + if ( m_xDocument.is() ) + xSheets.set(xSheets.query( m_xDocument->getSheets( ) )); + DBG_ASSERT( xSheets.is(), "OCellValueBinding::initialize: could not retrieve the sheets!" ); + + if ( xSheets.is() ) + { + // the concrete sheet + Reference< XCellRange > xSheet(xSheets->getByIndex( aAddress.Sheet ), UNO_QUERY); + DBG_ASSERT( xSheet.is(), "OCellValueBinding::initialize: NULL sheet, but no exception!" ); + + // the concrete cell + if ( xSheet.is() ) + { + m_xCell.set(xSheet->getCellByPosition( aAddress.Column, aAddress.Row )); + Reference< XCellAddressable > xAddressAccess( m_xCell, UNO_QUERY ); + DBG_ASSERT( xAddressAccess.is(), "OCellValueBinding::initialize: either NULL cell, or cell without address access!" ); + } + } + } + catch( const Exception& ) + { + DBG_ERROR( "OCellValueBinding::initialize: caught an exception while retrieving the cell object!" ); + } + + if ( !m_xCell.is() ) + throw Exception(); + // TODO error message + + m_xCellText.set(m_xCellText.query( m_xCell )); + + Reference<XModifyBroadcaster> xBroadcaster( m_xCell, UNO_QUERY ); + if ( xBroadcaster.is() ) + { + xBroadcaster->addModifyListener( this ); + } + + // TODO: add as XEventListener to the cell, so we get notified when it dies, + // and can dispose ourself then + + // TODO: somehow add as listener so we get notified when the address of the cell changes + // We need to forward this as change in our BoundCell property to our property change listeners + + // TODO: be an XModifyBroadcaster, so that changes in our cell can be notified + // to the BindableValue which is/will be bound to this instance. + + m_bInitialized = sal_True; + // TODO: place your code here + } + + +//......................................................................... +} // namespace calc +//......................................................................... diff --git a/sc/source/ui/unoobj/cellvaluebinding.hxx b/sc/source/ui/unoobj/cellvaluebinding.hxx new file mode 100644 index 000000000000..c9537d546f7b --- /dev/null +++ b/sc/source/ui/unoobj/cellvaluebinding.hxx @@ -0,0 +1,171 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef SC_CELLVALUEBINDING_HXX +#define SC_CELLVALUEBINDING_HXX + +#include <com/sun/star/form/binding/XValueBinding.hpp> +#include <com/sun/star/util/XModifyBroadcaster.hpp> +#include <cppuhelper/compbase5.hxx> +#include <comphelper/propertycontainer.hxx> +#include <comphelper/uno3.hxx> +#include <comphelper/broadcasthelper.hxx> +#include <comphelper/proparrhlp.hxx> +#include <com/sun/star/table/XCell.hpp> +#include <com/sun/star/table/CellAddress.hpp> +#include <com/sun/star/sheet/XSpreadsheetDocument.hpp> +#include <com/sun/star/text/XTextRange.hpp> +#include <com/sun/star/lang/DisposedException.hpp> +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XInitialization.hpp> + + +//......................................................................... +namespace calc +{ +//......................................................................... + + //===================================================================== + //= OCellValueBinding + //===================================================================== + class OCellValueBinding; + // the base for our interfaces + typedef ::cppu::WeakAggComponentImplHelper5 < ::com::sun::star::form::binding::XValueBinding + , ::com::sun::star::lang::XServiceInfo + , ::com::sun::star::util::XModifyBroadcaster + , ::com::sun::star::util::XModifyListener + , ::com::sun::star::lang::XInitialization + > OCellValueBinding_Base; + // the base for the property handling + typedef ::comphelper::OPropertyContainer OCellValueBinding_PBase; + // the second base for property handling + typedef ::comphelper::OPropertyArrayUsageHelper< OCellValueBinding > + OCellValueBinding_PABase; + + class OCellValueBinding :public ::comphelper::OBaseMutex + ,public OCellValueBinding_Base // order matters! before OCellValueBinding_PBase, so rBHelper gets initialized + ,public OCellValueBinding_PBase + ,public OCellValueBinding_PABase + { + private: + ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XSpreadsheetDocument > + m_xDocument; /// the document where our cell lives + ::com::sun::star::uno::Reference< ::com::sun::star::table::XCell > + m_xCell; /// the cell we're bound to, for double value access + ::com::sun::star::uno::Reference< ::com::sun::star::text::XTextRange > + m_xCellText; /// the cell we're bound to, for text access + ::cppu::OInterfaceContainerHelper + m_aModifyListeners; /// our modify listeners + sal_Bool m_bInitialized; /// has XInitialization::initialize been called? + sal_Bool m_bListPos; /// constructed as ListPositionCellBinding? + + public: + OCellValueBinding( + const ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XSpreadsheetDocument >& _rxDocument, + sal_Bool _bListPos + ); + + using OCellValueBinding_PBase::getFastPropertyValue; + + protected: + ~OCellValueBinding( ); + + protected: + // XInterface + DECLARE_XINTERFACE() + + // XTypeProvider + DECLARE_XTYPEPROVIDER() + + // XValueBinding + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL getSupportedValueTypes( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsType( const ::com::sun::star::uno::Type& aType ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Any SAL_CALL getValue( const ::com::sun::star::uno::Type& aType ) throw (::com::sun::star::form::binding::IncompatibleTypesException, ::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setValue( const ::com::sun::star::uno::Any& aValue ) throw (::com::sun::star::form::binding::IncompatibleTypesException, ::com::sun::star::lang::NoSupportException, ::com::sun::star::uno::RuntimeException); + + // OComponentHelper/XComponent + virtual void SAL_CALL disposing(); + + // XServiceInfo + virtual ::rtl::OUString SAL_CALL getImplementationName( ) throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL supportsService( const ::rtl::OUString& ServiceName ) throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getSupportedServiceNames( ) throw (::com::sun::star::uno::RuntimeException); + + // XPropertySet + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo( ) throw(::com::sun::star::uno::RuntimeException); + + // OPropertySetHelper + virtual ::cppu::IPropertyArrayHelper& SAL_CALL getInfoHelper(); + virtual void SAL_CALL getFastPropertyValue( ::com::sun::star::uno::Any& _rValue, sal_Int32 _nHandle ) const; + + // ::comphelper::OPropertyArrayUsageHelper + virtual ::cppu::IPropertyArrayHelper* createArrayHelper( ) const; + + // XModifyBroadcaster + virtual void SAL_CALL addModifyListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL removeModifyListener( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XModifyListener >& aListener ) throw (::com::sun::star::uno::RuntimeException); + + // XModifyListener + virtual void SAL_CALL modified( const ::com::sun::star::lang::EventObject& aEvent ) throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL disposing( const ::com::sun::star::lang::EventObject& Source ) throw (::com::sun::star::uno::RuntimeException); + + // XInitialization + virtual void SAL_CALL initialize( const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& aArguments ) throw (::com::sun::star::uno::Exception, ::com::sun::star::uno::RuntimeException); + + private: + void checkDisposed( ) const + SAL_THROW( ( ::com::sun::star::lang::DisposedException ) ); + void checkValueType( const ::com::sun::star::uno::Type& _rType ) const + SAL_THROW( ( ::com::sun::star::form::binding::IncompatibleTypesException ) ); + void checkInitialized() + SAL_THROW( ( ::com::sun::star::uno::RuntimeException ) ); + + /** notifies our modify listeners + @precond + our mutex is <em>not</em> locked + */ + void notifyModified(); + + void setBooleanFormat(); + + private: + OCellValueBinding(); // never implemented + OCellValueBinding( const OCellValueBinding& ); // never implemented + OCellValueBinding& operator=( const OCellValueBinding& ); // never implemented + +#ifdef DBG_UTIL + private: + static const char* checkConsistency_static( const void* _pThis ); + const char* checkConsistency( ) const; +#endif + }; + +//......................................................................... +} // namespace calc +//......................................................................... + +#endif // SC_CELLVALUEBINDING_HXX diff --git a/sc/source/ui/unoobj/chart2uno.cxx b/sc/source/ui/unoobj/chart2uno.cxx new file mode 100644 index 000000000000..8a8081e412d3 --- /dev/null +++ b/sc/source/ui/unoobj/chart2uno.cxx @@ -0,0 +1,3914 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +#include "chart2uno.hxx" +#include "miscuno.hxx" +#include "document.hxx" +#include "unoguard.hxx" +#include "cell.hxx" +#include "chartpos.hxx" +#include "unonames.hxx" +#include "globstr.hrc" +#include "convuno.hxx" +#include "rangeutl.hxx" +#include "hints.hxx" +#include "unoreflist.hxx" +#include "compiler.hxx" +#include "reftokenhelper.hxx" +#include "chartlis.hxx" + +#include <sfx2/objsh.hxx> +#include <tools/table.hxx> + +#include <com/sun/star/beans/UnknownPropertyException.hpp> +#include <com/sun/star/sheet/XSpreadsheetDocument.hpp> +#include <com/sun/star/table/XCellRange.hpp> +#include <com/sun/star/table/CellAddress.hpp> +#include <com/sun/star/text/XText.hpp> +#include <comphelper/extract.hxx> + +#include <vector> +#include <list> +#include <rtl/math.hxx> + +SC_SIMPLE_SERVICE_INFO( ScChart2DataProvider, "ScChart2DataProvider", + "com.sun.star.chart2.data.DataProvider") +SC_SIMPLE_SERVICE_INFO( ScChart2DataSource, "ScChart2DataSource", + "com.sun.star.chart2.data.DataSource") +SC_SIMPLE_SERVICE_INFO( ScChart2LabeledDataSequence, "ScChart2LabeledDataSequence", + "com.sun.star.chart2.data.LabeledDataSequence") +SC_SIMPLE_SERVICE_INFO( ScChart2DataSequence, "ScChart2DataSequence", + "com.sun.star.chart2.data.DataSequence") +#if USE_CHART2_EMPTYDATASEQUENCE +SC_SIMPLE_SERVICE_INFO( ScChart2EmptyDataSequence, "ScChart2EmptyDataSequence", + "com.sun.star.chart2.data.DataSequence") +#endif + +using namespace ::com::sun::star; +using namespace ::formula; +using ::rtl::OUString; +using ::rtl::OUStringBuffer; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; +using ::std::auto_ptr; +using ::std::vector; +using ::std::list; +using ::std::distance; +using ::std::unary_function; +using ::std::hash_set; +using ::boost::shared_ptr; + +namespace +{ +const SfxItemPropertyMapEntry* lcl_GetDataProviderPropertyMap() +{ + static SfxItemPropertyMapEntry aDataProviderPropertyMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_INCLUDEHIDDENCELLS), 0, &getBooleanCppuType(), 0, 0 }, + {0,0,0,0,0,0} + }; + return aDataProviderPropertyMap_Impl; +} + +const SfxItemPropertyMapEntry* lcl_GetDataSequencePropertyMap() +{ + static SfxItemPropertyMapEntry aDataSequencePropertyMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_HIDDENVALUES), 0, &getCppuType((uno::Sequence<sal_Int32>*)0 ), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_ROLE), 0, &getCppuType((::com::sun::star::chart2::data::DataSequenceRole*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_INCLUDEHIDDENCELLS), 0, &getBooleanCppuType(), 0, 0 }, + {0,0,0,0,0,0} + }; + return aDataSequencePropertyMap_Impl; +} + +template< typename T > +::com::sun::star::uno::Sequence< T > lcl_VectorToSequence( + const ::std::vector< T > & rCont ) +{ + ::com::sun::star::uno::Sequence< T > aResult( rCont.size()); + ::std::copy( rCont.begin(), rCont.end(), aResult.getArray()); + return aResult; +} + +struct lcl_appendTableNumber : public ::std::unary_function< SCTAB, void > +{ + lcl_appendTableNumber( ::rtl::OUStringBuffer & rBuffer ) : + m_rBuffer( rBuffer ) + {} + void operator() ( SCTAB nTab ) + { + // there is no append with SCTAB or sal_Int16 + m_rBuffer.append( static_cast< sal_Int32 >( nTab )); + m_rBuffer.append( sal_Unicode( ' ' )); + } +private: + ::rtl::OUStringBuffer & m_rBuffer; +}; + +::rtl::OUString lcl_createTableNumberList( const ::std::list< SCTAB > & rTableList ) +{ + ::rtl::OUStringBuffer aBuffer; + ::std::for_each( rTableList.begin(), rTableList.end(), lcl_appendTableNumber( aBuffer )); + // remove last trailing ' ' + if( aBuffer.getLength() > 0 ) + aBuffer.setLength( aBuffer.getLength() - 1 ); + return aBuffer.makeStringAndClear(); +} + +uno::Reference< frame::XModel > lcl_GetXModel( ScDocument * pDoc ) +{ + uno::Reference< frame::XModel > xModel; + SfxObjectShell * pObjSh( pDoc ? pDoc->GetDocumentShell() : 0 ); + if( pObjSh ) + xModel.set( pObjSh->GetModel()); + return xModel; +} + +uno::Reference< sheet::XSpreadsheetDocument > lcl_GetSpreadSheetDocument( ScDocument * pDoc ) +{ + return uno::Reference< sheet::XSpreadsheetDocument >( lcl_GetXModel( pDoc ), uno::UNO_QUERY ); +} + +// ============================================================================ + +namespace { + +struct DeleteInstance : public unary_function<FormulaToken*, void> +{ + void operator() (FormulaToken* p) const + { + delete p; + } +}; + +} + +struct TokenTable +{ + SCROW mnRowCount; + SCCOL mnColCount; + vector<FormulaToken*> maTokens; + + void init( SCCOL nColCount, SCROW nRowCount ) + { + mnColCount = nColCount; + mnRowCount = nRowCount; + maTokens.reserve(mnColCount*mnRowCount); + } + void clear() + { + for_each(maTokens.begin(), maTokens.end(), DeleteInstance()); + } + + void push_back( FormulaToken* pToken ) + { + maTokens.push_back( pToken ); + DBG_ASSERT( maTokens.size()<= static_cast<sal_uInt32>( mnColCount*mnRowCount ), "too much tokens" ); + } + + sal_uInt32 getIndex(SCCOL nCol, SCROW nRow) const + { + DBG_ASSERT( nCol<mnColCount, "wrong column index" ); + DBG_ASSERT( nRow<mnRowCount, "wrong row index" ); + sal_uInt32 nRet = static_cast<sal_uInt32>(nCol*mnRowCount + nRow); + DBG_ASSERT( maTokens.size()>= static_cast<sal_uInt32>( mnColCount*mnRowCount ), "too few tokens" ); + return nRet; + } + + vector<ScSharedTokenRef>* getColRanges(SCCOL nCol) const; + vector<ScSharedTokenRef>* getRowRanges(SCROW nRow) const; + vector<ScSharedTokenRef>* getAllRanges() const; +}; + +vector<ScSharedTokenRef>* TokenTable::getColRanges(SCCOL nCol) const +{ + if (nCol >= mnColCount) + return NULL; + if( mnRowCount<=0 ) + return NULL; + + auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>); + sal_uInt32 nLast = getIndex(nCol, mnRowCount-1); + for (sal_uInt32 i = getIndex(nCol, 0); i <= nLast; ++i) + { + FormulaToken* p = maTokens[i]; + if (!p) + continue; + + ScSharedTokenRef pCopy(static_cast<ScToken*>(p->Clone())); + ScRefTokenHelper::join(*pTokens, pCopy); + } + return pTokens.release(); +} + +vector<ScSharedTokenRef>* TokenTable::getRowRanges(SCROW nRow) const +{ + if (nRow >= mnRowCount) + return NULL; + if( mnColCount<=0 ) + return NULL; + + auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>); + sal_uInt32 nLast = getIndex(mnColCount-1, nRow); + for (sal_uInt32 i = getIndex(0, nRow); i <= nLast; i += mnRowCount) + { + FormulaToken* p = maTokens[i]; + if (!p) + continue; + + ScSharedTokenRef p2(static_cast<ScToken*>(p->Clone())); + ScRefTokenHelper::join(*pTokens, p2); + } + return pTokens.release(); +} + +vector<ScSharedTokenRef>* TokenTable::getAllRanges() const +{ + auto_ptr< vector<ScSharedTokenRef> > pTokens(new vector<ScSharedTokenRef>); + sal_uInt32 nStop = mnColCount*mnRowCount; + for (sal_uInt32 i = 0; i < nStop; i++) + { + FormulaToken* p = maTokens[i]; + if (!p) + continue; + + ScSharedTokenRef p2(static_cast<ScToken*>(p->Clone())); + ScRefTokenHelper::join(*pTokens, p2); + } + return pTokens.release(); +} + +// ============================================================================ + +class Chart2PositionMap +{ +public: + Chart2PositionMap(SCCOL nColCount, SCROW nRowCount, + bool bFillRowHeader, bool bFillColumnHeader, Table& rCols, + ScDocument* pDoc ); + ~Chart2PositionMap(); + + SCCOL getDataColCount() const { return mnDataColCount; } + SCROW getDataRowCount() const { return mnDataRowCount; } + + vector<ScSharedTokenRef>* getLeftUpperCornerRanges() const; + vector<ScSharedTokenRef>* getAllColHeaderRanges() const; + vector<ScSharedTokenRef>* getAllRowHeaderRanges() const; + + vector<ScSharedTokenRef>* getColHeaderRanges(SCCOL nChartCol) const; + vector<ScSharedTokenRef>* getRowHeaderRanges(SCROW nChartRow) const; + + vector<ScSharedTokenRef>* getDataColRanges(SCCOL nCol) const; + vector<ScSharedTokenRef>* getDataRowRanges(SCROW nRow) const; + +private: + SCCOL mnDataColCount; + SCROW mnDataRowCount; + + TokenTable maLeftUpperCorner; //nHeaderColCount*nHeaderRowCount + TokenTable maColHeaders; //mnDataColCount*nHeaderRowCount + TokenTable maRowHeaders; //nHeaderColCount*mnDataRowCount + TokenTable maData;//mnDataColCount*mnDataRowCount +}; + +Chart2PositionMap::Chart2PositionMap(SCCOL nAllColCount, SCROW nAllRowCount, + bool bFillRowHeader, bool bFillColumnHeader, Table& rCols, ScDocument* pDoc) +{ + // if bFillRowHeader is true, at least the first column serves as a row header. + // If more than one column is pure text all the first pure text columns are used as header. + // Likewise, if bFillColumnHeader is true, at least the first row serves as a column header. + // If more than one row is pure text all the first pure text rows are used as header. + + SCROW nHeaderRowCount = (bFillColumnHeader && nAllColCount && nAllRowCount) ? 1 : 0; + SCCOL nHeaderColCount = (bFillRowHeader && nAllColCount && nAllRowCount) ? 1 : 0; + + if( nHeaderColCount || nHeaderRowCount ) + { + const SCCOL nInitialHeaderColCount = nHeaderColCount; + //check whether there is more than one text column or row that should be added to the headers + SCROW nSmallestValueRowIndex = nAllRowCount; + bool bFoundValues = false; + bool bFoundAnything = false; + Table* pCol = static_cast<Table*>(rCols.First()); + for (SCCOL nCol = 0; !bFoundValues && nCol < nAllColCount; ++nCol) + { + if (pCol && nCol>=nHeaderColCount) + { + ScToken* pToken = static_cast<ScToken*>(pCol->First()); + for (SCROW nRow = 0; !bFoundValues && nRow < nSmallestValueRowIndex; ++nRow) + { + if (pToken && nRow>=nHeaderRowCount) + { + ScRange aRange; + bool bExternal = false; + StackVar eType = pToken->GetType(); + if( eType==svExternal || eType==svExternalSingleRef || eType==svExternalDoubleRef || eType==svExternalName ) + bExternal = true;//lllll todo correct? + ScSharedTokenRef pSharedToken(static_cast<ScToken*>(pToken->Clone())); + ScRefTokenHelper::getRangeFromToken(aRange, pSharedToken, bExternal ); + SCCOL nCol1=0, nCol2=0; + SCROW nRow1=0, nRow2=0; + SCTAB nTab1=0, nTab2=0; + aRange.GetVars( nCol1, nRow1, nTab1, nCol2, nRow2, nTab2 ); + if (pDoc && pDoc->HasValueData( nCol1, nRow1, nTab1 )) + { + bFoundValues = bFoundAnything = true; + nSmallestValueRowIndex = std::min( nSmallestValueRowIndex, nRow ); + } + if( !bFoundAnything ) + { + if (pDoc && pDoc->HasData( nCol1, nRow1, nTab1 ) ) + bFoundAnything = true; + } + } + pToken = static_cast<ScToken*>(pCol->Next()); + } + if(!bFoundValues && nHeaderColCount>0) + nHeaderColCount++; + } + pCol = static_cast<Table*>(rCols.Next()); + } + if( bFoundAnything ) + { + if(nHeaderRowCount>0) + { + if( bFoundValues ) + nHeaderRowCount = nSmallestValueRowIndex; + else if( nAllRowCount>1 ) + nHeaderRowCount = nAllRowCount-1; + } + } + else //if the cells are completely empty, just use single header rows and columns + nHeaderColCount = nInitialHeaderColCount; + } + + mnDataColCount = nAllColCount - nHeaderColCount; + mnDataRowCount = nAllRowCount - nHeaderRowCount; + + maLeftUpperCorner.init(nHeaderColCount,nHeaderRowCount); + maColHeaders.init(mnDataColCount,nHeaderRowCount); + maRowHeaders.init(nHeaderColCount,mnDataRowCount); + maData.init(mnDataColCount,mnDataRowCount); + + Table* pCol = static_cast<Table*>(rCols.First()); + FormulaToken* pToken = static_cast<FormulaToken*>(pCol->First()); + for (SCCOL nCol = 0; nCol < nAllColCount; ++nCol) + { + if (pCol) + { + pToken = static_cast<FormulaToken*>(pCol->First()); + for (SCROW nRow = 0; nRow < nAllRowCount; ++nRow) + { + if( nCol < nHeaderColCount ) + { + if( nRow < nHeaderRowCount ) + maLeftUpperCorner.push_back(pToken); + else + maRowHeaders.push_back(pToken); + } + else if( nRow < nHeaderRowCount ) + maColHeaders.push_back(pToken); + else + maData.push_back(pToken); + + pToken = static_cast<FormulaToken*>(pCol->Next()); + } + } + pCol = static_cast<Table*>(rCols.Next()); + } +} + +Chart2PositionMap::~Chart2PositionMap() +{ + maLeftUpperCorner.clear(); + maColHeaders.clear(); + maRowHeaders.clear(); + maData.clear(); +} + +vector<ScSharedTokenRef>* Chart2PositionMap::getLeftUpperCornerRanges() const +{ + return maLeftUpperCorner.getAllRanges(); +} +vector<ScSharedTokenRef>* Chart2PositionMap::getAllColHeaderRanges() const +{ + return maColHeaders.getAllRanges(); +} +vector<ScSharedTokenRef>* Chart2PositionMap::getAllRowHeaderRanges() const +{ + return maRowHeaders.getAllRanges(); +} +vector<ScSharedTokenRef>* Chart2PositionMap::getColHeaderRanges(SCCOL nCol) const +{ + return maColHeaders.getColRanges( nCol); +} +vector<ScSharedTokenRef>* Chart2PositionMap::getRowHeaderRanges(SCROW nRow) const +{ + return maRowHeaders.getRowRanges( nRow); +} + +vector<ScSharedTokenRef>* Chart2PositionMap::getDataColRanges(SCCOL nCol) const +{ + return maData.getColRanges( nCol); +} + +vector<ScSharedTokenRef>* Chart2PositionMap::getDataRowRanges(SCROW nRow) const +{ + return maData.getRowRanges( nRow); +} + +// ---------------------------------------------------------------------------- + +/** + * Designed to be a drop-in replacement for ScChartPositioner, in order to + * handle external references. + */ +class Chart2Positioner +{ + enum GlueType + { + GLUETYPE_NA, + GLUETYPE_NONE, + GLUETYPE_COLS, + GLUETYPE_ROWS, + GLUETYPE_BOTH + }; + +public: + Chart2Positioner(ScDocument* pDoc, const vector<ScSharedTokenRef>& rRefTokens) : + mpRefTokens(new vector<ScSharedTokenRef>(rRefTokens)), + mpPositionMap(NULL), + meGlue(GLUETYPE_NA), + mpDoc(pDoc), + mbColHeaders(false), + mbRowHeaders(false), + mbDummyUpperLeft(false) + { + } + + ~Chart2Positioner() + { + } + + void setHeaders(bool bColHeaders, bool bRowHeaders) + { + mbColHeaders = bColHeaders; + mbRowHeaders = bRowHeaders; + } + + bool hasColHeaders() const { return mbColHeaders; } + bool hasRowHeaders() const { return mbRowHeaders; } + + Chart2PositionMap* getPositionMap() + { + createPositionMap(); + return mpPositionMap.get(); + } + +private: + Chart2Positioner(); // disabled + + void invalidateGlue(); + void glueState(); + void createPositionMap(); + +private: + shared_ptr< vector<ScSharedTokenRef> > mpRefTokens; + auto_ptr<Chart2PositionMap> mpPositionMap; + GlueType meGlue; + SCCOL mnStartCol; + SCROW mnStartRow; + ScDocument* mpDoc; + bool mbColHeaders:1; + bool mbRowHeaders:1; + bool mbDummyUpperLeft:1; +}; + +void Chart2Positioner::invalidateGlue() +{ + meGlue = GLUETYPE_NA; + mpPositionMap.reset(NULL); +} + +void Chart2Positioner::glueState() +{ + if (meGlue != GLUETYPE_NA) + return; + + mbDummyUpperLeft = false; + if (mpRefTokens->size() <= 1) + { + const ScSharedTokenRef& p = mpRefTokens->front(); + ScComplexRefData aData; + if (ScRefTokenHelper::getDoubleRefDataFromToken(aData, p)) + { + if (aData.Ref1.nTab == aData.Ref2.nTab) + meGlue = GLUETYPE_NONE; + else + meGlue = GLUETYPE_COLS; + mnStartCol = aData.Ref1.nCol; + mnStartRow = aData.Ref1.nRow; + } + else + { + invalidateGlue(); + mnStartCol = 0; + mnStartRow = 0; + } + return; + } + + ScComplexRefData aData; + ScRefTokenHelper::getDoubleRefDataFromToken(aData, mpRefTokens->front()); + mnStartCol = aData.Ref1.nCol; + mnStartRow = aData.Ref1.nRow; + + SCCOL nMaxCols = 0, nEndCol = 0; + SCROW nMaxRows = 0, nEndRow = 0; + for (vector<ScSharedTokenRef>::const_iterator itr = mpRefTokens->begin(), itrEnd = mpRefTokens->end() + ; itr != itrEnd; ++itr) + { + ScRefTokenHelper::getDoubleRefDataFromToken(aData, *itr); + SCCOLROW n1 = aData.Ref1.nCol; + SCCOLROW n2 = aData.Ref2.nCol; + if (n1 > MAXCOL) + n1 = MAXCOL; + if (n2 > MAXCOL) + n2 = MAXCOL; + SCCOLROW nTmp = n2 - n1 + 1; + if (n1 < mnStartCol) + mnStartCol = static_cast<SCCOL>(n1); + if (n2 > nEndCol) + nEndCol = static_cast<SCCOL>(n2); + if (nTmp > nMaxCols) + nMaxCols = static_cast<SCCOL>(nTmp); + + n1 = aData.Ref1.nRow; + n2 = aData.Ref2.nRow; + if (n1 > MAXROW) + n1 = MAXROW; + if (n2 > MAXROW) + n2 = MAXROW; + nTmp = n2 - n1 + 1; + + if (n1 < mnStartRow) + mnStartRow = static_cast<SCROW>(n1); + if (n2 > nEndRow) + nEndRow = static_cast<SCROW>(n2); + if (nTmp > nMaxRows) + nMaxRows = static_cast<SCROW>(nTmp); + } + + // total column size ? + SCCOL nC = nEndCol - mnStartCol + 1; + if (nC == 1) + { + meGlue = GLUETYPE_ROWS; + return; + } + // total row size ? + SCROW nR = nEndRow - mnStartRow + 1; + if (nR == 1) + { + meGlue = GLUETYPE_COLS; + return; + } + // #i103540# prevent invalid vector size + if ((nC <= 0) || (nR <= 0)) + { + invalidateGlue(); + mnStartCol = 0; + mnStartRow = 0; + return; + } + sal_uInt32 nCR = static_cast<sal_uInt32>(nC*nR); + + const sal_uInt8 nHole = 0; + const sal_uInt8 nOccu = 1; + const sal_uInt8 nFree = 2; + const sal_uInt8 nGlue = 3; + + vector<sal_uInt8> aCellStates(nCR); + for (vector<ScSharedTokenRef>::const_iterator itr = mpRefTokens->begin(), itrEnd = mpRefTokens->end(); + itr != itrEnd; ++itr) + { + ScRefTokenHelper::getDoubleRefDataFromToken(aData, *itr); + SCCOL nCol1 = static_cast<SCCOL>(aData.Ref1.nCol) - mnStartCol; + SCCOL nCol2 = static_cast<SCCOL>(aData.Ref2.nCol) - mnStartCol; + SCROW nRow1 = static_cast<SCROW>(aData.Ref1.nRow) - mnStartRow; + SCROW nRow2 = static_cast<SCROW>(aData.Ref2.nRow) - mnStartRow; + for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) + for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow) + { + size_t i = nCol*nR + nRow; + aCellStates[i] = nOccu; + } + } + bool bGlue = true; + + size_t i = 0; + bool bGlueCols = false; + for (SCCOL nCol = 0; bGlue && nCol < nC; ++nCol) + { + for (SCROW nRow = 0; bGlue && nRow < nR; ++nRow) + { + i = nCol*nR + nRow; + if (aCellStates[i] == nOccu) + { + if (nRow > 0 && nRow > 0) + bGlue = false; + else + nRow = nR; + } + else + aCellStates[i] = nFree; + } + i = (nCol+1)*nR - 1; // index for the last cell in the column. + if (bGlue && (aCellStates[i] == nFree)) + { + aCellStates[i] = nGlue; + bGlueCols = true; + } + } + + bool bGlueRows = false; + for (SCROW nRow = 0; bGlue && nRow < nR; ++nRow) + { + i = nRow; + for (SCCOL nCol = 0; bGlue && nCol < nC; ++nCol, i += nR) + { + if (aCellStates[i] == nOccu) + { + if (nCol > 0 && nRow > 0) + bGlue = false; + else + nCol = nC; + } + else + aCellStates[i] = nFree; + } + i = (nC-1)*nR + nRow; // index for the row position in the last column. + if (bGlue && aCellStates[i] == nFree) + { + aCellStates[i] = nGlue; + bGlueRows = true; + } + } + + i = 1; + for (sal_uInt32 n = 1; bGlue && n < nCR; ++n, ++i) + if (aCellStates[i] == nHole) + bGlue = false; + + if (bGlue) + { + if (bGlueCols && bGlueRows) + meGlue = GLUETYPE_BOTH; + else if (bGlueRows) + meGlue = GLUETYPE_ROWS; + else + meGlue = GLUETYPE_COLS; + if (aCellStates.front() != nOccu) + mbDummyUpperLeft = true; + } + else + meGlue = GLUETYPE_NONE; +} + +void Chart2Positioner::createPositionMap() +{ + if (meGlue == GLUETYPE_NA && mpPositionMap.get()) + mpPositionMap.reset(NULL); + + if (mpPositionMap.get()) + return; + + glueState(); + + bool bNoGlue = (meGlue == GLUETYPE_NONE); + auto_ptr<Table> pCols(new Table); + auto_ptr<FormulaToken> pNewAddress; + auto_ptr<Table> pNewRowTable(new Table); + Table* pCol = NULL; + SCROW nNoGlueRow = 0; + for (vector<ScSharedTokenRef>::const_iterator itr = mpRefTokens->begin(), itrEnd = mpRefTokens->end(); + itr != itrEnd; ++itr) + { + const ScSharedTokenRef& pToken = *itr; + + bool bExternal = ScRefTokenHelper::isExternalRef(pToken); + sal_uInt16 nFileId = bExternal ? pToken->GetIndex() : 0; + String aTabName = bExternal ? pToken->GetString() : String(); + + ScComplexRefData aData; + ScRefTokenHelper::getDoubleRefDataFromToken(aData, *itr); + const ScSingleRefData& s = aData.Ref1; + const ScSingleRefData& e = aData.Ref2; + SCCOL nCol1 = s.nCol, nCol2 = e.nCol; + SCROW nRow1 = s.nRow, nRow2 = e.nRow; + SCTAB nTab1 = s.nTab, nTab2 = e.nTab; + + for (SCTAB nTab = nTab1; nTab <= nTab2; ++nTab) + { + // What's this for ??? + sal_uInt32 nInsCol = (static_cast<sal_uInt32>(nTab) << 16) | + (bNoGlue ? 0 : static_cast<sal_uInt32>(nCol1)); + for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol, ++nInsCol) + { + if (bNoGlue || meGlue == GLUETYPE_ROWS) + { + pCol = static_cast<Table*>(pCols->Get(nInsCol)); + if (!pCol) + { + pCol = pNewRowTable.get(); + pCols->Insert(nInsCol, pNewRowTable.release()); + pNewRowTable.reset(new Table); + } + } + else + { + if (pCols->Insert(nInsCol, pNewRowTable.get())) + { + pCol = pNewRowTable.release(); + pNewRowTable.reset(new Table); + } + else + pCol = static_cast<Table*>(pCols->Get(nInsCol)); + } + + sal_uInt32 nInsRow = static_cast<sal_uInt32>(bNoGlue ? nNoGlueRow : nRow1); + for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow, ++nInsRow) + { + ScSingleRefData aCellData; + aCellData.InitFlags(); + aCellData.SetFlag3D(true); + aCellData.SetColRel(false); + aCellData.SetRowRel(false); + aCellData.SetTabRel(false); + aCellData.nCol = nCol; + aCellData.nRow = nRow; + aCellData.nTab = nTab; + + if (bExternal) + pNewAddress.reset(new ScExternalSingleRefToken(nFileId, aTabName, aCellData)); + else + pNewAddress.reset(new ScSingleRefToken(aCellData)); + + if (pCol->Insert(nInsRow, pNewAddress.get())) + pNewAddress.release(); // To prevent the instance from being destroyed. + } + } + } + nNoGlueRow += nRow2 - nRow1 + 1; + } + pNewAddress.reset(NULL); + pNewRowTable.reset(NULL); + + bool bFillRowHeader = mbRowHeaders; + bool bFillColumnHeader = mbColHeaders; + + SCSIZE nAllColCount = static_cast<SCSIZE>(pCols->Count()); + SCSIZE nAllRowCount = 0; + pCol = static_cast<Table*>(pCols->First()); + if (pCol) + { + if (mbDummyUpperLeft) + pCol->Insert(0, NULL); // Dummy fuer Beschriftung + nAllRowCount = static_cast<SCSIZE>(pCol->Count()); + } + + if( nAllColCount!=0 && nAllRowCount!=0 ) + { + if (bNoGlue) + { + Table* pFirstCol = static_cast<Table*>(pCols->First()); + sal_uInt32 nCount = pFirstCol->Count(); + pFirstCol->First(); + for (sal_uInt32 n = 0; n < nCount; ++n, pFirstCol->Next()) + { + sal_uInt32 nKey = pFirstCol->GetCurKey(); + pCols->First(); + for (pCol = static_cast<Table*>(pCols->Next()); pCol; pCol = static_cast<Table*>(pCols->Next())) + pCol->Insert(nKey, NULL); + } + } + } + mpPositionMap.reset( + new Chart2PositionMap( + static_cast<SCCOL>(nAllColCount), static_cast<SCROW>(nAllRowCount), + bFillRowHeader, bFillColumnHeader, *pCols, mpDoc)); + + // Destroy all column instances. + for (pCol = static_cast<Table*>(pCols->First()); pCol; pCol = static_cast<Table*>(pCols->Next())) + delete pCol; +} + +// ============================================================================ + +/** + * Function object to create a range string from a token list. + */ +class Tokens2RangeString : public unary_function<ScSharedTokenRef, void> +{ +public: + Tokens2RangeString(ScDocument* pDoc, FormulaGrammar::Grammar eGram, sal_Unicode cRangeSep) : + mpRangeStr(new OUStringBuffer), + mpDoc(pDoc), + meGrammar(eGram), + mcRangeSep(cRangeSep), + mbFirst(true) + { + } + + Tokens2RangeString(const Tokens2RangeString& r) : + mpRangeStr(r.mpRangeStr), + mpDoc(r.mpDoc), + meGrammar(r.meGrammar), + mcRangeSep(r.mcRangeSep), + mbFirst(r.mbFirst) + { + } + + void operator() (const ScSharedTokenRef& rToken) + { + ScCompiler aCompiler(mpDoc, ScAddress(0,0,0)); + aCompiler.SetGrammar(meGrammar); + String aStr; + aCompiler.CreateStringFromToken(aStr, rToken.get()); + if (mbFirst) + mbFirst = false; + else + mpRangeStr->append(mcRangeSep); + mpRangeStr->append(aStr); + } + + void getString(OUString& rStr) + { + rStr = mpRangeStr->makeStringAndClear(); + } + +private: + Tokens2RangeString(); // disabled + +private: + shared_ptr<OUStringBuffer> mpRangeStr; + ScDocument* mpDoc; + FormulaGrammar::Grammar meGrammar; + sal_Unicode mcRangeSep; + bool mbFirst; +}; + +/** + * Function object to convert a list of tokens into a string form suitable + * for ODF export. In ODF, a range is expressed as + * + * (start cell address):(end cell address) + * + * and each address doesn't include any '$' symbols. + */ +class Tokens2RangeStringXML : public unary_function<ScSharedTokenRef, void> +{ +public: + Tokens2RangeStringXML(ScDocument* pDoc) : + mpRangeStr(new OUStringBuffer), + mpDoc(pDoc), + mcRangeSep(' '), + mcAddrSep(':'), + mbFirst(true) + { + } + + Tokens2RangeStringXML(const Tokens2RangeStringXML& r) : + mpRangeStr(r.mpRangeStr), + mpDoc(r.mpDoc), + mcRangeSep(r.mcRangeSep), + mcAddrSep(r.mcAddrSep), + mbFirst(r.mbFirst) + { + } + + void operator() (const ScSharedTokenRef& rToken) + { + if (mbFirst) + mbFirst = false; + else + mpRangeStr->append(mcRangeSep); + + ScSharedTokenRef aStart, aEnd; + splitRangeToken(rToken, aStart, aEnd); + ScCompiler aCompiler(mpDoc, ScAddress(0,0,0)); + aCompiler.SetGrammar(FormulaGrammar::GRAM_ENGLISH); + { + String aStr; + aCompiler.CreateStringFromToken(aStr, aStart.get()); + mpRangeStr->append(aStr); + } + mpRangeStr->append(mcAddrSep); + { + String aStr; + aCompiler.CreateStringFromToken(aStr, aEnd.get()); + mpRangeStr->append(aStr); + } + } + + void getString(OUString& rStr) + { + rStr = mpRangeStr->makeStringAndClear(); + } + +private: + Tokens2RangeStringXML(); // disabled + + void splitRangeToken(const ScSharedTokenRef& pToken, ScSharedTokenRef& rStart, ScSharedTokenRef& rEnd) const + { + ScComplexRefData aData; + ScRefTokenHelper::getDoubleRefDataFromToken(aData, pToken); + bool bExternal = ScRefTokenHelper::isExternalRef(pToken); + sal_uInt16 nFileId = bExternal ? pToken->GetIndex() : 0; + String aTabName = bExternal ? pToken->GetString() : String(); + + // In saving to XML, we don't prepend address with '$'. + setRelative(aData.Ref1); + setRelative(aData.Ref2); + + // In XML, the end range must explicitly specify sheet name. + aData.Ref2.SetFlag3D(true); + + if (bExternal) + rStart.reset(new ScExternalSingleRefToken(nFileId, aTabName, aData.Ref1)); + else + rStart.reset(new ScSingleRefToken(aData.Ref1)); + + if (bExternal) + rEnd.reset(new ScExternalSingleRefToken(nFileId, aTabName, aData.Ref2)); + else + rEnd.reset(new ScSingleRefToken(aData.Ref2)); + } + + void setRelative(ScSingleRefData& rData) const + { + rData.SetColRel(true); + rData.SetRowRel(true); + rData.SetTabRel(true); + } + +private: + shared_ptr<OUStringBuffer> mpRangeStr; + ScDocument* mpDoc; + sal_Unicode mcRangeSep; + sal_Unicode mcAddrSep; + bool mbFirst; +}; + +void lcl_convertTokensToString(OUString& rStr, const vector<ScSharedTokenRef>& rTokens, ScDocument* pDoc) +{ + const sal_Unicode cRangeSep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0); + FormulaGrammar::Grammar eGrammar = pDoc->GetGrammar(); + Tokens2RangeString func(pDoc, eGrammar, cRangeSep); + func = for_each(rTokens.begin(), rTokens.end(), func); + func.getString(rStr); +} + +} // anonymous namespace + +// DataProvider ============================================================== + +ScChart2DataProvider::ScChart2DataProvider( ScDocument* pDoc ) + : m_pDocument( pDoc) + , m_aPropSet(lcl_GetDataProviderPropertyMap()) + , m_bIncludeHiddenCells( sal_True) +{ + if ( m_pDocument ) + m_pDocument->AddUnoObject( *this); +} + +ScChart2DataProvider::~ScChart2DataProvider() +{ + if ( m_pDocument ) + m_pDocument->RemoveUnoObject( *this); +} + + +void ScChart2DataProvider::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint) +{ + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + m_pDocument = NULL; + } +} + +::sal_Bool SAL_CALL ScChart2DataProvider::createDataSourcePossible( const uno::Sequence< beans::PropertyValue >& aArguments ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + if( ! m_pDocument ) + return false; + + rtl::OUString aRangeRepresentation; + for(sal_Int32 i = 0; i < aArguments.getLength(); ++i) + { + rtl::OUString sName(aArguments[i].Name); + if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CellRangeRepresentation"))) + { + aArguments[i].Value >>= aRangeRepresentation; + } + } + + vector<ScSharedTokenRef> aTokens; + ScRefTokenHelper::compileRangeRepresentation(aTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar()); + return !aTokens.empty(); +} + +namespace +{ + +ScChart2LabeledDataSequence* lcl_createScChart2DataSequenceFromTokens( auto_ptr< vector<ScSharedTokenRef> > pValueTokens, auto_ptr< vector<ScSharedTokenRef> > pLabelTokens, + ScDocument* pDoc, const uno::Reference < chart2::data::XDataProvider >& xDP, bool bIncludeHiddenCells ) +{ + ScChart2LabeledDataSequence* pRet = 0; + bool bHasValues = pValueTokens.get() && !pValueTokens->empty(); + bool bHasLabel = pLabelTokens.get() && !pLabelTokens->empty(); + if( bHasValues || bHasLabel ) + { + pRet = new ScChart2LabeledDataSequence(pDoc); + if(bHasValues) + { + uno::Reference < chart2::data::XDataSequence > xSeq(new ScChart2DataSequence(pDoc, xDP, pValueTokens.release(), bIncludeHiddenCells)); + pRet->setValues(xSeq); + } + if(bHasLabel) + { + uno::Reference < chart2::data::XDataSequence > xLabelSeq(new ScChart2DataSequence(pDoc, xDP, pLabelTokens.release(), bIncludeHiddenCells)); + pRet->setLabel(xLabelSeq); + } + } + return pRet; +} + +//---------------------------------------------------- +/** + * Check the current list of reference tokens, and add the upper left + * corner of the minimum range that encloses all ranges if certain + * conditions are met. + * + * @param rRefTokens list of reference tokens + * + * @return true if the corner was added, false otherwise. + */ +bool lcl_addUpperLeftCornerIfMissing(vector<ScSharedTokenRef>& rRefTokens, + SCROW nCornerRowCount=1, SCCOL nCornerColumnCount=1) +{ + using ::std::max; + using ::std::min; + + if (rRefTokens.empty()) + return false; + + SCCOL nMinCol = MAXCOLCOUNT; + SCROW nMinRow = MAXROWCOUNT; + SCCOL nMaxCol = 0; + SCROW nMaxRow = 0; + SCTAB nTab = 0; + + USHORT nFileId = 0; + String aExtTabName; + bool bExternal = false; + + vector<ScSharedTokenRef>::const_iterator itr = rRefTokens.begin(), itrEnd = rRefTokens.end(); + + // Get the first ref token. + ScSharedTokenRef pToken = *itr; + switch (pToken->GetType()) + { + case svSingleRef: + { + const ScSingleRefData& rData = pToken->GetSingleRef(); + nMinCol = rData.nCol; + nMinRow = rData.nRow; + nMaxCol = rData.nCol; + nMaxRow = rData.nRow; + nTab = rData.nTab; + } + break; + case svDoubleRef: + { + const ScComplexRefData& rData = pToken->GetDoubleRef(); + nMinCol = min(rData.Ref1.nCol, rData.Ref2.nCol); + nMinRow = min(rData.Ref1.nRow, rData.Ref2.nRow); + nMaxCol = max(rData.Ref1.nCol, rData.Ref2.nCol); + nMaxRow = max(rData.Ref1.nRow, rData.Ref2.nRow); + nTab = rData.Ref1.nTab; + } + break; + case svExternalSingleRef: + { + const ScSingleRefData& rData = pToken->GetSingleRef(); + nMinCol = rData.nCol; + nMinRow = rData.nRow; + nMaxCol = rData.nCol; + nMaxRow = rData.nRow; + nTab = rData.nTab; + nFileId = pToken->GetIndex(); + aExtTabName = pToken->GetString(); + bExternal = true; + } + break; + case svExternalDoubleRef: + { + const ScComplexRefData& rData = pToken->GetDoubleRef(); + nMinCol = min(rData.Ref1.nCol, rData.Ref2.nCol); + nMinRow = min(rData.Ref1.nRow, rData.Ref2.nRow); + nMaxCol = max(rData.Ref1.nCol, rData.Ref2.nCol); + nMaxRow = max(rData.Ref1.nRow, rData.Ref2.nRow); + nTab = rData.Ref1.nTab; + nFileId = pToken->GetIndex(); + aExtTabName = pToken->GetString(); + bExternal = true; + } + break; + default: + ; + } + + // Determine the minimum range enclosing all data ranges. Also make sure + // that they are all on the same table. + + for (++itr; itr != itrEnd; ++itr) + { + pToken = *itr; + switch (pToken->GetType()) + { + case svSingleRef: + { + const ScSingleRefData& rData = pToken->GetSingleRef(); + + nMinCol = min(nMinCol, rData.nCol); + nMinRow = min(nMinRow, rData.nRow); + nMaxCol = max(nMaxCol, rData.nCol); + nMaxRow = max(nMaxRow, rData.nRow); + if (nTab != rData.nTab || bExternal) + return false; + } + break; + case svDoubleRef: + { + const ScComplexRefData& rData = pToken->GetDoubleRef(); + + nMinCol = min(nMinCol, rData.Ref1.nCol); + nMinCol = min(nMinCol, rData.Ref2.nCol); + nMinRow = min(nMinRow, rData.Ref1.nRow); + nMinRow = min(nMinRow, rData.Ref2.nRow); + + nMaxCol = max(nMaxCol, rData.Ref1.nCol); + nMaxCol = max(nMaxCol, rData.Ref2.nCol); + nMaxRow = max(nMaxRow, rData.Ref1.nRow); + nMaxRow = max(nMaxRow, rData.Ref2.nRow); + + if (nTab != rData.Ref1.nTab || bExternal) + return false; + } + break; + case svExternalSingleRef: + { + if (!bExternal) + return false; + + if (nFileId != pToken->GetIndex() || aExtTabName != pToken->GetString()) + return false; + + const ScSingleRefData& rData = pToken->GetSingleRef(); + + nMinCol = min(nMinCol, rData.nCol); + nMinRow = min(nMinRow, rData.nRow); + nMaxCol = max(nMaxCol, rData.nCol); + nMaxRow = max(nMaxRow, rData.nRow); + } + break; + case svExternalDoubleRef: + { + if (!bExternal) + return false; + + if (nFileId != pToken->GetIndex() || aExtTabName != pToken->GetString()) + return false; + + const ScComplexRefData& rData = pToken->GetDoubleRef(); + + nMinCol = min(nMinCol, rData.Ref1.nCol); + nMinCol = min(nMinCol, rData.Ref2.nCol); + nMinRow = min(nMinRow, rData.Ref1.nRow); + nMinRow = min(nMinRow, rData.Ref2.nRow); + + nMaxCol = max(nMaxCol, rData.Ref1.nCol); + nMaxCol = max(nMaxCol, rData.Ref2.nCol); + nMaxRow = max(nMaxRow, rData.Ref1.nRow); + nMaxRow = max(nMaxRow, rData.Ref2.nRow); + } + break; + default: + ; + } + } + + if (nMinRow >= nMaxRow || nMinCol >= nMaxCol || + nMinRow >= MAXROWCOUNT || nMinCol >= MAXCOLCOUNT || + nMaxRow >= MAXROWCOUNT || nMaxCol >= MAXCOLCOUNT) + { + // Invalid range. Bail out. + return false; + } + + // Check if the following conditions are met: + // + // 1) The upper-left corner cell is not included. + // 2) The three adjacent cells of that corner cell are included. + + bool bRight = false, bBottom = false, bDiagonal = false; + for (itr = rRefTokens.begin(); itr != itrEnd; ++itr) + { + pToken = *itr; + switch (pToken->GetType()) + { + case svSingleRef: + case svExternalSingleRef: + { + const ScSingleRefData& rData = pToken->GetSingleRef(); + if (rData.nCol == nMinCol && rData.nRow == nMinRow) + // The corner cell is contained. + return false; + + if (rData.nCol == nMinCol+nCornerColumnCount && rData.nRow == nMinRow) + bRight = true; + + if (rData.nCol == nMinCol && rData.nRow == nMinRow+nCornerRowCount) + bBottom = true; + + if (rData.nCol == nMinCol+nCornerColumnCount && rData.nRow == nMinRow+nCornerRowCount) + bDiagonal = true; + } + break; + case svDoubleRef: + case svExternalDoubleRef: + { + const ScComplexRefData& rData = pToken->GetDoubleRef(); + const ScSingleRefData& r1 = rData.Ref1; + const ScSingleRefData& r2 = rData.Ref2; + if (r1.nCol <= nMinCol && nMinCol <= r2.nCol && + r1.nRow <= nMinRow && nMinRow <= r2.nRow) + // The corner cell is contained. + return false; + + if (r1.nCol <= nMinCol+nCornerColumnCount && nMinCol+nCornerColumnCount <= r2.nCol && + r1.nRow <= nMinRow && nMinRow <= r2.nRow) + bRight = true; + + if (r1.nCol <= nMinCol && nMinCol <= r2.nCol && + r1.nRow <= nMinRow+nCornerRowCount && nMinRow+nCornerRowCount <= r2.nRow) + bBottom = true; + + if (r1.nCol <= nMinCol+nCornerColumnCount && nMinCol+nCornerColumnCount <= r2.nCol && + r1.nRow <= nMinRow+nCornerRowCount && nMinRow+nCornerRowCount <= r2.nRow) + bDiagonal = true; + } + break; + default: + ; + } + } + + if (!bRight || !bBottom || !bDiagonal) + // Not all the adjacent cells are included. Bail out. + return false; + +#if 0 // Do we really need to do this ??? + if (rRefTokens.size() == 2) + { + // Make a simple rectangular range if possible. + ScRange aRightPart(ScAddress(nMinCol+1, nMinRow, nTab), ScAddress(nMaxCol, nMaxRow, nTab)); + ScRange aBottomPart(ScAddress(nMinCol, nMinRow+1, nTab), ScAddress(nMaxCol, nMaxRow, nTab)); + vector<ScRange> aRanges; + aRanges.reserve(2); + aRanges.push_back(aRightPart); + aRanges.push_back(aBottomPart); + if (lcl_isRangeContained(rRefTokens, aRanges)) + { + // Consolidate them into a single rectangle. + ScComplexRefData aData; + aData.InitFlags(); + aData.Ref1.SetFlag3D(true); + aData.Ref1.SetColRel(false); + aData.Ref1.SetRowRel(false); + aData.Ref1.SetTabRel(false); + aData.Ref2.SetColRel(false); + aData.Ref2.SetRowRel(false); + aData.Ref2.SetTabRel(false); + aData.Ref1.nCol = nMinCol; + aData.Ref1.nRow = nMinRow; + aData.Ref1.nTab = nTab; + aData.Ref2.nCol = nMaxCol; + aData.Ref2.nRow = nMaxRow; + aData.Ref2.nTab = nTab; + vector<ScSharedTokenRef> aNewTokens; + aNewTokens.reserve(1); + if (bExternal) + { + ScSharedTokenRef p( + new ScExternalDoubleRefToken(nFileId, aExtTabName, aData)); + aNewTokens.push_back(p); + } + else + { + ScSharedTokenRef p(new ScDoubleRefToken(aData)); + aNewTokens.push_back(p); + } + rRefTokens.swap(aNewTokens); + return true; + } + } +#endif + + ScSingleRefData aData; + aData.InitFlags(); + aData.SetFlag3D(true); + aData.SetColRel(false); + aData.SetRowRel(false); + aData.SetTabRel(false); + aData.nCol = nMinCol; + aData.nRow = nMinRow; + aData.nTab = nTab; + + if( nCornerRowCount==1 && nCornerColumnCount==1 ) + { + if (bExternal) + { + ScSharedTokenRef pCorner( + new ScExternalSingleRefToken(nFileId, aExtTabName, aData)); + ScRefTokenHelper::join(rRefTokens, pCorner); + } + else + { + ScSharedTokenRef pCorner(new ScSingleRefToken(aData)); + ScRefTokenHelper::join(rRefTokens, pCorner); + } + } + else + { + ScSingleRefData aDataEnd(aData); + aDataEnd.nCol += (nCornerColumnCount-1); + aDataEnd.nRow += (nCornerRowCount-1); + ScComplexRefData r; + r.Ref1=aData; + r.Ref2=aDataEnd; + if (bExternal) + { + ScSharedTokenRef pCorner( + new ScExternalDoubleRefToken(nFileId, aExtTabName, r)); + ScRefTokenHelper::join(rRefTokens, pCorner); + } + else + { + ScSharedTokenRef pCorner(new ScDoubleRefToken(r)); + ScRefTokenHelper::join(rRefTokens, pCorner); + } + } + + return true; +} + +} + +uno::Reference< chart2::data::XDataSource> SAL_CALL +ScChart2DataProvider::createDataSource( + const uno::Sequence< beans::PropertyValue >& aArguments ) + throw( lang::IllegalArgumentException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( ! m_pDocument ) + throw uno::RuntimeException(); + + uno::Reference< chart2::data::XDataSource> xResult; + bool bLabel = true; + bool bCategories = false; + bool bOrientCol = true; + ::rtl::OUString aRangeRepresentation; + uno::Sequence< sal_Int32 > aSequenceMapping; + for(sal_Int32 i = 0; i < aArguments.getLength(); ++i) + { + rtl::OUString sName(aArguments[i].Name); + if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("DataRowSource"))) + { + chart::ChartDataRowSource eSource = chart::ChartDataRowSource_COLUMNS; + if( ! (aArguments[i].Value >>= eSource)) + { + sal_Int32 nSource(0); + if( aArguments[i].Value >>= nSource ) + eSource = (static_cast< chart::ChartDataRowSource >( nSource )); + } + bOrientCol = (eSource == chart::ChartDataRowSource_COLUMNS); + } + else if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("FirstCellAsLabel"))) + { + bLabel = ::cppu::any2bool(aArguments[i].Value); + } + else if (aArguments[i].Name == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("HasCategories"))) + { + bCategories = ::cppu::any2bool(aArguments[i].Value); + } + else if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("CellRangeRepresentation"))) + { + aArguments[i].Value >>= aRangeRepresentation; + } + else if (aArguments[i].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("SequenceMapping"))) + { + aArguments[i].Value >>= aSequenceMapping; + } + } + + vector<ScSharedTokenRef> aRefTokens; + ScRefTokenHelper::compileRangeRepresentation(aRefTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar()); + if (aRefTokens.empty()) + // Invalid range representation. Bail out. + throw lang::IllegalArgumentException(); + + if (bLabel) + lcl_addUpperLeftCornerIfMissing(aRefTokens); //#i90669# + + bool bColHeaders = (bOrientCol ? bLabel : bCategories ); + bool bRowHeaders = (bOrientCol ? bCategories : bLabel ); + + Chart2Positioner aChPositioner(m_pDocument, aRefTokens); + aChPositioner.setHeaders(bColHeaders, bRowHeaders); + + const Chart2PositionMap* pChartMap = aChPositioner.getPositionMap(); + if (!pChartMap) + // No chart position map instance. Bail out. + return xResult; + + ScChart2DataSource* pDS = NULL; + std::list < ScChart2LabeledDataSequence* > aSeqs; + + // Fill Categories + if( bCategories ) + { + auto_ptr< vector<ScSharedTokenRef> > pValueTokens(NULL); + if (bOrientCol) + pValueTokens.reset(pChartMap->getAllRowHeaderRanges()); + else + pValueTokens.reset(pChartMap->getAllColHeaderRanges()); + + auto_ptr< vector<ScSharedTokenRef> > pLabelTokens(NULL); + pLabelTokens.reset(pChartMap->getLeftUpperCornerRanges()); + + ScChart2LabeledDataSequence* pCategories = lcl_createScChart2DataSequenceFromTokens( pValueTokens, pLabelTokens, m_pDocument, this, m_bIncludeHiddenCells );//ownership of pointers is transfered! + if( pCategories ) + aSeqs.push_back(pCategories); + } + + // Fill Serieses (values and label) + sal_Int32 nCount = bOrientCol ? pChartMap->getDataColCount() : pChartMap->getDataRowCount(); + for (sal_Int32 i = 0; i < nCount; ++i) + { + auto_ptr< vector<ScSharedTokenRef> > pValueTokens(NULL); + auto_ptr< vector<ScSharedTokenRef> > pLabelTokens(NULL); + if (bOrientCol) + { + pValueTokens.reset(pChartMap->getDataColRanges(static_cast<SCCOL>(i))); + pLabelTokens.reset(pChartMap->getColHeaderRanges(static_cast<SCCOL>(i))); + } + else + { + pValueTokens.reset(pChartMap->getDataRowRanges(static_cast<SCROW>(i))); + pLabelTokens.reset(pChartMap->getRowHeaderRanges(static_cast<SCROW>(i))); + } + ScChart2LabeledDataSequence* pChartSeries = lcl_createScChart2DataSequenceFromTokens( pValueTokens, pLabelTokens, m_pDocument, this, m_bIncludeHiddenCells ); //ownership of pointers is transfered! + if( pChartSeries ) + aSeqs.push_back(pChartSeries); + } + + pDS = new ScChart2DataSource(m_pDocument); + std::list < ScChart2LabeledDataSequence* >::iterator aItr(aSeqs.begin()); + std::list < ScChart2LabeledDataSequence* >::iterator aEndItr(aSeqs.end()); + + //reorder labeled sequences according to aSequenceMapping + std::vector< ScChart2LabeledDataSequence* > aSeqVector; + while(aItr != aEndItr) + { + aSeqVector.push_back(*aItr); + ++aItr; + } + + std::map< sal_Int32, ScChart2LabeledDataSequence* > aSequenceMap; + for( sal_Int32 nNewIndex = 0; nNewIndex < aSequenceMapping.getLength(); nNewIndex++ ) + { + // note: assuming that the values in the sequence mapping are always non-negative + std::vector< ScChart2LabeledDataSequence* >::size_type nOldIndex( static_cast< sal_uInt32 >( aSequenceMapping[nNewIndex] )); + if( nOldIndex < aSeqVector.size() ) + { + pDS->AddLabeledSequence( aSeqVector[nOldIndex] ); + aSeqVector[nOldIndex] = 0; + } + + } + + std::vector< ScChart2LabeledDataSequence* >::iterator aVectorItr(aSeqVector.begin()); + std::vector< ScChart2LabeledDataSequence* >::iterator aVectorEndItr(aSeqVector.end()); + while(aVectorItr != aVectorEndItr) + { + if(*aVectorItr) + pDS->AddLabeledSequence(*aVectorItr); + ++aVectorItr; + } + + xResult.set( pDS ); + return xResult; +} + +namespace +{ + +/** + * Function object to create a list of table numbers from a token list. + */ +class InsertTabNumber : public unary_function<ScSharedTokenRef, void> +{ +public: + InsertTabNumber() : + mpTabNumList(new list<SCTAB>()) + { + } + + InsertTabNumber(const InsertTabNumber& r) : + mpTabNumList(r.mpTabNumList) + { + } + + void operator() (const ScSharedTokenRef& pToken) const + { + if (!ScRefTokenHelper::isRef(pToken)) + return; + + const ScSingleRefData& r = pToken->GetSingleRef(); + mpTabNumList->push_back(r.nTab); + } + + void getList(list<SCTAB>& rList) + { + mpTabNumList->swap(rList); + } +private: + shared_ptr< list<SCTAB> > mpTabNumList; +}; + +class RangeAnalyzer +{ +public: + RangeAnalyzer(); + void initRangeAnalyzer( const vector<ScSharedTokenRef>& rTokens ); + void analyzeRange( sal_Int32& rnDataInRows, sal_Int32& rnDataInCols, + bool& rbRowSourceAmbiguous ) const; + bool inSameSingleRow( RangeAnalyzer& rOther ); + bool inSameSingleColumn( RangeAnalyzer& rOther ); + SCROW getRowCount() { return mnRowCount; } + SCCOL getColumnCount() { return mnColumnCount; } + +private: + bool mbEmpty; + bool mbAmbiguous; + SCROW mnRowCount; + SCCOL mnColumnCount; + + SCCOL mnStartColumn; + SCROW mnStartRow; +}; + +RangeAnalyzer::RangeAnalyzer() + : mbEmpty(true) + , mbAmbiguous(false) + , mnRowCount(0) + , mnColumnCount(0) + , mnStartColumn(-1) + , mnStartRow(-1) +{ +} + +void RangeAnalyzer::initRangeAnalyzer( const vector<ScSharedTokenRef>& rTokens ) +{ + mnRowCount=0; + mnColumnCount=0; + mnStartColumn = -1; + mnStartRow = -1; + mbAmbiguous=false; + if( rTokens.empty() ) + { + mbEmpty=true; + return; + } + mbEmpty=false; + + vector<ScSharedTokenRef>::const_iterator itr = rTokens.begin(), itrEnd = rTokens.end(); + for (; itr != itrEnd ; ++itr) + { + ScSharedTokenRef aRefToken = *itr; + StackVar eVar = aRefToken->GetType(); + if (eVar == svDoubleRef || eVar == svExternalDoubleRef) + { + const ScComplexRefData& r = aRefToken->GetDoubleRef(); + if (r.Ref1.nTab == r.Ref2.nTab) + { + mnColumnCount = std::max<SCCOL>( mnColumnCount, static_cast<SCCOL>(abs(r.Ref2.nCol - r.Ref1.nCol)+1) ); + mnRowCount = std::max<SCROW>( mnRowCount, static_cast<SCROW>(abs(r.Ref2.nRow - r.Ref1.nRow)+1) ); + if( mnStartColumn == -1 ) + { + mnStartColumn = r.Ref1.nCol; + mnStartRow = r.Ref1.nRow; + } + else + { + if( mnStartColumn != r.Ref1.nCol && mnStartRow != r.Ref1.nRow ) + mbAmbiguous=true; + } + } + else + mbAmbiguous=true; + } + else if (eVar == svSingleRef || eVar == svExternalSingleRef) + { + const ScSingleRefData& r = aRefToken->GetSingleRef(); + mnColumnCount = std::max<SCCOL>( mnColumnCount, 1); + mnRowCount = std::max<SCROW>( mnRowCount, 1); + if( mnStartColumn == -1 ) + { + mnStartColumn = r.nCol; + mnStartRow = r.nRow; + } + else + { + if( mnStartColumn != r.nCol && mnStartRow != r.nRow ) + mbAmbiguous=true; + } + } + else + mbAmbiguous=true; + } +} + +void RangeAnalyzer::analyzeRange( sal_Int32& rnDataInRows, + sal_Int32& rnDataInCols, + bool& rbRowSourceAmbiguous ) const +{ + if(!mbEmpty && !mbAmbiguous) + { + if( mnRowCount==1 && mnColumnCount>1 ) + ++rnDataInRows; + else if( mnColumnCount==1 && mnRowCount>1 ) + ++rnDataInCols; + else if( mnRowCount>1 && mnColumnCount>1 ) + rbRowSourceAmbiguous = true; + } + else if( !mbEmpty ) + rbRowSourceAmbiguous = true; +} + +bool RangeAnalyzer::inSameSingleRow( RangeAnalyzer& rOther ) +{ + if( mnStartRow==rOther.mnStartRow && + mnRowCount==1 && rOther.mnRowCount==1 ) + return true; + return false; +} + +bool RangeAnalyzer::inSameSingleColumn( RangeAnalyzer& rOther ) +{ + if( mnStartColumn==rOther.mnStartColumn && + mnColumnCount==1 && rOther.mnColumnCount==1 ) + return true; + return false; +} + +} //end anonymous namespace + +uno::Sequence< beans::PropertyValue > SAL_CALL ScChart2DataProvider::detectArguments( + const uno::Reference< chart2::data::XDataSource >& xDataSource ) + throw (uno::RuntimeException) +{ + ::std::vector< beans::PropertyValue > aResult; + bool bRowSourceDetected = false; + bool bFirstCellAsLabel = false; + bool bHasCategories = false; + ::rtl::OUString sRangeRep; + + bool bHasCategoriesLabels = false; + vector<ScSharedTokenRef> aAllCategoriesValuesTokens; + vector<ScSharedTokenRef> aAllSeriesLabelTokens; + + chart::ChartDataRowSource eRowSource = chart::ChartDataRowSource_COLUMNS; + + vector<ScSharedTokenRef> aAllTokens; + + // parse given data source and collect infos + { + ScUnoGuard aGuard; + DBG_ASSERT( m_pDocument, "No Document -> no detectArguments" ); + if(!m_pDocument ||!xDataSource.is()) + return lcl_VectorToSequence( aResult ); + + sal_Int32 nDataInRows = 0; + sal_Int32 nDataInCols = 0; + bool bRowSourceAmbiguous = false; + + Sequence< Reference< chart2::data::XLabeledDataSequence > > aSequences( xDataSource->getDataSequences()); + const sal_Int32 nCount( aSequences.getLength()); + RangeAnalyzer aPrevLabel,aPrevValues; + for( sal_Int32 nIdx=0; nIdx<nCount; ++nIdx ) + { + Reference< chart2::data::XLabeledDataSequence > xLS(aSequences[nIdx]); + if( xLS.is() ) + { + bool bThisIsCategories = false; + if(!bHasCategories) + { + Reference< beans::XPropertySet > xSeqProp( xLS->getValues(), uno::UNO_QUERY ); + ::rtl::OUString aRole; + if( xSeqProp.is() && (xSeqProp->getPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Role"))) >>= aRole) && + aRole.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("categories")) ) + bThisIsCategories = bHasCategories = true; + } + + RangeAnalyzer aLabel,aValues; + // label + Reference< chart2::data::XDataSequence > xLabel( xLS->getLabel()); + if( xLabel.is()) + { + bFirstCellAsLabel = true; + vector<ScSharedTokenRef> aTokens; + ScRefTokenHelper::compileRangeRepresentation( aTokens, xLabel->getSourceRangeRepresentation(), m_pDocument, m_pDocument->GetGrammar() ); + aLabel.initRangeAnalyzer(aTokens); + vector<ScSharedTokenRef>::const_iterator itr = aTokens.begin(), itrEnd = aTokens.end(); + for (; itr != itrEnd; ++itr) + { + ScRefTokenHelper::join(aAllTokens, *itr); + if(!bThisIsCategories) + ScRefTokenHelper::join(aAllSeriesLabelTokens, *itr); + } + if(bThisIsCategories) + bHasCategoriesLabels=true; + } + // values + Reference< chart2::data::XDataSequence > xValues( xLS->getValues()); + if( xValues.is()) + { + vector<ScSharedTokenRef> aTokens; + ScRefTokenHelper::compileRangeRepresentation( aTokens, xValues->getSourceRangeRepresentation(), m_pDocument, m_pDocument->GetGrammar() ); + aValues.initRangeAnalyzer(aTokens); + vector<ScSharedTokenRef>::const_iterator itr = aTokens.begin(), itrEnd = aTokens.end(); + for (; itr != itrEnd; ++itr) + { + ScRefTokenHelper::join(aAllTokens, *itr); + if(bThisIsCategories) + ScRefTokenHelper::join(aAllCategoriesValuesTokens, *itr); + } + } + //detect row source + if(!bThisIsCategories || nCount==1) //categories might span multiple rows *and* columns, so they should be used for detection only if nothing else is available + { + if (!bRowSourceAmbiguous) + { + aValues.analyzeRange(nDataInRows,nDataInCols,bRowSourceAmbiguous); + aLabel.analyzeRange(nDataInRows,nDataInCols,bRowSourceAmbiguous); + if (nDataInRows > 1 && nDataInCols > 1) + bRowSourceAmbiguous = true; + else if( !bRowSourceAmbiguous && !nDataInRows && !nDataInCols ) + { + if( aValues.inSameSingleColumn( aLabel ) ) + nDataInCols++; + else if( aValues.inSameSingleRow( aLabel ) ) + nDataInRows++; + else + { + //#i86188# also detect a single column split into rows correctly + if( aValues.inSameSingleColumn( aPrevValues ) ) + nDataInRows++; + else if( aValues.inSameSingleRow( aPrevValues ) ) + nDataInCols++; + else if( aLabel.inSameSingleColumn( aPrevLabel ) ) + nDataInRows++; + else if( aLabel.inSameSingleRow( aPrevLabel ) ) + nDataInCols++; + } + } + } + } + aPrevValues=aValues; + aPrevLabel=aLabel; + } + } + + if (!bRowSourceAmbiguous) + { + bRowSourceDetected = true; + eRowSource = ( nDataInRows > 0 + ? chart::ChartDataRowSource_ROWS + : chart::ChartDataRowSource_COLUMNS ); + } + else + { + // set DataRowSource to the better of the two ambiguities + eRowSource = ( nDataInRows > nDataInCols + ? chart::ChartDataRowSource_ROWS + : chart::ChartDataRowSource_COLUMNS ); + } + + } + + // TableNumberList + { + list<SCTAB> aTableNumList; + InsertTabNumber func; + func = for_each(aAllTokens.begin(), aAllTokens.end(), func); + func.getList(aTableNumList); + aResult.push_back( + beans::PropertyValue( ::rtl::OUString::createFromAscii("TableNumberList"), -1, + uno::makeAny( lcl_createTableNumberList( aTableNumList ) ), + beans::PropertyState_DIRECT_VALUE )); + } + + // DataRowSource (calculated before) + if( bRowSourceDetected ) + { + aResult.push_back( + beans::PropertyValue( ::rtl::OUString::createFromAscii("DataRowSource"), -1, + uno::makeAny( eRowSource ), beans::PropertyState_DIRECT_VALUE )); + } + + // HasCategories + if( bRowSourceDetected ) + { + aResult.push_back( + beans::PropertyValue( ::rtl::OUString::createFromAscii("HasCategories"), -1, + uno::makeAny( bHasCategories ), beans::PropertyState_DIRECT_VALUE )); + } + + // FirstCellAsLabel + if( bRowSourceDetected ) + { + aResult.push_back( + beans::PropertyValue( ::rtl::OUString::createFromAscii("FirstCellAsLabel"), -1, + uno::makeAny( bFirstCellAsLabel ), beans::PropertyState_DIRECT_VALUE )); + } + + // Add the left upper corner to the range if it is missing. + if (bRowSourceDetected && bFirstCellAsLabel && bHasCategories && !bHasCategoriesLabels ) + { + RangeAnalyzer aTop,aLeft; + if( eRowSource==chart::ChartDataRowSource_COLUMNS ) + { + aTop.initRangeAnalyzer(aAllSeriesLabelTokens); + aLeft.initRangeAnalyzer(aAllCategoriesValuesTokens); + } + else + { + aTop.initRangeAnalyzer(aAllCategoriesValuesTokens); + aLeft.initRangeAnalyzer(aAllSeriesLabelTokens); + } + lcl_addUpperLeftCornerIfMissing(aAllTokens, aTop.getRowCount(), aLeft.getColumnCount());//e.g. #i91212# + } + + // Get range string. + lcl_convertTokensToString(sRangeRep, aAllTokens, m_pDocument); + + // add cell range property + aResult.push_back( + beans::PropertyValue( ::rtl::OUString::createFromAscii("CellRangeRepresentation"), -1, + uno::makeAny( sRangeRep ), beans::PropertyState_DIRECT_VALUE )); + + //Sequence Mapping + bool bSequencesReordered = true;//todo detect this above or detect this sequence mapping cheaper ... + if( bSequencesReordered && bRowSourceDetected ) + { + bool bDifferentIndexes = false; + + std::vector< sal_Int32 > aSequenceMappingVector; + + uno::Reference< chart2::data::XDataSource > xCompareDataSource; + try + { + xCompareDataSource.set( this->createDataSource( lcl_VectorToSequence( aResult ) ) ); + } + catch( const lang::IllegalArgumentException & ) + { + // creation of data source to compare didn't work, so we cannot + // create a sequence mapping + } + + if( xDataSource.is() && xCompareDataSource.is() ) + { + uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence> > aOldSequences( + xCompareDataSource->getDataSequences() ); + uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aNewSequences( + xDataSource->getDataSequences()); + + rtl::OUString aOldLabel; + rtl::OUString aNewLabel; + rtl::OUString aOldValues; + rtl::OUString aNewValues; + rtl::OUString aEmpty; + + for( sal_Int32 nNewIndex = 0; nNewIndex < aNewSequences.getLength(); nNewIndex++ ) + { + uno::Reference< chart2::data::XLabeledDataSequence> xNew( aNewSequences[nNewIndex] ); + for( sal_Int32 nOldIndex = 0; nOldIndex < aOldSequences.getLength(); nOldIndex++ ) + { + uno::Reference< chart2::data::XLabeledDataSequence> xOld( aOldSequences[nOldIndex] ); + + if( xOld.is() && xNew.is() ) + { + aOldLabel = aNewLabel = aOldValues = aNewValues = aEmpty; + if( xOld.is() && xOld->getLabel().is() ) + aOldLabel = xOld->getLabel()->getSourceRangeRepresentation(); + if( xNew.is() && xNew->getLabel().is() ) + aNewLabel = xNew->getLabel()->getSourceRangeRepresentation(); + if( xOld.is() && xOld->getValues().is() ) + aOldValues = xOld->getValues()->getSourceRangeRepresentation(); + if( xNew.is() && xNew->getValues().is() ) + aNewValues = xNew->getValues()->getSourceRangeRepresentation(); + + if( aOldLabel.equals(aNewLabel) + && ( aOldValues.equals(aNewValues) ) ) + { + if( nOldIndex!=nNewIndex ) + bDifferentIndexes = true; + aSequenceMappingVector.push_back(nOldIndex); + break; + } + } + } + } + } + + if( bDifferentIndexes && aSequenceMappingVector.size() ) + { + aResult.push_back( + beans::PropertyValue( ::rtl::OUString::createFromAscii("SequenceMapping"), -1, + uno::makeAny( lcl_VectorToSequence(aSequenceMappingVector) ) + , beans::PropertyState_DIRECT_VALUE )); + } + } + + return lcl_VectorToSequence( aResult ); +} + +::sal_Bool SAL_CALL ScChart2DataProvider::createDataSequenceByRangeRepresentationPossible( const ::rtl::OUString& aRangeRepresentation ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + if( ! m_pDocument ) + return false; + + vector<ScSharedTokenRef> aTokens; + ScRefTokenHelper::compileRangeRepresentation(aTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar()); + return !aTokens.empty(); +} + +uno::Reference< chart2::data::XDataSequence > SAL_CALL + ScChart2DataProvider::createDataSequenceByRangeRepresentation( + const ::rtl::OUString& aRangeRepresentation ) + throw (lang::IllegalArgumentException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference< chart2::data::XDataSequence > xResult; + + DBG_ASSERT( m_pDocument, "No Document -> no createDataSequenceByRangeRepresentation" ); + if(!m_pDocument || (aRangeRepresentation.getLength() == 0)) + return xResult; + + // Note: the range representation must be in Calc A1 format. The import + // filters use this method to pass data ranges, and they have no idea what + // the current formula syntax is. In the future we should add another + // method to allow the client code to directly pass tokens representing + // ranges. + + vector<ScSharedTokenRef> aRefTokens; + ScRefTokenHelper::compileRangeRepresentation(aRefTokens, aRangeRepresentation, m_pDocument); + if (aRefTokens.empty()) + return xResult; + + // ScChart2DataSequence manages the life cycle of pRefTokens. + vector<ScSharedTokenRef>* pRefTokens = new vector<ScSharedTokenRef>(); + pRefTokens->swap(aRefTokens); + xResult.set(new ScChart2DataSequence(m_pDocument, this, pRefTokens, m_bIncludeHiddenCells)); + + return xResult; +} + +uno::Reference< sheet::XRangeSelection > SAL_CALL ScChart2DataProvider::getRangeSelection() + throw (uno::RuntimeException) +{ + uno::Reference< sheet::XRangeSelection > xResult; + + uno::Reference< frame::XModel > xModel( lcl_GetXModel( m_pDocument )); + if( xModel.is()) + xResult.set( xModel->getCurrentController(), uno::UNO_QUERY ); + + return xResult; +} + +/*uno::Reference< util::XNumberFormatsSupplier > SAL_CALL ScChart2DataProvider::getNumberFormatsSupplier() + throw (uno::RuntimeException) +{ + return uno::Reference< util::XNumberFormatsSupplier >( lcl_GetXModel( m_pDocument ), uno::UNO_QUERY ); +}*/ + +// XRangeXMLConversion --------------------------------------------------- + +rtl::OUString SAL_CALL ScChart2DataProvider::convertRangeToXML( const rtl::OUString& sRangeRepresentation ) + throw ( uno::RuntimeException, lang::IllegalArgumentException ) +{ + OUString aRet; + if (!m_pDocument) + return aRet; + + if (!sRangeRepresentation.getLength()) + // Empty data range is allowed. + return aRet; + + vector<ScSharedTokenRef> aRefTokens; + ScRefTokenHelper::compileRangeRepresentation(aRefTokens, sRangeRepresentation, m_pDocument, m_pDocument->GetGrammar()); + if (aRefTokens.empty()) + throw lang::IllegalArgumentException(); + + Tokens2RangeStringXML converter(m_pDocument); + converter = for_each(aRefTokens.begin(), aRefTokens.end(), converter); + converter.getString(aRet); + + return aRet; +} + +rtl::OUString SAL_CALL ScChart2DataProvider::convertRangeFromXML( const rtl::OUString& sXMLRange ) + throw ( uno::RuntimeException, lang::IllegalArgumentException ) +{ + const sal_Unicode cSep = ' '; + const sal_Unicode cQuote = '\''; + + if (!m_pDocument) + { + // #i74062# When loading flat XML, this is called before the referenced sheets are in the document, + // so the conversion has to take place directly with the strings, without looking up the sheets. + + rtl::OUStringBuffer sRet; + sal_Int32 nOffset = 0; + while( nOffset >= 0 ) + { + rtl::OUString sToken; + ScRangeStringConverter::GetTokenByOffset( sToken, sXMLRange, nOffset, cSep, cQuote ); + if( nOffset >= 0 ) + { + // convert one address (remove dots) + + String aUIString(sToken); + + sal_Int32 nIndex = ScRangeStringConverter::IndexOf( sToken, ':', 0, cQuote ); + if ( nIndex >= 0 && nIndex < aUIString.Len() - 1 && + aUIString.GetChar((xub_StrLen)nIndex + 1) == (sal_Unicode) '.' ) + aUIString.Erase( (xub_StrLen)nIndex + 1, 1 ); + + if ( aUIString.GetChar(0) == (sal_Unicode) '.' ) + aUIString.Erase( 0, 1 ); + + if( sRet.getLength() ) + sRet.append( (sal_Unicode) ';' ); + sRet.append( aUIString ); + } + } + + return sRet.makeStringAndClear(); + } + + OUString aRet; + ScRangeStringConverter::GetStringFromXMLRangeString(aRet, sXMLRange, m_pDocument); + return aRet; +} + +// DataProvider XPropertySet ------------------------------------------------- + +uno::Reference< beans::XPropertySetInfo> SAL_CALL +ScChart2DataProvider::getPropertySetInfo() throw( uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef = + new SfxItemPropertySetInfo( m_aPropSet.getPropertyMap() ); + return aRef; +} + + +void SAL_CALL ScChart2DataProvider::setPropertyValue( + const ::rtl::OUString& rPropertyName, const uno::Any& rValue) + throw( beans::UnknownPropertyException, + beans::PropertyVetoException, + lang::IllegalArgumentException, + lang::WrappedTargetException, uno::RuntimeException) +{ + if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS))) + { + if ( !(rValue >>= m_bIncludeHiddenCells)) + throw lang::IllegalArgumentException(); + } + else + throw beans::UnknownPropertyException(); +} + + +uno::Any SAL_CALL ScChart2DataProvider::getPropertyValue( + const ::rtl::OUString& rPropertyName) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + uno::Any aRet; + if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS))) + aRet <<= m_bIncludeHiddenCells; + else + throw beans::UnknownPropertyException(); + return aRet; +} + + +void SAL_CALL ScChart2DataProvider::addPropertyChangeListener( + const ::rtl::OUString& /*rPropertyName*/, + const uno::Reference< beans::XPropertyChangeListener>& /*xListener*/) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + OSL_ENSURE( false, "Not yet implemented" ); +} + + +void SAL_CALL ScChart2DataProvider::removePropertyChangeListener( + const ::rtl::OUString& /*rPropertyName*/, + const uno::Reference< beans::XPropertyChangeListener>& /*rListener*/) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + OSL_ENSURE( false, "Not yet implemented" ); +} + + +void SAL_CALL ScChart2DataProvider::addVetoableChangeListener( + const ::rtl::OUString& /*rPropertyName*/, + const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + OSL_ENSURE( false, "Not yet implemented" ); +} + + +void SAL_CALL ScChart2DataProvider::removeVetoableChangeListener( + const ::rtl::OUString& /*rPropertyName*/, + const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/ ) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + OSL_ENSURE( false, "Not yet implemented" ); +} + +// DataSource ================================================================ + +ScChart2DataSource::ScChart2DataSource( ScDocument* pDoc) + : m_pDocument( pDoc) +{ + if ( m_pDocument ) + m_pDocument->AddUnoObject( *this); +} + + +ScChart2DataSource::~ScChart2DataSource() +{ + if ( m_pDocument ) + m_pDocument->RemoveUnoObject( *this); +} + + +void ScChart2DataSource::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint) +{ + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + m_pDocument = NULL; + } +} + + +uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence> > SAL_CALL +ScChart2DataSource::getDataSequences() throw ( uno::RuntimeException) +{ + ScUnoGuard aGuard; + + LabeledList::const_iterator aItr(m_aLabeledSequences.begin()); + LabeledList::const_iterator aEndItr(m_aLabeledSequences.end()); + + uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence > > aRet(m_aLabeledSequences.size()); + + sal_Int32 i = 0; + while (aItr != aEndItr) + { + aRet[i] = *aItr; + ++i; + ++aItr; + } + + return aRet; + +/* typedef ::std::vector< uno::Reference< chart2::data::XLabeledDataSequence > > tVec; + tVec aVec; + bool bSeries = false; + // split into columns - FIXME: different if GlueState() is used + for ( ScRangePtr p = m_xRanges->First(); p; p = m_xRanges->Next()) + { + for ( SCCOL nCol = p->aStart.Col(); nCol <= p->aEnd.Col(); ++nCol) + { + uno::Reference< chart2::data::XLabeledDataSequence > xLabeledSeq( + new ScChart2LabeledDataSequence( m_pDocument)); + if( xLabeledSeq.is()) + { + aVec.push_back( xLabeledSeq ); + if( bSeries ) + { + ScRangeListRef aColRanges = new ScRangeList; + // one single sheet selected assumed for now + aColRanges->Append( ScRange( nCol, p->aStart.Row(), + p->aStart.Tab(), nCol, p->aStart.Row(), + p->aStart.Tab())); + // TEST: add range two times, once as label, once as data + // TODO: create pure Numerical and Text sequences if possible + uno::Reference< chart2::data::XDataSequence > xLabel( + new ScChart2DataSequence( m_pDocument, aColRanges)); + + // set role + uno::Reference< beans::XPropertySet > xProp( xLabel, uno::UNO_QUERY ); + if( xProp.is()) + xProp->setPropertyValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )), + ::uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "label" )))); + + xLabeledSeq->setLabel( xLabel ); + } + + ScRangeListRef aColRanges = new ScRangeList; + + // one single sheet selected assumed for now + aColRanges->Append( ScRange( nCol, p->aStart.Row() + 1, + p->aStart.Tab(), nCol, p->aEnd.Row(), + p->aStart.Tab())); + uno::Reference< chart2::data::XDataSequence > xData( + new ScChart2DataSequence( m_pDocument, aColRanges)); + + // set role + uno::Reference< beans::XPropertySet > xProp( xData, uno::UNO_QUERY ); + if( xProp.is()) + xProp->setPropertyValue( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Role" )), + ::uno::makeAny( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "values" )))); + + xLabeledSeq->setValues( xData ); + + bSeries = true; + } + } + } + uno::Sequence< uno::Reference< chart2::data::XLabeledDataSequence> > aSequences( + aVec.size()); + uno::Reference< chart2::data::XLabeledDataSequence> * pArr = aSequences.getArray(); + sal_Int32 j = 0; + for ( tVec::const_iterator iSeq = aVec.begin(); iSeq != aVec.end(); + ++iSeq, ++j) + { + pArr[j] = *iSeq; + } + return aSequences;*/ +} + +void ScChart2DataSource::AddLabeledSequence(const uno::Reference < chart2::data::XLabeledDataSequence >& xNew) +{ + m_aLabeledSequences.push_back(xNew); +} + +// LabeledDataSequence ======================================================= + +ScChart2LabeledDataSequence::ScChart2LabeledDataSequence( + ScDocument* pDoc ) : + m_pDocument( pDoc ) +{ + if ( m_pDocument ) + m_pDocument->AddUnoObject( *this); +} + +ScChart2LabeledDataSequence::~ScChart2LabeledDataSequence() +{ + if ( m_pDocument ) + m_pDocument->RemoveUnoObject( *this); +} + +// SfxListener ----------------------------------------------------------- + +void ScChart2LabeledDataSequence::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint) +{ + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + ScUnoGuard aGuard; + m_pDocument = NULL; + } +} + +// XLabeledDataSequence -------------------------------------------------- + +uno::Reference< chart2::data::XDataSequence > SAL_CALL ScChart2LabeledDataSequence::getValues() + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + return m_aData; +} + +void SAL_CALL ScChart2LabeledDataSequence::setValues( + const uno::Reference< chart2::data::XDataSequence >& xSequence ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + m_aData = xSequence; +} + +uno::Reference< chart2::data::XDataSequence > SAL_CALL ScChart2LabeledDataSequence::getLabel() + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + return m_aLabel; +} + +void SAL_CALL ScChart2LabeledDataSequence::setLabel( + const uno::Reference< chart2::data::XDataSequence >& xSequence ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + m_aLabel = xSequence; +} + +// XCloneable ================================================================ + +uno::Reference< util::XCloneable > SAL_CALL ScChart2LabeledDataSequence::createClone() + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference< util::XCloneable > xToClone(m_aData, uno::UNO_QUERY); + if (xToClone.is()) + { + ScChart2LabeledDataSequence* pRet = new ScChart2LabeledDataSequence(m_pDocument); + uno::Reference< chart2::data::XDataSequence > xSequence(xToClone->createClone(), uno::UNO_QUERY); + pRet->setValues(xSequence); + xToClone.set(m_aLabel, uno::UNO_QUERY); + if(xToClone.is()) + { + xSequence.set(xToClone->createClone(), uno::UNO_QUERY); + pRet->setLabel(xSequence); + } + return pRet; + } + return NULL; +} + +// XModifyBroadcaster ======================================================== + +void SAL_CALL ScChart2LabeledDataSequence::addModifyListener( const uno::Reference< util::XModifyListener >& aListener ) + throw (uno::RuntimeException) +{ + // quick'n dirty: just add the listener to each DataSequence + + uno::Reference<util::XModifyBroadcaster> xDataBroadcaster( m_aData, uno::UNO_QUERY ); + if ( xDataBroadcaster.is() ) + xDataBroadcaster->addModifyListener( aListener ); + uno::Reference<util::XModifyBroadcaster> xLabelBroadcaster( m_aLabel, uno::UNO_QUERY ); + if ( xLabelBroadcaster.is() ) + xLabelBroadcaster->addModifyListener( aListener ); +} + +void SAL_CALL ScChart2LabeledDataSequence::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) + throw (uno::RuntimeException) +{ + uno::Reference<util::XModifyBroadcaster> xDataBroadcaster( m_aData, uno::UNO_QUERY ); + if ( xDataBroadcaster.is() ) + xDataBroadcaster->removeModifyListener( aListener ); + uno::Reference<util::XModifyBroadcaster> xLabelBroadcaster( m_aLabel, uno::UNO_QUERY ); + if ( xLabelBroadcaster.is() ) + xLabelBroadcaster->removeModifyListener( aListener ); +} + +// DataSequence ============================================================== + +ScChart2DataSequence::Item::Item() : + mfValue(0.0), mbIsValue(false) +{ + ::rtl::math::setNan(&mfValue); +} + +ScChart2DataSequence::HiddenRangeListener::HiddenRangeListener(ScChart2DataSequence& rParent) : + mrParent(rParent) +{ +} + +ScChart2DataSequence::HiddenRangeListener::~HiddenRangeListener() +{ +} + +void ScChart2DataSequence::HiddenRangeListener::notify() +{ + mrParent.setDataChangedHint(true); +} + +ScChart2DataSequence::ScChart2DataSequence( ScDocument* pDoc, + const uno::Reference < chart2::data::XDataProvider >& xDP, + vector<ScSharedTokenRef>* pTokens, + bool bIncludeHiddenCells ) + : m_bIncludeHiddenCells( bIncludeHiddenCells) + , m_nObjectId( 0 ) + , m_pDocument( pDoc) + , m_pTokens(pTokens) + , m_pRangeIndices(NULL) + , m_pExtRefListener(NULL) + , m_xDataProvider( xDP) + , m_aPropSet(lcl_GetDataSequencePropertyMap()) + , m_pHiddenListener(NULL) + , m_pValueListener( NULL ) + , m_bGotDataChangedHint(false) + , m_bExtDataRebuildQueued(false) +{ + DBG_ASSERT(pTokens, "reference token list is null"); + + if ( m_pDocument ) + { + m_pDocument->AddUnoObject( *this); + m_nObjectId = m_pDocument->GetNewUnoId(); + } + // FIXME: real implementation of identifier and it's mapping to ranges. + // Reuse ScChartListener? + + // BM: don't use names of named ranges but the UI range strings +// String aStr; +// rRangeList->Format( aStr, SCR_ABS_3D, m_pDocument ); +// m_aIdentifier = ::rtl::OUString( aStr ); + +// m_aIdentifier = ::rtl::OUString::createFromAscii( "ID_"); +// static sal_Int32 nID = 0; +// m_aIdentifier += ::rtl::OUString::valueOf( ++nID); +} + +ScChart2DataSequence::~ScChart2DataSequence() +{ + if ( m_pDocument ) + { + m_pDocument->RemoveUnoObject( *this); + if (m_pHiddenListener.get()) + { + ScChartListenerCollection* pCLC = m_pDocument->GetChartListenerCollection(); + if (pCLC) + pCLC->EndListeningHiddenRange(m_pHiddenListener.get()); + } + StopListeningToAllExternalRefs(); + } + + delete m_pValueListener; +} + +void ScChart2DataSequence::RefChanged() +{ + if( m_pValueListener && m_aValueListeners.Count() != 0 ) + { + m_pValueListener->EndListeningAll(); + + if( m_pDocument ) + { + ScChartListenerCollection* pCLC = NULL; + if (m_pHiddenListener.get()) + { + pCLC = m_pDocument->GetChartListenerCollection(); + if (pCLC) + pCLC->EndListeningHiddenRange(m_pHiddenListener.get()); + } + + vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end(); + for (; itr != itrEnd; ++itr) + { + ScRange aRange; + if (!ScRefTokenHelper::getRangeFromToken(aRange, *itr)) + continue; + + m_pDocument->StartListeningArea(aRange, m_pValueListener); + if (pCLC) + pCLC->StartListeningHiddenRange(aRange, m_pHiddenListener.get()); + } + } + } +} + +void ScChart2DataSequence::BuildDataCache() +{ + m_bExtDataRebuildQueued = false; + + if (!m_aDataArray.empty()) + return; + + if (!m_pTokens.get()) + { + DBG_ERROR("m_pTokens == NULL! Something is wrong."); + return; + } + + StopListeningToAllExternalRefs(); + + ::std::list<sal_Int32> aHiddenValues; + sal_Int32 nDataCount = 0; + sal_Int32 nHiddenValueCount = 0; + + for (vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end(); + itr != itrEnd; ++itr) + { + if (ScRefTokenHelper::isExternalRef(*itr)) + { + nDataCount += FillCacheFromExternalRef(*itr); + } + else + { + ScRange aRange; + if (!ScRefTokenHelper::getRangeFromToken(aRange, *itr)) + continue; + + SCCOL nLastCol = -1; + SCROW nLastRow = -1; + for (SCTAB nTab = aRange.aStart.Tab(); nTab <= aRange.aEnd.Tab(); ++nTab) + { + for (SCCOL nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol) + { + for (SCROW nRow = aRange.aStart.Row(); nRow <= aRange.aEnd.Row(); ++nRow) + { + bool bColHidden = m_pDocument->ColHidden(nCol, nTab, nLastCol); + bool bRowHidden = m_pDocument->RowHidden(nRow, nTab, nLastRow); + + if (bColHidden || bRowHidden) + { + // hidden cell + ++nHiddenValueCount; + aHiddenValues.push_back(nDataCount-1); + + if( !m_bIncludeHiddenCells ) + continue; + } + + m_aDataArray.push_back(Item()); + Item& rItem = m_aDataArray.back(); + ++nDataCount; + + ScAddress aAdr(nCol, nRow, nTab); + ScBaseCell* pCell = m_pDocument->GetCell(aAdr); + if (!pCell) + continue; + + if (pCell->HasStringData()) + rItem.maString = pCell->GetStringData(); + else + { + String aStr; + m_pDocument->GetString(nCol, nRow, nTab, aStr); + rItem.maString = aStr; + } + + switch (pCell->GetCellType()) + { + case CELLTYPE_VALUE: + rItem.mfValue = static_cast< ScValueCell*>(pCell)->GetValue(); + rItem.mbIsValue = true; + break; + case CELLTYPE_FORMULA: + { + ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell); + USHORT nErr = pFCell->GetErrCode(); + if (nErr) + break; + + if (pFCell->HasValueData()) + { + rItem.mfValue = pFCell->GetValue(); + rItem.mbIsValue = true; + } + } + break; +#if DBG_UTIL + case CELLTYPE_DESTROYED: +#endif + case CELLTYPE_EDIT: + case CELLTYPE_NONE: + case CELLTYPE_NOTE: + case CELLTYPE_STRING: + case CELLTYPE_SYMBOLS: + default: + ; // do nothing + } + } + } + } + } + } + + // convert the hidden cell list to sequence. + m_aHiddenValues.realloc(nHiddenValueCount); + sal_Int32* pArr = m_aHiddenValues.getArray(); + ::std::list<sal_Int32>::const_iterator itr = aHiddenValues.begin(), itrEnd = aHiddenValues.end(); + for (;itr != itrEnd; ++itr, ++pArr) + *pArr = *itr; + + // Clear the data series cache when the array is re-built. + m_aMixedDataCache.realloc(0); +} + +void ScChart2DataSequence::RebuildDataCache() +{ + if (!m_bExtDataRebuildQueued) + { + m_aDataArray.clear(); + m_pDocument->BroadcastUno(ScHint(SC_HINT_DATACHANGED, ScAddress(), NULL)); + m_bExtDataRebuildQueued = true; + m_bGotDataChangedHint = true; + } +} + +sal_Int32 ScChart2DataSequence::FillCacheFromExternalRef(const ScSharedTokenRef& pToken) +{ + ScExternalRefManager* pRefMgr = m_pDocument->GetExternalRefManager(); + ScRange aRange; + if (!ScRefTokenHelper::getRangeFromToken(aRange, pToken, true)) + return 0; + + sal_uInt16 nFileId = pToken->GetIndex(); + const String& rTabName = pToken->GetString(); + ScExternalRefCache::TokenArrayRef pArray = pRefMgr->getDoubleRefTokens(nFileId, rTabName, aRange, NULL); + if (!pArray) + // no external data exists for this range. + return 0; + + // Start listening for this external document. + ExternalRefListener* pExtRefListener = GetExtRefListener(); + pRefMgr->addLinkListener(nFileId, pExtRefListener); + pExtRefListener->addFileId(nFileId); + + ScExternalRefCache::TableTypeRef pTable = pRefMgr->getCacheTable(nFileId, rTabName, false, NULL); + sal_Int32 nDataCount = 0; + for (FormulaToken* p = pArray->First(); p; p = pArray->Next()) + { + // Cached external range is always represented as a single + // matrix token, although that might change in the future when + // we introduce a new token type to store multi-table range + // data. + + if (p->GetType() != svMatrix) + { + DBG_ERROR("Cached array is not a matrix token."); + continue; + } + + const ScMatrix* pMat = static_cast<ScToken*>(p)->GetMatrix(); + SCSIZE nCSize, nRSize; + pMat->GetDimensions(nCSize, nRSize); + for (SCSIZE nC = 0; nC < nCSize; ++nC) + { + for (SCSIZE nR = 0; nR < nRSize; ++nR) + { + if (pMat->IsValue(nC, nR) || pMat->IsBoolean(nC, nR)) + { + m_aDataArray.push_back(Item()); + Item& rItem = m_aDataArray.back(); + ++nDataCount; + + rItem.mbIsValue = true; + rItem.mfValue = pMat->GetDouble(nC, nR); + + SvNumberFormatter* pFormatter = m_pDocument->GetFormatTable(); + if (pFormatter) + { + String aStr; + const double fVal = rItem.mfValue; + Color* pColor = NULL; + sal_uInt32 nFmt = 0; + if (pTable) + { + // Get the correct format index from the cache. + SCCOL nCol = aRange.aStart.Col() + static_cast<SCCOL>(nC); + SCROW nRow = aRange.aStart.Row() + static_cast<SCROW>(nR); + pTable->getCell(nCol, nRow, &nFmt); + } + pFormatter->GetOutputString(fVal, nFmt, aStr, &pColor); + rItem.maString = aStr; + } + } + else if (pMat->IsString(nC, nR)) + { + m_aDataArray.push_back(Item()); + Item& rItem = m_aDataArray.back(); + ++nDataCount; + + rItem.mbIsValue = false; + rItem.maString = pMat->GetString(nC, nR); + } + } + } + } + return nDataCount; +} + +void ScChart2DataSequence::UpdateTokensFromRanges(const ScRangeList& rRanges) +{ + if (!m_pRangeIndices.get()) + return; + + sal_uInt32 nCount = rRanges.Count(); + for (sal_uInt32 i = 0; i < nCount; ++i) + { + ScSharedTokenRef pToken; + ScRange* pRange = static_cast<ScRange*>(rRanges.GetObject(i)); + DBG_ASSERT(pRange, "range object is NULL."); + + ScRefTokenHelper::getTokenFromRange(pToken, *pRange); + sal_uInt32 nOrigPos = (*m_pRangeIndices)[i]; + (*m_pTokens)[nOrigPos] = pToken; + } + + RefChanged(); + + // any change of the range address is broadcast to value (modify) listeners + if ( m_aValueListeners.Count() ) + m_bGotDataChangedHint = true; +} + +ScChart2DataSequence::ExternalRefListener* ScChart2DataSequence::GetExtRefListener() +{ + if (!m_pExtRefListener.get()) + m_pExtRefListener.reset(new ExternalRefListener(*this, m_pDocument)); + + return m_pExtRefListener.get(); +} + +void ScChart2DataSequence::StopListeningToAllExternalRefs() +{ + if (!m_pExtRefListener.get()) + return; + + const hash_set<sal_uInt16>& rFileIds = m_pExtRefListener->getAllFileIds(); + hash_set<sal_uInt16>::const_iterator itr = rFileIds.begin(), itrEnd = rFileIds.end(); + ScExternalRefManager* pRefMgr = m_pDocument->GetExternalRefManager(); + for (; itr != itrEnd; ++itr) + pRefMgr->removeLinkListener(*itr, m_pExtRefListener.get()); + + m_pExtRefListener.reset(NULL); +} + +void ScChart2DataSequence::CopyData(const ScChart2DataSequence& r) +{ + if (!m_pDocument) + { + DBG_ERROR("document instance is NULL!?"); + return; + } + + list<Item> aDataArray(r.m_aDataArray); + m_aDataArray.swap(aDataArray); + + m_aHiddenValues = r.m_aHiddenValues; + m_aRole = r.m_aRole; + + if (r.m_pRangeIndices.get()) + m_pRangeIndices.reset(new vector<sal_uInt32>(*r.m_pRangeIndices)); + + if (r.m_pExtRefListener.get()) + { + // Re-register all external files that the old instance was + // listening to. + + ScExternalRefManager* pRefMgr = m_pDocument->GetExternalRefManager(); + m_pExtRefListener.reset(new ExternalRefListener(*this, m_pDocument)); + const hash_set<sal_uInt16>& rFileIds = r.m_pExtRefListener->getAllFileIds(); + hash_set<sal_uInt16>::const_iterator itr = rFileIds.begin(), itrEnd = rFileIds.end(); + for (; itr != itrEnd; ++itr) + { + pRefMgr->addLinkListener(*itr, m_pExtRefListener.get()); + m_pExtRefListener->addFileId(*itr); + } + } +} + +void ScChart2DataSequence::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint) +{ + if ( rHint.ISA( SfxSimpleHint ) ) + { + ULONG nId = static_cast<const SfxSimpleHint&>(rHint).GetId(); + if ( nId ==SFX_HINT_DYING ) + { + m_pDocument = NULL; + } + else if ( nId == SFX_HINT_DATACHANGED ) + { + // delayed broadcast as in ScCellRangesBase + + if ( m_bGotDataChangedHint && m_pDocument ) + { + m_aDataArray.clear(); + lang::EventObject aEvent; + aEvent.Source.set((cppu::OWeakObject*)this); + + if( m_pDocument ) + { + for ( USHORT n=0; n<m_aValueListeners.Count(); n++ ) + m_pDocument->AddUnoListenerCall( *m_aValueListeners[n], aEvent ); + } + + m_bGotDataChangedHint = false; + } + } + else if ( nId == SC_HINT_CALCALL ) + { + // broadcast from DoHardRecalc - set m_bGotDataChangedHint + // (SFX_HINT_DATACHANGED follows separately) + + if ( m_aValueListeners.Count() ) + m_bGotDataChangedHint = true; + } + } + else if ( rHint.ISA( ScUpdateRefHint ) ) + { + // Create a range list from the token list, have the range list + // updated, and bring the change back to the token list. + + ScRangeList aRanges; + m_pRangeIndices.reset(new vector<sal_uInt32>()); + vector<ScSharedTokenRef>::const_iterator itrBeg = m_pTokens->begin(), itrEnd = m_pTokens->end(); + for (vector<ScSharedTokenRef>::const_iterator itr = itrBeg ;itr != itrEnd; ++itr) + { + if (!ScRefTokenHelper::isExternalRef(*itr)) + { + ScRange aRange; + ScRefTokenHelper::getRangeFromToken(aRange, *itr); + aRanges.Append(aRange); + sal_uInt32 nPos = distance(itrBeg, itr); + m_pRangeIndices->push_back(nPos); + } + } + + DBG_ASSERT(m_pRangeIndices->size() == static_cast<size_t>(aRanges.Count()), + "range list and range index list have different sizes."); + + auto_ptr<ScRangeList> pUndoRanges; + if ( m_pDocument->HasUnoRefUndo() ) + pUndoRanges.reset(new ScRangeList(aRanges)); + + const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint; + bool bChanged = aRanges.UpdateReference( + rRef.GetMode(), m_pDocument, rRef.GetRange(), rRef.GetDx(), rRef.GetDy(), rRef.GetDz()); + + if (bChanged) + { + DBG_ASSERT(m_pRangeIndices->size() == static_cast<size_t>(aRanges.Count()), + "range list and range index list have different sizes after the reference update."); + + // Bring the change back from the range list to the token list. + UpdateTokensFromRanges(aRanges); + + if (pUndoRanges.get()) + m_pDocument->AddUnoRefChange(m_nObjectId, *pUndoRanges); + } + } + else if ( rHint.ISA( ScUnoRefUndoHint ) ) + { + const ScUnoRefUndoHint& rUndoHint = static_cast<const ScUnoRefUndoHint&>(rHint); + + do + { + if (rUndoHint.GetObjectId() != m_nObjectId) + break; + + // The hint object provides the old ranges. Restore the old state + // from these ranges. + + if (!m_pRangeIndices.get() || m_pRangeIndices->empty()) + { + DBG_ERROR(" faulty range indices"); + break; + } + + const ScRangeList& rRanges = rUndoHint.GetRanges(); + + sal_uInt32 nCount = rRanges.Count(); + if (nCount != m_pRangeIndices->size()) + { + DBG_ERROR("range count and range index count differ."); + break; + } + + UpdateTokensFromRanges(rRanges); + } + while (false); + } +} + + +IMPL_LINK( ScChart2DataSequence, ValueListenerHdl, SfxHint*, pHint ) +{ + if ( m_pDocument && pHint && pHint->ISA( SfxSimpleHint ) && + ((const SfxSimpleHint*)pHint)->GetId() & (SC_HINT_DATACHANGED | SC_HINT_DYING) ) + { + // This may be called several times for a single change, if several formulas + // in the range are notified. So only a flag is set that is checked when + // SFX_HINT_DATACHANGED is received. + + setDataChangedHint(true); + } + return 0; +} + +// ---------------------------------------------------------------------------- + +ScChart2DataSequence::ExternalRefListener::ExternalRefListener( + ScChart2DataSequence& rParent, ScDocument* pDoc) : + ScExternalRefManager::LinkListener(), + mrParent(rParent), + mpDoc(pDoc) +{ +} + +ScChart2DataSequence::ExternalRefListener::~ExternalRefListener() +{ + if (!mpDoc || mpDoc->IsInDtorClear()) + // The document is being destroyed. Do nothing. + return; + + // Make sure to remove all pointers to this object. + mpDoc->GetExternalRefManager()->removeLinkListener(this); +} + +void ScChart2DataSequence::ExternalRefListener::notify(sal_uInt16 nFileId, ScExternalRefManager::LinkUpdateType eType) +{ + switch (eType) + { + case ScExternalRefManager::LINK_MODIFIED: + { + if (maFileIds.count(nFileId)) + // We are listening to this external document. + mrParent.RebuildDataCache(); + } + break; + case ScExternalRefManager::LINK_BROKEN: + removeFileId(nFileId); + break; + } +} + +void ScChart2DataSequence::ExternalRefListener::addFileId(sal_uInt16 nFileId) +{ + maFileIds.insert(nFileId); +} + +void ScChart2DataSequence::ExternalRefListener::removeFileId(sal_uInt16 nFileId) +{ + maFileIds.erase(nFileId); +} + +const hash_set<sal_uInt16>& ScChart2DataSequence::ExternalRefListener::getAllFileIds() +{ + return maFileIds; +} + +// ---------------------------------------------------------------------------- + +uno::Sequence< uno::Any> SAL_CALL ScChart2DataSequence::getData() + throw ( uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( !m_pDocument) + throw uno::RuntimeException(); + + BuildDataCache(); + + if (!m_aMixedDataCache.getLength()) + { + // Build a cache for the 1st time... + + sal_Int32 nCount = m_aDataArray.size(); + m_aMixedDataCache.realloc(nCount); + uno::Any* pArr = m_aMixedDataCache.getArray(); + ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end(); + for (; itr != itrEnd; ++itr, ++pArr) + { + if (itr->mbIsValue) + *pArr <<= itr->mfValue; + else + *pArr <<= itr->maString; + } + } + return m_aMixedDataCache; +} + +// XNumericalDataSequence -------------------------------------------------- + +uno::Sequence< double > SAL_CALL ScChart2DataSequence::getNumericalData() + throw ( uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( !m_pDocument) + throw uno::RuntimeException(); + + BuildDataCache(); + + double fNAN; + ::rtl::math::setNan(&fNAN); + + sal_Int32 nCount = m_aDataArray.size(); + uno::Sequence<double> aSeq(nCount); + double* pArr = aSeq.getArray(); + ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end(); + for (; itr != itrEnd; ++itr, ++pArr) + *pArr = itr->mbIsValue ? itr->mfValue : fNAN; + + return aSeq; +} + +// XTextualDataSequence -------------------------------------------------- + +uno::Sequence< rtl::OUString > SAL_CALL ScChart2DataSequence::getTextualData( ) throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( !m_pDocument) + throw uno::RuntimeException(); + + BuildDataCache(); + + sal_Int32 nCount = m_aDataArray.size(); + uno::Sequence<rtl::OUString> aSeq(nCount); + rtl::OUString* pArr = aSeq.getArray(); + ::std::list<Item>::const_iterator itr = m_aDataArray.begin(), itrEnd = m_aDataArray.end(); + for (; itr != itrEnd; ++itr, ++pArr) + *pArr = itr->maString; + + return aSeq; +} + +::rtl::OUString SAL_CALL ScChart2DataSequence::getSourceRangeRepresentation() + throw ( uno::RuntimeException) +{ + ScUnoGuard aGuard; + OUString aStr; + DBG_ASSERT( m_pDocument, "No Document -> no SourceRangeRepresentation" ); + if (m_pDocument && m_pTokens.get()) + lcl_convertTokensToString(aStr, *m_pTokens, m_pDocument); + + return aStr; +} + +namespace { + +/** + * This function object is used to accumulatively count the numbers of + * columns and rows in all reference tokens. + */ +class AccumulateRangeSize : public unary_function<ScSharedTokenRef, void> +{ +public: + AccumulateRangeSize() : + mnCols(0), mnRows(0) {} + + AccumulateRangeSize(const AccumulateRangeSize& r) : + mnCols(r.mnCols), mnRows(r.mnRows) {} + + void operator() (const ScSharedTokenRef& pToken) + { + ScRange r; + bool bExternal = ScRefTokenHelper::isExternalRef(pToken); + ScRefTokenHelper::getRangeFromToken(r, pToken, bExternal); + r.Justify(); + mnCols += r.aEnd.Col() - r.aStart.Col() + 1; + mnRows += r.aEnd.Row() - r.aStart.Row() + 1; + } + + SCCOL getCols() const { return mnCols; } + SCROW getRows() const { return mnRows; } +private: + SCCOL mnCols; + SCROW mnRows; +}; + +/** + * This function object is used to generate label strings from a list of + * reference tokens. + */ +class GenerateLabelStrings : public unary_function<ScSharedTokenRef, void> +{ +public: + GenerateLabelStrings(sal_Int32 nSize, chart2::data::LabelOrigin eOrigin, bool bColumn) : + mpLabels(new Sequence<OUString>(nSize)), + meOrigin(eOrigin), + mnCount(0), + mbColumn(bColumn) {} + + GenerateLabelStrings(const GenerateLabelStrings& r) : + mpLabels(r.mpLabels), + meOrigin(r.meOrigin), + mnCount(r.mnCount), + mbColumn(r.mbColumn) {} + + void operator() (const ScSharedTokenRef& pToken) + { + bool bExternal = ScRefTokenHelper::isExternalRef(pToken); + ScRange aRange; + ScRefTokenHelper::getRangeFromToken(aRange, pToken, bExternal); + OUString* pArr = mpLabels->getArray(); + if (mbColumn) + { + for (SCCOL nCol = aRange.aStart.Col(); nCol <= aRange.aEnd.Col(); ++nCol) + { + if ( meOrigin != chart2::data::LabelOrigin_LONG_SIDE) + { + String aString = ScGlobal::GetRscString(STR_COLUMN); + aString += ' '; + ScAddress aPos( nCol, 0, 0 ); + String aColStr; + aPos.Format( aColStr, SCA_VALID_COL, NULL ); + aString += aColStr; + pArr[mnCount] = aString; + } + else //only indices for categories + pArr[mnCount] = String::CreateFromInt32( mnCount+1 ); + ++mnCount; + } + } + else + { + for (sal_Int32 nRow = aRange.aStart.Row(); nRow <= aRange.aEnd.Row(); ++nRow) + { + if (meOrigin != chart2::data::LabelOrigin_LONG_SIDE) + { + String aString = ScGlobal::GetRscString(STR_ROW); + aString += ' '; + aString += String::CreateFromInt32( nRow+1 ); + pArr[mnCount] = aString; + } + else //only indices for categories + pArr[mnCount] = String::CreateFromInt32( mnCount+1 ); + ++mnCount; + } + } + } + + Sequence<OUString> getLabels() const { return *mpLabels; } + +private: + GenerateLabelStrings(); // disabled + + shared_ptr< Sequence<OUString> > mpLabels; + chart2::data::LabelOrigin meOrigin; + sal_Int32 mnCount; + bool mbColumn; +}; + +} + +uno::Sequence< ::rtl::OUString > SAL_CALL ScChart2DataSequence::generateLabel(chart2::data::LabelOrigin eOrigin) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( !m_pDocument) + throw uno::RuntimeException(); + + if (!m_pTokens.get()) + return Sequence<OUString>(); + + // Determine the total size of all ranges. + AccumulateRangeSize func; + func = for_each(m_pTokens->begin(), m_pTokens->end(), func); + SCCOL nCols = func.getCols(); + SCROW nRows = func.getRows(); + + // Detemine whether this is column-major or row-major. + bool bColumn = true; + if ((eOrigin == chart2::data::LabelOrigin_SHORT_SIDE) || + (eOrigin == chart2::data::LabelOrigin_LONG_SIDE)) + { + if (nRows > nCols) + { + if (eOrigin == chart2::data::LabelOrigin_SHORT_SIDE) + bColumn = true; + else + bColumn = false; + } + else if (nCols > nRows) + { + if (eOrigin == chart2::data::LabelOrigin_SHORT_SIDE) + bColumn = false; + else + bColumn = true; + } + else + return Sequence<OUString>(); + } + + // Generate label strings based on the info so far. + sal_Int32 nCount = bColumn ? nCols : nRows; + GenerateLabelStrings genLabels(nCount, eOrigin, bColumn); + genLabels = for_each(m_pTokens->begin(), m_pTokens->end(), genLabels); + Sequence<OUString> aSeq = genLabels.getLabels(); + + return aSeq; +} + +::sal_Int32 SAL_CALL ScChart2DataSequence::getNumberFormatKeyByIndex( ::sal_Int32 nIndex ) + throw (lang::IndexOutOfBoundsException, + uno::RuntimeException) +{ + // index -1 means a heuristic value for the entire sequence + bool bGetSeriesFormat = (nIndex == -1); + sal_Int32 nResult = 0; + + ScUnoGuard aGuard; + if ( !m_pDocument || !m_pTokens.get()) + return nResult; + + sal_Int32 nCount = 0; + bool bFound = false; + ScRangePtr p; + + uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( lcl_GetSpreadSheetDocument( m_pDocument )); + if (!xSpreadDoc.is()) + return nResult; + + uno::Reference<container::XIndexAccess> xIndex( xSpreadDoc->getSheets(), uno::UNO_QUERY ); + if (!xIndex.is()) + return nResult; + + ScRangeList aRanges; + ScRefTokenHelper::getRangeListFromTokens(aRanges, *m_pTokens); + uno::Reference< table::XCellRange > xSheet; + for ( p = aRanges.First(); p && !bFound; p = aRanges.Next()) + { + // TODO: use DocIter? + table::CellAddress aStart, aEnd; + ScUnoConversion::FillApiAddress( aStart, p->aStart ); + ScUnoConversion::FillApiAddress( aEnd, p->aEnd ); + for ( sal_Int16 nSheet = aStart.Sheet; nSheet <= aEnd.Sheet && !bFound; ++nSheet) + { + xSheet.set(xIndex->getByIndex(nSheet), uno::UNO_QUERY); + for ( sal_Int32 nCol = aStart.Column; nCol <= aEnd.Column && !bFound; ++nCol) + { + for ( sal_Int32 nRow = aStart.Row; nRow <= aEnd.Row && !bFound; ++nRow) + { + if( bGetSeriesFormat ) + { + // TODO: use nicer heuristic + // return format of first non-empty cell + uno::Reference< text::XText > xText( + xSheet->getCellByPosition(nCol, nRow), uno::UNO_QUERY); + if (xText.is() && xText->getString().getLength()) + { + uno::Reference< beans::XPropertySet > xProp(xText, uno::UNO_QUERY); + if( xProp.is()) + xProp->getPropertyValue( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NumberFormat"))) >>= nResult; + bFound = true; + break; + } + } + else if( nCount == nIndex ) + { + uno::Reference< beans::XPropertySet > xProp( + xSheet->getCellByPosition(nCol, nRow), uno::UNO_QUERY); + if( xProp.is()) + xProp->getPropertyValue( + ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("NumberFormat"))) >>= nResult; + bFound = true; + break; + } + ++nCount; + } + } + } + } + + return nResult; +} + +// XCloneable ================================================================ + +uno::Reference< util::XCloneable > SAL_CALL ScChart2DataSequence::createClone() + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + + auto_ptr< vector<ScSharedTokenRef> > pTokensNew; + if (m_pTokens.get()) + { + // Clone tokens. + pTokensNew.reset(new vector<ScSharedTokenRef>); + pTokensNew->reserve(m_pTokens->size()); + vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end(); + for (; itr != itrEnd; ++itr) + { + ScSharedTokenRef p(static_cast<ScToken*>((*itr)->Clone())); + pTokensNew->push_back(p); + } + } + + auto_ptr<ScChart2DataSequence> p(new ScChart2DataSequence(m_pDocument, m_xDataProvider, pTokensNew.release(), m_bIncludeHiddenCells)); + p->CopyData(*this); + Reference< util::XCloneable > xClone(p.release()); + + return xClone; +} + +// XModifyBroadcaster ======================================================== + +void SAL_CALL ScChart2DataSequence::addModifyListener( const uno::Reference< util::XModifyListener >& aListener ) + throw (uno::RuntimeException) +{ + // like ScCellRangesBase::addModifyListener + ScUnoGuard aGuard; + if (!m_pTokens.get() || m_pTokens->empty()) + return; + + ScRangeList aRanges; + ScRefTokenHelper::getRangeListFromTokens(aRanges, *m_pTokens); + uno::Reference<util::XModifyListener> *pObj = + new uno::Reference<util::XModifyListener>( aListener ); + m_aValueListeners.Insert( pObj, m_aValueListeners.Count() ); + + if ( m_aValueListeners.Count() == 1 ) + { + if (!m_pValueListener) + m_pValueListener = new ScLinkListener( LINK( this, ScChart2DataSequence, ValueListenerHdl ) ); + + if (!m_pHiddenListener.get()) + m_pHiddenListener.reset(new HiddenRangeListener(*this)); + + if( m_pDocument ) + { + ScChartListenerCollection* pCLC = m_pDocument->GetChartListenerCollection(); + vector<ScSharedTokenRef>::const_iterator itr = m_pTokens->begin(), itrEnd = m_pTokens->end(); + for (; itr != itrEnd; ++itr) + { + ScRange aRange; + if (!ScRefTokenHelper::getRangeFromToken(aRange, *itr)) + continue; + + m_pDocument->StartListeningArea( aRange, m_pValueListener ); + if (pCLC) + pCLC->StartListeningHiddenRange(aRange, m_pHiddenListener.get()); + } + } + + acquire(); // don't lose this object (one ref for all listeners) + } +} + +void SAL_CALL ScChart2DataSequence::removeModifyListener( const uno::Reference< util::XModifyListener >& aListener ) + throw (uno::RuntimeException) +{ + // like ScCellRangesBase::removeModifyListener + + ScUnoGuard aGuard; + if (!m_pTokens.get() || m_pTokens->empty()) + return; + + acquire(); // in case the listeners have the last ref - released below + + USHORT nCount = m_aValueListeners.Count(); + for ( USHORT n=nCount; n--; ) + { + uno::Reference<util::XModifyListener> *pObj = m_aValueListeners[n]; + if ( *pObj == aListener ) + { + m_aValueListeners.DeleteAndDestroy( n ); + + if ( m_aValueListeners.Count() == 0 ) + { + if (m_pValueListener) + m_pValueListener->EndListeningAll(); + + if (m_pHiddenListener.get() && m_pDocument) + { + ScChartListenerCollection* pCLC = m_pDocument->GetChartListenerCollection(); + if (pCLC) + pCLC->EndListeningHiddenRange(m_pHiddenListener.get()); + } + + release(); // release the ref for the listeners + } + + break; + } + } + + release(); // might delete this object +} + +// DataSequence XPropertySet ------------------------------------------------- + +uno::Reference< beans::XPropertySetInfo> SAL_CALL +ScChart2DataSequence::getPropertySetInfo() throw( uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef = + new SfxItemPropertySetInfo( m_aPropSet.getPropertyMap() ); + return aRef; +} + + +void SAL_CALL ScChart2DataSequence::setPropertyValue( + const ::rtl::OUString& rPropertyName, const uno::Any& rValue) + throw( beans::UnknownPropertyException, + beans::PropertyVetoException, + lang::IllegalArgumentException, + lang::WrappedTargetException, uno::RuntimeException) +{ + if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE))) + { + if ( !(rValue >>= m_aRole)) + throw lang::IllegalArgumentException(); + } + else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS))) + { + sal_Bool bOldValue = m_bIncludeHiddenCells; + if ( !(rValue >>= m_bIncludeHiddenCells)) + throw lang::IllegalArgumentException(); + if( bOldValue != m_bIncludeHiddenCells ) + m_aDataArray.clear();//data array is dirty now + } + else + throw beans::UnknownPropertyException(); + // TODO: support optional properties +} + + +uno::Any SAL_CALL ScChart2DataSequence::getPropertyValue( + const ::rtl::OUString& rPropertyName) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + uno::Any aRet; + if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE))) + aRet <<= m_aRole; + else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS))) + aRet <<= m_bIncludeHiddenCells; + else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM(SC_UNONAME_HIDDENVALUES))) + { + // This property is read-only thus cannot be set externally via + // setPropertyValue(...). + BuildDataCache(); + aRet <<= m_aHiddenValues; + } + else + throw beans::UnknownPropertyException(); + // TODO: support optional properties + return aRet; +} + + +void SAL_CALL ScChart2DataSequence::addPropertyChangeListener( + const ::rtl::OUString& /*rPropertyName*/, + const uno::Reference< beans::XPropertyChangeListener>& /*xListener*/) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + // FIXME: real implementation +// throw uno::RuntimeException(); + OSL_ENSURE( false, "Not yet implemented" ); +} + + +void SAL_CALL ScChart2DataSequence::removePropertyChangeListener( + const ::rtl::OUString& /*rPropertyName*/, + const uno::Reference< beans::XPropertyChangeListener>& /*rListener*/) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + // FIXME: real implementation +// throw uno::RuntimeException(); + OSL_ENSURE( false, "Not yet implemented" ); +} + + +void SAL_CALL ScChart2DataSequence::addVetoableChangeListener( + const ::rtl::OUString& /*rPropertyName*/, + const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + // FIXME: real implementation +// throw uno::RuntimeException(); + OSL_ENSURE( false, "Not yet implemented" ); +} + + +void SAL_CALL ScChart2DataSequence::removeVetoableChangeListener( + const ::rtl::OUString& /*rPropertyName*/, + const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + // FIXME: real implementation +// throw uno::RuntimeException(); + OSL_ENSURE( false, "Not yet implemented" ); +} + +void ScChart2DataSequence::setDataChangedHint(bool b) +{ + m_bGotDataChangedHint = b; +} + +// XUnoTunnel + +// sal_Int64 SAL_CALL ScChart2DataSequence::getSomething( +// const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +// { +// if ( rId.getLength() == 16 && +// 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), +// rId.getConstArray(), 16 ) ) +// { +// return (sal_Int64)this; +// } +// return 0; +// } + +// // static +// const uno::Sequence<sal_Int8>& ScChart2DataSequence::getUnoTunnelId() +// { +// static uno::Sequence<sal_Int8> * pSeq = 0; +// if( !pSeq ) +// { +// osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); +// if( !pSeq ) +// { +// static uno::Sequence< sal_Int8 > aSeq( 16 ); +// rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); +// pSeq = &aSeq; +// } +// } +// return *pSeq; +// } + +// // static +// ScChart2DataSequence* ScChart2DataSequence::getImplementation( const uno::Reference<uno::XInterface> xObj ) +// { +// ScChart2DataSequence* pRet = NULL; +// uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); +// if (xUT.is()) +// pRet = (ScChart2DataSequence*) xUT->getSomething( getUnoTunnelId() ); +// return pRet; +// } + +#if USE_CHART2_EMPTYDATASEQUENCE +// DataSequence ============================================================== + +ScChart2EmptyDataSequence::ScChart2EmptyDataSequence( ScDocument* pDoc, + const uno::Reference < chart2::data::XDataProvider >& xDP, + const ScRangeListRef& rRangeList, + sal_Bool bColumn) + : m_bIncludeHiddenCells( sal_True) + , m_xRanges( rRangeList) + , m_pDocument( pDoc) + , m_xDataProvider( xDP) + , m_aPropSet(lcl_GetDataSequencePropertyMap()) + , m_bColumn(bColumn) +{ + if ( m_pDocument ) + m_pDocument->AddUnoObject( *this); + // FIXME: real implementation of identifier and it's mapping to ranges. + // Reuse ScChartListener? + + // BM: don't use names of named ranges but the UI range strings +// String aStr; +// rRangeList->Format( aStr, SCR_ABS_3D, m_pDocument ); +// m_aIdentifier = ::rtl::OUString( aStr ); + +// m_aIdentifier = ::rtl::OUString::createFromAscii( "ID_"); +// static sal_Int32 nID = 0; +// m_aIdentifier += ::rtl::OUString::valueOf( ++nID); +} + + +ScChart2EmptyDataSequence::~ScChart2EmptyDataSequence() +{ + if ( m_pDocument ) + m_pDocument->RemoveUnoObject( *this); +} + + +void ScChart2EmptyDataSequence::Notify( SfxBroadcaster& /*rBC*/, const SfxHint& rHint) +{ + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + m_pDocument = NULL; + } +} + + +uno::Sequence< uno::Any> SAL_CALL ScChart2EmptyDataSequence::getData() + throw ( uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( !m_pDocument) + throw uno::RuntimeException(); + return uno::Sequence< uno::Any>(); +} + +// XTextualDataSequence -------------------------------------------------- + +uno::Sequence< rtl::OUString > SAL_CALL ScChart2EmptyDataSequence::getTextualData( ) throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( !m_pDocument) + throw uno::RuntimeException(); + + sal_Int32 nCount = 0; + ScRangePtr p; + + DBG_ASSERT(m_xRanges->Count() == 1, "not handled count of ranges"); + + for ( p = m_xRanges->First(); p; p = m_xRanges->Next()) + { + p->Justify(); + // TODO: handle overlaping ranges? + nCount += m_bColumn ? p->aEnd.Col() - p->aStart.Col() + 1 : p->aEnd.Row() - p->aStart.Row() + 1; + } + uno::Sequence< rtl::OUString > aSeq( nCount); + rtl::OUString* pArr = aSeq.getArray(); + nCount = 0; + for ( p = m_xRanges->First(); p; p = m_xRanges->Next()) + { + if (m_bColumn) + { + for (SCCOL nCol = p->aStart.Col(); nCol <= p->aEnd.Col(); ++nCol) + { + String aString = ScGlobal::GetRscString(STR_COLUMN); + aString += ' '; + ScAddress aPos( nCol, 0, 0 ); + String aColStr; + aPos.Format( aColStr, SCA_VALID_COL, NULL ); + aString += aColStr; + pArr[nCount] = aString; + ++nCount; + } + } + else + { + for (sal_Int32 nRow = p->aStart.Row(); nRow <= p->aEnd.Row(); ++nRow) + { + String aString = ScGlobal::GetRscString(STR_ROW); + aString += ' '; + aString += String::CreateFromInt32( nRow+1 ); + pArr[nCount] = aString; + ++nCount; + } + } + } + return aSeq; +} + +::rtl::OUString SAL_CALL ScChart2EmptyDataSequence::getSourceRangeRepresentation() + throw ( uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aStr; + DBG_ASSERT( m_pDocument, "No Document -> no SourceRangeRepresentation" ); + if( m_pDocument ) + m_xRanges->Format( aStr, SCR_ABS_3D, m_pDocument, m_pDocument->GetAddressConvention() ); + return aStr; +} + +uno::Sequence< ::rtl::OUString > SAL_CALL ScChart2EmptyDataSequence::generateLabel(chart2::data::LabelOrigin /*nOrigin*/) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Sequence< ::rtl::OUString > aRet; + return aRet; +} + +::sal_Int32 SAL_CALL ScChart2EmptyDataSequence::getNumberFormatKeyByIndex( ::sal_Int32 /*nIndex*/ ) + throw (lang::IndexOutOfBoundsException, + uno::RuntimeException) +{ + sal_Int32 nResult = 0; + + ScUnoGuard aGuard; + if ( !m_pDocument) + return nResult; + + return nResult; +} + +// XCloneable ================================================================ + +uno::Reference< util::XCloneable > SAL_CALL ScChart2EmptyDataSequence::createClone() + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (m_xDataProvider.is()) + { + // copy properties + uno::Reference < util::XCloneable > xClone(new ScChart2EmptyDataSequence(m_pDocument, m_xDataProvider, new ScRangeList(*m_xRanges), m_bColumn)); + uno::Reference< beans::XPropertySet > xProp( xClone, uno::UNO_QUERY ); + if( xProp.is()) + { + xProp->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_ROLE )), + uno::makeAny( m_aRole )); + xProp->setPropertyValue( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS )), + uno::makeAny( m_bIncludeHiddenCells )); + } + return xClone; + } + return uno::Reference< util::XCloneable >(); +} + +// XModifyBroadcaster ======================================================== + +void SAL_CALL ScChart2EmptyDataSequence::addModifyListener( const uno::Reference< util::XModifyListener >& /*aListener*/ ) + throw (uno::RuntimeException) +{ + // TODO: Implement +} + +void SAL_CALL ScChart2EmptyDataSequence::removeModifyListener( const uno::Reference< util::XModifyListener >& /*aListener*/ ) + throw (uno::RuntimeException) +{ + // TODO: Implement +} + +// DataSequence XPropertySet ------------------------------------------------- + +uno::Reference< beans::XPropertySetInfo> SAL_CALL +ScChart2EmptyDataSequence::getPropertySetInfo() throw( uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef = + new SfxItemPropertySetInfo( m_aPropSet.getPropertyMap() ); + return aRef; +} + + +void SAL_CALL ScChart2EmptyDataSequence::setPropertyValue( + const ::rtl::OUString& rPropertyName, const uno::Any& rValue) + throw( beans::UnknownPropertyException, + beans::PropertyVetoException, + lang::IllegalArgumentException, + lang::WrappedTargetException, uno::RuntimeException) +{ + if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE))) + { + if ( !(rValue >>= m_aRole)) + throw lang::IllegalArgumentException(); + } + else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS))) + { + if ( !(rValue >>= m_bIncludeHiddenCells)) + throw lang::IllegalArgumentException(); + } + else + throw beans::UnknownPropertyException(); + // TODO: support optional properties +} + + +uno::Any SAL_CALL ScChart2EmptyDataSequence::getPropertyValue( + const ::rtl::OUString& rPropertyName) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + uno::Any aRet; + if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_ROLE))) + aRet <<= m_aRole; + else if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_UNONAME_INCLUDEHIDDENCELLS))) + aRet <<= m_bIncludeHiddenCells; + else + throw beans::UnknownPropertyException(); + // TODO: support optional properties + return aRet; +} + + +void SAL_CALL ScChart2EmptyDataSequence::addPropertyChangeListener( + const ::rtl::OUString& /*rPropertyName*/, + const uno::Reference< beans::XPropertyChangeListener>& /*xListener*/) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + // FIXME: real implementation +// throw uno::RuntimeException(); + OSL_ENSURE( false, "Not yet implemented" ); +} + + +void SAL_CALL ScChart2EmptyDataSequence::removePropertyChangeListener( + const ::rtl::OUString& /*rPropertyName*/, + const uno::Reference< beans::XPropertyChangeListener>& /*rListener*/) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + // FIXME: real implementation +// throw uno::RuntimeException(); + OSL_ENSURE( false, "Not yet implemented" ); +} + + +void SAL_CALL ScChart2EmptyDataSequence::addVetoableChangeListener( + const ::rtl::OUString& /*rPropertyName*/, + const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + // FIXME: real implementation +// throw uno::RuntimeException(); + OSL_ENSURE( false, "Not yet implemented" ); +} + + +void SAL_CALL ScChart2EmptyDataSequence::removeVetoableChangeListener( + const ::rtl::OUString& /*rPropertyName*/, + const uno::Reference< beans::XVetoableChangeListener>& /*rListener*/ ) + throw( beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + // FIXME: real implementation +// throw uno::RuntimeException(); + OSL_ENSURE( false, "Not yet implemented" ); +} + +// XUnoTunnel + +// sal_Int64 SAL_CALL ScChart2EmptyDataSequence::getSomething( +// const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +// { +// if ( rId.getLength() == 16 && +// 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), +// rId.getConstArray(), 16 ) ) +// { +// return (sal_Int64)this; +// } +// return 0; +// } + +// // static +// const uno::Sequence<sal_Int8>& ScChart2EmptyDataSequence::getUnoTunnelId() +// { +// static uno::Sequence<sal_Int8> * pSeq = 0; +// if( !pSeq ) +// { +// osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); +// if( !pSeq ) +// { +// static uno::Sequence< sal_Int8 > aSeq( 16 ); +// rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); +// pSeq = &aSeq; +// } +// } +// return *pSeq; +// } + +// // static +// ScChart2DataSequence* ScChart2EmptyDataSequence::getImplementation( const uno::Reference<uno::XInterface> xObj ) +// { +// ScChart2DataSequence* pRet = NULL; +// uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); +// if (xUT.is()) +// pRet = (ScChart2EmptyDataSequence*) xUT->getSomething( getUnoTunnelId() ); +// return pRet; +// } +#endif diff --git a/sc/source/ui/unoobj/chartuno.cxx b/sc/source/ui/unoobj/chartuno.cxx new file mode 100644 index 000000000000..86f59d66a7a4 --- /dev/null +++ b/sc/source/ui/unoobj/chartuno.cxx @@ -0,0 +1,817 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + +#include <com/sun/star/embed/Aspects.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/chart2/data/XDataReceiver.hpp> +#include <com/sun/star/chart/ChartDataRowSource.hpp> +#include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/embed/Aspects.hpp> +#include <com/sun/star/table/CellRangeAddress.hpp> + +#include <svx/svditer.hxx> +#include <svx/svdoole2.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdundo.hxx> +#include <sfx2/app.hxx> +#include <unotools/moduleoptions.hxx> +#include <sot/clsids.hxx> +#include <toolkit/helper/vclunohelper.hxx> + +#include "chartuno.hxx" +#include "miscuno.hxx" +#include "docsh.hxx" +#include "drwlayer.hxx" +#include "undodat.hxx" +#include "chartarr.hxx" +#include "chartlis.hxx" +#include "unoguard.hxx" +#include "chart2uno.hxx" +#include "convuno.hxx" + +using namespace com::sun::star; + +#define PROP_HANDLE_RELATED_CELLRANGES 1 + +//------------------------------------------------------------------------ + +SC_SIMPLE_SERVICE_INFO( ScChartObj, "ScChartObj", "com.sun.star.table.TableChart" ) +SC_SIMPLE_SERVICE_INFO( ScChartsObj, "ScChartsObj", "com.sun.star.table.TableCharts" ) + +//------------------------------------------------------------------------ + +SdrOle2Obj* lcl_FindChartObj( ScDocShell* pDocShell, SCTAB nTab, const String& rName ) +{ + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); + if (pDrawLayer) + { + SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab)); + DBG_ASSERT(pPage, "Page nicht gefunden"); + if (pPage) + { + SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + if ( pObject->GetObjIdentifier() == OBJ_OLE2 && pDoc->IsChart(pObject) ) + { + uno::Reference < embed::XEmbeddedObject > xObj = ((SdrOle2Obj*)pObject)->GetObjRef(); + if ( xObj.is() ) + { + String aObjName = pDocShell->GetEmbeddedObjectContainer().GetEmbeddedObjectName( xObj ); + if ( aObjName == rName ) + return (SdrOle2Obj*)pObject; + } + } + pObject = aIter.Next(); + } + } + } + } + return NULL; +} + +//------------------------------------------------------------------------ + +ScChartsObj::ScChartsObj(ScDocShell* pDocSh, SCTAB nT) : + pDocShell( pDocSh ), + nTab( nT ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScChartsObj::~ScChartsObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScChartsObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + //! Referenz-Update + + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +ScChartObj* ScChartsObj::GetObjectByIndex_Impl(long nIndex) const +{ + String aName; + if ( pDocShell ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); + if (pDrawLayer) + { + SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab)); + DBG_ASSERT(pPage, "Page nicht gefunden"); + if (pPage) + { + long nPos = 0; + SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + if ( pObject->GetObjIdentifier() == OBJ_OLE2 && pDoc->IsChart(pObject) ) + { + if ( nPos == nIndex ) + { + uno::Reference < embed::XEmbeddedObject > xObj = ((SdrOle2Obj*)pObject)->GetObjRef(); + if ( xObj.is() ) + aName = pDocShell->GetEmbeddedObjectContainer().GetEmbeddedObjectName( xObj ); + break; // nicht weitersuchen + } + ++nPos; + } + pObject = aIter.Next(); + } + } + } + } + + if (aName.Len()) + return new ScChartObj( pDocShell, nTab, aName ); + return NULL; +} + +ScChartObj* ScChartsObj::GetObjectByName_Impl(const rtl::OUString& aName) const +{ + String aNameString(aName); + if ( lcl_FindChartObj( pDocShell, nTab, aNameString ) ) + return new ScChartObj( pDocShell, nTab, aNameString ); + return NULL; +} + +// XTableCharts + +void SAL_CALL ScChartsObj::addNewByName( const rtl::OUString& aName, + const awt::Rectangle& aRect, + const uno::Sequence<table::CellRangeAddress>& aRanges, + sal_Bool bColumnHeaders, sal_Bool bRowHeaders ) + throw(::com::sun::star::uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (!pDocShell) + return; + + ScDocument* pDoc = pDocShell->GetDocument(); + ScDrawLayer* pModel = pDocShell->MakeDrawLayer(); + SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab)); + DBG_ASSERT(pPage,"addChart: keine Page"); + if (!pPage || !pDoc) + return; + + // chart can't be inserted if any ole object with that name exists on any table + // (empty string: generate valid name) + + String aNameString(aName); + SCTAB nDummy; + if ( aNameString.Len() && pModel->GetNamedObject( aNameString, OBJ_OLE2, nDummy ) ) + { + // object exists - only RuntimeException is specified + throw uno::RuntimeException(); + } + + ScRangeList* pList = new ScRangeList; + USHORT nRangeCount = (USHORT)aRanges.getLength(); + if (nRangeCount) + { + const table::CellRangeAddress* pAry = aRanges.getConstArray(); + for (USHORT i=0; i<nRangeCount; i++) + { + ScRange aRange( static_cast<SCCOL>(pAry[i].StartColumn), pAry[i].StartRow, pAry[i].Sheet, + static_cast<SCCOL>(pAry[i].EndColumn), pAry[i].EndRow, pAry[i].Sheet ); + pList->Append( aRange ); + } + } + ScRangeListRef xNewRanges( pList ); + + uno::Reference < embed::XEmbeddedObject > xObj; + ::rtl::OUString aTmp( aNameString ); + if ( SvtModuleOptions().IsChart() ) + xObj = pDocShell->GetEmbeddedObjectContainer().CreateEmbeddedObject( SvGlobalName( SO3_SCH_CLASSID ).GetByteSequence(), aTmp ); + if ( xObj.is() ) + { + String aObjName = aTmp; // wirklich eingefuegter Name... + + // Rechteck anpassen + //! Fehler/Exception, wenn leer/ungueltig ??? + Point aRectPos( aRect.X, aRect.Y ); + if (aRectPos.X() < 0) aRectPos.X() = 0; + if (aRectPos.Y() < 0) aRectPos.Y() = 0; + Size aRectSize( aRect.Width, aRect.Height ); + if (aRectSize.Width() <= 0) aRectSize.Width() = 5000; // Default-Groesse + if (aRectSize.Height() <= 0) aRectSize.Height() = 5000; + Rectangle aInsRect( aRectPos, aRectSize ); + + sal_Int64 nAspect(embed::Aspects::MSOLE_CONTENT); + MapUnit aMapUnit(VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) )); + Size aSize(aInsRect.GetSize()); + aSize = Window::LogicToLogic( aSize, MapMode( MAP_100TH_MM ), MapMode( aMapUnit ) ); + awt::Size aSz; + aSz.Width = aSize.Width(); + aSz.Height = aSize.Height(); + + // Calc -> DataProvider + uno::Reference< chart2::data::XDataProvider > xDataProvider = new + ScChart2DataProvider( pDoc ); + // Chart -> DataReceiver + uno::Reference< chart2::data::XDataReceiver > xReceiver; + uno::Reference< embed::XComponentSupplier > xCompSupp( xObj, uno::UNO_QUERY ); + if( xCompSupp.is()) + xReceiver.set( xCompSupp->getComponent(), uno::UNO_QUERY ); + if( xReceiver.is()) + { + String sRangeStr; + xNewRanges->Format(sRangeStr, SCR_ABS_3D, pDoc); + + // connect + if( sRangeStr.Len() ) + xReceiver->attachDataProvider( xDataProvider ); + else + sRangeStr = String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM( "all" ) ); + + uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( pDocShell->GetModel(), uno::UNO_QUERY ); + xReceiver->attachNumberFormatsSupplier( xNumberFormatsSupplier ); + + // set arguments + uno::Sequence< beans::PropertyValue > aArgs( 4 ); + aArgs[0] = beans::PropertyValue( + ::rtl::OUString::createFromAscii("CellRangeRepresentation"), -1, + uno::makeAny( ::rtl::OUString( sRangeStr )), beans::PropertyState_DIRECT_VALUE ); + aArgs[1] = beans::PropertyValue( + ::rtl::OUString::createFromAscii("HasCategories"), -1, + uno::makeAny( bRowHeaders ), beans::PropertyState_DIRECT_VALUE ); + aArgs[2] = beans::PropertyValue( + ::rtl::OUString::createFromAscii("FirstCellAsLabel"), -1, + uno::makeAny( bColumnHeaders ), beans::PropertyState_DIRECT_VALUE ); + aArgs[3] = beans::PropertyValue( + ::rtl::OUString::createFromAscii("DataRowSource"), -1, + uno::makeAny( chart::ChartDataRowSource_COLUMNS ), beans::PropertyState_DIRECT_VALUE ); + xReceiver->setArguments( aArgs ); + } + + ScChartListener* pChartListener = + new ScChartListener( aObjName, pDoc, xNewRanges ); + pDoc->GetChartListenerCollection()->Insert( pChartListener ); + pChartListener->StartListeningTo(); + + SdrOle2Obj* pObj = new SdrOle2Obj( ::svt::EmbeddedObjectRef( xObj, embed::Aspects::MSOLE_CONTENT ), aObjName, aInsRect ); + + // set VisArea + if( xObj.is()) + xObj->setVisualAreaSize( nAspect, aSz ); + + pPage->InsertObject( pObj ); + pModel->AddUndo( new SdrUndoInsertObj( *pObj ) ); //! Undo-Kommentar? + + // Dies veranlaesst Chart zum sofortigen Update + //SvData aEmpty; + //aIPObj->SendDataChanged( aEmpty ); + } +} + +void SAL_CALL ScChartsObj::removeByName( const rtl::OUString& aName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aNameString(aName); + SdrOle2Obj* pObj = lcl_FindChartObj( pDocShell, nTab, aNameString ); + if (pObj) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScDrawLayer* pModel = pDoc->GetDrawLayer(); // ist nicht 0 + SdrPage* pPage = pModel->GetPage(static_cast<sal_uInt16>(nTab)); // ist nicht 0 + + pModel->AddUndo( new SdrUndoRemoveObj( *pObj ) ); //! Undo-Kommentar? + pPage->RemoveObject( pObj->GetOrdNum() ); + + //! Notify etc.??? + } +} + +// XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScChartsObj::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.table.TableChartsEnumeration"))); +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScChartsObj::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + INT32 nCount = 0; + if ( pDocShell ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); + if (pDrawLayer) + { + SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab)); + DBG_ASSERT(pPage, "Page nicht gefunden"); + if (pPage) + { + SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + if ( pObject->GetObjIdentifier() == OBJ_OLE2 && pDoc->IsChart(pObject) ) + ++nCount; + pObject = aIter.Next(); + } + } + } + } + return nCount; +} + +uno::Any SAL_CALL ScChartsObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<table::XTableChart> xChart(GetObjectByIndex_Impl(nIndex)); + if (xChart.is()) + return uno::makeAny(xChart); + else + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +uno::Type SAL_CALL ScChartsObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((uno::Reference<table::XTableChart>*)0); +} + +sal_Bool SAL_CALL ScChartsObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCount() != 0; +} + +uno::Any SAL_CALL ScChartsObj::getByName( const rtl::OUString& aName ) + throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<table::XTableChart> xChart(GetObjectByName_Impl(aName)); + if (xChart.is()) + return uno::makeAny(xChart); + else + throw container::NoSuchElementException(); +// return uno::Any(); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScChartsObj::getElementNames() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + + long nCount = getCount(); + uno::Sequence<rtl::OUString> aSeq(nCount); + rtl::OUString* pAry = aSeq.getArray(); + + long nPos = 0; + ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); + if (pDrawLayer) + { + SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab)); + DBG_ASSERT(pPage, "Page nicht gefunden"); + if (pPage) + { + SdrObjListIter aIter( *pPage, IM_DEEPNOGROUPS ); + SdrObject* pObject = aIter.Next(); + while (pObject) + { + if ( pObject->GetObjIdentifier() == OBJ_OLE2 && pDoc->IsChart(pObject) ) + { + String aName; + uno::Reference < embed::XEmbeddedObject > xObj = ((SdrOle2Obj*)pObject)->GetObjRef(); + if ( xObj.is() ) + aName = pDocShell->GetEmbeddedObjectContainer().GetEmbeddedObjectName( xObj ); + + DBG_ASSERT(nPos<nCount, "huch, verzaehlt?"); + pAry[nPos++] = aName; + } + pObject = aIter.Next(); + } + } + } + DBG_ASSERT(nPos==nCount, "nanu, verzaehlt?"); + + return aSeq; + } + return uno::Sequence<rtl::OUString>(0); +} + +sal_Bool SAL_CALL ScChartsObj::hasByName( const rtl::OUString& aName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aNameString(aName); + return ( lcl_FindChartObj( pDocShell, nTab, aNameString ) != NULL ); +} + +//------------------------------------------------------------------------ + +ScChartObj::ScChartObj(ScDocShell* pDocSh, SCTAB nT, const String& rN) + :ScChartObj_Base( m_aMutex ) + ,ScChartObj_PBase( ScChartObj_Base::rBHelper ) + ,pDocShell( pDocSh ) + ,nTab( nT ) + ,aChartName( rN ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); + + uno::Sequence< table::CellRangeAddress > aInitialPropValue; + registerPropertyNoMember( ::rtl::OUString::createFromAscii( "RelatedCellRanges" ), + PROP_HANDLE_RELATED_CELLRANGES, beans::PropertyAttribute::MAYBEVOID, + ::getCppuType( &aInitialPropValue ), &aInitialPropValue ); +} + +ScChartObj::~ScChartObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScChartObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + //! Referenz-Update + + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +void ScChartObj::GetData_Impl( ScRangeListRef& rRanges, bool& rColHeaders, bool& rRowHeaders ) const +{ + bool bFound = false; + ScDocument* pDoc = (pDocShell? pDocShell->GetDocument(): 0); + + if( pDoc ) + { + uno::Reference< chart2::XChartDocument > xChartDoc( pDoc->GetChartByName( aChartName ) ); + if( xChartDoc.is() ) + { + uno::Reference< chart2::data::XDataReceiver > xReceiver( xChartDoc, uno::UNO_QUERY ); + uno::Reference< chart2::data::XDataProvider > xProvider = xChartDoc->getDataProvider(); + if( xReceiver.is() && xProvider.is() ) + { + uno::Sequence< beans::PropertyValue > aArgs( xProvider->detectArguments( xReceiver->getUsedData() ) ); + + rtl::OUString aRanges; + chart::ChartDataRowSource eDataRowSource = chart::ChartDataRowSource_COLUMNS; + bool bHasCategories=false; + bool bFirstCellAsLabel=false; + const beans::PropertyValue* pPropArray = aArgs.getConstArray(); + long nPropCount = aArgs.getLength(); + for (long i = 0; i < nPropCount; i++) + { + const beans::PropertyValue& rProp = pPropArray[i]; + String aPropName(rProp.Name); + + if (aPropName.EqualsAscii( "CellRangeRepresentation" )) + rProp.Value >>= aRanges; + else if (aPropName.EqualsAscii( "DataRowSource" )) + eDataRowSource = (chart::ChartDataRowSource)ScUnoHelpFunctions::GetEnumFromAny( rProp.Value ); + else if (aPropName.EqualsAscii( "HasCategories" )) + bHasCategories = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value ); + else if (aPropName.EqualsAscii( "FirstCellAsLabel" )) + bFirstCellAsLabel = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value ); + } + + if( chart::ChartDataRowSource_COLUMNS == eDataRowSource ) + { + rColHeaders=bFirstCellAsLabel; + rRowHeaders=bHasCategories; + } + else + { + rColHeaders=bHasCategories; + rRowHeaders=bFirstCellAsLabel; + } + rRanges->Parse( aRanges, pDoc); + } + bFound = true; + } + } + if( !bFound ) + { + rRanges = 0; + rColHeaders = false; + rRowHeaders = false; + } +} + +void ScChartObj::Update_Impl( const ScRangeListRef& rRanges, bool bColHeaders, bool bRowHeaders ) +{ + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + BOOL bUndo(pDoc->IsUndoEnabled()); + + if (bUndo) + { + pDocShell->GetUndoManager()->AddUndoAction( + new ScUndoChartData( pDocShell, aChartName, rRanges, bColHeaders, bRowHeaders, FALSE ) ); + } + pDoc->UpdateChartArea( aChartName, rRanges, bColHeaders, bRowHeaders, FALSE ); + } +} + +// ::comphelper::OPropertySetHelper + +::cppu::IPropertyArrayHelper& ScChartObj::getInfoHelper() +{ + return *ScChartObj_PABase::getArrayHelper(); +} + +void ScChartObj::setFastPropertyValue_NoBroadcast( sal_Int32 nHandle, const uno::Any& rValue ) throw (uno::Exception) +{ + switch ( nHandle ) + { + case PROP_HANDLE_RELATED_CELLRANGES: + { + uno::Sequence< table::CellRangeAddress > aCellRanges; + if ( rValue >>= aCellRanges ) + { + ScRangeListRef rRangeList = new ScRangeList(); + const table::CellRangeAddress* pCellRanges = aCellRanges.getArray(); + sal_Int32 nCount = aCellRanges.getLength(); + for ( sal_Int32 i = 0; i < nCount; ++i ) + { + table::CellRangeAddress aCellRange = pCellRanges[ i ]; + ScRange aRange; + ScUnoConversion::FillScRange( aRange, aCellRange ); + rRangeList->Append( aRange ); + } + ScDocument* pDoc = ( pDocShell ? pDocShell->GetDocument() : NULL ); + ScChartListenerCollection* pCollection = ( pDoc ? pDoc->GetChartListenerCollection() : NULL ); + if ( pCollection ) + { + pCollection->ChangeListening( aChartName, rRangeList ); + } + } + } + break; + default: + { + } + break; + } +} + +void ScChartObj::getFastPropertyValue( uno::Any& rValue, sal_Int32 nHandle ) const +{ + switch ( nHandle ) + { + case PROP_HANDLE_RELATED_CELLRANGES: + { + ScDocument* pDoc = ( pDocShell ? pDocShell->GetDocument() : NULL ); + if ( pDoc ) + { + ScRange aEmptyRange; + USHORT nIndex = 0; + ScChartListener aSearcher( aChartName, pDoc, aEmptyRange ); + ScChartListenerCollection* pCollection = pDoc->GetChartListenerCollection(); + if ( pCollection && pCollection->Search( &aSearcher, nIndex ) ) + { + ScChartListener* pListener = static_cast< ScChartListener* >( pCollection->At( nIndex ) ); + if ( pListener ) + { + const ScRangeListRef& rRangeList = pListener->GetRangeList(); + if ( rRangeList.Is() ) + { + ULONG nCount = rRangeList->Count(); + uno::Sequence< table::CellRangeAddress > aCellRanges( nCount ); + table::CellRangeAddress* pCellRanges = aCellRanges.getArray(); + for ( USHORT i = 0; i < nCount; ++i ) + { + ScRange aRange( *rRangeList->GetObject( i ) ); + table::CellRangeAddress aCellRange; + ScUnoConversion::FillApiRange( aCellRange, aRange ); + pCellRanges[ i ] = aCellRange; + } + rValue <<= aCellRanges; + } + } + } + } + } + break; + default: + { + } + break; + } +} + +// ::comphelper::OPropertyArrayUsageHelper + +::cppu::IPropertyArrayHelper* ScChartObj::createArrayHelper() const +{ + uno::Sequence< beans::Property > aProps; + describeProperties( aProps ); + return new ::cppu::OPropertyArrayHelper( aProps ); +} + +// XInterface + +IMPLEMENT_FORWARD_XINTERFACE2( ScChartObj, ScChartObj_Base, ScChartObj_PBase ) + +// XTypeProvider + +IMPLEMENT_FORWARD_XTYPEPROVIDER2( ScChartObj, ScChartObj_Base, ScChartObj_PBase ) + +// XComponent + +void ScChartObj::disposing() +{ + ScChartObj_Base::disposing(); +} + +// XTableChart + +sal_Bool SAL_CALL ScChartObj::getHasColumnHeaders() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScRangeListRef xRanges = new ScRangeList; + bool bColHeaders, bRowHeaders; + GetData_Impl( xRanges, bColHeaders, bRowHeaders ); + return bColHeaders; +} + +void SAL_CALL ScChartObj::setHasColumnHeaders( sal_Bool bHasColumnHeaders ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScRangeListRef xRanges = new ScRangeList; + bool bOldColHeaders, bOldRowHeaders; + GetData_Impl( xRanges, bOldColHeaders, bOldRowHeaders ); + if ( bOldColHeaders != (bHasColumnHeaders != sal_False) ) + Update_Impl( xRanges, bHasColumnHeaders, bOldRowHeaders ); +} + +sal_Bool SAL_CALL ScChartObj::getHasRowHeaders() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScRangeListRef xRanges = new ScRangeList; + bool bColHeaders, bRowHeaders; + GetData_Impl( xRanges, bColHeaders, bRowHeaders ); + return bRowHeaders; +} + +void SAL_CALL ScChartObj::setHasRowHeaders( sal_Bool bHasRowHeaders ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScRangeListRef xRanges = new ScRangeList; + bool bOldColHeaders, bOldRowHeaders; + GetData_Impl( xRanges, bOldColHeaders, bOldRowHeaders ); + if ( bOldRowHeaders != (bHasRowHeaders != sal_False) ) + Update_Impl( xRanges, bOldColHeaders, bHasRowHeaders ); +} + +uno::Sequence<table::CellRangeAddress> SAL_CALL ScChartObj::getRanges() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScRangeListRef xRanges = new ScRangeList; + bool bColHeaders, bRowHeaders; + GetData_Impl( xRanges, bColHeaders, bRowHeaders ); + if ( xRanges.Is() ) + { + ULONG nCount = xRanges->Count(); + + table::CellRangeAddress aRangeAddress; + uno::Sequence<table::CellRangeAddress> aSeq(nCount); + table::CellRangeAddress* pAry = aSeq.getArray(); + for (USHORT i=0; i<nCount; i++) + { + ScRange aRange(*xRanges->GetObject(i)); + + aRangeAddress.Sheet = aRange.aStart.Tab(); + aRangeAddress.StartColumn = aRange.aStart.Col(); + aRangeAddress.StartRow = aRange.aStart.Row(); + aRangeAddress.EndColumn = aRange.aEnd.Col(); + aRangeAddress.EndRow = aRange.aEnd.Row(); + + pAry[i] = aRangeAddress; + } + return aSeq; + } + + DBG_ERROR("ScChartObj::getRanges: keine Ranges"); + return uno::Sequence<table::CellRangeAddress>(); +} + +void SAL_CALL ScChartObj::setRanges( const uno::Sequence<table::CellRangeAddress>& aRanges ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScRangeListRef xOldRanges = new ScRangeList; + bool bColHeaders, bRowHeaders; + GetData_Impl( xOldRanges, bColHeaders, bRowHeaders ); + + ScRangeList* pList = new ScRangeList; + USHORT nRangeCount = (USHORT)aRanges.getLength(); + if (nRangeCount) + { + const table::CellRangeAddress* pAry = aRanges.getConstArray(); + for (USHORT i=0; i<nRangeCount; i++) + { + ScRange aRange( static_cast<SCCOL>(pAry[i].StartColumn), pAry[i].StartRow, pAry[i].Sheet, + static_cast<SCCOL>(pAry[i].EndColumn), pAry[i].EndRow, pAry[i].Sheet ); + pList->Append( aRange ); + } + } + ScRangeListRef xNewRanges( pList ); + + if ( !xOldRanges.Is() || *xOldRanges != *xNewRanges ) + Update_Impl( xNewRanges, bColHeaders, bRowHeaders ); +} + +// XEmbeddedObjectSupplier + +uno::Reference<lang::XComponent> SAL_CALL ScChartObj::getEmbeddedObject() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + SdrOle2Obj* pObject = lcl_FindChartObj( pDocShell, nTab, aChartName ); + if ( pObject && svt::EmbeddedObjectRef::TryRunningState( pObject->GetObjRef() ) ) + { + //TODO/LATER: is it OK that something is returned for *all* objects, not only own objects? + return uno::Reference < lang::XComponent > ( pObject->GetObjRef()->getComponent(), uno::UNO_QUERY ); + } + + return NULL; +} + +// XNamed + +rtl::OUString SAL_CALL ScChartObj::getName() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return aChartName; +} + +void SAL_CALL ScChartObj::setName( const rtl::OUString& /* aName */ ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + throw uno::RuntimeException(); // name cannot be changed +} + +// XPropertySet + +uno::Reference< beans::XPropertySetInfo > ScChartObj::getPropertySetInfo() throw (uno::RuntimeException) +{ + return createPropertySetInfo( getInfoHelper() ) ; +} + +//------------------------------------------------------------------------ + + + diff --git a/sc/source/ui/unoobj/confuno.cxx b/sc/source/ui/unoobj/confuno.cxx new file mode 100644 index 000000000000..a680185a1d1c --- /dev/null +++ b/sc/source/ui/unoobj/confuno.cxx @@ -0,0 +1,488 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include "confuno.hxx" +#include "unonames.hxx" +#include "unoguard.hxx" +#include "scdll.hxx" +#include "docsh.hxx" +#include "miscuno.hxx" +#include "forbiuno.hxx" +#include "viewopti.hxx" +#include "docpool.hxx" +#include "sc.hrc" + +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <sfx2/printer.hxx> +#include <xmloff/xmluconv.hxx> +#include <rtl/ustrbuf.hxx> + +using namespace com::sun::star; + +#define SCCOMPSCPREADSHEETSETTINGS_SERVICE "com.sun.star.comp.SpreadsheetSettings" +#define SCDOCUMENTSETTINGS_SERVICE "com.sun.star.document.Settings" +#define SCSAVEVERSION "SaveVersionOnClose" + + +const SfxItemPropertyMapEntry* lcl_GetConfigPropertyMap() +{ + static SfxItemPropertyMapEntry aConfigPropertyMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNO_SHOWZERO), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SHOWNOTES), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SHOWGRID), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_GRIDCOLOR), 0, &getCppuType((sal_Int32*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SHOWPAGEBR), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_LINKUPD), 0, &getCppuType((sal_Int16*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_COLROWHDR), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SHEETTABS), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_OUTLSYMB), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SNAPTORASTER), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_RASTERVIS), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_RASTERRESX), 0, &getCppuType((sal_Int32*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_RASTERRESY), 0, &getCppuType((sal_Int32*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_RASTERSUBX), 0, &getCppuType((sal_Int32*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_RASTERSUBY), 0, &getCppuType((sal_Int32*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_RASTERSYNC), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_AUTOCALC), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_PRINTERNAME), 0, &getCppuType((rtl::OUString*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_PRINTERSETUP), 0, &getCppuType((uno::Sequence<sal_Int8>*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_APPLYDOCINF), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_FORBIDDEN), 0, &getCppuType((uno::Reference<i18n::XForbiddenCharacters>*)0), beans::PropertyAttribute::READONLY, 0}, + {MAP_CHAR_LEN(SC_UNO_CHARCOMP), 0, &getCppuType((sal_Int16*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_ASIANKERN), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SCSAVEVERSION), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_UPDTEMPL), 0, &getBooleanCppuType(), 0, 0}, + /*Stampit enable/disable print cancel */ + {MAP_CHAR_LEN(SC_UNO_ALLOWPRINTJOBCANCEL), 0, &getBooleanCppuType(), 0, 0}, + // --> PB 2004-08-25 #i33095# Security Options + {MAP_CHAR_LEN(SC_UNO_LOADREADONLY), 0, &getBooleanCppuType(), 0, 0}, + // <-- + {MAP_CHAR_LEN(SC_UNO_SHAREDOC), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_MODIFYPASSWORDINFO), 0, &getCppuType((uno::Sequence< beans::PropertyValue >*)0), 0, 0}, + {0,0,0,0,0,0} + }; + return aConfigPropertyMap_Impl; +} + +//------------------------------------------------------------------------ + +ScDocumentConfiguration::ScDocumentConfiguration(ScDocShell* pDocSh) + : pDocShell(pDocSh) , + aPropSet ( lcl_GetConfigPropertyMap() ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScDocumentConfiguration::~ScDocumentConfiguration() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScDocumentConfiguration::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + // Referenz-Update interessiert hier nicht + + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +// XPropertySet + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDocumentConfiguration::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef( + new SfxItemPropertySetInfo( aPropSet.getPropertyMap() )); + return aRef; +} + +void SAL_CALL ScDocumentConfiguration::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if(pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + if (pDoc) + { + sal_Bool bUpdateHeights = sal_False; + + ScViewOptions aViewOpt(pDoc->GetViewOptions()); + + /*Stampit enable/disable print cancel */ + if ( aPropertyName.compareToAscii( SC_UNO_ALLOWPRINTJOBCANCEL ) == 0 ) + pDocShell->Stamp_SetPrintCancelState( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + /*Stampit enable/disable print cancel */ + + else if ( aPropertyName.compareToAscii( SC_UNO_SHOWZERO ) == 0 ) + aViewOpt.SetOption(VOPT_NULLVALS, ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aPropertyName.compareToAscii( SC_UNO_SHOWNOTES ) == 0 ) + aViewOpt.SetOption(VOPT_NOTES, ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aPropertyName.compareToAscii( SC_UNO_SHOWGRID ) == 0 ) + aViewOpt.SetOption(VOPT_GRID, ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aPropertyName.compareToAscii( SC_UNO_GRIDCOLOR ) == 0 ) + { + sal_Int64 nColor = 0; + if (aValue >>= nColor) + { + String aColorName; + Color aColor(static_cast<sal_uInt32>(nColor)); + aViewOpt.SetGridColor(aColor, aColorName); + } + } + else if ( aPropertyName.compareToAscii( SC_UNO_SHOWPAGEBR ) == 0 ) + aViewOpt.SetOption(VOPT_PAGEBREAKS, ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aPropertyName.compareToAscii( SC_UNONAME_LINKUPD ) == 0 ) + pDoc->SetLinkMode( static_cast<ScLkUpdMode> ( ScUnoHelpFunctions::GetInt16FromAny( aValue ) ) ); + else if ( aPropertyName.compareToAscii( SC_UNO_COLROWHDR ) == 0 ) + aViewOpt.SetOption(VOPT_HEADER, ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aPropertyName.compareToAscii( SC_UNO_SHEETTABS ) == 0 ) + aViewOpt.SetOption(VOPT_TABCONTROLS, ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aPropertyName.compareToAscii( SC_UNO_OUTLSYMB ) == 0 ) + aViewOpt.SetOption(VOPT_OUTLINER, ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aPropertyName.compareToAscii( SC_UNO_AUTOCALC ) == 0 ) + pDoc->SetAutoCalc( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aPropertyName.compareToAscii( SC_UNO_PRINTERNAME ) == 0 ) + { + rtl::OUString sPrinterName; + if ( aValue >>= sPrinterName ) + { + // #i75610# if the name is empty, do nothing (don't create any printer) + if ( sPrinterName.getLength() != 0 && pDocShell->GetCreateMode() != SFX_CREATE_MODE_EMBEDDED ) + { + SfxPrinter* pPrinter = pDocShell->GetPrinter(); + if (pPrinter) + { + String aString(sPrinterName); + if (pPrinter->GetName() != aString) + { + SfxPrinter* pNewPrinter = new SfxPrinter( pPrinter->GetOptions().Clone(), aString ); + if (pNewPrinter->IsKnown()) + pDocShell->SetPrinter( pNewPrinter, SFX_PRINTER_PRINTER ); + else + delete pNewPrinter; + } + } + else + throw uno::RuntimeException(); + } + } + else + throw lang::IllegalArgumentException(); + } + else if ( aPropertyName.compareToAscii( SC_UNO_PRINTERSETUP ) == 0 ) + { + uno::Sequence<sal_Int8> aSequence; + if ( aValue >>= aSequence ) + { + sal_uInt32 nSize = aSequence.getLength(); + // #i75610# if the sequence is empty, do nothing (don't create any printer) + if ( nSize != 0 ) + { + SvMemoryStream aStream (aSequence.getArray(), nSize, STREAM_READ ); + aStream.Seek ( STREAM_SEEK_TO_BEGIN ); + SfxItemSet* pSet = new SfxItemSet( *pDoc->GetPool(), + SID_PRINTER_NOTFOUND_WARN, SID_PRINTER_NOTFOUND_WARN, + SID_PRINTER_CHANGESTODOC, SID_PRINTER_CHANGESTODOC, + SID_PRINT_SELECTEDSHEET, SID_PRINT_SELECTEDSHEET, + SID_SCPRINTOPTIONS, SID_SCPRINTOPTIONS, + NULL ); + pDocShell->SetPrinter( SfxPrinter::Create( aStream, pSet ) ); + } + } + } + else if ( aPropertyName.compareToAscii( SC_UNO_APPLYDOCINF ) == 0 ) + { + sal_Bool bTmp=sal_True; + if ( aValue >>= bTmp ) + pDocShell->SetUseUserData( bTmp ); + } + else if ( aPropertyName.compareToAscii( SC_UNO_FORBIDDEN ) == 0 ) + { + // read-only - should not be set + } + else if ( aPropertyName.compareToAscii( SC_UNO_CHARCOMP ) == 0 ) + { + // Int16 contains CharacterCompressionType values + sal_Int16 nUno = ScUnoHelpFunctions::GetInt16FromAny( aValue ); + pDoc->SetAsianCompression( (BYTE) nUno ); + bUpdateHeights = sal_True; + } + else if ( aPropertyName.compareToAscii( SC_UNO_ASIANKERN ) == 0 ) + { + pDoc->SetAsianKerning( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + bUpdateHeights = sal_True; + } + else if ( aPropertyName.compareToAscii( SCSAVEVERSION ) == 0) + { + sal_Bool bTmp=sal_False; + if ( aValue >>= bTmp ) + pDocShell->SetSaveVersionOnClose( bTmp ); + } + else if ( aPropertyName.compareToAscii( SC_UNO_UPDTEMPL ) == 0 ) + { + sal_Bool bTmp=sal_True; + if ( aValue >>= bTmp ) + pDocShell->SetQueryLoadTemplate( bTmp ); + } + else if ( aPropertyName.compareToAscii( SC_UNO_LOADREADONLY ) == 0 ) + { + sal_Bool bTmp=sal_False; + if ( aValue >>= bTmp ) + pDocShell->SetLoadReadonly( bTmp ); + } + else if ( aPropertyName.compareToAscii( SC_UNO_SHAREDOC ) == 0 ) + { + sal_Bool bDocShared = sal_False; + if ( aValue >>= bDocShared ) + { + pDocShell->SetSharedXMLFlag( bDocShared ); + } + } + else if ( aPropertyName.compareToAscii( SC_UNO_MODIFYPASSWORDINFO ) == 0 ) + { + uno::Sequence< beans::PropertyValue > aInfo; + if ( !( aValue >>= aInfo ) ) + throw lang::IllegalArgumentException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Value of type Sequence<PropertyValue> expected!" ) ), + uno::Reference< uno::XInterface >(), + 2 ); + + if ( !pDocShell->SetModifyPasswordInfo( aInfo ) ) + throw beans::PropertyVetoException( + ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "The hash is not allowed to be changed now!" ) ), + uno::Reference< uno::XInterface >() ); + } + else + { + ScGridOptions aGridOpt(aViewOpt.GetGridOptions()); + if ( aPropertyName.compareToAscii( SC_UNO_SNAPTORASTER ) == 0 ) + aGridOpt.SetUseGridSnap( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aPropertyName.compareToAscii( SC_UNO_RASTERVIS ) == 0 ) + aGridOpt.SetGridVisible( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aPropertyName.compareToAscii( SC_UNO_RASTERRESX ) == 0 ) + aGridOpt.SetFldDrawX( static_cast <sal_uInt32> ( ScUnoHelpFunctions::GetInt32FromAny( aValue ) ) ); + else if ( aPropertyName.compareToAscii( SC_UNO_RASTERRESY ) == 0 ) + aGridOpt.SetFldDrawY( static_cast <sal_uInt32> ( ScUnoHelpFunctions::GetInt32FromAny( aValue ) ) ); + else if ( aPropertyName.compareToAscii( SC_UNO_RASTERSUBX ) == 0 ) + aGridOpt.SetFldDivisionX( static_cast <sal_uInt32> ( ScUnoHelpFunctions::GetInt32FromAny( aValue ) ) ); + else if ( aPropertyName.compareToAscii( SC_UNO_RASTERSUBY ) == 0 ) + aGridOpt.SetFldDivisionY( static_cast <sal_uInt32> ( ScUnoHelpFunctions::GetInt32FromAny( aValue ) ) ); + else if ( aPropertyName.compareToAscii( SC_UNO_RASTERSYNC ) == 0 ) + aGridOpt.SetSynchronize( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else + throw beans::UnknownPropertyException(); + aViewOpt.SetGridOptions(aGridOpt); + } + pDoc->SetViewOptions(aViewOpt); + + if ( bUpdateHeights && !pDoc->IsImportingXML() ) + { + // update automatic row heights and repaint + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab=0; nTab<nTabCount; nTab++) + if ( !pDocShell->AdjustRowHeight( 0, MAXROW, nTab ) ) + pDocShell->PostPaint( 0,0,nTab, MAXCOL,MAXROW,nTab, PAINT_GRID ); + pDocShell->SetDocumentModified(); + } + } + else + throw uno::RuntimeException(); + } + else + throw uno::RuntimeException(); +} + +uno::Any SAL_CALL ScDocumentConfiguration::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Any aRet; + + if(pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + if (pDoc) + { + const ScViewOptions& aViewOpt = pDoc->GetViewOptions(); + + /*Stampit enable/disable print cancel */ + if ( aPropertyName.compareToAscii( SC_UNO_ALLOWPRINTJOBCANCEL ) == 0 ) + ScUnoHelpFunctions::SetBoolInAny( aRet, pDocShell->Stamp_GetPrintCancelState() ); + /*Stampit enable/disable print cancel */ + + else if ( aPropertyName.compareToAscii( SC_UNO_SHOWZERO ) == 0 ) + ScUnoHelpFunctions::SetBoolInAny( aRet, aViewOpt.GetOption( VOPT_NULLVALS ) ); + else if ( aPropertyName.compareToAscii( SC_UNO_SHOWNOTES ) == 0 ) + ScUnoHelpFunctions::SetBoolInAny( aRet, aViewOpt.GetOption( VOPT_NOTES ) ); + else if ( aPropertyName.compareToAscii( SC_UNO_SHOWGRID ) == 0 ) + ScUnoHelpFunctions::SetBoolInAny( aRet, aViewOpt.GetOption( VOPT_GRID ) ); + else if ( aPropertyName.compareToAscii( SC_UNO_GRIDCOLOR ) == 0 ) + { + String aColorName; + Color aColor = aViewOpt.GetGridColor(&aColorName); + aRet <<= static_cast<sal_Int64>(aColor.GetColor()); + } + else if ( aPropertyName.compareToAscii( SC_UNO_SHOWPAGEBR ) == 0 ) + ScUnoHelpFunctions::SetBoolInAny( aRet, aViewOpt.GetOption( VOPT_PAGEBREAKS ) ); + else if ( aPropertyName.compareToAscii( SC_UNONAME_LINKUPD ) == 0 ) + aRet <<= static_cast<sal_Int16> ( pDoc->GetLinkMode() ); + else if ( aPropertyName.compareToAscii( SC_UNO_COLROWHDR ) == 0 ) + ScUnoHelpFunctions::SetBoolInAny( aRet, aViewOpt.GetOption( VOPT_HEADER ) ); + else if ( aPropertyName.compareToAscii( SC_UNO_SHEETTABS ) == 0 ) + ScUnoHelpFunctions::SetBoolInAny( aRet, aViewOpt.GetOption( VOPT_TABCONTROLS ) ); + else if ( aPropertyName.compareToAscii( SC_UNO_OUTLSYMB ) == 0 ) + ScUnoHelpFunctions::SetBoolInAny( aRet, aViewOpt.GetOption( VOPT_OUTLINER ) ); + else if ( aPropertyName.compareToAscii( SC_UNO_AUTOCALC ) == 0 ) + ScUnoHelpFunctions::SetBoolInAny( aRet, pDoc->GetAutoCalc() ); + else if ( aPropertyName.compareToAscii( SC_UNO_PRINTERNAME ) == 0 ) + { + // #i75610# don't create the printer, return empty string if no printer created yet + // (as in SwXDocumentSettings) + SfxPrinter* pPrinter = pDoc->GetPrinter( FALSE ); + if (pPrinter) + aRet <<= rtl::OUString ( pPrinter->GetName()); + else + aRet <<= rtl::OUString(); + } + else if ( aPropertyName.compareToAscii( SC_UNO_PRINTERSETUP ) == 0 ) + { + // #i75610# don't create the printer, return empty sequence if no printer created yet + // (as in SwXDocumentSettings) + SfxPrinter* pPrinter = pDoc->GetPrinter( FALSE ); + if (pPrinter) + { + SvMemoryStream aStream; + pPrinter->Store( aStream ); + aStream.Seek ( STREAM_SEEK_TO_END ); + sal_uInt32 nSize = aStream.Tell(); + aStream.Seek ( STREAM_SEEK_TO_BEGIN ); + uno::Sequence < sal_Int8 > aSequence( nSize ); + aStream.Read ( aSequence.getArray(), nSize ); + aRet <<= aSequence; + } + else + aRet <<= uno::Sequence<sal_Int8>(); + } + else if ( aPropertyName.compareToAscii( SC_UNO_APPLYDOCINF ) == 0 ) + aRet <<= pDocShell->IsUseUserData(); + else if ( aPropertyName.compareToAscii( SC_UNO_FORBIDDEN ) == 0 ) + { + aRet <<= uno::Reference<i18n::XForbiddenCharacters>(new ScForbiddenCharsObj( pDocShell )); + } + else if ( aPropertyName.compareToAscii( SC_UNO_CHARCOMP ) == 0 ) + aRet <<= static_cast<sal_Int16> ( pDoc->GetAsianCompression() ); + else if ( aPropertyName.compareToAscii( SC_UNO_ASIANKERN ) == 0 ) + ScUnoHelpFunctions::SetBoolInAny( aRet, pDoc->GetAsianKerning() ); + else if ( aPropertyName.compareToAscii( SCSAVEVERSION ) == 0) + aRet <<= pDocShell->IsSaveVersionOnClose(); + else if ( aPropertyName.compareToAscii( SC_UNO_UPDTEMPL ) == 0 ) + aRet <<= pDocShell->IsQueryLoadTemplate(); + else if ( aPropertyName.compareToAscii( SC_UNO_LOADREADONLY ) == 0 ) + aRet <<= pDocShell->IsLoadReadonly(); + // <-- + else if ( aPropertyName.compareToAscii( SC_UNO_SHAREDOC ) == 0 ) + { + ScUnoHelpFunctions::SetBoolInAny( aRet, pDocShell->HasSharedXMLFlagSet() ); + } + else if ( aPropertyName.compareToAscii( SC_UNO_MODIFYPASSWORDINFO ) == 0 ) + aRet <<= pDocShell->GetModifyPasswordInfo(); + else + { + const ScGridOptions& aGridOpt = aViewOpt.GetGridOptions(); + if ( aPropertyName.compareToAscii( SC_UNO_SNAPTORASTER ) == 0 ) + ScUnoHelpFunctions::SetBoolInAny( aRet, aGridOpt.GetUseGridSnap() ); + else if ( aPropertyName.compareToAscii( SC_UNO_RASTERVIS ) == 0 ) + ScUnoHelpFunctions::SetBoolInAny( aRet, aGridOpt.GetGridVisible() ); + else if ( aPropertyName.compareToAscii( SC_UNO_RASTERRESX ) == 0 ) + aRet <<= static_cast<sal_Int32> ( aGridOpt.GetFldDrawX() ); + else if ( aPropertyName.compareToAscii( SC_UNO_RASTERRESY ) == 0 ) + aRet <<= static_cast<sal_Int32> ( aGridOpt.GetFldDrawY() ); + else if ( aPropertyName.compareToAscii( SC_UNO_RASTERSUBX ) == 0 ) + aRet <<= static_cast<sal_Int32> ( aGridOpt.GetFldDivisionX() ); + else if ( aPropertyName.compareToAscii( SC_UNO_RASTERSUBY ) == 0 ) + aRet <<= static_cast<sal_Int32> ( aGridOpt.GetFldDivisionY() ); + else if ( aPropertyName.compareToAscii( SC_UNO_RASTERSYNC ) == 0 ) + ScUnoHelpFunctions::SetBoolInAny( aRet, aGridOpt.GetSynchronize() ); + else + throw beans::UnknownPropertyException(); + } + } + else + throw uno::RuntimeException(); + } + else + throw uno::RuntimeException(); + + return aRet; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDocumentConfiguration ) + +// XServiceInfo + +rtl::OUString SAL_CALL ScDocumentConfiguration::getImplementationName() throw(uno::RuntimeException) +{ + return rtl::OUString::createFromAscii( "ScDocumentConfiguration" ); +} + +sal_Bool SAL_CALL ScDocumentConfiguration::supportsService( const rtl::OUString& rServiceName ) + throw(uno::RuntimeException) +{ + String aServiceStr( rServiceName ); + return aServiceStr.EqualsAscii( SCCOMPSCPREADSHEETSETTINGS_SERVICE ) || + aServiceStr.EqualsAscii( SCDOCUMENTSETTINGS_SERVICE ); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScDocumentConfiguration::getSupportedServiceNames() + throw(uno::RuntimeException) +{ + uno::Sequence<rtl::OUString> aRet(2); + rtl::OUString* pArray = aRet.getArray(); + pArray[0] = rtl::OUString::createFromAscii( SCCOMPSCPREADSHEETSETTINGS_SERVICE ); + pArray[1] = rtl::OUString::createFromAscii( SCDOCUMENTSETTINGS_SERVICE ); + return aRet; +} + +//------------------------------------------------------------------------- + diff --git a/sc/source/ui/unoobj/convuno.cxx b/sc/source/ui/unoobj/convuno.cxx new file mode 100644 index 000000000000..e3b0c09b25c2 --- /dev/null +++ b/sc/source/ui/unoobj/convuno.cxx @@ -0,0 +1,64 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include <tools/debug.hxx> +#include <i18npool/mslangid.hxx> + +#include "convuno.hxx" +#include "global.hxx" + +using namespace com::sun::star; + +//------------------------------------------------------------------------ + +// everything is static... + +LanguageType ScUnoConversion::GetLanguage( const lang::Locale& rLocale ) +{ + // empty language -> LANGUAGE_SYSTEM + if ( rLocale.Language.getLength() == 0 ) + return LANGUAGE_SYSTEM; + + LanguageType eRet = MsLangId::convertLocaleToLanguage( rLocale ); + if ( eRet == LANGUAGE_NONE ) + eRet = LANGUAGE_SYSTEM; //! or throw an exception? + + return eRet; +} + +void ScUnoConversion::FillLocale( lang::Locale& rLocale, LanguageType eLang ) +{ + MsLangId::convertLanguageToLocale( eLang, rLocale ); +} + + + diff --git a/sc/source/ui/unoobj/cursuno.cxx b/sc/source/ui/unoobj/cursuno.cxx new file mode 100644 index 000000000000..daf075964a3a --- /dev/null +++ b/sc/source/ui/unoobj/cursuno.cxx @@ -0,0 +1,510 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include "scitems.hxx" +#include <svl/intitem.hxx> +#include <svl/zforlist.hxx> +#include <rtl/uuid.h> + +#include "cursuno.hxx" +#include "cellsuno.hxx" +#include "docsh.hxx" +#include "hints.hxx" +#include "markdata.hxx" +#include "dociter.hxx" +#include "unoguard.hxx" +#include "miscuno.hxx" + +using namespace com::sun::star; + +//------------------------------------------------------------------------ + +#define SCSHEETCELLCURSOR_SERVICE "com.sun.star.sheet.SheetCellCursor" +#define SCCELLCURSOR_SERVICE "com.sun.star.table.CellCursor" + +//------------------------------------------------------------------------ + +ScCellCursorObj::ScCellCursorObj(ScDocShell* pDocSh, const ScRange& rR) : + ScCellRangeObj( pDocSh, rR ) +{ +} + +ScCellCursorObj::~ScCellCursorObj() +{ +} + +uno::Any SAL_CALL ScCellCursorObj::queryInterface( const uno::Type& rType ) throw(uno::RuntimeException) +{ + SC_QUERYINTERFACE( sheet::XSheetCellCursor ) + SC_QUERYINTERFACE( sheet::XUsedAreaCursor ) + SC_QUERYINTERFACE( table::XCellCursor ) + + return ScCellRangeObj::queryInterface( rType ); +} + +void SAL_CALL ScCellCursorObj::acquire() throw() +{ + ScCellRangeObj::acquire(); +} + +void SAL_CALL ScCellCursorObj::release() throw() +{ + ScCellRangeObj::release(); +} + +uno::Sequence<uno::Type> SAL_CALL ScCellCursorObj::getTypes() throw(uno::RuntimeException) +{ + static uno::Sequence<uno::Type> aTypes; + if ( aTypes.getLength() == 0 ) + { + uno::Sequence<uno::Type> aParentTypes(ScCellRangeObj::getTypes()); + long nParentLen = aParentTypes.getLength(); + const uno::Type* pParentPtr = aParentTypes.getConstArray(); + + aTypes.realloc( nParentLen + 3 ); + uno::Type* pPtr = aTypes.getArray(); + pPtr[nParentLen + 0] = getCppuType((const uno::Reference<sheet::XSheetCellCursor>*)0); + pPtr[nParentLen + 1] = getCppuType((const uno::Reference<sheet::XUsedAreaCursor>*)0); + pPtr[nParentLen + 2] = getCppuType((const uno::Reference<table::XCellCursor>*)0); + + for (long i=0; i<nParentLen; i++) + pPtr[i] = pParentPtr[i]; // parent types first + } + return aTypes; +} + +uno::Sequence<sal_Int8> SAL_CALL ScCellCursorObj::getImplementationId() throw(uno::RuntimeException) +{ + static uno::Sequence< sal_Int8 > aId; + if( aId.getLength() == 0 ) + { + aId.realloc( 16 ); + rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True ); + } + return aId; +} + +// XSheetCellCursor + +void SAL_CALL ScCellCursorObj::collapseToCurrentRegion() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + const ScRangeList& rRanges = GetRangeList(); + DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); + ScRange aOneRange(*rRanges.GetObject(0)); + + aOneRange.Justify(); + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + SCCOL nStartCol = aOneRange.aStart.Col(); + SCROW nStartRow = aOneRange.aStart.Row(); + SCCOL nEndCol = aOneRange.aEnd.Col(); + SCROW nEndRow = aOneRange.aEnd.Row(); + SCTAB nTab = aOneRange.aStart.Tab(); + + pDocSh->GetDocument()->GetDataArea( + nTab, nStartCol, nStartRow, nEndCol, nEndRow, TRUE, false ); + + ScRange aNew( nStartCol, nStartRow, nTab, nEndCol, nEndRow, nTab ); + SetNewRange( aNew ); + } +} + +void SAL_CALL ScCellCursorObj::collapseToCurrentArray() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + const ScRangeList& rRanges = GetRangeList(); + DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); + ScRange aOneRange(*rRanges.GetObject(0)); + + aOneRange.Justify(); + ScAddress aCursor(aOneRange.aStart); // use the start address of the range + + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + ScRange aMatrix; + + // finding the matrix range is now in GetMatrixFormulaRange in the document + if ( pDoc->GetMatrixFormulaRange( aCursor, aMatrix ) ) + { + SetNewRange( aMatrix ); + } + } + // thats a Bug, that this assertion comes; the API Reference says, that + // if there is no Matrix, the Range is left unchanged; they says nothing + // about a exception + /*if (!bFound) + { + DBG_ERROR("keine Matrix"); + //! Exception, oder was? + }*/ +} + +void SAL_CALL ScCellCursorObj::collapseToMergedArea() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + const ScRangeList& rRanges = GetRangeList(); + DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); + ScRange aNewRange(*rRanges.GetObject(0)); + + ScDocument* pDoc = pDocSh->GetDocument(); + pDoc->ExtendOverlapped( aNewRange ); + pDoc->ExtendMerge( aNewRange ); // after ExtendOverlapped! + + SetNewRange( aNewRange ); + } +} + +void SAL_CALL ScCellCursorObj::expandToEntireColumns() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + const ScRangeList& rRanges = GetRangeList(); + DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); + ScRange aNewRange(*rRanges.GetObject(0)); + + aNewRange.aStart.SetRow( 0 ); + aNewRange.aEnd.SetRow( MAXROW ); + + SetNewRange( aNewRange ); +} + +void SAL_CALL ScCellCursorObj::expandToEntireRows() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + const ScRangeList& rRanges = GetRangeList(); + DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); + ScRange aNewRange(*rRanges.GetObject(0)); + + aNewRange.aStart.SetCol( 0 ); + aNewRange.aEnd.SetCol( MAXCOL ); + + SetNewRange( aNewRange ); +} + +void SAL_CALL ScCellCursorObj::collapseToSize( sal_Int32 nColumns, sal_Int32 nRows ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( nColumns <= 0 || nRows <= 0 ) + { + DBG_ERROR("leerer Range geht nicht"); + //! und dann? + } + else + { + const ScRangeList& rRanges = GetRangeList(); + DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); + ScRange aNewRange(*rRanges.GetObject(0)); + + aNewRange.Justify(); //! wirklich? + + long nEndX = aNewRange.aStart.Col() + nColumns - 1; + long nEndY = aNewRange.aStart.Row() + nRows - 1; + if ( nEndX < 0 ) nEndX = 0; + if ( nEndX > MAXCOL ) nEndX = MAXCOL; + if ( nEndY < 0 ) nEndY = 0; + if ( nEndY > MAXROW ) nEndY = MAXROW; + //! Fehler/Exception oder so, wenn zu gross/zu klein? + + aNewRange.aEnd.SetCol((SCCOL)nEndX); + aNewRange.aEnd.SetRow((SCROW)nEndY); + + aNewRange.Justify(); //! wirklich? + + SetNewRange( aNewRange ); + } +} + +// XUsedAreaCursor + +void SAL_CALL ScCellCursorObj::gotoStartOfUsedArea( sal_Bool bExpand ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + const ScRangeList& rRanges = GetRangeList(); + DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); + ScRange aNewRange(*rRanges.GetObject(0)); + SCTAB nTab = aNewRange.aStart.Tab(); + + SCCOL nUsedX = 0; // Anfang holen + SCROW nUsedY = 0; + if (!pDocSh->GetDocument()->GetDataStart( nTab, nUsedX, nUsedY )) + { + nUsedX = 0; + nUsedY = 0; + } + + aNewRange.aStart.SetCol( nUsedX ); + aNewRange.aStart.SetRow( nUsedY ); + if (!bExpand) + aNewRange.aEnd = aNewRange.aStart; + SetNewRange( aNewRange ); + } +} + +void SAL_CALL ScCellCursorObj::gotoEndOfUsedArea( sal_Bool bExpand ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + const ScRangeList& rRanges = GetRangeList(); + DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); + ScRange aNewRange(*rRanges.GetObject(0)); + SCTAB nTab = aNewRange.aStart.Tab(); + + SCCOL nUsedX = 0; // Ende holen + SCROW nUsedY = 0; + if (!pDocSh->GetDocument()->GetTableArea( nTab, nUsedX, nUsedY )) + { + nUsedX = 0; + nUsedY = 0; + } + + aNewRange.aEnd.SetCol( nUsedX ); + aNewRange.aEnd.SetRow( nUsedY ); + if (!bExpand) + aNewRange.aStart = aNewRange.aEnd; + SetNewRange( aNewRange ); + } +} + +// XCellCursor + +void SAL_CALL ScCellCursorObj::gotoStart() throw(uno::RuntimeException) +{ + // this is similar to collapseToCurrentRegion + //! something like gotoEdge with 4 possible directions is needed + + ScUnoGuard aGuard; + const ScRangeList& rRanges = GetRangeList(); + DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); + ScRange aOneRange(*rRanges.GetObject(0)); + + aOneRange.Justify(); + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + SCCOL nStartCol = aOneRange.aStart.Col(); + SCROW nStartRow = aOneRange.aStart.Row(); + SCCOL nEndCol = aOneRange.aEnd.Col(); + SCROW nEndRow = aOneRange.aEnd.Row(); + SCTAB nTab = aOneRange.aStart.Tab(); + + pDocSh->GetDocument()->GetDataArea( + nTab, nStartCol, nStartRow, nEndCol, nEndRow, FALSE, false ); + + ScRange aNew( nStartCol, nStartRow, nTab ); + SetNewRange( aNew ); + } +} + +void SAL_CALL ScCellCursorObj::gotoEnd() throw(uno::RuntimeException) +{ + // this is similar to collapseToCurrentRegion + //! something like gotoEdge with 4 possible directions is needed + + ScUnoGuard aGuard; + const ScRangeList& rRanges = GetRangeList(); + DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); + ScRange aOneRange(*rRanges.GetObject(0)); + + aOneRange.Justify(); + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + { + SCCOL nStartCol = aOneRange.aStart.Col(); + SCROW nStartRow = aOneRange.aStart.Row(); + SCCOL nEndCol = aOneRange.aEnd.Col(); + SCROW nEndRow = aOneRange.aEnd.Row(); + SCTAB nTab = aOneRange.aStart.Tab(); + + pDocSh->GetDocument()->GetDataArea( + nTab, nStartCol, nStartRow, nEndCol, nEndRow, FALSE, false ); + + ScRange aNew( nEndCol, nEndRow, nTab ); + SetNewRange( aNew ); + } +} + +void SAL_CALL ScCellCursorObj::gotoNext() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + const ScRangeList& rRanges = GetRangeList(); + DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); + ScRange aOneRange(*rRanges.GetObject(0)); + + aOneRange.Justify(); + ScAddress aCursor(aOneRange.aStart); // bei Block immer den Start nehmen + + ScMarkData aMark; // not used with bMarked=FALSE + SCCOL nNewX = aCursor.Col(); + SCROW nNewY = aCursor.Row(); + SCTAB nTab = aCursor.Tab(); + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + pDocSh->GetDocument()->GetNextPos( nNewX,nNewY, nTab, 1,0, FALSE,TRUE, aMark ); + //! sonst Exception oder so + + SetNewRange( ScRange( nNewX, nNewY, nTab ) ); +} + +void SAL_CALL ScCellCursorObj::gotoPrevious() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + const ScRangeList& rRanges = GetRangeList(); + DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); + ScRange aOneRange(*rRanges.GetObject(0)); + + aOneRange.Justify(); + ScAddress aCursor(aOneRange.aStart); // bei Block immer den Start nehmen + + ScMarkData aMark; // not used with bMarked=FALSE + SCCOL nNewX = aCursor.Col(); + SCROW nNewY = aCursor.Row(); + SCTAB nTab = aCursor.Tab(); + ScDocShell* pDocSh = GetDocShell(); + if ( pDocSh ) + pDocSh->GetDocument()->GetNextPos( nNewX,nNewY, nTab, -1,0, FALSE,TRUE, aMark ); + //! sonst Exception oder so + + SetNewRange( ScRange( nNewX, nNewY, nTab ) ); +} + +void SAL_CALL ScCellCursorObj::gotoOffset( sal_Int32 nColumnOffset, sal_Int32 nRowOffset ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + const ScRangeList& rRanges = GetRangeList(); + DBG_ASSERT( rRanges.Count() == 1, "Range? Ranges?" ); + ScRange aOneRange(*rRanges.GetObject(0)); + aOneRange.Justify(); + + if ( aOneRange.aStart.Col() + nColumnOffset >= 0 && + aOneRange.aEnd.Col() + nColumnOffset <= MAXCOL && + aOneRange.aStart.Row() + nRowOffset >= 0 && + aOneRange.aEnd.Row() + nRowOffset <= MAXROW ) + { + ScRange aNew( (SCCOL)(aOneRange.aStart.Col() + nColumnOffset), + (SCROW)(aOneRange.aStart.Row() + nRowOffset), + aOneRange.aStart.Tab(), + (SCCOL)(aOneRange.aEnd.Col() + nColumnOffset), + (SCROW)(aOneRange.aEnd.Row() + nRowOffset), + aOneRange.aEnd.Tab() ); + SetNewRange( aNew ); + } +} + +// XSheetCellRange + +uno::Reference<sheet::XSpreadsheet> SAL_CALL ScCellCursorObj::getSpreadsheet() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ScCellRangeObj::getSpreadsheet(); +} + +// XCellRange + +uno::Reference<table::XCell> SAL_CALL ScCellCursorObj::getCellByPosition( + sal_Int32 nColumn, sal_Int32 nRow ) + throw(lang::IndexOutOfBoundsException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ScCellRangeObj::getCellByPosition(nColumn,nRow); +} + +uno::Reference<table::XCellRange> SAL_CALL ScCellCursorObj::getCellRangeByPosition( + sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom ) + throw(lang::IndexOutOfBoundsException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ScCellRangeObj::getCellRangeByPosition(nLeft,nTop,nRight,nBottom); +} + +uno::Reference<table::XCellRange> SAL_CALL ScCellCursorObj::getCellRangeByName( + const rtl::OUString& rRange ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ScCellRangeObj::getCellRangeByName(rRange); +} + +// XServiceInfo + +rtl::OUString SAL_CALL ScCellCursorObj::getImplementationName() throw(uno::RuntimeException) +{ + return rtl::OUString::createFromAscii( "ScCellCursorObj" ); +} + +sal_Bool SAL_CALL ScCellCursorObj::supportsService( const rtl::OUString& rServiceName ) + throw(uno::RuntimeException) +{ + String aServiceStr( rServiceName ); + return aServiceStr.EqualsAscii( SCSHEETCELLCURSOR_SERVICE ) || + aServiceStr.EqualsAscii( SCCELLCURSOR_SERVICE ) || + ScCellRangeObj::supportsService(rServiceName); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScCellCursorObj::getSupportedServiceNames() + throw(uno::RuntimeException) +{ + // get all service names from cell range + uno::Sequence<rtl::OUString> aParentSeq(ScCellRangeObj::getSupportedServiceNames()); + sal_Int32 nParentLen = aParentSeq.getLength(); + const rtl::OUString* pParentArr = aParentSeq.getConstArray(); + + // SheetCellCursor should be first (?) + uno::Sequence<rtl::OUString> aTotalSeq( nParentLen + 2 ); + rtl::OUString* pTotalArr = aTotalSeq.getArray(); + pTotalArr[0] = rtl::OUString::createFromAscii( SCSHEETCELLCURSOR_SERVICE ); + pTotalArr[1] = rtl::OUString::createFromAscii( SCCELLCURSOR_SERVICE ); + + // append cell range services + for (long i=0; i<nParentLen; i++) + pTotalArr[i+2] = pParentArr[i]; + + return aTotalSeq; +} + + + + diff --git a/sc/source/ui/unoobj/dapiuno.cxx b/sc/source/ui/unoobj/dapiuno.cxx new file mode 100755 index 000000000000..c7bf89671161 --- /dev/null +++ b/sc/source/ui/unoobj/dapiuno.cxx @@ -0,0 +1,3554 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +#include <algorithm> +#include <svl/smplhint.hxx> +#include <rtl/uuid.h> + +#include "dapiuno.hxx" +#include "datauno.hxx" +#include "miscuno.hxx" +#include "convuno.hxx" +#include "docsh.hxx" +#include "tabvwsh.hxx" +#include "pivot.hxx" +#include "rangeutl.hxx" +#include "unoguard.hxx" +#include "dpobject.hxx" +#include "dpshttab.hxx" +#include "dpsdbtab.hxx" +#include "dpsave.hxx" +#include "dbdocfun.hxx" +#include "unonames.hxx" +#include "dpgroup.hxx" +#include "dpdimsave.hxx" +#include "hints.hxx" + +#include <com/sun/star/sheet/XHierarchiesSupplier.hpp> +#include <com/sun/star/sheet/XLevelsSupplier.hpp> +#include <com/sun/star/sheet/XMembersSupplier.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/sheet/DataImportMode.hpp> +#include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp> +#include <com/sun/star/sheet/DataPilotFieldFilter.hpp> +#include <com/sun/star/sheet/DataPilotOutputRangeType.hpp> +#include <com/sun/star/sheet/DataPilotTablePositionData.hpp> + +#include <comphelper/extract.hxx> +#include <comphelper/sequence.hxx> + +using namespace com::sun::star; +using namespace com::sun::star::sheet; + +using ::rtl::OUString; + +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::RuntimeException; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; + +using ::com::sun::star::container::ElementExistException; +using ::com::sun::star::container::NoSuchElementException; +using ::com::sun::star::container::XEnumeration; +using ::com::sun::star::container::XIndexAccess; +using ::com::sun::star::container::XNameAccess; +using ::com::sun::star::container::XNamed; + +using ::com::sun::star::beans::PropertyVetoException; +using ::com::sun::star::beans::UnknownPropertyException; +using ::com::sun::star::beans::XPropertyChangeListener; +using ::com::sun::star::beans::XPropertySet; +using ::com::sun::star::beans::XPropertySetInfo; +using ::com::sun::star::beans::XVetoableChangeListener; + +using ::com::sun::star::lang::IllegalArgumentException; +using ::com::sun::star::lang::IndexOutOfBoundsException; +using ::com::sun::star::lang::WrappedTargetException; + +using ::com::sun::star::table::CellAddress; +using ::com::sun::star::table::CellRangeAddress; + +// ============================================================================ + +namespace { + +const SfxItemPropertyMapEntry* lcl_GetDataPilotDescriptorBaseMap() +{ + static SfxItemPropertyMapEntry aDataPilotDescriptorBaseMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNO_COLGRAND), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_DRILLDOWN), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_IGNEMPROWS), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_IMPORTDESC), 0, &getCppuType((uno::Sequence<beans::PropertyValue>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_RPTEMPTY), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_ROWGRAND), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_SERVICEARG), 0, &getCppuType((uno::Sequence<beans::PropertyValue>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_SHOWFILT), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_SOURCESERV), 0, &getCppuType((rtl::OUString*)0), 0, 0 }, + {0,0,0,0,0,0} + }; + return aDataPilotDescriptorBaseMap_Impl; +} + +// ---------------------------------------------------------------------------- + +const SfxItemPropertyMapEntry* lcl_GetDataPilotFieldMap() +{ + using namespace ::com::sun::star::beans::PropertyAttribute; + static SfxItemPropertyMapEntry aDataPilotFieldMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_AUTOSHOW), 0, &getCppuType((DataPilotFieldAutoShowInfo*)0), MAYBEVOID, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_FUNCTION), 0, &getCppuType((GeneralFunction*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_GROUPINFO), 0, &getCppuType((DataPilotFieldGroupInfo*)0), MAYBEVOID, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_HASAUTOSHOW), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_HASLAYOUTINFO),0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_HASREFERENCE), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_HASSORTINFO), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_ISGROUP), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_LAYOUTINFO), 0, &getCppuType((DataPilotFieldLayoutInfo*)0), MAYBEVOID, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_ORIENT), 0, &getCppuType((DataPilotFieldOrientation*)0), MAYBEVOID, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_REFERENCE), 0, &getCppuType((DataPilotFieldReference*)0), MAYBEVOID, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_SELPAGE), 0, &getCppuType((OUString*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_SHOWEMPTY), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_SORTINFO), 0, &getCppuType((DataPilotFieldSortInfo*)0), MAYBEVOID, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_SUBTOTALS), 0, &getCppuType((Sequence<GeneralFunction>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_USESELPAGE), 0, &getBooleanCppuType(), 0, 0 }, + {0,0,0,0,0,0} + }; + return aDataPilotFieldMap_Impl; +} + +// ---------------------------------------------------------------------------- + +const SfxItemPropertyMapEntry* lcl_GetDataPilotItemMap() +{ + static SfxItemPropertyMapEntry aDataPilotItemMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_ISHIDDEN), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_POS), 0, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_SHOWDETAIL), 0, &getBooleanCppuType(), 0, 0 }, + {0,0,0,0,0,0} + }; + return aDataPilotItemMap_Impl; +} + +// ---------------------------------------------------------------------------- + +inline bool lclCheckValidDouble( double fValue, sal_Bool bAuto ) +{ + return bAuto || ::rtl::math::isFinite( fValue ); +} + +bool lclCheckMinMaxStep( const DataPilotFieldGroupInfo& rInfo ) +{ + return + lclCheckValidDouble( rInfo.Start, rInfo.HasAutoStart ) && + lclCheckValidDouble( rInfo.End, rInfo.HasAutoEnd ) && + (rInfo.HasAutoStart || rInfo.HasAutoEnd || (rInfo.Start <= rInfo.End)) && + lclCheckValidDouble( rInfo.Step, sal_False ) && + (0.0 <= rInfo.Step); +} + +} // namespace + +// ============================================================================ + +SC_SIMPLE_SERVICE_INFO( ScDataPilotDescriptor, "ScDataPilotDescriptor", "stardiv::one::sheet::DataPilotDescriptor" ) +SC_SIMPLE_SERVICE_INFO( ScDataPilotFieldObj, "ScDataPilotFieldObj", "com.sun.star.sheet.DataPilotField" ) +SC_SIMPLE_SERVICE_INFO( ScDataPilotFieldsObj, "ScDataPilotFieldsObj", "com.sun.star.sheet.DataPilotFields" ) +SC_SIMPLE_SERVICE_INFO( ScDataPilotTableObj, "ScDataPilotTableObj", "com.sun.star.sheet.DataPilotTable" ) +SC_SIMPLE_SERVICE_INFO( ScDataPilotTablesObj, "ScDataPilotTablesObj", "com.sun.star.sheet.DataPilotTables" ) +SC_SIMPLE_SERVICE_INFO( ScDataPilotItemsObj, "ScDataPilotItemsObj", "com.sun.star.sheet.DataPilotItems" ) +SC_SIMPLE_SERVICE_INFO( ScDataPilotItemObj, "ScDataPilotItemObj", "com.sun.star.sheet.DataPilotItem" ) + +SC_SIMPLE_SERVICE_INFO( ScDataPilotFieldGroupsObj, "ScDataPilotFieldGroupsObj", "com.sun.star.sheet.DataPilotFieldGroups" ) +SC_SIMPLE_SERVICE_INFO( ScDataPilotFieldGroupObj, "ScDataPilotFieldGroupObj", "com.sun.star.sheet.DataPilotFieldGroup" ) +SC_SIMPLE_SERVICE_INFO( ScDataPilotFieldGroupItemObj, "ScDataPilotFieldGroupItemObj", "com.sun.star.sheet.DataPilotFieldGroupItem" ) + +//------------------------------------------------------------------------ + +// name that is used in the API for the data layout field +#define SC_DATALAYOUT_NAME "Data" + +//------------------------------------------------------------------------ + +GeneralFunction ScDataPilotConversion::FirstFunc( USHORT nBits ) +{ + if ( nBits & PIVOT_FUNC_SUM ) return GeneralFunction_SUM; + if ( nBits & PIVOT_FUNC_COUNT ) return GeneralFunction_COUNT; + if ( nBits & PIVOT_FUNC_AVERAGE ) return GeneralFunction_AVERAGE; + if ( nBits & PIVOT_FUNC_MAX ) return GeneralFunction_MAX; + if ( nBits & PIVOT_FUNC_MIN ) return GeneralFunction_MIN; + if ( nBits & PIVOT_FUNC_PRODUCT ) return GeneralFunction_PRODUCT; + if ( nBits & PIVOT_FUNC_COUNT_NUM ) return GeneralFunction_COUNTNUMS; + if ( nBits & PIVOT_FUNC_STD_DEV ) return GeneralFunction_STDEV; + if ( nBits & PIVOT_FUNC_STD_DEVP ) return GeneralFunction_STDEVP; + if ( nBits & PIVOT_FUNC_STD_VAR ) return GeneralFunction_VAR; + if ( nBits & PIVOT_FUNC_STD_VARP ) return GeneralFunction_VARP; + if ( nBits & PIVOT_FUNC_AUTO ) return GeneralFunction_AUTO; + return GeneralFunction_NONE; +} + +USHORT ScDataPilotConversion::FunctionBit( GeneralFunction eFunc ) +{ + USHORT nRet = PIVOT_FUNC_NONE; // 0 + switch (eFunc) + { + case GeneralFunction_SUM: nRet = PIVOT_FUNC_SUM; break; + case GeneralFunction_COUNT: nRet = PIVOT_FUNC_COUNT; break; + case GeneralFunction_AVERAGE: nRet = PIVOT_FUNC_AVERAGE; break; + case GeneralFunction_MAX: nRet = PIVOT_FUNC_MAX; break; + case GeneralFunction_MIN: nRet = PIVOT_FUNC_MIN; break; + case GeneralFunction_PRODUCT: nRet = PIVOT_FUNC_PRODUCT; break; + case GeneralFunction_COUNTNUMS: nRet = PIVOT_FUNC_COUNT_NUM; break; + case GeneralFunction_STDEV: nRet = PIVOT_FUNC_STD_DEV; break; + case GeneralFunction_STDEVP: nRet = PIVOT_FUNC_STD_DEVP; break; + case GeneralFunction_VAR: nRet = PIVOT_FUNC_STD_VAR; break; + case GeneralFunction_VARP: nRet = PIVOT_FUNC_STD_VARP; break; + case GeneralFunction_AUTO: nRet = PIVOT_FUNC_AUTO; break; + default: + { + // added to avoid warnings + } + } + return nRet; +} + +void ScDataPilotConversion::FillGroupInfo( DataPilotFieldGroupInfo& rInfo, const ScDPNumGroupInfo& rGroupInfo ) +{ + rInfo.HasDateValues = rGroupInfo.DateValues; + rInfo.HasAutoStart = rGroupInfo.AutoStart; + rInfo.Start = rGroupInfo.Start; + rInfo.HasAutoEnd = rGroupInfo.AutoEnd; + rInfo.End = rGroupInfo.End; + rInfo.Step = rGroupInfo.Step; +} + +//------------------------------------------------------------------------ + +ScDPObject* lcl_GetDPObject( ScDocShell* pDocShell, SCTAB nTab, const String& rName ) +{ + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScDPCollection* pColl = pDoc->GetDPCollection(); + if ( pColl ) + { + USHORT nCount = pColl->GetCount(); + for (USHORT i=0; i<nCount; i++) + { + ScDPObject* pDPObj = (*pColl)[i]; + if ( pDPObj->GetOutRange().aStart.Tab() == nTab && + pDPObj->GetName() == rName ) + return pDPObj; + } + } + } + return NULL; // nicht gefunden +} + +String lcl_CreatePivotName( ScDocShell* pDocShell ) +{ + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScDPCollection* pColl = pDoc->GetDPCollection(); + if ( pColl ) + return pColl->CreateNewName(); + } + return String(); // sollte nicht vorkommen +} + +sal_Int32 lcl_GetObjectIndex( ScDPObject* pDPObj, const ScFieldIdentifier& rFieldId ) +{ + // used for items - nRepeat in identifier can be ignored + if ( pDPObj ) + { + sal_Int32 nCount = pDPObj->GetDimCount(); + for ( sal_Int32 nDim = 0; nDim < nCount; ++nDim ) + { + BOOL bIsDataLayout = FALSE; + OUString aDimName( pDPObj->GetDimName( nDim, bIsDataLayout ) ); + if ( rFieldId.mbDataLayout ? bIsDataLayout : (aDimName == rFieldId.maFieldName) ) + return nDim; + } + } + return -1; // none +} + +//------------------------------------------------------------------------ + +ScDataPilotTablesObj::ScDataPilotTablesObj(ScDocShell* pDocSh, SCTAB nT) : + pDocShell( pDocSh ), + nTab( nT ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScDataPilotTablesObj::~ScDataPilotTablesObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScDataPilotTablesObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + //! Referenz-Update + + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +// XDataPilotTables + +ScDataPilotTableObj* ScDataPilotTablesObj::GetObjectByIndex_Impl( sal_Int32 nIndex ) +{ + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScDPCollection* pColl = pDoc->GetDPCollection(); + if ( pColl ) + { + // count tables on this sheet + // api only handles sheet data at this time + //! allow all data sources!!! + sal_Int32 nFound = 0; + USHORT nCount = pColl->GetCount(); + for (USHORT i=0; i<nCount; i++) + { + ScDPObject* pDPObj = (*pColl)[i]; + if ( pDPObj->GetOutRange().aStart.Tab() == nTab ) + { + if ( nFound == nIndex ) + { + String aName = pDPObj->GetName(); + return new ScDataPilotTableObj( pDocShell, nTab, aName ); + } + ++nFound; + } + } + } + } + return NULL; +} + +ScDataPilotTableObj* ScDataPilotTablesObj::GetObjectByName_Impl(const OUString& rName) +{ + if (hasByName(rName)) + return new ScDataPilotTableObj( pDocShell, nTab, rName ); + return 0; +} + +Reference<XDataPilotDescriptor> SAL_CALL ScDataPilotTablesObj::createDataPilotDescriptor() + throw(RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + return new ScDataPilotDescriptor(pDocShell); + return NULL; +} + +bool lcl_IsDuplicated( const Reference<XPropertySet> xDimProps ) +{ + try + { + Any aAny = xDimProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_ORIGINAL ) ) ); + Reference< XNamed > xOriginal( aAny, UNO_QUERY ); + return xOriginal.is(); + } + catch( Exception& ) + { + } + return false; +} + +OUString lcl_GetOriginalName( const Reference< XNamed > xDim ) +{ + Reference< XNamed > xOriginal; + + Reference< XPropertySet > xDimProps( xDim, UNO_QUERY ); + if ( xDimProps.is() ) + { + try + { + Any aAny = xDimProps->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_ORIGINAL))); + aAny >>= xOriginal; + } + catch( Exception& ) + { + } + } + + if ( !xOriginal.is() ) + xOriginal = xDim; + + return xOriginal->getName(); +} + +void SAL_CALL ScDataPilotTablesObj::insertNewByName( const OUString& aNewName, + const CellAddress& aOutputAddress, + const Reference<XDataPilotDescriptor>& xDescriptor ) + throw(RuntimeException) +{ + ScUnoGuard aGuard; + if (!xDescriptor.is()) return; + + // inserting with already existing name? + if ( aNewName.getLength() && hasByName( aNewName ) ) + throw RuntimeException(); // no other exceptions specified + + BOOL bDone = FALSE; + ScDataPilotDescriptorBase* pImp = ScDataPilotDescriptorBase::getImplementation( xDescriptor ); + if ( pDocShell && pImp ) + { + ScDPObject* pNewObj = pImp->GetDPObject(); + + if (pNewObj) + { + ScRange aOutputRange((SCCOL)aOutputAddress.Column, (SCROW)aOutputAddress.Row, (SCTAB)aOutputAddress.Sheet, + (SCCOL)aOutputAddress.Column, (SCROW)aOutputAddress.Row, (SCTAB)aOutputAddress.Sheet); + pNewObj->SetOutRange(aOutputRange); + String aName = aNewName; + if (!aName.Len()) + aName = lcl_CreatePivotName( pDocShell ); + pNewObj->SetName(aName); + String aTag = xDescriptor->getTag(); + pNewObj->SetTag(aTag); + + // todo: handle double fields (for more information see ScDPObject + + ScDBDocFunc aFunc(*pDocShell); + bDone = aFunc.DataPilotUpdate( NULL, pNewObj, TRUE, TRUE ); + } + } + + if (!bDone) + throw RuntimeException(); // no other exceptions specified +} + +void SAL_CALL ScDataPilotTablesObj::removeByName( const OUString& aName ) + throw(RuntimeException) +{ + ScUnoGuard aGuard; + String aNameStr(aName); + ScDPObject* pDPObj = lcl_GetDPObject( pDocShell, nTab, aNameStr ); + if (pDPObj && pDocShell) + { + ScDBDocFunc aFunc(*pDocShell); + aFunc.DataPilotUpdate( pDPObj, NULL, TRUE, TRUE ); // remove - incl. undo etc. + } + else + throw RuntimeException(); // no other exceptions specified +} + +// XEnumerationAccess + +Reference< XEnumeration > SAL_CALL ScDataPilotTablesObj::createEnumeration() throw(RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.DataPilotTablesEnumeration"))); +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScDataPilotTablesObj::getCount() throw(RuntimeException) +{ + ScUnoGuard aGuard; + if ( pDocShell ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScDPCollection* pColl = pDoc->GetDPCollection(); + if ( pColl ) + { + // count tables on this sheet + // api only handles sheet data at this time + //! allow all data sources!!! + + USHORT nFound = 0; + USHORT nCount = pColl->GetCount(); + for (USHORT i=0; i<nCount; i++) + { + ScDPObject* pDPObj = (*pColl)[i]; + if ( pDPObj->GetOutRange().aStart.Tab() == nTab ) + ++nFound; + } + return nFound; + } + } + + return 0; +} + +Any SAL_CALL ScDataPilotTablesObj::getByIndex( sal_Int32 nIndex ) + throw(IndexOutOfBoundsException, WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + Reference<XDataPilotTable2> xTable(GetObjectByIndex_Impl(nIndex)); + if (!xTable.is()) + throw IndexOutOfBoundsException(); + return Any( xTable ); +} + +uno::Type SAL_CALL ScDataPilotTablesObj::getElementType() throw(RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((Reference<XDataPilotTable2>*)0); +} + +sal_Bool SAL_CALL ScDataPilotTablesObj::hasElements() throw(RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +// XNameAccess + +Any SAL_CALL ScDataPilotTablesObj::getByName( const OUString& aName ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + Reference<XDataPilotTable2> xTable(GetObjectByName_Impl(aName)); + if (!xTable.is()) + throw NoSuchElementException(); + return Any( xTable ); +} + +Sequence<OUString> SAL_CALL ScDataPilotTablesObj::getElementNames() + throw(RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScDPCollection* pColl = pDoc->GetDPCollection(); + if ( pColl ) + { + // count tables on this sheet + // api only handles sheet data at this time + //! allow all data sources!!! + + USHORT nFound = 0; + USHORT nCount = pColl->GetCount(); + USHORT i; + for (i=0; i<nCount; i++) + { + ScDPObject* pDPObj = (*pColl)[i]; + if ( pDPObj->GetOutRange().aStart.Tab() == nTab ) + ++nFound; + } + + USHORT nPos = 0; + Sequence<OUString> aSeq(nFound); + OUString* pAry = aSeq.getArray(); + for (i=0; i<nCount; i++) + { + ScDPObject* pDPObj = (*pColl)[i]; + if ( pDPObj->GetOutRange().aStart.Tab() == nTab ) + pAry[nPos++] = pDPObj->GetName(); + } + + return aSeq; + } + } + return Sequence<OUString>(0); +} + +sal_Bool SAL_CALL ScDataPilotTablesObj::hasByName( const OUString& aName ) + throw(RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScDPCollection* pColl = pDoc->GetDPCollection(); + if ( pColl ) + { + String aNamStr(aName); + USHORT nCount = pColl->GetCount(); + for (USHORT i=0; i<nCount; i++) + { + // api only handles sheet data at this time + //! allow all data sources!!! + + ScDPObject* pDPObj = (*pColl)[i]; + if ( pDPObj->GetOutRange().aStart.Tab() == nTab && + pDPObj->GetName() == aNamStr ) + return TRUE; + } + } + } + return FALSE; +} + +//------------------------------------------------------------------------ + +ScDataPilotDescriptorBase::ScDataPilotDescriptorBase(ScDocShell* pDocSh) : + maPropSet( lcl_GetDataPilotDescriptorBaseMap() ), + pDocShell( pDocSh ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScDataPilotDescriptorBase::~ScDataPilotDescriptorBase() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +Any SAL_CALL ScDataPilotDescriptorBase::queryInterface( const uno::Type& rType ) + throw(RuntimeException) +{ + SC_QUERYINTERFACE( XDataPilotDescriptor ) + SC_QUERYINTERFACE( XPropertySet ) + SC_QUERYINTERFACE( XDataPilotDataLayoutFieldSupplier ) + SC_QUERYINTERFACE( XNamed ) // base of XDataPilotDescriptor + SC_QUERYINTERFACE( lang::XUnoTunnel ) + SC_QUERYINTERFACE( lang::XTypeProvider ) + SC_QUERYINTERFACE( lang::XServiceInfo ) + + return OWeakObject::queryInterface( rType ); +} + +void SAL_CALL ScDataPilotDescriptorBase::acquire() throw() +{ + OWeakObject::acquire(); +} + +void SAL_CALL ScDataPilotDescriptorBase::release() throw() +{ + OWeakObject::release(); +} + +Sequence< uno::Type > SAL_CALL ScDataPilotDescriptorBase::getTypes() + throw(RuntimeException) +{ + static Sequence< uno::Type > aTypes; + if ( aTypes.getLength() == 0 ) + { + aTypes.realloc( 6 ); + uno::Type* pPtr = aTypes.getArray(); + pPtr[ 0 ] = getCppuType( (const Reference< XDataPilotDescriptor >*)0 ); + pPtr[ 1 ] = getCppuType( (const Reference< XPropertySet >*)0 ); + pPtr[ 2 ] = getCppuType( (const Reference< XDataPilotDataLayoutFieldSupplier >*)0 ); + pPtr[ 3 ] = getCppuType( (const Reference< lang::XUnoTunnel >*)0 ); + pPtr[ 4 ] = getCppuType( (const Reference< lang::XTypeProvider >*)0 ); + pPtr[ 5 ] = getCppuType( (const Reference< lang::XServiceInfo >*)0 ); + } + return aTypes; +} + +Sequence<sal_Int8> SAL_CALL ScDataPilotDescriptorBase::getImplementationId() + throw(RuntimeException) +{ + static Sequence< sal_Int8 > aId; + if( aId.getLength() == 0 ) + { + aId.realloc( 16 ); + rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True ); + } + return aId; +} + +void ScDataPilotDescriptorBase::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + //! Referenz-Update? + + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +// XDataPilotDescriptor + +CellRangeAddress SAL_CALL ScDataPilotDescriptorBase::getSourceRange() + throw(RuntimeException) +{ + ScUnoGuard aGuard; + + ScDPObject* pDPObject(GetDPObject()); + if (!pDPObject) + throw RuntimeException(); + + CellRangeAddress aRet; + if (pDPObject->IsSheetData()) + ScUnoConversion::FillApiRange( aRet, pDPObject->GetSheetDesc()->aSourceRange ); + return aRet; +} + +void SAL_CALL ScDataPilotDescriptorBase::setSourceRange( const CellRangeAddress& aSourceRange ) throw(RuntimeException) +{ + ScUnoGuard aGuard; + + ScDPObject* pDPObject = GetDPObject(); + if (!pDPObject) + throw RuntimeException(); + + ScSheetSourceDesc aSheetDesc; + if (pDPObject->IsSheetData()) + aSheetDesc = *pDPObject->GetSheetDesc(); + ScUnoConversion::FillScRange( aSheetDesc.aSourceRange, aSourceRange ); + pDPObject->SetSheetDesc( aSheetDesc ); + SetDPObject( pDPObject ); +} + +Reference<XSheetFilterDescriptor> SAL_CALL ScDataPilotDescriptorBase::getFilterDescriptor() + throw(RuntimeException) +{ + ScUnoGuard aGuard; + return new ScDataPilotFilterDescriptor( pDocShell, this ); +} + +Reference<XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getDataPilotFields() + throw(RuntimeException) +{ + ScUnoGuard aGuard; + return new ScDataPilotFieldsObj( *this ); +} + +Reference<XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getColumnFields() + throw(RuntimeException) +{ + ScUnoGuard aGuard; + return new ScDataPilotFieldsObj( *this, DataPilotFieldOrientation_COLUMN ); +} + +Reference<XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getRowFields() + throw(RuntimeException) +{ + ScUnoGuard aGuard; + return new ScDataPilotFieldsObj( *this, DataPilotFieldOrientation_ROW ); +} + +Reference<XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getPageFields() + throw(RuntimeException) +{ + ScUnoGuard aGuard; + return new ScDataPilotFieldsObj( *this, DataPilotFieldOrientation_PAGE ); +} + +Reference<XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getDataFields() + throw(RuntimeException) +{ + ScUnoGuard aGuard; + return new ScDataPilotFieldsObj( *this, DataPilotFieldOrientation_DATA ); +} + +Reference<XIndexAccess> SAL_CALL ScDataPilotDescriptorBase::getHiddenFields() + throw(RuntimeException) +{ + ScUnoGuard aGuard; + return new ScDataPilotFieldsObj( *this, DataPilotFieldOrientation_HIDDEN ); +} + +// XPropertySet +Reference< XPropertySetInfo > SAL_CALL ScDataPilotDescriptorBase::getPropertySetInfo( ) + throw(RuntimeException) +{ + ScUnoGuard aGuard; + static Reference<XPropertySetInfo> aRef = + new SfxItemPropertySetInfo( maPropSet.getPropertyMap() ); + return aRef; +} + +void SAL_CALL ScDataPilotDescriptorBase::setPropertyValue( const OUString& aPropertyName, const Any& aValue ) + throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, + WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + ScDPObject* pDPObject = GetDPObject(); + if (pDPObject) + { + ScDPSaveData* pOldData = pDPObject->GetSaveData(); + DBG_ASSERT(pOldData, "Here should be a SaveData"); + if ( pOldData ) + { + ScDPSaveData aNewData( *pOldData ); + + String aNameString = aPropertyName; + if ( aNameString.EqualsAscii( SC_UNO_COLGRAND ) ) + { + aNewData.SetColumnGrand(::cppu::any2bool( aValue )); + } + else if ( aNameString.EqualsAscii( SC_UNO_IGNEMPROWS ) ) + { + aNewData.SetIgnoreEmptyRows(::cppu::any2bool( aValue )); + } + else if ( aNameString.EqualsAscii( SC_UNO_RPTEMPTY ) ) + { + aNewData.SetRepeatIfEmpty(::cppu::any2bool( aValue )); + } + else if ( aNameString.EqualsAscii( SC_UNO_ROWGRAND ) ) + { + aNewData.SetRowGrand(::cppu::any2bool( aValue )); + } + else if ( aNameString.EqualsAscii( SC_UNO_SHOWFILT ) ) + { + aNewData.SetFilterButton(::cppu::any2bool( aValue )); + } + else if ( aNameString.EqualsAscii( SC_UNO_DRILLDOWN ) ) + { + aNewData.SetDrillDown(::cppu::any2bool( aValue )); + } + else if ( aNameString.EqualsAscii( SC_UNO_IMPORTDESC ) ) + { + uno::Sequence<beans::PropertyValue> aArgSeq; + if ( aValue >>= aArgSeq ) + { + ScImportSourceDesc aImportDesc; + + const ScImportSourceDesc* pOldDesc = pDPObject->GetImportSourceDesc(); + if (pOldDesc) + aImportDesc = *pOldDesc; + + ScImportParam aParam; + ScImportDescriptor::FillImportParam( aParam, aArgSeq ); + + USHORT nNewType = sheet::DataImportMode_NONE; + if ( aParam.bImport ) + { + if ( aParam.bSql ) + nNewType = sheet::DataImportMode_SQL; + else if ( aParam.nType == ScDbQuery ) + nNewType = sheet::DataImportMode_QUERY; + else + nNewType = sheet::DataImportMode_TABLE; + } + aImportDesc.nType = nNewType; + aImportDesc.aDBName = aParam.aDBName; + aImportDesc.aObject = aParam.aStatement; + aImportDesc.bNative = aParam.bNative; + + pDPObject->SetImportDesc( aImportDesc ); + } + } + else if ( aNameString.EqualsAscii( SC_UNO_SOURCESERV ) ) + { + rtl::OUString aStrVal; + if ( aValue >>= aStrVal ) + { + String aEmpty; + ScDPServiceDesc aServiceDesc(aEmpty, aEmpty, aEmpty, aEmpty, aEmpty); + + const ScDPServiceDesc* pOldDesc = pDPObject->GetDPServiceDesc(); + if (pOldDesc) + aServiceDesc = *pOldDesc; + + aServiceDesc.aServiceName = aStrVal; + + pDPObject->SetServiceData( aServiceDesc ); + } + } + else if ( aNameString.EqualsAscii( SC_UNO_SERVICEARG ) ) + { + uno::Sequence<beans::PropertyValue> aArgSeq; + if ( aValue >>= aArgSeq ) + { + String aEmpty; + ScDPServiceDesc aServiceDesc(aEmpty, aEmpty, aEmpty, aEmpty, aEmpty); + + const ScDPServiceDesc* pOldDesc = pDPObject->GetDPServiceDesc(); + if (pOldDesc) + aServiceDesc = *pOldDesc; + + rtl::OUString aStrVal; + sal_Int32 nArgs = aArgSeq.getLength(); + for (sal_Int32 nArgPos=0; nArgPos<nArgs; ++nArgPos) + { + const beans::PropertyValue& rProp = aArgSeq[nArgPos]; + String aPropName(rProp.Name); + + if (aPropName.EqualsAscii( SC_UNO_SOURCENAME )) + { + if ( rProp.Value >>= aStrVal ) + aServiceDesc.aParSource = aStrVal; + } + else if (aPropName.EqualsAscii( SC_UNO_OBJECTNAME )) + { + if ( rProp.Value >>= aStrVal ) + aServiceDesc.aParName = aStrVal; + } + else if (aPropName.EqualsAscii( SC_UNO_USERNAME )) + { + if ( rProp.Value >>= aStrVal ) + aServiceDesc.aParUser = aStrVal; + } + else if (aPropName.EqualsAscii( SC_UNO_PASSWORD )) + { + if ( rProp.Value >>= aStrVal ) + aServiceDesc.aParPass = aStrVal; + } + } + + pDPObject->SetServiceData( aServiceDesc ); + } + } + else + throw UnknownPropertyException(); + + pDPObject->SetSaveData( aNewData ); + } + + SetDPObject(pDPObject); + } +} + +Any SAL_CALL ScDataPilotDescriptorBase::getPropertyValue( const OUString& aPropertyName ) + throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + Any aRet; + + ScDPObject* pDPObject(GetDPObject()); + if (pDPObject) + { + ScDPSaveData* pOldData = pDPObject->GetSaveData(); + DBG_ASSERT(pOldData, "Here should be a SaveData"); + if ( pOldData ) + { + ScDPSaveData aNewData( *pOldData ); + + String aNameString = aPropertyName; + if ( aNameString.EqualsAscii( SC_UNO_COLGRAND ) ) + { + aRet = ::cppu::bool2any( aNewData.GetColumnGrand() ); + } + else if ( aNameString.EqualsAscii( SC_UNO_IGNEMPROWS ) ) + { + aRet = ::cppu::bool2any( aNewData.GetIgnoreEmptyRows() ); + } + else if ( aNameString.EqualsAscii( SC_UNO_RPTEMPTY ) ) + { + aRet = ::cppu::bool2any( aNewData.GetRepeatIfEmpty() ); + } + else if ( aNameString.EqualsAscii( SC_UNO_ROWGRAND ) ) + { + aRet = ::cppu::bool2any( aNewData.GetRowGrand() ); + } + else if ( aNameString.EqualsAscii( SC_UNO_SHOWFILT ) ) + { + aRet = ::cppu::bool2any( aNewData.GetFilterButton() ); + } + else if ( aNameString.EqualsAscii( SC_UNO_DRILLDOWN ) ) + { + aRet = ::cppu::bool2any( aNewData.GetDrillDown() ); + } + else if ( aNameString.EqualsAscii( SC_UNO_IMPORTDESC ) ) + { + const ScImportSourceDesc* pImportDesc = pDPObject->GetImportSourceDesc(); + if ( pImportDesc ) + { + // fill ScImportParam so ScImportDescriptor::FillProperties can be used + ScImportParam aParam; + aParam.bImport = ( pImportDesc->nType != sheet::DataImportMode_NONE ); + aParam.aDBName = pImportDesc->aDBName; + aParam.aStatement = pImportDesc->aObject; + aParam.bNative = pImportDesc->bNative; + aParam.bSql = ( pImportDesc->nType == sheet::DataImportMode_SQL ); + aParam.nType = static_cast<BYTE>(( pImportDesc->nType == sheet::DataImportMode_QUERY ) ? ScDbQuery : ScDbTable); + + uno::Sequence<beans::PropertyValue> aSeq( ScImportDescriptor::GetPropertyCount() ); + ScImportDescriptor::FillProperties( aSeq, aParam ); + aRet <<= aSeq; + } + else + { + // empty sequence + uno::Sequence<beans::PropertyValue> aEmpty(0); + aRet <<= aEmpty; + } + } + else if ( aNameString.EqualsAscii( SC_UNO_SOURCESERV ) ) + { + rtl::OUString aServiceName; + const ScDPServiceDesc* pServiceDesc = pDPObject->GetDPServiceDesc(); + if (pServiceDesc) + aServiceName = pServiceDesc->aServiceName; + aRet <<= aServiceName; // empty string if no ServiceDesc set + } + else if ( aNameString.EqualsAscii( SC_UNO_SERVICEARG ) ) + { + const ScDPServiceDesc* pServiceDesc = pDPObject->GetDPServiceDesc(); + if (pServiceDesc) + { + uno::Sequence<beans::PropertyValue> aSeq( 4 ); + beans::PropertyValue* pArray = aSeq.getArray(); + pArray[0].Name = rtl::OUString::createFromAscii( SC_UNO_SOURCENAME ); + pArray[0].Value <<= rtl::OUString( pServiceDesc->aParSource ); + pArray[1].Name = rtl::OUString::createFromAscii( SC_UNO_OBJECTNAME ); + pArray[1].Value <<= rtl::OUString( pServiceDesc->aParName ); + pArray[2].Name = rtl::OUString::createFromAscii( SC_UNO_USERNAME ); + pArray[2].Value <<= rtl::OUString( pServiceDesc->aParUser ); + pArray[3].Name = rtl::OUString::createFromAscii( SC_UNO_PASSWORD ); + pArray[3].Value <<= rtl::OUString( pServiceDesc->aParPass ); + aRet <<= aSeq; + } + else + { + // empty sequence + uno::Sequence<beans::PropertyValue> aEmpty(0); + aRet <<= aEmpty; + } + } + else + throw UnknownPropertyException(); + } + } + + return aRet; +} + +void SAL_CALL ScDataPilotDescriptorBase::addPropertyChangeListener( + const OUString& /* aPropertyName */, const Reference<XPropertyChangeListener >& /* xListener */ ) + throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ +} + +void SAL_CALL ScDataPilotDescriptorBase::removePropertyChangeListener( + const OUString& /* aPropertyName */, const Reference<XPropertyChangeListener >& /* aListener */ ) + throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ +} + +void SAL_CALL ScDataPilotDescriptorBase::addVetoableChangeListener( + const OUString& /* PropertyName */, const Reference<XVetoableChangeListener >& /* aListener */ ) + throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ +} + +void SAL_CALL ScDataPilotDescriptorBase::removeVetoableChangeListener( + const OUString& /* PropertyName */, const Reference<XVetoableChangeListener >& /* aListener */ ) + throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ +} + +// XDataPilotDataLayoutFieldSupplier + +Reference< XDataPilotField > SAL_CALL ScDataPilotDescriptorBase::getDataLayoutField() throw(RuntimeException) +{ + ScUnoGuard aGuard; + if( ScDPObject* pDPObject = GetDPObject() ) + { + if( ScDPSaveData* pSaveData = pDPObject->GetSaveData() ) + { + if( /*ScDPSaveDimension* pDataDim =*/ pSaveData->GetDataLayoutDimension() ) + { + ScFieldIdentifier aFieldId( OUString( RTL_CONSTASCII_USTRINGPARAM( SC_DATALAYOUT_NAME ) ), 0, true ); + return new ScDataPilotFieldObj( *this, aFieldId ); + } + } + } + return 0; +} + +// XUnoTunnel + +sal_Int64 SAL_CALL ScDataPilotDescriptorBase::getSomething( + const Sequence<sal_Int8 >& rId ) throw(RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); + } + return 0; +} + +// static +const Sequence<sal_Int8>& ScDataPilotDescriptorBase::getUnoTunnelId() +{ + static Sequence<sal_Int8> * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +// static +ScDataPilotDescriptorBase* ScDataPilotDescriptorBase::getImplementation( + const Reference<XDataPilotDescriptor> xObj ) +{ + ScDataPilotDescriptorBase* pRet = NULL; + Reference<lang::XUnoTunnel> xUT( xObj, UNO_QUERY ); + if (xUT.is()) + pRet = reinterpret_cast<ScDataPilotDescriptorBase*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId()))); + return pRet; +} + +//------------------------------------------------------------------------ + +ScDataPilotTableObj::ScDataPilotTableObj(ScDocShell* pDocSh, SCTAB nT, const String& rN) : + ScDataPilotDescriptorBase( pDocSh ), + nTab( nT ), + aName( rN ), + aModifyListeners( 0 ) +{ +} + +ScDataPilotTableObj::~ScDataPilotTableObj() +{ +} + +Any SAL_CALL ScDataPilotTableObj::queryInterface( const uno::Type& rType ) + throw(RuntimeException) +{ + // since we manually do resolve the query for XDataPilotTable2 + // we also need to do the same for XDataPilotTable + SC_QUERYINTERFACE( XDataPilotTable ) + SC_QUERYINTERFACE( XDataPilotTable2 ) + SC_QUERYINTERFACE( XModifyBroadcaster ) + + return ScDataPilotDescriptorBase::queryInterface( rType ); +} + +void SAL_CALL ScDataPilotTableObj::acquire() throw() +{ + ScDataPilotDescriptorBase::acquire(); +} + +void SAL_CALL ScDataPilotTableObj::release() throw() +{ + ScDataPilotDescriptorBase::release(); +} + +Sequence< uno::Type > SAL_CALL ScDataPilotTableObj::getTypes() throw(RuntimeException) +{ + static Sequence< uno::Type > aTypes; + if ( aTypes.getLength() == 0 ) + { + Sequence< uno::Type > aParentTypes = ScDataPilotDescriptorBase::getTypes(); + sal_Int32 nParentLen = aParentTypes.getLength(); + const uno::Type* pParentPtr = aParentTypes.getConstArray(); + + aTypes.realloc( nParentLen + 2 ); + uno::Type* pPtr = aTypes.getArray(); + for (sal_Int32 i = 0; i < nParentLen; ++i) + pPtr[ i ] = pParentPtr[ i ]; // parent types first + + pPtr[ nParentLen ] = getCppuType( (const Reference< XDataPilotTable2 >*)0 ); + pPtr[ nParentLen+1 ] = getCppuType( (const Reference< XModifyBroadcaster >*)0 ); + } + return aTypes; +} + +Sequence<sal_Int8> SAL_CALL ScDataPilotTableObj::getImplementationId() + throw(RuntimeException) +{ + static Sequence< sal_Int8 > aId; + if( aId.getLength() == 0 ) + { + aId.realloc( 16 ); + rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True ); + } + return aId; +} + +// --- +ScDPObject* ScDataPilotTableObj::GetDPObject() const +{ + return lcl_GetDPObject(GetDocShell(), nTab, aName); +} + +void ScDataPilotTableObj::SetDPObject( ScDPObject* pDPObject ) +{ + ScDocShell* pDocSh = GetDocShell(); + ScDPObject* pDPObj = lcl_GetDPObject(pDocSh, nTab, aName); + if ( pDPObj && pDocSh ) + { + ScDBDocFunc aFunc(*pDocSh); + aFunc.DataPilotUpdate( pDPObj, pDPObject, TRUE, TRUE ); + } +} + +// "rest of XDataPilotDescriptor" + +OUString SAL_CALL ScDataPilotTableObj::getName() throw(RuntimeException) +{ + ScUnoGuard aGuard; + ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName); + if (pDPObj) + return pDPObj->GetName(); + return OUString(); +} + +void SAL_CALL ScDataPilotTableObj::setName( const OUString& aNewName ) + throw(RuntimeException) +{ + ScUnoGuard aGuard; + ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName); + if (pDPObj) + { + //! test for existing names !!! + + String aString(aNewName); + pDPObj->SetName( aString ); //! Undo - DBDocFunc ??? + aName = aString; + + // DataPilotUpdate would do too much (output table is not changed) + GetDocShell()->SetDocumentModified(); + } +} + +OUString SAL_CALL ScDataPilotTableObj::getTag() throw(RuntimeException) +{ + ScUnoGuard aGuard; + ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName); + if (pDPObj) + return pDPObj->GetTag(); + return OUString(); +} + +void SAL_CALL ScDataPilotTableObj::setTag( const OUString& aNewTag ) + throw(RuntimeException) +{ + ScUnoGuard aGuard; + ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName); + if (pDPObj) + { + String aString(aNewTag); + pDPObj->SetTag( aString ); //! Undo - DBDocFunc ??? + + // DataPilotUpdate would do too much (output table is not changed) + GetDocShell()->SetDocumentModified(); + } +} + +// XDataPilotTable + +CellRangeAddress SAL_CALL ScDataPilotTableObj::getOutputRange() throw(RuntimeException) +{ + ScUnoGuard aGuard; + CellRangeAddress aRet; + ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName); + if (pDPObj) + { + ScRange aRange(pDPObj->GetOutRange()); + aRet.Sheet = aRange.aStart.Tab(); + aRet.StartColumn = aRange.aStart.Col(); + aRet.StartRow = aRange.aStart.Row(); + aRet.EndColumn = aRange.aEnd.Col(); + aRet.EndRow = aRange.aEnd.Row(); + } + return aRet; +} + +ULONG RefreshDPObject( ScDPObject *pDPObj, ScDocument *pDoc, ScDocShell *pDocSh, BOOL bRecord, BOOL bApi ); + +void SAL_CALL ScDataPilotTableObj::refresh() throw(RuntimeException) +{ + ScUnoGuard aGuard; + if( ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName) ) + RefreshDPObject( pDPObj, NULL, GetDocShell(), TRUE, TRUE ); + //if (pDPObj) + //{ + // ScDPObject* pNew = new ScDPObject(*pDPObj); + // ScDBDocFunc aFunc(*GetDocShell()); + // aFunc.DataPilotUpdate( pDPObj, pNew, TRUE, TRUE ); + // delete pNew; // DataPilotUpdate copies settings from "new" object + //} + +} + +Sequence< Sequence<Any> > SAL_CALL ScDataPilotTableObj::getDrillDownData(const CellAddress& aAddr) + throw (RuntimeException) +{ + ScUnoGuard aGuard; + Sequence< Sequence<Any> > aTabData; + ScAddress aAddr2(static_cast<SCCOL>(aAddr.Column), static_cast<SCROW>(aAddr.Row), aAddr.Sheet); + ScDPObject* pObj = GetDPObject(); + if (!pObj) + throw RuntimeException(); + + pObj->GetDrillDownData(aAddr2, aTabData); + return aTabData; +} + +DataPilotTablePositionData SAL_CALL ScDataPilotTableObj::getPositionData(const CellAddress& aAddr) + throw (RuntimeException) +{ + ScUnoGuard aGuard; + DataPilotTablePositionData aPosData; + ScAddress aAddr2(static_cast<SCCOL>(aAddr.Column), static_cast<SCROW>(aAddr.Row), aAddr.Sheet); + ScDPObject* pObj = GetDPObject(); + if (!pObj) + throw RuntimeException(); + + pObj->GetPositionData(aAddr2, aPosData); + return aPosData; +} + +void SAL_CALL ScDataPilotTableObj::insertDrillDownSheet(const CellAddress& aAddr) + throw (RuntimeException) +{ + ScUnoGuard aGuard; + ScDPObject* pDPObj = GetDPObject(); + if (!pDPObj) + throw RuntimeException(); + + Sequence<DataPilotFieldFilter> aFilters; + pDPObj->GetDataFieldPositionData( + ScAddress(static_cast<SCCOL>(aAddr.Column), static_cast<SCROW>(aAddr.Row), aAddr.Sheet), aFilters); + GetDocShell()->GetBestViewShell()->ShowDataPilotSourceData(*pDPObj, aFilters); +} + +CellRangeAddress SAL_CALL ScDataPilotTableObj::getOutputRangeByType( sal_Int32 nType ) + throw (IllegalArgumentException, RuntimeException) +{ + ScUnoGuard aGuard; + if (nType < 0 || nType > DataPilotOutputRangeType::RESULT) + throw IllegalArgumentException(); + + CellRangeAddress aRet; + if (ScDPObject* pDPObj = lcl_GetDPObject(GetDocShell(), nTab, aName)) + ScUnoConversion::FillApiRange( aRet, pDPObj->GetOutputRangeByType( nType ) ); + return aRet; +} + +void SAL_CALL ScDataPilotTableObj::addModifyListener( const uno::Reference<util::XModifyListener>& aListener ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + + uno::Reference<util::XModifyListener> *pObj = new uno::Reference<util::XModifyListener>( aListener ); + aModifyListeners.Insert( pObj, aModifyListeners.Count() ); + + if ( aModifyListeners.Count() == 1 ) + { + acquire(); // don't lose this object (one ref for all listeners) + } +} + +void SAL_CALL ScDataPilotTableObj::removeModifyListener( const uno::Reference<util::XModifyListener>& aListener ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + + acquire(); // in case the listeners have the last ref - released below + + USHORT nCount = aModifyListeners.Count(); + for ( USHORT n=nCount; n--; ) + { + uno::Reference<util::XModifyListener> *pObj = aModifyListeners[n]; + if ( *pObj == aListener ) + { + aModifyListeners.DeleteAndDestroy( n ); + + if ( aModifyListeners.Count() == 0 ) + { + release(); // release the ref for the listeners + } + + break; + } + } + + release(); // might delete this object +} + +void ScDataPilotTableObj::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) +{ + if ( rHint.ISA(ScDataPilotModifiedHint) && + static_cast<const ScDataPilotModifiedHint&>(rHint).GetName() == aName ) + { + Refreshed_Impl(); + } + + ScDataPilotDescriptorBase::Notify( rBC, rHint ); +} + +void ScDataPilotTableObj::Refreshed_Impl() +{ + lang::EventObject aEvent; + aEvent.Source.set((cppu::OWeakObject*)this); + + // the EventObject holds a Ref to this object until after the listener calls + + ScDocument* pDoc = GetDocShell()->GetDocument(); + for ( USHORT n=0; n<aModifyListeners.Count(); n++ ) + pDoc->AddUnoListenerCall( *aModifyListeners[n], aEvent ); +} + +// ============================================================================ + +ScDataPilotDescriptor::ScDataPilotDescriptor(ScDocShell* pDocSh) : + ScDataPilotDescriptorBase( pDocSh ), + mpDPObject(new ScDPObject(pDocSh ? pDocSh->GetDocument() : NULL) ) +{ + mpDPObject->SetAlive(sal_True); + ScDPSaveData aSaveData; + // set defaults like in ScPivotParam constructor + aSaveData.SetColumnGrand( sal_True ); + aSaveData.SetRowGrand( sal_True ); + aSaveData.SetIgnoreEmptyRows( sal_False ); + aSaveData.SetRepeatIfEmpty( sal_False ); + mpDPObject->SetSaveData(aSaveData); + ScSheetSourceDesc aSheetDesc; + mpDPObject->SetSheetDesc(aSheetDesc); + mpDPObject->GetSource(); +} + +ScDataPilotDescriptor::~ScDataPilotDescriptor() +{ + delete mpDPObject; +} + +ScDPObject* ScDataPilotDescriptor::GetDPObject() const +{ + return mpDPObject; +} + +void ScDataPilotDescriptor::SetDPObject( ScDPObject* pDPObject ) +{ + if (mpDPObject != pDPObject) + { + delete mpDPObject; + mpDPObject = pDPObject; + DBG_ERROR("replace DPObject should not happen"); + } +} + +// "rest of XDataPilotDescriptor" + +OUString SAL_CALL ScDataPilotDescriptor::getName() throw(RuntimeException) +{ + ScUnoGuard aGuard; + return mpDPObject->GetName(); +} + +void SAL_CALL ScDataPilotDescriptor::setName( const OUString& aNewName ) + throw(RuntimeException) +{ + ScUnoGuard aGuard; + mpDPObject->SetName( aNewName ); +} + +OUString SAL_CALL ScDataPilotDescriptor::getTag() throw(RuntimeException) +{ + ScUnoGuard aGuard; + return mpDPObject->GetTag(); +} + +void SAL_CALL ScDataPilotDescriptor::setTag( const OUString& aNewTag ) + throw(RuntimeException) +{ + ScUnoGuard aGuard; + mpDPObject->SetTag( aNewTag ); +} + +// ============================================================================ + +ScDataPilotChildObjBase::ScDataPilotChildObjBase( ScDataPilotDescriptorBase& rParent ) : + mrParent( rParent ) +{ + mrParent.acquire(); +} + +ScDataPilotChildObjBase::ScDataPilotChildObjBase( ScDataPilotDescriptorBase& rParent, const ScFieldIdentifier& rFieldId ) : + mrParent( rParent ), + maFieldId( rFieldId ) +{ + mrParent.acquire(); +} + +ScDataPilotChildObjBase::~ScDataPilotChildObjBase() +{ + mrParent.release(); +} + +ScDPObject* ScDataPilotChildObjBase::GetDPObject() const +{ + return mrParent.GetDPObject(); +} + +void ScDataPilotChildObjBase::SetDPObject( ScDPObject* pDPObject ) +{ + mrParent.SetDPObject( pDPObject ); +} + +ScDPSaveDimension* ScDataPilotChildObjBase::GetDPDimension( ScDPObject** ppDPObject ) const +{ + if( ScDPObject* pDPObj = GetDPObject() ) + { + if( ppDPObject ) *ppDPObject = pDPObj; + if( ScDPSaveData* pSaveData = pDPObj->GetSaveData() ) + { + if( maFieldId.mbDataLayout ) + return pSaveData->GetDataLayoutDimension(); + + if( maFieldId.mnFieldIdx == 0 ) + return pSaveData->GetDimensionByName( maFieldId.maFieldName ); + + // find dimension with specified index (search in duplicated dimensions) + String aFieldName = maFieldId.maFieldName; // needed for comparison + const List& rDimensions = pSaveData->GetDimensions(); + ULONG nDimCount = rDimensions.Count(); + sal_Int32 nFoundIdx = 0; + for( ULONG nDim = 0; nDim < nDimCount; ++nDim ) + { + ScDPSaveDimension* pDim = static_cast< ScDPSaveDimension* >( rDimensions.GetObject( nDim ) ); + if( !pDim->IsDataLayout() && (pDim->GetName() == aFieldName) ) + { + if( nFoundIdx == maFieldId.mnFieldIdx ) + return pDim; + ++nFoundIdx; + } + } + } + } + return 0; +} + +sal_Int32 ScDataPilotChildObjBase::GetMemberCount() const +{ + sal_Int32 nRet = 0; + Reference<XNameAccess> xMembersNA = GetMembers(); + if (xMembersNA.is()) + { + Reference< XIndexAccess > xMembersIA( new ScNameToIndexAccess( xMembersNA ) ); + nRet = xMembersIA->getCount(); + } + return nRet; +} + +Reference< XNameAccess > ScDataPilotChildObjBase::GetMembers() const +{ + Reference< XNameAccess > xMembersNA; + if( ScDPObject* pDPObj = GetDPObject() ) + pDPObj->GetMembersNA( lcl_GetObjectIndex( pDPObj, maFieldId ), xMembersNA ); + return xMembersNA; +} + +// ============================================================================ + +ScDataPilotFieldsObj::ScDataPilotFieldsObj( ScDataPilotDescriptorBase& rParent ) : + ScDataPilotChildObjBase( rParent ) +{ +} + +ScDataPilotFieldsObj::ScDataPilotFieldsObj( ScDataPilotDescriptorBase& rParent, DataPilotFieldOrientation eOrient ) : + ScDataPilotChildObjBase( rParent ), + maOrient( eOrient ) +{ +} + +ScDataPilotFieldsObj::~ScDataPilotFieldsObj() +{ +} + +sal_Int32 lcl_GetFieldCount( const Reference<XDimensionsSupplier>& rSource, const Any& rOrient ) +{ + sal_Int32 nRet = 0; + + Reference<XNameAccess> xDimsName(rSource->getDimensions()); + Reference<XIndexAccess> xIntDims(new ScNameToIndexAccess( xDimsName )); + sal_Int32 nIntCount = xIntDims->getCount(); + if (rOrient.hasValue()) + { + // all fields of the specified orientation, including duplicated + Reference<XPropertySet> xDim; + for (sal_Int32 i = 0; i < nIntCount; ++i) + { + xDim.set(xIntDims->getByIndex(i), UNO_QUERY); + if (xDim.is() && (xDim->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_ORIENTAT))) == rOrient)) + ++nRet; + } + } + else + { + // count all non-duplicated fields + + Reference<XPropertySet> xDim; + for (sal_Int32 i = 0; i < nIntCount; ++i) + { + xDim.set(xIntDims->getByIndex(i), UNO_QUERY); + if ( xDim.is() && !lcl_IsDuplicated( xDim ) ) + ++nRet; + } + } + + return nRet; +} + +BOOL lcl_GetFieldDataByIndex( const Reference<XDimensionsSupplier>& rSource, + const Any& rOrient, SCSIZE nIndex, ScFieldIdentifier& rFieldId ) +{ + BOOL bOk = FALSE; + SCSIZE nPos = 0; + sal_Int32 nDimIndex = 0; + + Reference<XNameAccess> xDimsName(rSource->getDimensions()); + Reference<XIndexAccess> xIntDims(new ScNameToIndexAccess( xDimsName )); + sal_Int32 nIntCount = xIntDims->getCount(); + Reference<XPropertySet> xDim; + if (rOrient.hasValue()) + { + sal_Int32 i = 0; + while (i < nIntCount && !bOk) + { + xDim.set(xIntDims->getByIndex(i), UNO_QUERY); + if (xDim.is() && (xDim->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_ORIENTAT))) == rOrient)) + { + if (nPos == nIndex) + { + bOk = sal_True; + nDimIndex = i; + } + else + ++nPos; + } + ++i; + } + } + else + { + sal_Int32 i = 0; + while (i < nIntCount && !bOk) + { + xDim.set(xIntDims->getByIndex(i), UNO_QUERY); + if ( xDim.is() && !lcl_IsDuplicated( xDim ) ) + { + if (nPos == nIndex) + { + bOk = sal_True; + nDimIndex = i; + } + else + ++nPos; + } + ++i; + } + } + + if ( bOk ) + { + xDim.set( xIntDims->getByIndex(nDimIndex), UNO_QUERY ); + Reference<XNamed> xDimName( xDim, UNO_QUERY ); + if ( xDimName.is() ) + { + OUString sOriginalName( lcl_GetOriginalName( xDimName ) ); + rFieldId.maFieldName = sOriginalName; + rFieldId.mbDataLayout = ScUnoHelpFunctions::GetBoolProperty( xDim, + OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_ISDATALA)) ); + + sal_Int32 nRepeat = 0; + if ( rOrient.hasValue() && lcl_IsDuplicated( xDim ) ) + { + // find the repeat count + // (this relies on the original dimension always being before the duplicates) + + Reference<XNamed> xPrevName; + for (sal_Int32 i = 0; i < nDimIndex; ++i) + { + xPrevName.set( xIntDims->getByIndex(i), UNO_QUERY ); + if ( xPrevName.is() && lcl_GetOriginalName( xPrevName ) == sOriginalName ) + ++nRepeat; + } + } + rFieldId.mnFieldIdx = nRepeat; + } + else + bOk = sal_False; + } + + return bOk; +} + +BOOL lcl_GetFieldDataByName( ScDPObject* pDPObj, const OUString& rFieldName, ScFieldIdentifier& rFieldId ) +{ + // "By name" is always the first match. + // The name "Data" always refers to the data layout field. + rFieldId.maFieldName = rFieldName; + rFieldId.mnFieldIdx = 0; + rFieldId.mbDataLayout = rFieldName.equalsAscii( SC_DATALAYOUT_NAME ); + + pDPObj->GetSource(); // IsDimNameInUse doesn't update source data + + // check if the named field exists (not for data layout) + return rFieldId.mbDataLayout || pDPObj->IsDimNameInUse( rFieldName ); +} + +// XDataPilotFields + +ScDataPilotFieldObj* ScDataPilotFieldsObj::GetObjectByIndex_Impl( sal_Int32 nIndex ) const +{ +// TODO + if (ScDPObject* pObj = GetDPObject()) + { + ScFieldIdentifier aFieldId; + if (lcl_GetFieldDataByIndex( pObj->GetSource(), maOrient, nIndex, aFieldId )) + return new ScDataPilotFieldObj( mrParent, aFieldId, maOrient ); + } + return 0; +} + +ScDataPilotFieldObj* ScDataPilotFieldsObj::GetObjectByName_Impl(const OUString& aName) const +{ + if (ScDPObject* pDPObj = GetDPObject()) + { + ScFieldIdentifier aFieldId; + if (lcl_GetFieldDataByName( pDPObj, aName, aFieldId )) + return new ScDataPilotFieldObj( mrParent, aFieldId, maOrient ); + } + return 0; +} + +// XEnumerationAccess + +Reference<XEnumeration> SAL_CALL ScDataPilotFieldsObj::createEnumeration() + throw(RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.DataPilotFieldsEnumeration"))); +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScDataPilotFieldsObj::getCount() throw(RuntimeException) +{ + ScUnoGuard aGuard; +// TODO + ScDPObject* pDPObj = GetDPObject(); + return pDPObj ? lcl_GetFieldCount( pDPObj->GetSource(), maOrient ) : 0; +} + +Any SAL_CALL ScDataPilotFieldsObj::getByIndex( sal_Int32 nIndex ) + throw(IndexOutOfBoundsException, WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + Reference< XPropertySet > xField( GetObjectByIndex_Impl( nIndex ) ); + if (!xField.is()) + throw IndexOutOfBoundsException(); + return Any( xField ); +} + +uno::Type SAL_CALL ScDataPilotFieldsObj::getElementType() throw(RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((Reference<XPropertySet>*)0); +} + +sal_Bool SAL_CALL ScDataPilotFieldsObj::hasElements() throw(RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +Any SAL_CALL ScDataPilotFieldsObj::getByName( const OUString& aName ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + Reference<XPropertySet> xField(GetObjectByName_Impl(aName)); + if (!xField.is()) + throw NoSuchElementException(); + return Any( xField ); +} + +Sequence<OUString> SAL_CALL ScDataPilotFieldsObj::getElementNames() + throw(RuntimeException) +{ + ScUnoGuard aGuard; +// TODO + if (ScDPObject* pDPObj = GetDPObject()) + { + Sequence< OUString > aSeq( lcl_GetFieldCount( pDPObj->GetSource(), maOrient ) ); + OUString* pAry = aSeq.getArray(); + const List& rDimensions = pDPObj->GetSaveData()->GetDimensions(); + sal_Int32 nDimCount = rDimensions.Count(); + for (sal_Int32 nDim = 0; nDim < nDimCount; nDim++) + { + ScDPSaveDimension* pDim = (ScDPSaveDimension*)rDimensions.GetObject(nDim); + if(maOrient.hasValue() && (pDim->GetOrientation() == maOrient.get< DataPilotFieldOrientation >())) + { + *pAry = pDim->GetName(); + ++pAry; + } + } + return aSeq; + } + return Sequence<OUString>(); +} + +sal_Bool SAL_CALL ScDataPilotFieldsObj::hasByName( const OUString& aName ) + throw(RuntimeException) +{ + ScUnoGuard aGuard; + + return GetObjectByName_Impl(aName) != NULL; +} + +//------------------------------------------------------------------------ + +ScDataPilotFieldObj::ScDataPilotFieldObj( + ScDataPilotDescriptorBase& rParent, const ScFieldIdentifier& rFieldId ) : + ScDataPilotChildObjBase( rParent, rFieldId ), + maPropSet( lcl_GetDataPilotFieldMap() ) +{ +} + +ScDataPilotFieldObj::ScDataPilotFieldObj( ScDataPilotDescriptorBase& rParent, + const ScFieldIdentifier& rFieldId, const Any& rOrient ) : + ScDataPilotChildObjBase( rParent, rFieldId ), + maPropSet( lcl_GetDataPilotFieldMap() ), + maOrient( rOrient ) +{ +} + +ScDataPilotFieldObj::~ScDataPilotFieldObj() +{ +} + +// XNamed + +OUString SAL_CALL ScDataPilotFieldObj::getName() throw(RuntimeException) +{ + ScUnoGuard aGuard; + OUString aName; + if( ScDPSaveDimension* pDim = GetDPDimension() ) + { + if( pDim->IsDataLayout() ) + aName = OUString( RTL_CONSTASCII_USTRINGPARAM( SC_DATALAYOUT_NAME ) ); + else + { + const rtl::OUString* pLayoutName = pDim->GetLayoutName(); + if (pLayoutName) + aName = *pLayoutName; + else + aName = pDim->GetName(); + } } + return aName; +} + +void SAL_CALL ScDataPilotFieldObj::setName( const OUString& rName ) throw(RuntimeException) +{ + ScUnoGuard aGuard; + ScDPObject* pDPObj = 0; + ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ); + if( pDim && !pDim->IsDataLayout() ) + { + String aName( rName ); + pDim->SetLayoutName(aName); + SetDPObject( pDPObj ); + } +} + +// XPropertySet + +Reference<XPropertySetInfo> SAL_CALL ScDataPilotFieldObj::getPropertySetInfo() + throw(RuntimeException) +{ + ScUnoGuard aGuard; + static Reference<XPropertySetInfo> aRef( + new SfxItemPropertySetInfo( maPropSet.getPropertyMap() )); + return aRef; +} + +void SAL_CALL ScDataPilotFieldObj::setPropertyValue( const OUString& aPropertyName, const Any& aValue ) + throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + String aNameString(aPropertyName); + if ( aNameString.EqualsAscii( SC_UNONAME_FUNCTION ) ) + { + // #i109350# use GetEnumFromAny because it also allows sal_Int32 + GeneralFunction eFunction = (GeneralFunction) + ScUnoHelpFunctions::GetEnumFromAny( aValue ); + setFunction( eFunction ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_SUBTOTALS ) ) + { + Sequence< GeneralFunction > aSubtotals; + if( aValue >>= aSubtotals ) + setSubtotals( aSubtotals ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_ORIENT ) ) + { + //! test for correct enum type? + DataPilotFieldOrientation eOrient = (DataPilotFieldOrientation) + ScUnoHelpFunctions::GetEnumFromAny( aValue ); + setOrientation( eOrient ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_SELPAGE ) ) + { + OUString sCurrentPage; + if (aValue >>= sCurrentPage) + setCurrentPage(sCurrentPage); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_USESELPAGE ) ) + { + setUseCurrentPage(cppu::any2bool(aValue)); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_HASAUTOSHOW ) ) + { + if (!cppu::any2bool(aValue)) + setAutoShowInfo(NULL); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_AUTOSHOW ) ) + { + DataPilotFieldAutoShowInfo aInfo; + if (aValue >>= aInfo) + setAutoShowInfo(&aInfo); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_HASLAYOUTINFO ) ) + { + if (!cppu::any2bool(aValue)) + setLayoutInfo(NULL); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_LAYOUTINFO ) ) + { + DataPilotFieldLayoutInfo aInfo; + if (aValue >>= aInfo) + setLayoutInfo(&aInfo); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_HASREFERENCE ) ) + { + if (!cppu::any2bool(aValue)) + setReference(NULL); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_REFERENCE ) ) + { + DataPilotFieldReference aRef; + if (aValue >>= aRef) + setReference(&aRef); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_HASSORTINFO ) ) + { + if (!cppu::any2bool(aValue)) + setSortInfo(NULL); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_SORTINFO ) ) + { + DataPilotFieldSortInfo aInfo; + if (aValue >>= aInfo) + setSortInfo(&aInfo); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_ISGROUP ) ) + { + if (!cppu::any2bool(aValue)) + setGroupInfo(NULL); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_GROUPINFO ) ) + { + DataPilotFieldGroupInfo aInfo; + if (aValue >>= aInfo) + setGroupInfo(&aInfo); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_SHOWEMPTY ) ) + { + setShowEmpty(cppu::any2bool(aValue)); + } +} + +Any SAL_CALL ScDataPilotFieldObj::getPropertyValue( const OUString& aPropertyName ) + throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + String aNameString(aPropertyName); + Any aRet; + + if ( aNameString.EqualsAscii( SC_UNONAME_FUNCTION ) ) + aRet <<= getFunction(); + else if ( aNameString.EqualsAscii( SC_UNONAME_SUBTOTALS ) ) + aRet <<= getSubtotals(); + else if ( aNameString.EqualsAscii( SC_UNONAME_ORIENT ) ) + aRet <<= getOrientation(); + else if ( aNameString.EqualsAscii( SC_UNONAME_SELPAGE ) ) + aRet <<= getCurrentPage(); + else if ( aNameString.EqualsAscii( SC_UNONAME_USESELPAGE ) ) + aRet <<= getUseCurrentPage(); + else if ( aNameString.EqualsAscii( SC_UNONAME_HASAUTOSHOW ) ) + aRet = ::cppu::bool2any(getAutoShowInfo() != NULL); + else if ( aNameString.EqualsAscii( SC_UNONAME_AUTOSHOW ) ) + { + const DataPilotFieldAutoShowInfo* pInfo = getAutoShowInfo(); + if (pInfo) + aRet <<= DataPilotFieldAutoShowInfo(*pInfo); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_HASLAYOUTINFO ) ) + aRet = ::cppu::bool2any(getLayoutInfo() != NULL); + else if ( aNameString.EqualsAscii( SC_UNONAME_LAYOUTINFO ) ) + { + const DataPilotFieldLayoutInfo* pInfo = getLayoutInfo(); + if (pInfo) + aRet <<= DataPilotFieldLayoutInfo(*pInfo); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_HASREFERENCE ) ) + aRet = ::cppu::bool2any(getReference() != NULL); + else if ( aNameString.EqualsAscii( SC_UNONAME_REFERENCE ) ) + { + const DataPilotFieldReference* pRef = getReference(); + if (pRef) + aRet <<= DataPilotFieldReference(*pRef); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_HASSORTINFO ) ) + aRet = ::cppu::bool2any(getSortInfo() != NULL); + else if ( aNameString.EqualsAscii( SC_UNONAME_SORTINFO ) ) + { + const DataPilotFieldSortInfo* pInfo = getSortInfo(); + if (pInfo) + aRet <<= DataPilotFieldSortInfo(*pInfo); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_ISGROUP ) ) + aRet = ::cppu::bool2any(hasGroupInfo()); + else if ( aNameString.EqualsAscii( SC_UNONAME_GROUPINFO ) ) + { + aRet <<= getGroupInfo(); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_SHOWEMPTY ) ) + aRet <<= getShowEmpty(); + + return aRet; +} + +// XDatePilotField + +Reference<XIndexAccess> SAL_CALL ScDataPilotFieldObj::getItems() + throw (RuntimeException) +{ + ScUnoGuard aGuard; + if (!mxItems.is()) + mxItems.set( new ScDataPilotItemsObj( mrParent, maFieldId ) ); + return mxItems; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDataPilotFieldObj ) + +DataPilotFieldOrientation ScDataPilotFieldObj::getOrientation() const +{ + ScUnoGuard aGuard; + ScDPSaveDimension* pDim = GetDPDimension(); + return pDim ? static_cast< DataPilotFieldOrientation >( pDim->GetOrientation() ) : DataPilotFieldOrientation_HIDDEN; +} + +void ScDataPilotFieldObj::setOrientation(DataPilotFieldOrientation eNew) +{ + ScUnoGuard aGuard; + if (maOrient.hasValue() && (eNew == maOrient.get< DataPilotFieldOrientation >())) + return; + + ScDPObject* pDPObj = 0; + if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) ) + { + ScDPSaveData* pSaveData = pDPObj->GetSaveData(); + + /* If the field was taken from getDataPilotFields(), don't reset the + orientation for an existing use, but create a duplicated field + instead (for "Data" orientation only). */ + if ( !maOrient.hasValue() && !maFieldId.mbDataLayout && + (pDim->GetOrientation() != DataPilotFieldOrientation_HIDDEN) && + (eNew == DataPilotFieldOrientation_DATA) ) + { + + ScDPSaveDimension* pNewDim = 0; + + // look for existing duplicate with orientation "hidden" + + String aNameStr( maFieldId.maFieldName ); + const List& rDimensions = pSaveData->GetDimensions(); + sal_Int32 nDimCount = rDimensions.Count(); + sal_Int32 nFound = 0; + for ( sal_Int32 nDim = 0; nDim < nDimCount && !pNewDim; nDim++ ) + { + ScDPSaveDimension* pOneDim = static_cast<ScDPSaveDimension*>(rDimensions.GetObject(nDim)); + if ( !pOneDim->IsDataLayout() && (pOneDim->GetName() == aNameStr) ) + { + if ( pOneDim->GetOrientation() == DataPilotFieldOrientation_HIDDEN ) + pNewDim = pOneDim; // use this one + else + ++nFound; // count existing non-hidden occurences + } + } + + if ( !pNewDim ) // if none found, create a new duplicated dimension + pNewDim = &pSaveData->DuplicateDimension( *pDim ); + + maFieldId.mnFieldIdx = nFound; // keep accessing the new one + pDim = pNewDim; + } + + pDim->SetOrientation(sal::static_int_cast<USHORT>(eNew)); + + // move changed field behind all other fields (make it the last field in dimension) + pSaveData->SetPosition( pDim, pSaveData->GetDimensions().Count() ); + + SetDPObject( pDPObj ); + + maOrient <<= eNew; // modifying the same object's orientation again doesn't create another duplicate + } +} + +GeneralFunction ScDataPilotFieldObj::getFunction() const +{ + ScUnoGuard aGuard; + GeneralFunction eRet = GeneralFunction_NONE; + if( ScDPSaveDimension* pDim = GetDPDimension() ) + { + if( pDim->GetOrientation() != DataPilotFieldOrientation_DATA ) + { + // for non-data fields, property Function is the subtotals + long nSubCount = pDim->GetSubTotalsCount(); + if ( nSubCount > 0 ) + eRet = (GeneralFunction)pDim->GetSubTotalFunc(0); // always use the first one + // else keep NONE + } + else + eRet = (GeneralFunction)pDim->GetFunction(); + } + return eRet; +} + +void ScDataPilotFieldObj::setFunction(GeneralFunction eNewFunc) +{ + ScUnoGuard aGuard; + ScDPObject* pDPObj = 0; + if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) ) + { + if( pDim->GetOrientation() != DataPilotFieldOrientation_DATA ) + { + // for non-data fields, property Function is the subtotals + if ( eNewFunc == GeneralFunction_NONE ) + pDim->SetSubTotals( 0, NULL ); + else + { + USHORT nFunc = sal::static_int_cast<USHORT>( eNewFunc ); + pDim->SetSubTotals( 1, &nFunc ); + } + } + else + pDim->SetFunction( sal::static_int_cast<USHORT>( eNewFunc ) ); + SetDPObject( pDPObj ); + } +} + +Sequence< GeneralFunction > ScDataPilotFieldObj::getSubtotals() const +{ + ScUnoGuard aGuard; + Sequence< GeneralFunction > aRet; + if( ScDPSaveDimension* pDim = GetDPDimension() ) + { + if( pDim->GetOrientation() != DataPilotFieldOrientation_DATA ) + { + // for non-data fields, property Functions is the sequence of subtotals + sal_Int32 nCount = static_cast< sal_Int32 >( pDim->GetSubTotalsCount() ); + if ( nCount > 0 ) + { + aRet.realloc( nCount ); + for( sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx ) + aRet[ nIdx ] = (GeneralFunction)pDim->GetSubTotalFunc( nIdx ); + } + } + } + return aRet; +} + +void ScDataPilotFieldObj::setSubtotals( const Sequence< GeneralFunction >& rSubtotals ) +{ + ScUnoGuard aGuard; + ScDPObject* pDPObj = 0; + if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) ) + { + if( pDim->GetOrientation() != DataPilotFieldOrientation_DATA ) + { + sal_Int32 nCount = rSubtotals.getLength(); + if( nCount == 1 ) + { + // count 1: all values are allowed (including NONE and AUTO) + if( rSubtotals[ 0 ] == GeneralFunction_NONE ) + pDim->SetSubTotals( 0, NULL ); + else + { + USHORT nFunc = sal::static_int_cast<USHORT>( rSubtotals[ 0 ] ); + pDim->SetSubTotals( 1, &nFunc ); + } + } + else if( nCount > 1 ) + { + // set multiple functions, ignore NONE and AUTO in this case + ::std::vector< USHORT > aSubt; + for( sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx ) + { + GeneralFunction eFunc = rSubtotals[ nIdx ]; + if( (eFunc != GeneralFunction_NONE) && (eFunc != GeneralFunction_AUTO) ) + { + // do not insert functions twice + USHORT nFunc = static_cast< USHORT >( eFunc ); + if( ::std::find( aSubt.begin(), aSubt.end(), nFunc ) == aSubt.end() ) + aSubt.push_back( nFunc ); + } + } + // set values from vector to ScDPSaveDimension + if ( aSubt.empty() ) + pDim->SetSubTotals( 0, NULL ); + else + pDim->SetSubTotals( static_cast< long >( aSubt.size() ), &aSubt.front() ); + } + } + SetDPObject( pDPObj ); + } +} + +OUString ScDataPilotFieldObj::getCurrentPage() const +{ + ScUnoGuard aGuard; + ScDPSaveDimension* pDim = GetDPDimension(); + if( pDim && pDim->HasCurrentPage() ) + return pDim->GetCurrentPage(); + return OUString(); +} + +void ScDataPilotFieldObj::setCurrentPage( const OUString& rPage ) +{ + ScUnoGuard aGuard; + ScDPObject* pDPObj = 0; + if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) ) + { + String aPage( rPage ); + pDim->SetCurrentPage( &aPage ); + SetDPObject( pDPObj ); + } +} + +sal_Bool ScDataPilotFieldObj::getUseCurrentPage() const +{ + ScUnoGuard aGuard; + ScDPSaveDimension* pDim = GetDPDimension(); + return pDim && pDim->HasCurrentPage(); +} + +void ScDataPilotFieldObj::setUseCurrentPage( sal_Bool bUse ) +{ + ScUnoGuard aGuard; + ScDPObject* pDPObj = 0; + if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) ) + { + if( bUse ) + { + /* It is somehow useless to set the property "HasSelectedPage" to + true, because it is still needed to set an explicit page name. */ + if( !pDim->HasCurrentPage() ) + { + String aPage; + pDim->SetCurrentPage( &aPage ); + } + } + else + pDim->SetCurrentPage( 0 ); + SetDPObject( pDPObj ); + } +} + +const DataPilotFieldAutoShowInfo* ScDataPilotFieldObj::getAutoShowInfo() +{ + ScUnoGuard aGuard; + ScDPSaveDimension* pDim = GetDPDimension(); + return pDim ? pDim->GetAutoShowInfo() : 0; +} + +void ScDataPilotFieldObj::setAutoShowInfo( const DataPilotFieldAutoShowInfo* pInfo ) +{ + ScUnoGuard aGuard; + ScDPObject* pDPObj = 0; + if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) ) + { + pDim->SetAutoShowInfo( pInfo ); + SetDPObject( pDPObj ); + } +} + +const DataPilotFieldLayoutInfo* ScDataPilotFieldObj::getLayoutInfo() +{ + ScUnoGuard aGuard; + ScDPSaveDimension* pDim = GetDPDimension(); + return pDim ? pDim->GetLayoutInfo() : 0; +} + +void ScDataPilotFieldObj::setLayoutInfo( const DataPilotFieldLayoutInfo* pInfo ) +{ + ScUnoGuard aGuard; + ScDPObject* pDPObj = 0; + if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) ) + { + pDim->SetLayoutInfo( pInfo ); + SetDPObject( pDPObj ); + } +} + +const DataPilotFieldReference* ScDataPilotFieldObj::getReference() +{ + ScUnoGuard aGuard; + ScDPSaveDimension* pDim = GetDPDimension(); + return pDim ? pDim->GetReferenceValue() : 0; +} + +void ScDataPilotFieldObj::setReference( const DataPilotFieldReference* pInfo ) +{ + ScUnoGuard aGuard; + ScDPObject* pDPObj = 0; + if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) ) + { + pDim->SetReferenceValue( pInfo ); + SetDPObject( pDPObj ); + } +} + +const DataPilotFieldSortInfo* ScDataPilotFieldObj::getSortInfo() +{ + ScUnoGuard aGuard; + ScDPSaveDimension* pDim = GetDPDimension(); + return pDim ? pDim->GetSortInfo() : 0; +} + +void ScDataPilotFieldObj::setSortInfo( const DataPilotFieldSortInfo* pInfo ) +{ + ScUnoGuard aGuard; + ScDPObject* pDPObj = 0; + if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) ) + { + pDim->SetSortInfo( pInfo ); + SetDPObject( pDPObj ); + } +} + +sal_Bool ScDataPilotFieldObj::getShowEmpty() const +{ + ScUnoGuard aGuard; + ScDPSaveDimension* pDim = GetDPDimension(); + return pDim && pDim->GetShowEmpty(); +} + +void ScDataPilotFieldObj::setShowEmpty( sal_Bool bShow ) +{ + ScUnoGuard aGuard; + ScDPObject* pDPObj = 0; + if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) ) + { + pDim->SetShowEmpty( bShow ); + SetDPObject( pDPObj ); + } +} + +sal_Bool ScDataPilotFieldObj::hasGroupInfo() +{ + ScUnoGuard aGuard; + ScDPObject* pDPObj = 0; + if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) ) + if( const ScDPDimensionSaveData* pDimData = pDPObj->GetSaveData()->GetExistingDimensionData() ) + return pDimData->GetNamedGroupDim( pDim->GetName() ) || pDimData->GetNumGroupDim( pDim->GetName() ); + return sal_False; +} + +DataPilotFieldGroupInfo ScDataPilotFieldObj::getGroupInfo() +{ + ScUnoGuard aGuard; + DataPilotFieldGroupInfo aInfo; + ScDPObject* pDPObj = 0; + if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) ) + { + if( const ScDPDimensionSaveData* pDimData = pDPObj->GetSaveData()->GetExistingDimensionData() ) + { + if( const ScDPSaveGroupDimension* pGroupDim = pDimData->GetNamedGroupDim( pDim->GetName() ) ) + { + // grouped by ... + aInfo.GroupBy = pGroupDim->GetDatePart(); + + // find source field + try + { + Reference< XNameAccess > xFields( mrParent.getDataPilotFields(), UNO_QUERY_THROW ); + aInfo.SourceField.set( xFields->getByName( pGroupDim->GetSourceDimName() ), UNO_QUERY ); + } + catch( Exception& ) + { + } + + ScDataPilotConversion::FillGroupInfo( aInfo, pGroupDim->GetDateInfo() ); + if( pGroupDim->GetDatePart() == 0 ) + { + // fill vector of group and group member information + ScFieldGroups aGroups; + for( sal_Int32 nIdx = 0, nCount = pGroupDim->GetGroupCount(); nIdx < nCount; ++nIdx ) + { + if( const ScDPSaveGroupItem* pGroup = pGroupDim->GetGroupByIndex( nIdx ) ) + { + ScFieldGroup aGroup; + aGroup.maName = pGroup->GetGroupName(); + for( sal_Int32 nMemIdx = 0, nMemCount = pGroup->GetElementCount(); nMemIdx < nMemCount; ++nMemIdx ) + if( const String* pMem = pGroup->GetElementByIndex( nMemIdx ) ) + aGroup.maMembers.push_back( *pMem ); + aGroups.push_back( aGroup ); + } + } + aInfo.Groups = new ScDataPilotFieldGroupsObj( aGroups ); + } + } + else if( const ScDPSaveNumGroupDimension* pNumGroupDim = pDimData->GetNumGroupDim( pDim->GetName() ) ) + { + if (pNumGroupDim->GetDatePart()) + { + ScDataPilotConversion::FillGroupInfo( aInfo, pNumGroupDim->GetDateInfo() ); + aInfo.GroupBy = pNumGroupDim->GetDatePart(); + } + else + { + ScDataPilotConversion::FillGroupInfo( aInfo, pNumGroupDim->GetInfo() ); + } + } + } + } + return aInfo; +} + +void ScDataPilotFieldObj::setGroupInfo( const DataPilotFieldGroupInfo* pInfo ) +{ + ScUnoGuard aGuard; + ScDPObject* pDPObj = 0; + if( /*ScDPSaveDimension* pDim =*/ GetDPDimension( &pDPObj ) ) + { + ScDPSaveData* pSaveData = pDPObj->GetSaveData(); + if( pInfo && lclCheckMinMaxStep( *pInfo ) ) + { + ScDPNumGroupInfo aInfo; + aInfo.Enable = sal_True; + aInfo.DateValues = pInfo->HasDateValues; + aInfo.AutoStart = pInfo->HasAutoStart; + aInfo.AutoEnd = pInfo->HasAutoEnd; + aInfo.Start = pInfo->Start; + aInfo.End = pInfo->End; + aInfo.Step = pInfo->Step; + Reference< XNamed > xNamed( pInfo->SourceField, UNO_QUERY ); + if( xNamed.is() ) + { + ScDPSaveGroupDimension aGroupDim( xNamed->getName(), getName() ); + if( pInfo->GroupBy ) + aGroupDim.SetDateInfo(aInfo, pInfo->GroupBy); + else + { + Reference<XIndexAccess> xIndex(pInfo->Groups, UNO_QUERY); + if (xIndex.is()) + { + sal_Int32 nCount(xIndex->getCount()); + for(sal_Int32 i = 0; i < nCount; i++) + { + Reference<XNamed> xGroupNamed(xIndex->getByIndex(i), UNO_QUERY); + if (xGroupNamed.is()) + { + ScDPSaveGroupItem aItem(xGroupNamed->getName()); + Reference<XIndexAccess> xGroupIndex(xGroupNamed, UNO_QUERY); + if (xGroupIndex.is()) + { + sal_Int32 nItemCount(xGroupIndex->getCount()); + for (sal_Int32 j = 0; j < nItemCount; ++j) + { + Reference<XNamed> xItemNamed(xGroupIndex->getByIndex(j), UNO_QUERY); + if (xItemNamed.is()) + aItem.AddElement(xItemNamed->getName()); + } + } + aGroupDim.AddGroupItem(aItem); + } + } + } + } + + // get dimension savedata or create new if none + ScDPDimensionSaveData& rDimSaveData = *pSaveData->GetDimensionData(); + rDimSaveData.ReplaceGroupDimension( aGroupDim ); + } + else // no source field in group info -> numeric group + { + ScDPDimensionSaveData* pDimData = pSaveData->GetDimensionData(); // created if not there + + ScDPSaveNumGroupDimension* pExisting = pDimData->GetNumGroupDimAcc( getName() ); + if ( pExisting ) + { + if (pInfo->GroupBy) + pExisting->SetDateInfo(aInfo, pInfo->GroupBy); + // modify existing group dimension + pExisting->SetGroupInfo( aInfo ); + } + else if (pInfo->GroupBy) + { + // create new group dimension + ScDPSaveNumGroupDimension aNumGroupDim( getName(), aInfo, pInfo->GroupBy ); + pDimData->AddNumGroupDimension( aNumGroupDim ); + } + else + { + // create new group dimension + ScDPSaveNumGroupDimension aNumGroupDim( getName(), aInfo ); + pDimData->AddNumGroupDimension( aNumGroupDim ); + } + } + } + else // null passed as argument + { + pSaveData->SetDimensionData( 0 ); + } + + pDPObj->SetSaveData( *pSaveData ); + SetDPObject( pDPObj ); + } +} + +sal_Bool ScDataPilotFieldObj::HasString(const Sequence< OUString >& rItems, const OUString& aString) +{ + sal_Bool bRet = sal_False; + + sal_Int32 nCount(rItems.getLength()); + sal_Int32 nItem(0); + while (nItem < nCount && !bRet) + { + bRet = rItems[nItem] == aString; + ++nItem; + } + + return bRet; +} + +// XDataPilotFieldGrouping +Reference< XDataPilotField > SAL_CALL ScDataPilotFieldObj::createNameGroup( const Sequence< OUString >& rItems ) + throw (RuntimeException, IllegalArgumentException) +{ + ScUnoGuard aGuard; + + Reference< XDataPilotField > xRet; + OUString sNewDim; + + if( !rItems.hasElements() ) + throw IllegalArgumentException(); + + ScDPObject* pDPObj = 0; + if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) ) + { + String aDimName = pDim->GetName(); + + ScDPSaveData aSaveData = *pDPObj->GetSaveData(); + ScDPDimensionSaveData* pDimData = aSaveData.GetDimensionData(); // created if not there + + // find original base + String aBaseDimName( aDimName ); + const ScDPSaveGroupDimension* pBaseGroupDim = pDimData->GetNamedGroupDim( aDimName ); + if ( pBaseGroupDim ) + { + // any entry's SourceDimName is the original base + aBaseDimName = pBaseGroupDim->GetSourceDimName(); + } + + // find existing group dimension + // (using the selected dim, can be intermediate group dim) + ScDPSaveGroupDimension* pGroupDimension = pDimData->GetGroupDimAccForBase( aDimName ); + + // remove the selected items from their groups + // (empty groups are removed, too) + sal_Int32 nEntryCount = rItems.getLength(); + sal_Int32 nEntry; + if ( pGroupDimension ) + { + for (nEntry=0; nEntry<nEntryCount; nEntry++) + { + String aEntryName(rItems[nEntry]); + if ( pBaseGroupDim ) + { + // for each selected (intermediate) group, remove all its items + // (same logic as for adding, below) + const ScDPSaveGroupItem* pBaseGroup = pBaseGroupDim->GetNamedGroup( aEntryName ); + if ( pBaseGroup ) + pBaseGroup->RemoveElementsFromGroups( *pGroupDimension ); // remove all elements + else + pGroupDimension->RemoveFromGroups( aEntryName ); + } + else + pGroupDimension->RemoveFromGroups( aEntryName ); + } + } + + ScDPSaveGroupDimension* pNewGroupDim = 0; + if ( !pGroupDimension ) + { + // create a new group dimension + String aGroupDimName = pDimData->CreateGroupDimName( aBaseDimName, *pDPObj, false, NULL ); + pNewGroupDim = new ScDPSaveGroupDimension( aBaseDimName, aGroupDimName ); + sNewDim = aGroupDimName; + + pGroupDimension = pNewGroupDim; // make changes to the new dim if none existed + + if ( pBaseGroupDim ) + { + // If it's a higher-order group dimension, pre-allocate groups for all + // non-selected original groups, so the individual base members aren't + // used for automatic groups (this would make the original groups hard + // to find). + //! Also do this when removing groups? + //! Handle this case dynamically with automatic groups? + + long nGroupCount = pBaseGroupDim->GetGroupCount(); + for ( long nGroup = 0; nGroup < nGroupCount; nGroup++ ) + { + const ScDPSaveGroupItem* pBaseGroup = pBaseGroupDim->GetGroupByIndex( nGroup ); + + StrData aStrData( pBaseGroup->GetGroupName() ); + if ( !HasString(rItems, aStrData.GetString()) ) //! ignore case? + { + // add an additional group for each item that is not in the selection + ScDPSaveGroupItem aGroup( pBaseGroup->GetGroupName() ); + aGroup.AddElementsFromGroup( *pBaseGroup ); + pGroupDimension->AddGroupItem( aGroup ); + } + } + } + } + String aGroupDimName = pGroupDimension->GetGroupDimName(); + + //! localized prefix string + String aGroupName = pGroupDimension->CreateGroupName( String( RTL_CONSTASCII_USTRINGPARAM( "Group" ) ) ); + ScDPSaveGroupItem aGroup( aGroupName ); + Reference< XNameAccess > xMembers = GetMembers(); + if (!xMembers.is()) + { + delete pNewGroupDim; + throw RuntimeException(); + } + + for (nEntry=0; nEntry<nEntryCount; nEntry++) + { + String aEntryName(rItems[nEntry]); + + if (!xMembers->hasByName(aEntryName)) + { + delete pNewGroupDim; + throw IllegalArgumentException(); + } + + if ( pBaseGroupDim ) + { + // for each selected (intermediate) group, add all its items + const ScDPSaveGroupItem* pBaseGroup = pBaseGroupDim->GetNamedGroup( aEntryName ); + if ( pBaseGroup ) + aGroup.AddElementsFromGroup( *pBaseGroup ); + else + aGroup.AddElement( aEntryName ); // no group found -> automatic group, add the item itself + } + else + aGroup.AddElement( aEntryName ); // no group dimension, add all items directly + } + + pGroupDimension->AddGroupItem( aGroup ); + + if ( pNewGroupDim ) + { + pDimData->AddGroupDimension( *pNewGroupDim ); + delete pNewGroupDim; // AddGroupDimension copies the object + // don't access pGroupDimension after here + } + pGroupDimension = pNewGroupDim = NULL; + + // set orientation + ScDPSaveDimension* pSaveDimension = aSaveData.GetDimensionByName( aGroupDimName ); + if ( pSaveDimension->GetOrientation() == DataPilotFieldOrientation_HIDDEN ) + { + ScDPSaveDimension* pOldDimension = aSaveData.GetDimensionByName( aDimName ); + pSaveDimension->SetOrientation( pOldDimension->GetOrientation() ); + long nPosition = 0; //! before (immediate) base + aSaveData.SetPosition( pSaveDimension, nPosition ); + } + + // apply changes + pDPObj->SetSaveData( aSaveData ); + SetDPObject( pDPObj ); + } + + // if new grouping field has been created (on first group), return it + if( sNewDim.getLength() > 0 ) + { + Reference< XNameAccess > xFields(mrParent.getDataPilotFields(), UNO_QUERY); + if (xFields.is()) + { + xRet.set(xFields->getByName(sNewDim), UNO_QUERY); + DBG_ASSERT(xRet.is(), "there is a name, so there should be also a field"); + } + } + return xRet; +} + +Reference < XDataPilotField > SAL_CALL ScDataPilotFieldObj::createDateGroup( const DataPilotFieldGroupInfo& rInfo ) + throw (RuntimeException, IllegalArgumentException) +{ + ScUnoGuard aGuard; + using namespace ::com::sun::star::sheet::DataPilotFieldGroupBy; + + // check min/max/step, HasDateValues must be set always + if( !rInfo.HasDateValues || !lclCheckMinMaxStep( rInfo ) ) + throw IllegalArgumentException(); + // only a single date flag is allowed + if( (rInfo.GroupBy == 0) || (rInfo.GroupBy > YEARS) || ((rInfo.GroupBy & (rInfo.GroupBy - 1)) != 0) ) + throw IllegalArgumentException(); + // step must be zero, if something else than DAYS is specified + if( rInfo.Step >= ((rInfo.GroupBy == DAYS) ? 32768.0 : 1.0) ) + throw IllegalArgumentException(); + + String aGroupDimName; + ScDPObject* pDPObj = 0; + if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) ) + { + ScDPNumGroupInfo aInfo; + aInfo.Enable = sal_True; + aInfo.DateValues = (rInfo.GroupBy == DAYS) && (rInfo.Step >= 1.0); + aInfo.AutoStart = rInfo.HasAutoStart; + aInfo.AutoEnd = rInfo.HasAutoEnd; + aInfo.Start = rInfo.Start; + aInfo.End = rInfo.End; + aInfo.Step = static_cast< sal_Int32 >( rInfo.Step ); + + // create a local copy of the entire save data (will be written back below) + ScDPSaveData aSaveData = *pDPObj->GetSaveData(); + // get or create dimension save data + ScDPDimensionSaveData& rDimData = *aSaveData.GetDimensionData(); + + // find source dimension name + const String& rDimName = pDim->GetName(); + const ScDPSaveGroupDimension* pGroupDim = rDimData.GetNamedGroupDim( rDimName ); + String aSrcDimName = pGroupDim ? pGroupDim->GetSourceDimName() : rDimName; + + // find a group dimension for the base field, or get numeric grouping + pGroupDim = rDimData.GetFirstNamedGroupDim( aSrcDimName ); + const ScDPSaveNumGroupDimension* pNumGroupDim = rDimData.GetNumGroupDim( aSrcDimName ); + + // do not group by dates, if named groups or numeric grouping is present + bool bHasNamedGrouping = pGroupDim && !pGroupDim->GetDateInfo().Enable; + bool bHasNumGrouping = pNumGroupDim && pNumGroupDim->GetInfo().Enable && !pNumGroupDim->GetInfo().DateValues && !pNumGroupDim->GetDateInfo().Enable; + if( bHasNamedGrouping || bHasNumGrouping ) + throw IllegalArgumentException(); + + if( aInfo.DateValues ) // create day ranges grouping + { + // first remove all named group dimensions + while( pGroupDim ) + { + String aGroupDimName2 = pGroupDim->GetGroupDimName(); + // find next group dimension before deleting this group + pGroupDim = rDimData.GetNextNamedGroupDim( aGroupDimName2 ); + // remove from dimension save data + rDimData.RemoveGroupDimension( aGroupDimName2 ); + // also remove save data settings for the dimension that no longer exists + aSaveData.RemoveDimensionByName( aGroupDimName2 ); + } + // create or replace the number grouping dimension + ScDPSaveNumGroupDimension aNumGroupDim( aSrcDimName, aInfo ); + rDimData.ReplaceNumGroupDimension( aNumGroupDim ); + } + else // create date grouping + { + // collect all existing date flags + sal_Int32 nDateParts = rDimData.CollectDateParts( aSrcDimName ); + if( nDateParts == 0 ) + { + // insert numeric group dimension, if no date groups exist yet (or replace day range grouping) + ScDPSaveNumGroupDimension aNumGroupDim( aSrcDimName, aInfo, rInfo.GroupBy ); + rDimData.ReplaceNumGroupDimension( aNumGroupDim ); + } + else if( (nDateParts & rInfo.GroupBy) == 0 ) // do nothing if date field exists already + { + // create new named group dimension for additional date groups + aGroupDimName = rDimData.CreateDateGroupDimName( rInfo.GroupBy, *pDPObj, true, 0 ); + ScDPSaveGroupDimension aGroupDim( aSrcDimName, aGroupDimName, aInfo, rInfo.GroupBy ); + rDimData.AddGroupDimension( aGroupDim ); + + // set orientation of new named group dimension + ScDPSaveDimension& rSaveDim = *aSaveData.GetDimensionByName( aGroupDimName ); + if( rSaveDim.GetOrientation() == DataPilotFieldOrientation_HIDDEN ) + { + ScDPSaveDimension& rOldDim = *aSaveData.GetDimensionByName( aSrcDimName ); + rSaveDim.SetOrientation( rOldDim.GetOrientation() ); + aSaveData.SetPosition( &rSaveDim, 0 ); //! before (immediate) base + } + } + } + + // apply changes + pDPObj->SetSaveData( aSaveData ); + SetDPObject( pDPObj ); + } + + // return the UNO object of the new dimension, after writing back saved data + Reference< XDataPilotField > xRet; + if( aGroupDimName.Len() > 0 ) try + { + Reference< XNameAccess > xFields( mrParent.getDataPilotFields(), UNO_QUERY_THROW ); + xRet.set( xFields->getByName( aGroupDimName ), UNO_QUERY ); + } + catch( Exception& ) + { + } + return xRet; +} + +// ============================================================================ + +namespace { + +bool lclExtractGroupMembers( ScFieldGroupMembers& rMembers, const Any& rElement ) +{ + // allow empty value to create a new group + if( !rElement.hasValue() ) + return true; + + // try to extract a simple sequence of strings + Sequence< OUString > aSeq; + if( rElement >>= aSeq ) + { + if( aSeq.hasElements() ) + rMembers.insert( rMembers.end(), aSeq.getConstArray(), aSeq.getConstArray() + aSeq.getLength() ); + return true; + } + + // try to use XIndexAccess providing objects that support XNamed + Reference< XIndexAccess > xItemsIA( rElement, UNO_QUERY ); + if( xItemsIA.is() ) + { + for( sal_Int32 nIdx = 0, nCount = xItemsIA->getCount(); nIdx < nCount; ++nIdx ) + { + try // getByIndex() should not throw, but we cannot be sure + { + Reference< XNamed > xItemName( xItemsIA->getByIndex( nIdx ), UNO_QUERY_THROW ); + rMembers.push_back( xItemName->getName() ); + } + catch( Exception& ) + { + // ignore exceptions, go ahead with next element in the array + } + } + return true; + } + + // nothing valid inside the Any -> return false + return false; +} + +} // namespace + +// ---------------------------------------------------------------------------- + +ScDataPilotFieldGroupsObj::ScDataPilotFieldGroupsObj( const ScFieldGroups& rGroups ) : + maGroups( rGroups ) +{ +} + +ScDataPilotFieldGroupsObj::~ScDataPilotFieldGroupsObj() +{ +} + +// XNameAccess + +Any SAL_CALL ScDataPilotFieldGroupsObj::getByName( const OUString& rName ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + if( implFindByName( rName ) == maGroups.end() ) + throw NoSuchElementException(); + return Any( Reference< XNameAccess >( new ScDataPilotFieldGroupObj( *this, rName ) ) ); +} + +Sequence< OUString > SAL_CALL ScDataPilotFieldGroupsObj::getElementNames() throw(RuntimeException) +{ + ScUnoGuard aGuard; + Sequence< OUString > aSeq; + if( !maGroups.empty() ) + { + aSeq.realloc( static_cast< sal_Int32 >( maGroups.size() ) ); + OUString* pName = aSeq.getArray(); + for( ScFieldGroups::iterator aIt = maGroups.begin(), aEnd = maGroups.end(); aIt != aEnd; ++aIt, ++pName ) + *pName = aIt->maName; + } + return aSeq; +} + +sal_Bool SAL_CALL ScDataPilotFieldGroupsObj::hasByName( const OUString& rName ) throw(RuntimeException) +{ + ScUnoGuard aGuard; + return implFindByName( rName ) != maGroups.end(); +} + +// XNameReplace + +void SAL_CALL ScDataPilotFieldGroupsObj::replaceByName( const OUString& rName, const Any& rElement ) + throw (IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + + if( rName.getLength() == 0 ) + throw IllegalArgumentException(); + + ScFieldGroups::iterator aIt = implFindByName( rName ); + if( aIt == maGroups.end() ) + throw NoSuchElementException(); + + // read all item names provided by the passed object + ScFieldGroupMembers aMembers; + if( !lclExtractGroupMembers( aMembers, rElement ) ) + throw IllegalArgumentException(); + + // copy and forget, faster than vector assignment + aIt->maMembers.swap( aMembers ); +} + +// XNameContainer + +void SAL_CALL ScDataPilotFieldGroupsObj::insertByName( const OUString& rName, const Any& rElement ) + throw (IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + + if( rName.getLength() == 0 ) + throw IllegalArgumentException(); + + ScFieldGroups::iterator aIt = implFindByName( rName ); + if( aIt != maGroups.end() ) + throw ElementExistException(); + + // read all item names provided by the passed object + ScFieldGroupMembers aMembers; + if( !lclExtractGroupMembers( aMembers, rElement ) ) + throw IllegalArgumentException(); + + // create the new entry if no error has been occured + maGroups.resize( maGroups.size() + 1 ); + ScFieldGroup& rGroup = maGroups.back(); + rGroup.maName = rName; + rGroup.maMembers.swap( aMembers ); +} + +void SAL_CALL ScDataPilotFieldGroupsObj::removeByName( const OUString& rName ) + throw (NoSuchElementException, WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + + if( rName.getLength() == 0 ) + throw IllegalArgumentException(); + + ScFieldGroups::iterator aIt = implFindByName( rName ); + if( aIt == maGroups.end() ) + throw NoSuchElementException(); + + maGroups.erase( aIt ); +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScDataPilotFieldGroupsObj::getCount() throw(RuntimeException) +{ + ScUnoGuard aGuard; + return static_cast< sal_Int32 >( maGroups.size() ); +} + +Any SAL_CALL ScDataPilotFieldGroupsObj::getByIndex( sal_Int32 nIndex ) + throw(IndexOutOfBoundsException, WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + if ((nIndex < 0) || (nIndex >= static_cast< sal_Int32 >( maGroups.size() ))) + throw IndexOutOfBoundsException(); + return Any( Reference< XNameAccess >( new ScDataPilotFieldGroupObj( *this, maGroups[ nIndex ].maName ) ) ); +} + +// XEnumerationAccess + +Reference<XEnumeration> SAL_CALL ScDataPilotFieldGroupsObj::createEnumeration() throw(RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration( this, OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.DataPilotFieldGroupsEnumeration" ) ) ); +} + +// XElementAccess + +uno::Type SAL_CALL ScDataPilotFieldGroupsObj::getElementType() throw(RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType( (Reference< XNameAccess >*)0 ); +} + +sal_Bool SAL_CALL ScDataPilotFieldGroupsObj::hasElements() throw(RuntimeException) +{ + ScUnoGuard aGuard; + return !maGroups.empty(); +} + +// implementation + +ScFieldGroup& ScDataPilotFieldGroupsObj::getFieldGroup( const OUString& rName ) throw(RuntimeException) +{ + ScUnoGuard aGuard; + ScFieldGroups::iterator aIt = implFindByName( rName ); + if( aIt == maGroups.end() ) + throw RuntimeException(); + return *aIt; +} + +void ScDataPilotFieldGroupsObj::renameFieldGroup( const OUString& rOldName, const OUString& rNewName ) throw(RuntimeException) +{ + ScUnoGuard aGuard; + ScFieldGroups::iterator aOldIt = implFindByName( rOldName ); + ScFieldGroups::iterator aNewIt = implFindByName( rNewName ); + // new name must not exist yet + if( (aOldIt == maGroups.end()) || ((aNewIt != maGroups.end()) && (aNewIt != aOldIt)) ) + throw RuntimeException(); + aOldIt->maName = rNewName; +} + +// private + +ScFieldGroups::iterator ScDataPilotFieldGroupsObj::implFindByName( const OUString& rName ) +{ + for( ScFieldGroups::iterator aIt = maGroups.begin(), aEnd = maGroups.end(); aIt != aEnd; ++aIt ) + if( aIt->maName == rName ) + return aIt; + return maGroups.end(); +} + +// ============================================================================ + +namespace { + +OUString lclExtractMember( const Any& rElement ) +{ + if( rElement.has< OUString >() ) + return rElement.get< OUString >(); + + Reference< XNamed > xNamed( rElement, UNO_QUERY ); + if( xNamed.is() ) + return xNamed->getName(); + + return OUString(); +} + +} // namespace + +// ---------------------------------------------------------------------------- + +ScDataPilotFieldGroupObj::ScDataPilotFieldGroupObj( ScDataPilotFieldGroupsObj& rParent, const OUString& rGroupName ) : + mrParent( rParent ), + maGroupName( rGroupName ) +{ + mrParent.acquire(); +} + +ScDataPilotFieldGroupObj::~ScDataPilotFieldGroupObj() +{ + mrParent.release(); +} + +// XNameAccess + +Any SAL_CALL ScDataPilotFieldGroupObj::getByName( const OUString& rName ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + ScFieldGroupMembers& rMembers = mrParent.getFieldGroup( maGroupName ).maMembers; + ScFieldGroupMembers::iterator aIt = ::std::find( rMembers.begin(), rMembers.end(), rName ); + if( aIt == rMembers.end() ) + throw NoSuchElementException(); + return Any( Reference< XNamed >( new ScDataPilotFieldGroupItemObj( *this, *aIt ) ) ); +} + +Sequence< OUString > SAL_CALL ScDataPilotFieldGroupObj::getElementNames() throw(RuntimeException) +{ + ScUnoGuard aGuard; + return ::comphelper::containerToSequence( mrParent.getFieldGroup( maGroupName ).maMembers ); +} + +sal_Bool SAL_CALL ScDataPilotFieldGroupObj::hasByName( const OUString& rName ) throw(RuntimeException) +{ + ScUnoGuard aGuard; + ScFieldGroupMembers& rMembers = mrParent.getFieldGroup( maGroupName ).maMembers; + return ::std::find( rMembers.begin(), rMembers.end(), rName ) != rMembers.end(); +} + +// XNameReplace + +void SAL_CALL ScDataPilotFieldGroupObj::replaceByName( const OUString& rName, const Any& rElement ) + throw (IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + + // it should be possible to quickly rename an item -> accept string or XNamed + OUString aNewName = lclExtractMember( rElement ); + if( (rName.getLength() == 0) || (aNewName.getLength() == 0) ) + throw IllegalArgumentException(); + if( rName == aNewName ) + return; + + ScFieldGroupMembers& rMembers = mrParent.getFieldGroup( maGroupName ).maMembers; + ScFieldGroupMembers::iterator aOldIt = ::std::find( rMembers.begin(), rMembers.end(), rName ); + ScFieldGroupMembers::iterator aNewIt = ::std::find( rMembers.begin(), rMembers.end(), aNewName ); + // throw if passed member name does not exist + if( aOldIt == rMembers.end() ) + throw NoSuchElementException(); + // throw if new name already exists + if( aNewIt != rMembers.end() ) + throw IllegalArgumentException(); + *aOldIt = aNewName; +} + +// XNameContainer + +void SAL_CALL ScDataPilotFieldGroupObj::insertByName( const OUString& rName, const Any& /*rElement*/ ) + throw (IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + + // we will ignore the passed element and just try to insert the name + if( rName.getLength() == 0 ) + throw IllegalArgumentException(); + + ScFieldGroupMembers& rMembers = mrParent.getFieldGroup( maGroupName ).maMembers; + ScFieldGroupMembers::iterator aIt = ::std::find( rMembers.begin(), rMembers.end(), rName ); + // throw if passed name already exists + if( aIt != rMembers.end() ) + throw IllegalArgumentException(); + rMembers.push_back( rName ); +} + +void SAL_CALL ScDataPilotFieldGroupObj::removeByName( const OUString& rName ) + throw (NoSuchElementException, WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + + if( rName.getLength() == 0 ) + throw IllegalArgumentException(); + ScFieldGroupMembers& rMembers = mrParent.getFieldGroup( maGroupName ).maMembers; + ScFieldGroupMembers::iterator aIt = ::std::find( rMembers.begin(), rMembers.end(), rName ); + // throw if passed name does not exist + if( aIt == rMembers.end() ) + throw NoSuchElementException(); + rMembers.erase( aIt ); +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScDataPilotFieldGroupObj::getCount() throw(RuntimeException) +{ + ScUnoGuard aGuard; + return static_cast< sal_Int32 >( mrParent.getFieldGroup( maGroupName ).maMembers.size() ); +} + +Any SAL_CALL ScDataPilotFieldGroupObj::getByIndex( sal_Int32 nIndex ) + throw(IndexOutOfBoundsException, WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + ScFieldGroupMembers& rMembers = mrParent.getFieldGroup( maGroupName ).maMembers; + if ((nIndex < 0) || (nIndex >= static_cast< sal_Int32 >( rMembers.size() ))) + throw IndexOutOfBoundsException(); + return Any( Reference< XNamed >( new ScDataPilotFieldGroupItemObj( *this, rMembers[ nIndex ] ) ) ); +} + +// XEnumerationAccess + +Reference< XEnumeration > SAL_CALL ScDataPilotFieldGroupObj::createEnumeration() throw(RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration( this, OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.DataPilotFieldGroupEnumeration" ) ) ); +} + +// XElementAccess + +uno::Type SAL_CALL ScDataPilotFieldGroupObj::getElementType() throw(RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType( (Reference< XNamed >*)0 ); +} + +sal_Bool SAL_CALL ScDataPilotFieldGroupObj::hasElements() throw(RuntimeException) +{ + ScUnoGuard aGuard; + return !mrParent.getFieldGroup( maGroupName ).maMembers.empty(); +} + +// XNamed + +OUString SAL_CALL ScDataPilotFieldGroupObj::getName() throw(RuntimeException) +{ + ScUnoGuard aGuard; + return maGroupName; +} + +void SAL_CALL ScDataPilotFieldGroupObj::setName( const OUString& rName ) throw(RuntimeException) +{ + ScUnoGuard aGuard; + mrParent.renameFieldGroup( maGroupName, rName ); + // if call to renameFieldGroup() did not throw, remember the new name + maGroupName = rName; +} + +// ============================================================================ + +ScDataPilotFieldGroupItemObj::ScDataPilotFieldGroupItemObj( ScDataPilotFieldGroupObj& rParent, const OUString& rName ) : + mrParent( rParent ), + maName( rName ) +{ + mrParent.acquire(); +} + +ScDataPilotFieldGroupItemObj::~ScDataPilotFieldGroupItemObj() +{ + mrParent.release(); +} + +// XNamed + +OUString SAL_CALL ScDataPilotFieldGroupItemObj::getName() throw(RuntimeException) +{ + ScUnoGuard aGuard; + return maName; +} + +void SAL_CALL ScDataPilotFieldGroupItemObj::setName( const OUString& rName ) throw(RuntimeException) +{ + ScUnoGuard aGuard; + mrParent.replaceByName( maName, Any( rName ) ); + // if call to replaceByName() did not throw, remember the new name + maName = rName; +} + +// ============================================================================ + +ScDataPilotItemsObj::ScDataPilotItemsObj( ScDataPilotDescriptorBase& rParent, const ScFieldIdentifier& rFieldId ) : + ScDataPilotChildObjBase( rParent, rFieldId ) +{ +} + +ScDataPilotItemsObj::~ScDataPilotItemsObj() +{ +} + +// XDataPilotItems + +ScDataPilotItemObj* ScDataPilotItemsObj::GetObjectByIndex_Impl( sal_Int32 nIndex ) const +{ + return ((0 <= nIndex) && (nIndex < GetMemberCount())) ? + new ScDataPilotItemObj( mrParent, maFieldId, nIndex ) : 0; +} + +// XNameAccess + +Any SAL_CALL ScDataPilotItemsObj::getByName( const OUString& aName ) + throw(NoSuchElementException, WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + Reference<XNameAccess> xMembers = GetMembers(); + if (xMembers.is()) + { + Reference<XIndexAccess> xMembersIndex(new ScNameToIndexAccess( xMembers )); + sal_Int32 nCount = xMembersIndex->getCount(); + sal_Bool bFound(sal_False); + sal_Int32 nItem = 0; + while (nItem < nCount && !bFound ) + { + Reference<XNamed> xMember(xMembersIndex->getByIndex(nItem), UNO_QUERY); + if (xMember.is() && (aName == xMember->getName())) + return Any( Reference< XPropertySet >( GetObjectByIndex_Impl( nItem ) ) ); + ++nItem; + } + if (!bFound) + throw NoSuchElementException(); + } + return Any(); +} + +Sequence<OUString> SAL_CALL ScDataPilotItemsObj::getElementNames() + throw(RuntimeException) +{ + ScUnoGuard aGuard; + Sequence< OUString > aSeq; + if( ScDPObject* pDPObj = GetDPObject() ) + pDPObj->GetMemberNames( lcl_GetObjectIndex( pDPObj, maFieldId ), aSeq ); + return aSeq; +} + +sal_Bool SAL_CALL ScDataPilotItemsObj::hasByName( const OUString& aName ) + throw(RuntimeException) +{ + ScUnoGuard aGuard; + sal_Bool bFound = sal_False; + Reference<XNameAccess> xMembers = GetMembers(); + if (xMembers.is()) + { + Reference<XIndexAccess> xMembersIndex(new ScNameToIndexAccess( xMembers )); + sal_Int32 nCount = xMembersIndex->getCount(); + sal_Int32 nItem = 0; + while (nItem < nCount && !bFound ) + { + Reference<XNamed> xMember(xMembersIndex->getByIndex(nItem), UNO_QUERY); + if (xMember.is() && aName == xMember->getName()) + bFound = sal_True; + else + nItem++; + } + } + return bFound; +} + +// XEnumerationAccess + +Reference<XEnumeration> SAL_CALL ScDataPilotItemsObj::createEnumeration() + throw(RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.DataPilotItemsEnumeration"))); +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScDataPilotItemsObj::getCount() throw(RuntimeException) +{ + ScUnoGuard aGuard; + return GetMemberCount(); +} + +Any SAL_CALL ScDataPilotItemsObj::getByIndex( sal_Int32 nIndex ) + throw(IndexOutOfBoundsException, WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + Reference< XPropertySet > xItem( GetObjectByIndex_Impl( nIndex ) ); + if (!xItem.is()) + throw IndexOutOfBoundsException(); + return Any( xItem ); +} + +uno::Type SAL_CALL ScDataPilotItemsObj::getElementType() throw(RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((Reference<XPropertySet>*)0); +} + +sal_Bool SAL_CALL ScDataPilotItemsObj::hasElements() throw(RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +//------------------------------------------------------------------------ + +ScDataPilotItemObj::ScDataPilotItemObj( ScDataPilotDescriptorBase& rParent, const ScFieldIdentifier& rFieldId, sal_Int32 nIndex ) : + ScDataPilotChildObjBase( rParent, rFieldId ), + maPropSet( lcl_GetDataPilotItemMap() ), + mnIndex( nIndex ) +{ +} + +ScDataPilotItemObj::~ScDataPilotItemObj() +{ +} + + // XNamed +OUString SAL_CALL ScDataPilotItemObj::getName() throw(RuntimeException) +{ + ScUnoGuard aGuard; + OUString sRet; + Reference<XNameAccess> xMembers = GetMembers(); + if (xMembers.is()) + { + Reference<XIndexAccess> xMembersIndex(new ScNameToIndexAccess( xMembers )); + sal_Int32 nCount = xMembersIndex->getCount(); + if (mnIndex < nCount) + { + Reference<XNamed> xMember(xMembersIndex->getByIndex(mnIndex), UNO_QUERY); + sRet = xMember->getName(); + } + } + return sRet; +} + +void SAL_CALL ScDataPilotItemObj::setName( const OUString& /* aName */ ) + throw(RuntimeException) +{ +} + + // XPropertySet +Reference< XPropertySetInfo > + SAL_CALL ScDataPilotItemObj::getPropertySetInfo( ) + throw(RuntimeException) +{ + ScUnoGuard aGuard; + static Reference<XPropertySetInfo> aRef = + new SfxItemPropertySetInfo( maPropSet.getPropertyMap() ); + return aRef; +} + +void SAL_CALL ScDataPilotItemObj::setPropertyValue( const OUString& aPropertyName, const Any& aValue ) + throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + ScDPObject* pDPObj = 0; + if( ScDPSaveDimension* pDim = GetDPDimension( &pDPObj ) ) + { + Reference<XNameAccess> xMembers = GetMembers(); + if( xMembers.is() ) + { + Reference<XIndexAccess> xMembersIndex( new ScNameToIndexAccess( xMembers ) ); + sal_Int32 nCount = xMembersIndex->getCount(); + if( mnIndex < nCount ) + { + Reference<XNamed> xMember(xMembersIndex->getByIndex(mnIndex), UNO_QUERY); + String sName(xMember->getName()); + ScDPSaveMember* pMember = pDim->GetMemberByName(sName); + if (pMember) + { + bool bGetNewIndex = false; + if ( aPropertyName.equalsAscii( SC_UNONAME_SHOWDETAIL ) ) + pMember->SetShowDetails(cppu::any2bool(aValue)); + else if ( aPropertyName.equalsAscii( SC_UNONAME_ISHIDDEN ) ) + pMember->SetIsVisible(!cppu::any2bool(aValue)); + else if ( aPropertyName.equalsAscii( SC_UNONAME_POS ) ) + { + sal_Int32 nNewPos = 0; + if ( ( aValue >>= nNewPos ) && nNewPos >= 0 && nNewPos < nCount ) + { + pDim->SetMemberPosition( sName, nNewPos ); + // get new effective index (depends on sorting mode, which isn't modified) + bGetNewIndex = true; + } + else + throw IllegalArgumentException(); + } + SetDPObject( pDPObj ); + + if ( bGetNewIndex ) // after SetDPObject, get the new index + { + OUString aOUName( sName ); + Sequence< OUString > aItemNames = xMembers->getElementNames(); + sal_Int32 nItemCount = aItemNames.getLength(); + for (sal_Int32 nItem=0; nItem<nItemCount; ++nItem) + if (aItemNames[nItem] == aOUName) + mnIndex = nItem; + } + } + } + } + } +} + +Any SAL_CALL ScDataPilotItemObj::getPropertyValue( const OUString& aPropertyName ) + throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + Any aRet; + if( ScDPSaveDimension* pDim = GetDPDimension() ) + { + Reference< XNameAccess > xMembers = GetMembers(); + if( xMembers.is() ) + { + Reference< XIndexAccess > xMembersIndex( new ScNameToIndexAccess( xMembers ) ); + sal_Int32 nCount = xMembersIndex->getCount(); + if( mnIndex < nCount ) + { + Reference< XNamed > xMember( xMembersIndex->getByIndex( mnIndex ), UNO_QUERY ); + String sName( xMember->getName() ); + ScDPSaveMember* pMember = pDim->GetExistingMemberByName( sName ); + if( aPropertyName.equalsAscii( SC_UNONAME_SHOWDETAIL ) ) + { + if (pMember && pMember->HasShowDetails()) + { + aRet <<= (bool)pMember->GetShowDetails(); + } + else + { + Reference< XPropertySet > xMemberProps( xMember, UNO_QUERY ); + if( xMemberProps.is() ) + aRet = xMemberProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_SHOWDETA ) ) ); + else + aRet <<= true; + } + } + else if ( aPropertyName.equalsAscii( SC_UNONAME_ISHIDDEN ) ) + { + if (pMember && pMember->HasIsVisible()) + { + aRet <<= !pMember->GetIsVisible(); + } + else + { + Reference< XPropertySet > xMemberProps( xMember, UNO_QUERY ); + if( xMemberProps.is() ) + aRet <<= !cppu::any2bool( xMemberProps->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNO_ISVISIBL ) ) ) ); + else + aRet <<= false; + } + } + else if ( aPropertyName.equalsAscii( SC_UNONAME_POS ) ) + { + aRet <<= mnIndex; + } + } + } + } + return aRet; +} + +void SAL_CALL ScDataPilotItemObj::addPropertyChangeListener( + const OUString& /* aPropertyName */, const Reference< XPropertyChangeListener >& /* xListener */ ) + throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ +} + +void SAL_CALL ScDataPilotItemObj::removePropertyChangeListener( + const OUString& /* aPropertyName */, const Reference< XPropertyChangeListener >& /* aListener */ ) + throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ +} + +void SAL_CALL ScDataPilotItemObj::addVetoableChangeListener( + const OUString& /* PropertyName */, const Reference< XVetoableChangeListener >& /* aListener */ ) + throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ +} + +void SAL_CALL ScDataPilotItemObj::removeVetoableChangeListener( + const OUString& /* PropertyName */, const Reference< XVetoableChangeListener >& /* aListener */ ) + throw(UnknownPropertyException, WrappedTargetException, RuntimeException) +{ +} + +//------------------------------------------------------------------------ + + + + diff --git a/sc/source/ui/unoobj/datauno.cxx b/sc/source/ui/unoobj/datauno.cxx new file mode 100644 index 000000000000..6e416764eb76 --- /dev/null +++ b/sc/source/ui/unoobj/datauno.cxx @@ -0,0 +1,2371 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include <tools/debug.hxx> +#include <svl/smplhint.hxx> +#include <svl/zforlist.hxx> +#include <rtl/uuid.h> + +#include <com/sun/star/awt/XBitmap.hpp> +#include <com/sun/star/util/SortField.hpp> +#include <com/sun/star/table/TableSortField.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/table/TableOrientation.hpp> +#include <com/sun/star/table/CellRangeAddress.hpp> +#include <com/sun/star/sheet/DataImportMode.hpp> +#include <com/sun/star/sheet/FilterOperator2.hpp> +#include <com/sun/star/sheet/TableFilterField2.hpp> + +#include "datauno.hxx" +#include "dapiuno.hxx" +#include "cellsuno.hxx" +#include "miscuno.hxx" +#include "targuno.hxx" +#include "rangeutl.hxx" +#include "dbcolect.hxx" +#include "docsh.hxx" +#include "dbdocfun.hxx" +#include "unoguard.hxx" +#include "unonames.hxx" +#include "globstr.hrc" +#ifndef SC_CONVUNO_HXX +#include "convuno.hxx" +#include "hints.hxx" +#endif +#include "attrib.hxx" +#include "dpshttab.hxx" +#include <comphelper/extract.hxx> +#include <svx/dataaccessdescriptor.hxx> + +using namespace com::sun::star; + +SV_IMPL_PTRARR( XDBRefreshListenerArr_Impl, XDBRefreshListenerPtr ); + +//------------------------------------------------------------------------ + +// alles ohne Which-ID, Map nur fuer PropertySetInfo + +const SfxItemPropertyMapEntry* lcl_GetSubTotalPropertyMap() +{ + // some old property names are for 5.2 compatibility + + static SfxItemPropertyMapEntry aSubTotalPropertyMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_BINDFMT), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_CASE), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_ENABSORT), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_ENUSLIST), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_FORMATS), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_INSBRK), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_ISCASE), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_MAXFLD), 0, &getCppuType((sal_Int32*)0), beans::PropertyAttribute::READONLY, 0}, + {MAP_CHAR_LEN(SC_UNONAME_SORTASC), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_ULIST), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_UINDEX), 0, &getCppuType((sal_Int32*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_USINDEX), 0, &getCppuType((sal_Int32*)0), 0, 0}, + {0,0,0,0,0,0} + }; + return aSubTotalPropertyMap_Impl; +} + +const SfxItemPropertyMapEntry* lcl_GetFilterPropertyMap() +{ + static SfxItemPropertyMapEntry aFilterPropertyMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_CONTHDR), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_COPYOUT), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_ISCASE), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_MAXFLD), 0, &getCppuType((sal_Int32*)0), beans::PropertyAttribute::READONLY, 0}, + {MAP_CHAR_LEN(SC_UNONAME_ORIENT), 0, &getCppuType((table::TableOrientation*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_OUTPOS), 0, &getCppuType((table::CellAddress*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_SAVEOUT), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_SKIPDUP), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_USEREGEX), 0, &getBooleanCppuType(), 0, 0}, + {0,0,0,0,0,0} + }; + return aFilterPropertyMap_Impl; +} + +const SfxItemPropertyMapEntry* lcl_GetDBRangePropertyMap() +{ + static SfxItemPropertyMapEntry aDBRangePropertyMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_AUTOFLT), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_FLTCRT), 0, &getCppuType((table::CellRangeAddress*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_FROMSELECT),0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_ISUSER), 0, &getBooleanCppuType(), beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_KEEPFORM), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_LINKDISPBIT), 0, &getCppuType((uno::Reference<awt::XBitmap>*)0), beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNO_LINKDISPNAME), 0, &getCppuType((rtl::OUString*)0), beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_MOVCELLS), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_REFPERIOD), 0, &getCppuType((sal_Int32*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_STRIPDAT), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_TOKENINDEX),0, &getCppuType((sal_Int32*)0), beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_USEFLTCRT),0, &getBooleanCppuType(), 0, 0}, + {0,0,0,0,0,0} + }; + return aDBRangePropertyMap_Impl; +} + + +//------------------------------------------------------------------------ + +#define SCDATABASERANGEOBJ_SERVICE "com.sun.star.sheet.DatabaseRange" + +SC_SIMPLE_SERVICE_INFO( ScConsolidationDescriptor, "ScConsolidationDescriptor", "com.sun.star.sheet.ConsolidationDescriptor" ) +SC_SIMPLE_SERVICE_INFO( ScDatabaseRangesObj, "ScDatabaseRangesObj", "com.sun.star.sheet.DatabaseRanges" ) +SC_SIMPLE_SERVICE_INFO( ScFilterDescriptorBase, "ScFilterDescriptorBase", "com.sun.star.sheet.SheetFilterDescriptor" ) +SC_SIMPLE_SERVICE_INFO( ScSubTotalDescriptorBase, "ScSubTotalDescriptorBase", "com.sun.star.sheet.SubTotalDescriptor" ) +SC_SIMPLE_SERVICE_INFO( ScSubTotalFieldObj, "ScSubTotalFieldObj", "com.sun.star.sheet.SubTotalField" ) + + +//------------------------------------------------------------------------ + +// static +ScSubTotalFunc ScDataUnoConversion::GeneralToSubTotal( sheet::GeneralFunction eSummary ) +{ + ScSubTotalFunc eSubTotal; + switch (eSummary) + { + case sheet::GeneralFunction_NONE: eSubTotal = SUBTOTAL_FUNC_NONE; break; + case sheet::GeneralFunction_SUM: eSubTotal = SUBTOTAL_FUNC_SUM; break; + case sheet::GeneralFunction_COUNT: eSubTotal = SUBTOTAL_FUNC_CNT2; break; + case sheet::GeneralFunction_AVERAGE: eSubTotal = SUBTOTAL_FUNC_AVE; break; + case sheet::GeneralFunction_MAX: eSubTotal = SUBTOTAL_FUNC_MAX; break; + case sheet::GeneralFunction_MIN: eSubTotal = SUBTOTAL_FUNC_MIN; break; + case sheet::GeneralFunction_PRODUCT: eSubTotal = SUBTOTAL_FUNC_PROD; break; + case sheet::GeneralFunction_COUNTNUMS: eSubTotal = SUBTOTAL_FUNC_CNT; break; + case sheet::GeneralFunction_STDEV: eSubTotal = SUBTOTAL_FUNC_STD; break; + case sheet::GeneralFunction_STDEVP: eSubTotal = SUBTOTAL_FUNC_STDP; break; + case sheet::GeneralFunction_VAR: eSubTotal = SUBTOTAL_FUNC_VAR; break; + case sheet::GeneralFunction_VARP: eSubTotal = SUBTOTAL_FUNC_VARP; break; + case sheet::GeneralFunction_AUTO: + default: + DBG_ERROR("GeneralToSubTotal: falscher enum"); + eSubTotal = SUBTOTAL_FUNC_NONE; + } + return eSubTotal; +} + +// static +sheet::GeneralFunction ScDataUnoConversion::SubTotalToGeneral( ScSubTotalFunc eSubTotal ) +{ + sheet::GeneralFunction eGeneral; + switch (eSubTotal) + { + case SUBTOTAL_FUNC_NONE: eGeneral = sheet::GeneralFunction_NONE; break; + case SUBTOTAL_FUNC_AVE: eGeneral = sheet::GeneralFunction_AVERAGE; break; + case SUBTOTAL_FUNC_CNT: eGeneral = sheet::GeneralFunction_COUNTNUMS; break; + case SUBTOTAL_FUNC_CNT2: eGeneral = sheet::GeneralFunction_COUNT; break; + case SUBTOTAL_FUNC_MAX: eGeneral = sheet::GeneralFunction_MAX; break; + case SUBTOTAL_FUNC_MIN: eGeneral = sheet::GeneralFunction_MIN; break; + case SUBTOTAL_FUNC_PROD: eGeneral = sheet::GeneralFunction_PRODUCT; break; + case SUBTOTAL_FUNC_STD: eGeneral = sheet::GeneralFunction_STDEV; break; + case SUBTOTAL_FUNC_STDP: eGeneral = sheet::GeneralFunction_STDEVP; break; + case SUBTOTAL_FUNC_SUM: eGeneral = sheet::GeneralFunction_SUM; break; + case SUBTOTAL_FUNC_VAR: eGeneral = sheet::GeneralFunction_VAR; break; + case SUBTOTAL_FUNC_VARP: eGeneral = sheet::GeneralFunction_VARP; break; + default: + DBG_ERROR("SubTotalToGeneral: falscher enum"); + eGeneral = sheet::GeneralFunction_NONE; + break; + } + return eGeneral; +} + +//------------------------------------------------------------------------ + +// ScImportDescriptor: alles static + +long ScImportDescriptor::GetPropertyCount() +{ + return 4; +} + +void ScImportDescriptor::FillProperties( uno::Sequence<beans::PropertyValue>& rSeq, const ScImportParam& rParam ) +{ + DBG_ASSERT( rSeq.getLength() == GetPropertyCount(), "falscher Count" ); + + beans::PropertyValue* pArray = rSeq.getArray(); + + sheet::DataImportMode eMode = sheet::DataImportMode_NONE; + if ( rParam.bImport ) + { + if ( rParam.bSql ) + eMode = sheet::DataImportMode_SQL; + else if ( rParam.nType == ScDbQuery ) + eMode = sheet::DataImportMode_QUERY; + else + eMode = sheet::DataImportMode_TABLE; // Type ist immer ScDbQuery oder ScDbTable + } + + ::svx::ODataAccessDescriptor aDescriptor; + aDescriptor.setDataSource(rParam.aDBName); + if (aDescriptor.has( svx::daDataSource )) + { + pArray[0].Name = rtl::OUString::createFromAscii( SC_UNONAME_DBNAME ); + pArray[0].Value <<= rtl::OUString( rParam.aDBName ); + } + else if (aDescriptor.has( svx::daConnectionResource )) + { + pArray[0].Name = rtl::OUString::createFromAscii( SC_UNONAME_CONRES ); + pArray[0].Value <<= rtl::OUString( rParam.aDBName ); + } + + pArray[1].Name = rtl::OUString::createFromAscii( SC_UNONAME_SRCTYPE ); + pArray[1].Value <<= eMode; + + pArray[2].Name = rtl::OUString::createFromAscii( SC_UNONAME_SRCOBJ ); + pArray[2].Value <<= rtl::OUString( rParam.aStatement ); + + pArray[3].Name = rtl::OUString::createFromAscii( SC_UNONAME_ISNATIVE ); + ScUnoHelpFunctions::SetBoolInAny( pArray[3].Value, rParam.bNative ); +} + +void ScImportDescriptor::FillImportParam( ScImportParam& rParam, const uno::Sequence<beans::PropertyValue>& rSeq ) +{ + rtl::OUString aStrVal; + const beans::PropertyValue* pPropArray = rSeq.getConstArray(); + long nPropCount = rSeq.getLength(); + for (long i = 0; i < nPropCount; i++) + { + const beans::PropertyValue& rProp = pPropArray[i]; + String aPropName(rProp.Name); + + if (aPropName.EqualsAscii( SC_UNONAME_ISNATIVE )) + rParam.bNative = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value ); + else if (aPropName.EqualsAscii( SC_UNONAME_DBNAME )) + { + if ( rProp.Value >>= aStrVal ) + rParam.aDBName = String( aStrVal ); + } + else if (aPropName.EqualsAscii( SC_UNONAME_CONRES )) + { + if ( rProp.Value >>= aStrVal ) + rParam.aDBName = String( aStrVal ); + } + else if (aPropName.EqualsAscii( SC_UNONAME_SRCOBJ )) + { + if ( rProp.Value >>= aStrVal ) + rParam.aStatement = String( aStrVal ); + } + else if (aPropName.EqualsAscii( SC_UNONAME_SRCTYPE )) + { + //! test for correct enum type? + sheet::DataImportMode eMode = (sheet::DataImportMode) + ScUnoHelpFunctions::GetEnumFromAny( rProp.Value ); + switch (eMode) + { + case sheet::DataImportMode_NONE: + rParam.bImport = FALSE; + break; + case sheet::DataImportMode_SQL: + rParam.bImport = TRUE; + rParam.bSql = TRUE; + break; + case sheet::DataImportMode_TABLE: + rParam.bImport = TRUE; + rParam.bSql = FALSE; + rParam.nType = ScDbTable; + break; + case sheet::DataImportMode_QUERY: + rParam.bImport = TRUE; + rParam.bSql = FALSE; + rParam.nType = ScDbQuery; + break; + default: + DBG_ERROR("falscher Mode"); + rParam.bImport = FALSE; + } + } + } +} + +//------------------------------------------------------------------------ + +// ScSortDescriptor: alles static + +//! SortAscending muss aus der SheetSortDescriptor service-Beschreibung raus + +long ScSortDescriptor::GetPropertyCount() +{ + return 9; // TableSortDescriptor and SheetSortDescriptor +} + +void ScSortDescriptor::FillProperties( uno::Sequence<beans::PropertyValue>& rSeq, const ScSortParam& rParam ) +{ + DBG_ASSERT( rSeq.getLength() == GetPropertyCount(), "falscher Count" ); + + beans::PropertyValue* pArray = rSeq.getArray(); + + // Uno-Werte zusammensuchen + + table::CellAddress aOutPos; + aOutPos.Sheet = rParam.nDestTab; + aOutPos.Column = rParam.nDestCol; + aOutPos.Row = rParam.nDestRow; + + USHORT nSortCount = 0; + while ( nSortCount < MAXSORT && rParam.bDoSort[nSortCount] ) + ++nSortCount; + + uno::Sequence<table::TableSortField> aFields(nSortCount); + if (nSortCount) + { + table::TableSortField* pFieldArray = aFields.getArray(); + for (USHORT i=0; i<nSortCount; i++) + { + pFieldArray[i].Field = rParam.nField[i]; + pFieldArray[i].IsAscending = rParam.bAscending[i]; + pFieldArray[i].FieldType = table::TableSortFieldType_AUTOMATIC; // immer Automatic + pFieldArray[i].IsCaseSensitive = rParam.bCaseSens; + pFieldArray[i].CollatorLocale = rParam.aCollatorLocale; + pFieldArray[i].CollatorAlgorithm = rtl::OUString( rParam.aCollatorAlgorithm ); + } + } + + // Sequence fuellen + + pArray[0].Name = rtl::OUString::createFromAscii( SC_UNONAME_ISSORTCOLUMNS ); + pArray[0].Value = ::cppu::bool2any(!rParam.bByRow); + + pArray[1].Name = rtl::OUString::createFromAscii( SC_UNONAME_CONTHDR ); + ScUnoHelpFunctions::SetBoolInAny( pArray[1].Value, rParam.bHasHeader ); + + pArray[2].Name = rtl::OUString::createFromAscii( SC_UNONAME_MAXFLD ); + pArray[2].Value <<= (sal_Int32) MAXSORT; + + pArray[3].Name = rtl::OUString::createFromAscii( SC_UNONAME_SORTFLD ); + pArray[3].Value <<= aFields; + + pArray[4].Name = rtl::OUString::createFromAscii( SC_UNONAME_BINDFMT ); + ScUnoHelpFunctions::SetBoolInAny( pArray[4].Value, rParam.bIncludePattern ); + + pArray[5].Name = rtl::OUString::createFromAscii( SC_UNONAME_COPYOUT ); + ScUnoHelpFunctions::SetBoolInAny( pArray[5].Value, !rParam.bInplace ); + + pArray[6].Name = rtl::OUString::createFromAscii( SC_UNONAME_OUTPOS ); + pArray[6].Value <<= aOutPos; + + pArray[7].Name = rtl::OUString::createFromAscii( SC_UNONAME_ISULIST ); + ScUnoHelpFunctions::SetBoolInAny( pArray[7].Value, rParam.bUserDef ); + + pArray[8].Name = rtl::OUString::createFromAscii( SC_UNONAME_UINDEX ); + pArray[8].Value <<= (sal_Int32) rParam.nUserIndex; +} + +void ScSortDescriptor::FillSortParam( ScSortParam& rParam, const uno::Sequence<beans::PropertyValue>& rSeq ) +{ + sal_Bool bOldSortDescriptor(sal_False); + sal_Bool bNewSortDescriptor(sal_False); + const beans::PropertyValue* pPropArray = rSeq.getConstArray(); + long nPropCount = rSeq.getLength(); + for (long nProp = 0; nProp < nPropCount; nProp++) + { + const beans::PropertyValue& rProp = pPropArray[nProp]; + String aPropName(rProp.Name); + + if (aPropName.EqualsAscii( SC_UNONAME_ORIENT )) + { + bOldSortDescriptor = sal_True; + //! test for correct enum type? + table::TableOrientation eOrient = (table::TableOrientation) + ScUnoHelpFunctions::GetEnumFromAny( rProp.Value ); + rParam.bByRow = ( eOrient != table::TableOrientation_COLUMNS ); + } + else if (aPropName.EqualsAscii( SC_UNONAME_ISSORTCOLUMNS )) + { + bNewSortDescriptor = sal_True; + rParam.bByRow = !::cppu::any2bool(rProp.Value); + } + else if (aPropName.EqualsAscii( SC_UNONAME_CONTHDR )) + rParam.bHasHeader = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value ); + else if (aPropName.EqualsAscii( SC_UNONAME_MAXFLD )) + { + sal_Int32 nVal; + if ( (rProp.Value >>= nVal) && nVal > MAXSORT ) + { + //! specify exceptions + //! throw lang::IllegalArgumentException(); + } + } + else if (aPropName.EqualsAscii( SC_UNONAME_SORTFLD )) + { + uno::Sequence<util::SortField> aSeq; + uno::Sequence<table::TableSortField> aNewSeq; + if ( rProp.Value >>= aSeq ) + { + bOldSortDescriptor = sal_True; + INT32 nCount = aSeq.getLength(); + INT32 i; + if ( nCount > MAXSORT ) + { + DBG_ERROR("Zu viele Sortierfelder"); + nCount = MAXSORT; + } + const util::SortField* pFieldArray = aSeq.getConstArray(); + for (i=0; i<nCount; i++) + { + rParam.nField[i] = (SCCOLROW)pFieldArray[i].Field; + rParam.bAscending[i] = pFieldArray[i].SortAscending; + + // FieldType wird ignoriert + rParam.bDoSort[i] = TRUE; + } + for (i=nCount; i<MAXSORT; i++) + rParam.bDoSort[i] = FALSE; + } + else if ( rProp.Value >>= aNewSeq ) + { + bNewSortDescriptor = sal_True; + INT32 nCount = aNewSeq.getLength(); + INT32 i; + if ( nCount > MAXSORT ) + { + DBG_ERROR("Zu viele Sortierfelder"); + nCount = MAXSORT; + } + const table::TableSortField* pFieldArray = aNewSeq.getConstArray(); + for (i=0; i<nCount; i++) + { + rParam.nField[i] = (SCCOLROW)pFieldArray[i].Field; + rParam.bAscending[i] = pFieldArray[i].IsAscending; + + // only one is possible, sometime we should make it possible to have different for every entry + rParam.bCaseSens = pFieldArray[i].IsCaseSensitive; + rParam.aCollatorLocale = pFieldArray[i].CollatorLocale; + rParam.aCollatorAlgorithm = pFieldArray[i].CollatorAlgorithm; + + // FieldType wird ignoriert + rParam.bDoSort[i] = TRUE; + } + for (i=nCount; i<MAXSORT; i++) + rParam.bDoSort[i] = FALSE; + } + } + else if (aPropName.EqualsAscii( SC_UNONAME_ISCASE )) + { + bOldSortDescriptor = sal_True; + rParam.bCaseSens = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value ); + } + else if (aPropName.EqualsAscii( SC_UNONAME_BINDFMT )) + rParam.bIncludePattern = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value ); + else if (aPropName.EqualsAscii( SC_UNONAME_COPYOUT )) + rParam.bInplace = !ScUnoHelpFunctions::GetBoolFromAny( rProp.Value ); + else if (aPropName.EqualsAscii( SC_UNONAME_OUTPOS )) + { + table::CellAddress aAddress; + if ( rProp.Value >>= aAddress ) + { + rParam.nDestTab = aAddress.Sheet; + rParam.nDestCol = (SCCOL)aAddress.Column; + rParam.nDestRow = (SCROW)aAddress.Row; + } + } + else if (aPropName.EqualsAscii( SC_UNONAME_ISULIST )) + rParam.bUserDef = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value ); + else if (aPropName.EqualsAscii( SC_UNONAME_UINDEX )) + { + sal_Int32 nVal = 0; + if ( rProp.Value >>= nVal ) + rParam.nUserIndex = (USHORT)nVal; + } + else if (aPropName.EqualsAscii( SC_UNONAME_COLLLOC )) + { + bOldSortDescriptor = sal_True; + rProp.Value >>= rParam.aCollatorLocale; + } + else if (aPropName.EqualsAscii( SC_UNONAME_COLLALG )) + { + bOldSortDescriptor = sal_True; + rtl::OUString sStr; + if ( rProp.Value >>= sStr ) + rParam.aCollatorAlgorithm = sStr; + } + } +} + +//------------------------------------------------------------------------ + +ScSubTotalFieldObj::ScSubTotalFieldObj( ScSubTotalDescriptorBase* pDesc, USHORT nP ) : + xRef( pDesc ), // Objekt festhalten + rParent( *pDesc ), + nPos( nP ) +{ + DBG_ASSERT(pDesc, "ScSubTotalFieldObj: Parent ist 0"); +} + +ScSubTotalFieldObj::~ScSubTotalFieldObj() +{ +} + +// XSubTotalField + +sal_Int32 SAL_CALL ScSubTotalFieldObj::getGroupColumn() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScSubTotalParam aParam; + rParent.GetData(aParam); + + return aParam.nField[nPos]; +} + +void SAL_CALL ScSubTotalFieldObj::setGroupColumn( sal_Int32 nGroupColumn ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScSubTotalParam aParam; + rParent.GetData(aParam); + + aParam.nField[nPos] = (SCCOL)nGroupColumn; + + rParent.PutData(aParam); +} + +uno::Sequence<sheet::SubTotalColumn> SAL_CALL ScSubTotalFieldObj::getSubTotalColumns() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScSubTotalParam aParam; + rParent.GetData(aParam); + + SCCOL nCount = aParam.nSubTotals[nPos]; + uno::Sequence<sheet::SubTotalColumn> aSeq(nCount); + sheet::SubTotalColumn* pAry = aSeq.getArray(); + for (SCCOL i=0; i<nCount; i++) + { + pAry[i].Column = aParam.pSubTotals[nPos][i]; + pAry[i].Function = ScDataUnoConversion::SubTotalToGeneral( + aParam.pFunctions[nPos][i] ); + } + return aSeq; +} + +void SAL_CALL ScSubTotalFieldObj::setSubTotalColumns( + const uno::Sequence<sheet::SubTotalColumn>& aSubTotalColumns ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScSubTotalParam aParam; + rParent.GetData(aParam); + + UINT32 nColCount = aSubTotalColumns.getLength(); + if ( nColCount <= sal::static_int_cast<UINT32>(SCCOL_MAX) ) + { + SCCOL nCount = static_cast<SCCOL>(nColCount); + aParam.nSubTotals[nPos] = nCount; + if (nCount != 0) + { + aParam.pSubTotals[nPos] = new SCCOL[nCount]; + aParam.pFunctions[nPos] = new ScSubTotalFunc[nCount]; + + const sheet::SubTotalColumn* pAry = aSubTotalColumns.getConstArray(); + for (SCCOL i=0; i<nCount; i++) + { + aParam.pSubTotals[nPos][i] = static_cast<SCCOL>(pAry[i].Column); + aParam.pFunctions[nPos][i] = + ScDataUnoConversion::GeneralToSubTotal( pAry[i].Function ); + } + } + else + { + aParam.pSubTotals[nPos] = NULL; + aParam.pFunctions[nPos] = NULL; + } + } + //! sonst Exception oder so? (zuviele Spalten) + + rParent.PutData(aParam); +} + +//------------------------------------------------------------------------ + +ScSubTotalDescriptorBase::ScSubTotalDescriptorBase() : + aPropSet( lcl_GetSubTotalPropertyMap() ) +{ +} + +ScSubTotalDescriptorBase::~ScSubTotalDescriptorBase() +{ +} + +// GetData/PutData hier nur wegen NewInstance-Krempel implementiert... + +void ScSubTotalDescriptorBase::GetData( ScSubTotalParam& /* rParam */ ) const +{ + DBG_ERROR("ScSubTotalDescriptorBase::GetData soll nicht gerufen werden"); +} + +void ScSubTotalDescriptorBase::PutData( const ScSubTotalParam& /* rParam */ ) +{ + DBG_ERROR("ScSubTotalDescriptorBase::PutData soll nicht gerufen werden"); +} + +// XSubTotalDesctiptor + +ScSubTotalFieldObj* ScSubTotalDescriptorBase::GetObjectByIndex_Impl(USHORT nIndex) +{ + if ( nIndex < getCount() ) + return new ScSubTotalFieldObj( this, nIndex ); + return NULL; +} + +void SAL_CALL ScSubTotalDescriptorBase::clear() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScSubTotalParam aParam; + GetData(aParam); + + for (USHORT i=0; i<MAXSUBTOTAL; i++) + aParam.bGroupActive[i] = FALSE; + + //! Notify oder so fuer die Field-Objekte??? + + PutData(aParam); +} + +void SAL_CALL ScSubTotalDescriptorBase::addNew( + const uno::Sequence<sheet::SubTotalColumn>& aSubTotalColumns, + sal_Int32 nGroupColumn ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScSubTotalParam aParam; + GetData(aParam); + + USHORT nPos = 0; + while ( nPos < MAXSUBTOTAL && aParam.bGroupActive[nPos] ) + ++nPos; + + UINT32 nColCount = aSubTotalColumns.getLength(); + + if ( nPos < MAXSUBTOTAL && nColCount <= sal::static_int_cast<UINT32>(SCCOL_MAX) ) + { + aParam.bGroupActive[nPos] = TRUE; + aParam.nField[nPos] = static_cast<SCCOL>(nGroupColumn); + + delete aParam.pSubTotals[nPos]; + delete aParam.pFunctions[nPos]; + + SCCOL nCount = static_cast<SCCOL>(nColCount); + aParam.nSubTotals[nPos] = nCount; + if (nCount != 0) + { + aParam.pSubTotals[nPos] = new SCCOL[nCount]; + aParam.pFunctions[nPos] = new ScSubTotalFunc[nCount]; + + const sheet::SubTotalColumn* pAry = aSubTotalColumns.getConstArray(); + for (SCCOL i=0; i<nCount; i++) + { + aParam.pSubTotals[nPos][i] = static_cast<SCCOL>(pAry[i].Column); + aParam.pFunctions[nPos][i] = + ScDataUnoConversion::GeneralToSubTotal( pAry[i].Function ); + } + } + else + { + aParam.pSubTotals[nPos] = NULL; + aParam.pFunctions[nPos] = NULL; + } + } + else // too many fields / columns + throw uno::RuntimeException(); // no other exceptions specified + + PutData(aParam); +} + +// Flags/Einstellungen als Properties + +// XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScSubTotalDescriptorBase::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.SubTotalFieldsEnumeration"))); +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScSubTotalDescriptorBase::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScSubTotalParam aParam; + GetData(aParam); + + USHORT nCount = 0; + while ( nCount < MAXSUBTOTAL && aParam.bGroupActive[nCount] ) + ++nCount; + return nCount; +} + +uno::Any SAL_CALL ScSubTotalDescriptorBase::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<sheet::XSubTotalField> xField(GetObjectByIndex_Impl((USHORT)nIndex)); + if (xField.is()) + return uno::makeAny(xField); + else + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +uno::Type SAL_CALL ScSubTotalDescriptorBase::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((uno::Reference<sheet::XSubTotalField>*)0); +} + +sal_Bool SAL_CALL ScSubTotalDescriptorBase::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +// XPropertySet + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScSubTotalDescriptorBase::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef( + new SfxItemPropertySetInfo( aPropSet.getPropertyMap() )); + return aRef; +} + +void SAL_CALL ScSubTotalDescriptorBase::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScSubTotalParam aParam; + GetData(aParam); + + String aString(aPropertyName); + + // some old property names are for 5.2 compatibility + + if (aString.EqualsAscii( SC_UNONAME_CASE ) || aString.EqualsAscii( SC_UNONAME_ISCASE )) + aParam.bCaseSens = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + else if (aString.EqualsAscii( SC_UNONAME_FORMATS ) || aString.EqualsAscii( SC_UNONAME_BINDFMT )) + aParam.bIncludePattern = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + else if (aString.EqualsAscii( SC_UNONAME_ENABSORT )) + aParam.bDoSort = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + else if (aString.EqualsAscii( SC_UNONAME_SORTASC )) + aParam.bAscending = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + else if (aString.EqualsAscii( SC_UNONAME_INSBRK )) + aParam.bPagebreak = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + else if (aString.EqualsAscii( SC_UNONAME_ULIST ) || aString.EqualsAscii( SC_UNONAME_ENUSLIST )) + aParam.bUserDef = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + else if (aString.EqualsAscii( SC_UNONAME_UINDEX ) || aString.EqualsAscii( SC_UNONAME_USINDEX )) + { + sal_Int32 nVal = 0; + if ( aValue >>= nVal ) + aParam.nUserIndex = (USHORT)nVal; + } + else if (aString.EqualsAscii( SC_UNONAME_MAXFLD )) + { + sal_Int32 nVal = 0; + if ( (aValue >>= nVal) && nVal > sal::static_int_cast<sal_Int32>(MAXSUBTOTAL) ) + { + throw lang::IllegalArgumentException(); + } + } + + PutData(aParam); +} + +uno::Any SAL_CALL ScSubTotalDescriptorBase::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScSubTotalParam aParam; + GetData(aParam); + + String aString(aPropertyName); + uno::Any aRet; + + // some old property names are for 5.2 compatibility + + if (aString.EqualsAscii( SC_UNONAME_CASE ) || aString.EqualsAscii( SC_UNONAME_ISCASE )) + ScUnoHelpFunctions::SetBoolInAny( aRet, aParam.bCaseSens ); + else if (aString.EqualsAscii( SC_UNONAME_FORMATS ) || aString.EqualsAscii( SC_UNONAME_BINDFMT )) + ScUnoHelpFunctions::SetBoolInAny( aRet, aParam.bIncludePattern ); + else if (aString.EqualsAscii( SC_UNONAME_ENABSORT )) + ScUnoHelpFunctions::SetBoolInAny( aRet, aParam.bDoSort ); + else if (aString.EqualsAscii( SC_UNONAME_SORTASC )) + ScUnoHelpFunctions::SetBoolInAny( aRet, aParam.bAscending ); + else if (aString.EqualsAscii( SC_UNONAME_INSBRK )) + ScUnoHelpFunctions::SetBoolInAny( aRet, aParam.bPagebreak ); + else if (aString.EqualsAscii( SC_UNONAME_ULIST ) || aString.EqualsAscii( SC_UNONAME_ENUSLIST )) + ScUnoHelpFunctions::SetBoolInAny( aRet, aParam.bUserDef ); + else if (aString.EqualsAscii( SC_UNONAME_UINDEX ) || aString.EqualsAscii( SC_UNONAME_USINDEX )) + aRet <<= (sal_Int32) aParam.nUserIndex; + else if (aString.EqualsAscii( SC_UNONAME_MAXFLD )) + aRet <<= (sal_Int32) MAXSUBTOTAL; + + return aRet; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScSubTotalDescriptorBase ) + +// XUnoTunnel + +sal_Int64 SAL_CALL ScSubTotalDescriptorBase::getSomething( + const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); + } + return 0; +} + +// static +const uno::Sequence<sal_Int8>& ScSubTotalDescriptorBase::getUnoTunnelId() +{ + static uno::Sequence<sal_Int8> * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +// static +ScSubTotalDescriptorBase* ScSubTotalDescriptorBase::getImplementation( + const uno::Reference<sheet::XSubTotalDescriptor> xObj ) +{ + ScSubTotalDescriptorBase* pRet = NULL; + uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); + if (xUT.is()) + pRet = reinterpret_cast<ScSubTotalDescriptorBase*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId()))); + return pRet; +} + +//------------------------------------------------------------------------ + +ScSubTotalDescriptor::ScSubTotalDescriptor() +{ +} + +ScSubTotalDescriptor::~ScSubTotalDescriptor() +{ +} + +void ScSubTotalDescriptor::GetData( ScSubTotalParam& rParam ) const +{ + rParam = aStoredParam; // Abfrage fuer Interface +} + +void ScSubTotalDescriptor::PutData( const ScSubTotalParam& rParam ) +{ + aStoredParam = rParam; // vom Interface gesetzt +} + +void ScSubTotalDescriptor::SetParam( const ScSubTotalParam& rNew ) +{ + aStoredParam = rNew; // von aussen gesetzt +} + +//------------------------------------------------------------------------ + +ScRangeSubTotalDescriptor::ScRangeSubTotalDescriptor(ScDatabaseRangeObj* pPar) : + pParent(pPar) +{ + if (pParent) + pParent->acquire(); +} + +ScRangeSubTotalDescriptor::~ScRangeSubTotalDescriptor() +{ + if (pParent) + pParent->release(); +} + +void ScRangeSubTotalDescriptor::GetData( ScSubTotalParam& rParam ) const +{ + if (pParent) + pParent->GetSubTotalParam( rParam ); +} + +void ScRangeSubTotalDescriptor::PutData( const ScSubTotalParam& rParam ) +{ + if (pParent) + pParent->SetSubTotalParam( rParam ); +} + +//------------------------------------------------------------------------ + +ScConsolidationDescriptor::ScConsolidationDescriptor() +{ +} + +ScConsolidationDescriptor::~ScConsolidationDescriptor() +{ +} + +void ScConsolidationDescriptor::SetParam( const ScConsolidateParam& rNew ) +{ + aParam = rNew; +} + +// XConsolidationDescriptor + +sheet::GeneralFunction SAL_CALL ScConsolidationDescriptor::getFunction() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ScDataUnoConversion::SubTotalToGeneral(aParam.eFunction); +} + +void SAL_CALL ScConsolidationDescriptor::setFunction( sheet::GeneralFunction nFunction ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + aParam.eFunction = ScDataUnoConversion::GeneralToSubTotal(nFunction); +} + +uno::Sequence<table::CellRangeAddress> SAL_CALL ScConsolidationDescriptor::getSources() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + USHORT nCount = aParam.nDataAreaCount; + if (!aParam.ppDataAreas) + nCount = 0; + table::CellRangeAddress aRange; + uno::Sequence<table::CellRangeAddress> aSeq(nCount); + table::CellRangeAddress* pAry = aSeq.getArray(); + for (USHORT i=0; i<nCount; i++) + { + ScArea* pArea = aParam.ppDataAreas[i]; + if (pArea) + { + aRange.Sheet = pArea->nTab; + aRange.StartColumn = pArea->nColStart; + aRange.StartRow = pArea->nRowStart; + aRange.EndColumn = pArea->nColEnd; + aRange.EndRow = pArea->nRowEnd; + } + pAry[i] = aRange; + } + return aSeq; +} + +void SAL_CALL ScConsolidationDescriptor::setSources( + const uno::Sequence<table::CellRangeAddress>& aSources ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + USHORT nCount = (USHORT)aSources.getLength(); + if (nCount) + { + const table::CellRangeAddress* pAry = aSources.getConstArray(); + ScArea** pNew = new ScArea*[nCount]; + USHORT i; + for (i=0; i<nCount; i++) + pNew[i] = new ScArea( pAry[i].Sheet, + static_cast<SCCOL>(pAry[i].StartColumn), pAry[i].StartRow, + static_cast<SCCOL>(pAry[i].EndColumn), pAry[i].EndRow ); + + aParam.SetAreas( pNew, nCount ); // kopiert alles + + for (i=0; i<nCount; i++) + delete pNew[i]; + delete[] pNew; + } + else + aParam.ClearDataAreas(); +} + +table::CellAddress SAL_CALL ScConsolidationDescriptor::getStartOutputPosition() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + table::CellAddress aPos; + aPos.Column = aParam.nCol; + aPos.Row = aParam.nRow; + aPos.Sheet = aParam.nTab; + return aPos; +} + +void SAL_CALL ScConsolidationDescriptor::setStartOutputPosition( + const table::CellAddress& aStartOutputPosition ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + aParam.nCol = (SCCOL)aStartOutputPosition.Column; + aParam.nRow = (SCROW)aStartOutputPosition.Row; + aParam.nTab = aStartOutputPosition.Sheet; +} + +sal_Bool SAL_CALL ScConsolidationDescriptor::getUseColumnHeaders() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return aParam.bByCol; +} + +void SAL_CALL ScConsolidationDescriptor::setUseColumnHeaders( sal_Bool bUseColumnHeaders ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + aParam.bByCol = bUseColumnHeaders; +} + +sal_Bool SAL_CALL ScConsolidationDescriptor::getUseRowHeaders() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return aParam.bByRow; +} + +void SAL_CALL ScConsolidationDescriptor::setUseRowHeaders( sal_Bool bUseRowHeaders ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + aParam.bByRow = bUseRowHeaders; +} + +sal_Bool SAL_CALL ScConsolidationDescriptor::getInsertLinks() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return aParam.bReferenceData; +} + +void SAL_CALL ScConsolidationDescriptor::setInsertLinks( sal_Bool bInsertLinks ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + aParam.bReferenceData = bInsertLinks; +} + +//------------------------------------------------------------------------ + +ScFilterDescriptorBase::ScFilterDescriptorBase(ScDocShell* pDocShell) : + aPropSet( lcl_GetFilterPropertyMap() ), + pDocSh(pDocShell) +{ + if (pDocSh) + pDocSh->GetDocument()->AddUnoObject(*this); +} + +ScFilterDescriptorBase::~ScFilterDescriptorBase() +{ + if (pDocSh) + pDocSh->GetDocument()->RemoveUnoObject(*this); +} + +void ScFilterDescriptorBase::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( SfxSimpleHint ) ) + { + ULONG nId = ((const SfxSimpleHint&)rHint).GetId(); + if ( nId == SFX_HINT_DYING ) + { + pDocSh = NULL; // invalid + } + } +} + +// XSheetFilterDescriptor and XSheetFilterDescriptor2 + +uno::Sequence<sheet::TableFilterField> SAL_CALL ScFilterDescriptorBase::getFilterFields() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScQueryParam aParam; + GetData(aParam); + + SCSIZE nEntries = aParam.GetEntryCount(); // allozierte Eintraege im Param + SCSIZE nCount = 0; // aktive + while ( nCount < nEntries && + aParam.GetEntry(nCount).bDoQuery ) + ++nCount; + + sheet::TableFilterField aField; + uno::Sequence<sheet::TableFilterField> aSeq(static_cast<sal_Int32>(nCount)); + sheet::TableFilterField* pAry = aSeq.getArray(); + for (SCSIZE i=0; i<nCount; i++) + { + const ScQueryEntry& rEntry = aParam.GetEntry(i); + + rtl::OUString aStringValue; + if (rEntry.pStr) + aStringValue = *rEntry.pStr; + + aField.Connection = (rEntry.eConnect == SC_AND) ? sheet::FilterConnection_AND : + sheet::FilterConnection_OR; + aField.Field = rEntry.nField; + aField.IsNumeric = !rEntry.bQueryByString; + aField.StringValue = aStringValue; + aField.NumericValue = rEntry.nVal; + + switch (rEntry.eOp) // ScQueryOp + { + case SC_EQUAL: + { + aField.Operator = sheet::FilterOperator_EQUAL; + if (!rEntry.bQueryByString && *rEntry.pStr == EMPTY_STRING) + { + if (rEntry.nVal == SC_EMPTYFIELDS) + { + aField.Operator = sheet::FilterOperator_EMPTY; + aField.NumericValue = 0; + } + else if (rEntry.nVal == SC_NONEMPTYFIELDS) + { + aField.Operator = sheet::FilterOperator_NOT_EMPTY; + aField.NumericValue = 0; + } + } + } + break; + case SC_LESS: aField.Operator = sheet::FilterOperator_LESS; break; + case SC_GREATER: aField.Operator = sheet::FilterOperator_GREATER; break; + case SC_LESS_EQUAL: aField.Operator = sheet::FilterOperator_LESS_EQUAL; break; + case SC_GREATER_EQUAL: aField.Operator = sheet::FilterOperator_GREATER_EQUAL; break; + case SC_NOT_EQUAL: aField.Operator = sheet::FilterOperator_NOT_EQUAL; break; + case SC_TOPVAL: aField.Operator = sheet::FilterOperator_TOP_VALUES; break; + case SC_BOTVAL: aField.Operator = sheet::FilterOperator_BOTTOM_VALUES; break; + case SC_TOPPERC: aField.Operator = sheet::FilterOperator_TOP_PERCENT; break; + case SC_BOTPERC: aField.Operator = sheet::FilterOperator_BOTTOM_PERCENT; break; + default: + DBG_ERROR("Falscher Filter-enum"); + aField.Operator = sheet::FilterOperator_EMPTY; + } + pAry[i] = aField; + } + return aSeq; +} + +uno::Sequence<sheet::TableFilterField2> SAL_CALL ScFilterDescriptorBase::getFilterFields2() +throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScQueryParam aParam; + GetData(aParam); + + SCSIZE nEntries = aParam.GetEntryCount(); // allozierte Eintraege im Param + SCSIZE nCount = 0; // aktive + while ( nCount < nEntries && + aParam.GetEntry(nCount).bDoQuery ) + ++nCount; + + sheet::TableFilterField2 aField; + uno::Sequence<sheet::TableFilterField2> aSeq(static_cast<sal_Int32>(nCount)); + sheet::TableFilterField2* pAry = aSeq.getArray(); + for (SCSIZE i=0; i<nCount; i++) + { + const ScQueryEntry& rEntry = aParam.GetEntry(i); + + rtl::OUString aStringValue; + if (rEntry.pStr) + aStringValue = *rEntry.pStr; + + aField.Connection = (rEntry.eConnect == SC_AND) ? sheet::FilterConnection_AND : sheet::FilterConnection_OR; + aField.Field = rEntry.nField; + aField.IsNumeric = !rEntry.bQueryByString; + aField.StringValue = aStringValue; + aField.NumericValue = rEntry.nVal; + + switch (rEntry.eOp) // ScQueryOp + { + case SC_EQUAL: + { + aField.Operator = sheet::FilterOperator2::EQUAL; + if (!rEntry.bQueryByString && *rEntry.pStr == EMPTY_STRING) + { + if (rEntry.nVal == SC_EMPTYFIELDS) + { + aField.Operator = sheet::FilterOperator2::EMPTY; + aField.NumericValue = 0; + } + else if (rEntry.nVal == SC_NONEMPTYFIELDS) + { + aField.Operator = sheet::FilterOperator2::NOT_EMPTY; + aField.NumericValue = 0; + } + } + } + break; + case SC_LESS: aField.Operator = sheet::FilterOperator2::LESS; break; + case SC_GREATER: aField.Operator = sheet::FilterOperator2::GREATER; break; + case SC_LESS_EQUAL: aField.Operator = sheet::FilterOperator2::LESS_EQUAL; break; + case SC_GREATER_EQUAL: aField.Operator = sheet::FilterOperator2::GREATER_EQUAL; break; + case SC_NOT_EQUAL: aField.Operator = sheet::FilterOperator2::NOT_EQUAL; break; + case SC_TOPVAL: aField.Operator = sheet::FilterOperator2::TOP_VALUES; break; + case SC_BOTVAL: aField.Operator = sheet::FilterOperator2::BOTTOM_VALUES; break; + case SC_TOPPERC: aField.Operator = sheet::FilterOperator2::TOP_PERCENT; break; + case SC_BOTPERC: aField.Operator = sheet::FilterOperator2::BOTTOM_PERCENT; break; + case SC_CONTAINS: aField.Operator = sheet::FilterOperator2::CONTAINS; break; + case SC_DOES_NOT_CONTAIN: aField.Operator = sheet::FilterOperator2::DOES_NOT_CONTAIN; break; + case SC_BEGINS_WITH: aField.Operator = sheet::FilterOperator2::BEGINS_WITH; break; + case SC_DOES_NOT_BEGIN_WITH: aField.Operator = sheet::FilterOperator2::DOES_NOT_BEGIN_WITH; break; + case SC_ENDS_WITH: aField.Operator = sheet::FilterOperator2::ENDS_WITH; break; + case SC_DOES_NOT_END_WITH: aField.Operator = sheet::FilterOperator2::DOES_NOT_END_WITH; break; + default: + DBG_ERROR("Falscher Filter-enum"); + aField.Operator = sheet::FilterOperator2::EMPTY; + } + pAry[i] = aField; + } + return aSeq; +} + +void SAL_CALL ScFilterDescriptorBase::setFilterFields( + const uno::Sequence<sheet::TableFilterField>& aFilterFields ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScQueryParam aParam; + GetData(aParam); + + SCSIZE nCount = static_cast<SCSIZE>(aFilterFields.getLength()); + DBG_ASSERT( nCount <= MAXQUERY, "setFilterFields: zu viele" ); + + aParam.Resize( nCount ); + + const sheet::TableFilterField* pAry = aFilterFields.getConstArray(); + SCSIZE i; + for (i=0; i<nCount; i++) + { + ScQueryEntry& rEntry = aParam.GetEntry(i); + if (!rEntry.pStr) + rEntry.pStr = new String; // sollte nicht sein (soll immer initialisiert sein) + + rEntry.bDoQuery = TRUE; + rEntry.eConnect = (pAry[i].Connection == sheet::FilterConnection_AND) ? SC_AND : SC_OR; + rEntry.nField = pAry[i].Field; + rEntry.bQueryByString = !pAry[i].IsNumeric; + *rEntry.pStr = String( pAry[i].StringValue ); + rEntry.nVal = pAry[i].NumericValue; + + if (!rEntry.bQueryByString && pDocSh) + { + pDocSh->GetDocument()->GetFormatTable()->GetInputLineString(rEntry.nVal, 0, *rEntry.pStr); + } + + switch (pAry[i].Operator) // FilterOperator + { + case sheet::FilterOperator_EQUAL: rEntry.eOp = SC_EQUAL; break; + case sheet::FilterOperator_LESS: rEntry.eOp = SC_LESS; break; + case sheet::FilterOperator_GREATER: rEntry.eOp = SC_GREATER; break; + case sheet::FilterOperator_LESS_EQUAL: rEntry.eOp = SC_LESS_EQUAL; break; + case sheet::FilterOperator_GREATER_EQUAL: rEntry.eOp = SC_GREATER_EQUAL; break; + case sheet::FilterOperator_NOT_EQUAL: rEntry.eOp = SC_NOT_EQUAL; break; + case sheet::FilterOperator_TOP_VALUES: rEntry.eOp = SC_TOPVAL; break; + case sheet::FilterOperator_BOTTOM_VALUES: rEntry.eOp = SC_BOTVAL; break; + case sheet::FilterOperator_TOP_PERCENT: rEntry.eOp = SC_TOPPERC; break; + case sheet::FilterOperator_BOTTOM_PERCENT: rEntry.eOp = SC_BOTPERC; break; + case sheet::FilterOperator_EMPTY: + { + rEntry.eOp = SC_EQUAL; + rEntry.nVal = SC_EMPTYFIELDS; + rEntry.bQueryByString = FALSE; + *rEntry.pStr = EMPTY_STRING; + } + break; + case sheet::FilterOperator_NOT_EMPTY: + { + rEntry.eOp = SC_EQUAL; + rEntry.nVal = SC_NONEMPTYFIELDS; + rEntry.bQueryByString = FALSE; + *rEntry.pStr = EMPTY_STRING; + } + break; + default: + DBG_ERROR("Falscher Query-enum"); + rEntry.eOp = SC_EQUAL; + } + } + + SCSIZE nParamCount = aParam.GetEntryCount(); // Param wird nicht unter 8 resized + for (i=nCount; i<nParamCount; i++) + aParam.GetEntry(i).bDoQuery = FALSE; // ueberzaehlige Felder zuruecksetzen + + PutData(aParam); +} + +void SAL_CALL ScFilterDescriptorBase::setFilterFields2( + const uno::Sequence<sheet::TableFilterField2>& aFilterFields ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScQueryParam aParam; + GetData(aParam); + + SCSIZE nCount = static_cast<SCSIZE>(aFilterFields.getLength()); + DBG_ASSERT( nCount <= MAXQUERY, "setFilterFields: zu viele" ); + + aParam.Resize( nCount ); + + const sheet::TableFilterField2* pAry = aFilterFields.getConstArray(); + SCSIZE i; + for (i=0; i<nCount; i++) + { + ScQueryEntry& rEntry = aParam.GetEntry(i); + if (!rEntry.pStr) + rEntry.pStr = new String; // sollte nicht sein (soll immer initialisiert sein) + + rEntry.bDoQuery = TRUE; + rEntry.eConnect = (pAry[i].Connection == sheet::FilterConnection_AND) ? SC_AND : SC_OR; + rEntry.nField = pAry[i].Field; + rEntry.bQueryByString = !pAry[i].IsNumeric; + *rEntry.pStr = String( pAry[i].StringValue ); + rEntry.nVal = pAry[i].NumericValue; + + if (!rEntry.bQueryByString && pDocSh) + { + pDocSh->GetDocument()->GetFormatTable()->GetInputLineString(rEntry.nVal, 0, *rEntry.pStr); + } + + switch (pAry[i].Operator) // FilterOperator + { + case sheet::FilterOperator2::EQUAL: rEntry.eOp = SC_EQUAL; break; + case sheet::FilterOperator2::LESS: rEntry.eOp = SC_LESS; break; + case sheet::FilterOperator2::GREATER: rEntry.eOp = SC_GREATER; break; + case sheet::FilterOperator2::LESS_EQUAL: rEntry.eOp = SC_LESS_EQUAL; break; + case sheet::FilterOperator2::GREATER_EQUAL: rEntry.eOp = SC_GREATER_EQUAL; break; + case sheet::FilterOperator2::NOT_EQUAL: rEntry.eOp = SC_NOT_EQUAL; break; + case sheet::FilterOperator2::TOP_VALUES: rEntry.eOp = SC_TOPVAL; break; + case sheet::FilterOperator2::BOTTOM_VALUES: rEntry.eOp = SC_BOTVAL; break; + case sheet::FilterOperator2::TOP_PERCENT: rEntry.eOp = SC_TOPPERC; break; + case sheet::FilterOperator2::BOTTOM_PERCENT: rEntry.eOp = SC_BOTPERC; break; + case sheet::FilterOperator2::CONTAINS: rEntry.eOp = SC_CONTAINS; break; + case sheet::FilterOperator2::DOES_NOT_CONTAIN: rEntry.eOp = SC_DOES_NOT_CONTAIN; break; + case sheet::FilterOperator2::BEGINS_WITH: rEntry.eOp = SC_BEGINS_WITH; break; + case sheet::FilterOperator2::DOES_NOT_BEGIN_WITH: rEntry.eOp = SC_DOES_NOT_BEGIN_WITH;break; + case sheet::FilterOperator2::ENDS_WITH: rEntry.eOp = SC_ENDS_WITH; break; + case sheet::FilterOperator2::DOES_NOT_END_WITH: rEntry.eOp = SC_DOES_NOT_END_WITH; break; + case sheet::FilterOperator2::EMPTY: + { + rEntry.eOp = SC_EQUAL; + rEntry.nVal = SC_EMPTYFIELDS; + rEntry.bQueryByString = FALSE; + *rEntry.pStr = EMPTY_STRING; + } + break; + case sheet::FilterOperator2::NOT_EMPTY: + { + rEntry.eOp = SC_EQUAL; + rEntry.nVal = SC_NONEMPTYFIELDS; + rEntry.bQueryByString = FALSE; + *rEntry.pStr = EMPTY_STRING; + } + break; + default: + DBG_ERROR("Falscher Query-enum"); + rEntry.eOp = SC_EQUAL; + } + } + + SCSIZE nParamCount = aParam.GetEntryCount(); // Param wird nicht unter 8 resized + for (i=nCount; i<nParamCount; i++) + aParam.GetEntry(i).bDoQuery = FALSE; // ueberzaehlige Felder zuruecksetzen + + PutData(aParam); +} + +// Rest sind Properties + +// XPropertySet + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScFilterDescriptorBase::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef( + new SfxItemPropertySetInfo( aPropSet.getPropertyMap() )); + return aRef; +} + +void SAL_CALL ScFilterDescriptorBase::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScQueryParam aParam; + GetData(aParam); + + String aString(aPropertyName); + if (aString.EqualsAscii( SC_UNONAME_CONTHDR )) + aParam.bHasHeader = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + else if (aString.EqualsAscii( SC_UNONAME_COPYOUT )) + aParam.bInplace = !(ScUnoHelpFunctions::GetBoolFromAny( aValue )); + else if (aString.EqualsAscii( SC_UNONAME_ISCASE )) + aParam.bCaseSens = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + else if (aString.EqualsAscii( SC_UNONAME_MAXFLD )) + { + sal_Int32 nVal = 0; + if ( (aValue >>= nVal) && nVal > sal::static_int_cast<sal_Int32>(MAXQUERY) ) + { + throw lang::IllegalArgumentException(); + } + } + else if (aString.EqualsAscii( SC_UNONAME_ORIENT )) + { + //! test for correct enum type? + table::TableOrientation eOrient = (table::TableOrientation) + ScUnoHelpFunctions::GetEnumFromAny( aValue ); + aParam.bByRow = ( eOrient != table::TableOrientation_COLUMNS ); + } + else if (aString.EqualsAscii( SC_UNONAME_OUTPOS )) + { + table::CellAddress aAddress; + if ( aValue >>= aAddress ) + { + aParam.nDestTab = aAddress.Sheet; + aParam.nDestCol = (SCCOL)aAddress.Column; + aParam.nDestRow = (SCROW)aAddress.Row; + } + } + else if (aString.EqualsAscii( SC_UNONAME_SAVEOUT )) + aParam.bDestPers = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + else if (aString.EqualsAscii( SC_UNONAME_SKIPDUP )) + aParam.bDuplicate = !(ScUnoHelpFunctions::GetBoolFromAny( aValue )); + else if (aString.EqualsAscii( SC_UNONAME_USEREGEX )) + aParam.bRegExp = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + + PutData(aParam); +} + +uno::Any SAL_CALL ScFilterDescriptorBase::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScQueryParam aParam; + GetData(aParam); + + String aString(aPropertyName); + uno::Any aRet; + + if (aString.EqualsAscii( SC_UNONAME_CONTHDR )) + ScUnoHelpFunctions::SetBoolInAny( aRet, aParam.bHasHeader ); + else if (aString.EqualsAscii( SC_UNONAME_COPYOUT )) + ScUnoHelpFunctions::SetBoolInAny( aRet, !(aParam.bInplace) ); + else if (aString.EqualsAscii( SC_UNONAME_ISCASE )) + ScUnoHelpFunctions::SetBoolInAny( aRet, aParam.bCaseSens ); + else if (aString.EqualsAscii( SC_UNONAME_MAXFLD )) + aRet <<= (sal_Int32) MAXQUERY; + else if (aString.EqualsAscii( SC_UNONAME_ORIENT )) + { + table::TableOrientation eOrient = aParam.bByRow ? table::TableOrientation_ROWS : + table::TableOrientation_COLUMNS; + aRet <<= eOrient; + } + else if (aString.EqualsAscii( SC_UNONAME_OUTPOS )) + { + table::CellAddress aOutPos; + aOutPos.Sheet = aParam.nDestTab; + aOutPos.Column = aParam.nDestCol; + aOutPos.Row = aParam.nDestRow; + aRet <<= aOutPos; + } + else if (aString.EqualsAscii( SC_UNONAME_SAVEOUT )) + ScUnoHelpFunctions::SetBoolInAny( aRet, aParam.bDestPers ); + else if (aString.EqualsAscii( SC_UNONAME_SKIPDUP )) + ScUnoHelpFunctions::SetBoolInAny( aRet, !(aParam.bDuplicate) ); + else if (aString.EqualsAscii( SC_UNONAME_USEREGEX )) + ScUnoHelpFunctions::SetBoolInAny( aRet, aParam.bRegExp ); + + return aRet; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScFilterDescriptorBase ) + +//------------------------------------------------------------------------ + +ScFilterDescriptor::ScFilterDescriptor(ScDocShell* pDocShell) + : + ScFilterDescriptorBase(pDocShell) +{ +} + +ScFilterDescriptor::~ScFilterDescriptor() +{ +} + +void ScFilterDescriptor::GetData( ScQueryParam& rParam ) const +{ + rParam = aStoredParam; // Abfrage fuer Interface +} + +void ScFilterDescriptor::PutData( const ScQueryParam& rParam ) +{ + aStoredParam = rParam; // vom Interface gesetzt +} + +void ScFilterDescriptor::SetParam( const ScQueryParam& rNew ) +{ + aStoredParam = rNew; // von aussen gesetzt +} + +//------------------------------------------------------------------------ + +ScRangeFilterDescriptor::ScRangeFilterDescriptor(ScDocShell* pDocShell, ScDatabaseRangeObj* pPar) : + ScFilterDescriptorBase(pDocShell), + pParent(pPar) +{ + if (pParent) + pParent->acquire(); +} + +ScRangeFilterDescriptor::~ScRangeFilterDescriptor() +{ + if (pParent) + pParent->release(); +} + +void ScRangeFilterDescriptor::GetData( ScQueryParam& rParam ) const +{ + if (pParent) + pParent->GetQueryParam( rParam ); +} + +void ScRangeFilterDescriptor::PutData( const ScQueryParam& rParam ) +{ + if (pParent) + pParent->SetQueryParam( rParam ); +} + +//------------------------------------------------------------------------ + +ScDataPilotFilterDescriptor::ScDataPilotFilterDescriptor(ScDocShell* pDocShell, ScDataPilotDescriptorBase* pPar) : + ScFilterDescriptorBase(pDocShell), + pParent(pPar) +{ + if (pParent) + pParent->acquire(); +} + +ScDataPilotFilterDescriptor::~ScDataPilotFilterDescriptor() +{ + if (pParent) + pParent->release(); +} + +void ScDataPilotFilterDescriptor::GetData( ScQueryParam& rParam ) const +{ + if (pParent) + { + ScDPObject* pDPObj = pParent->GetDPObject(); + if (pDPObj && pDPObj->IsSheetData()) + rParam = pDPObj->GetSheetDesc()->aQueryParam; + } +} + +void ScDataPilotFilterDescriptor::PutData( const ScQueryParam& rParam ) +{ + if (pParent) + { + ScDPObject* pDPObj = pParent->GetDPObject(); + if (pDPObj) + { + ScSheetSourceDesc aSheetDesc; + if (pDPObj->IsSheetData()) + aSheetDesc = *pDPObj->GetSheetDesc(); + aSheetDesc.aQueryParam = rParam; + pDPObj->SetSheetDesc(aSheetDesc); + pParent->SetDPObject(pDPObj); + } + } +} + +//------------------------------------------------------------------------ + +ScDatabaseRangeObj::ScDatabaseRangeObj(ScDocShell* pDocSh, const String& rNm) : + pDocShell( pDocSh ), + aName( rNm ), + aPropSet( lcl_GetDBRangePropertyMap() ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScDatabaseRangeObj::~ScDatabaseRangeObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScDatabaseRangeObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + + if ( rHint.ISA( SfxSimpleHint ) && ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + pDocShell = NULL; // ungueltig geworden + else if ( rHint.ISA (ScDBRangeRefreshedHint) ) + { + ScDBData* pDBData = GetDBData_Impl(); + const ScDBRangeRefreshedHint& rRef = (const ScDBRangeRefreshedHint&)rHint; + ScImportParam aParam; + pDBData->GetImportParam(aParam); + if (aParam == rRef.GetImportParam()) + Refreshed_Impl(); + } +} + +// Hilfsfuntionen + +ScDBData* ScDatabaseRangeObj::GetDBData_Impl() const +{ + ScDBData* pRet = NULL; + if (pDocShell) + { + ScDBCollection* pNames = pDocShell->GetDocument()->GetDBCollection(); + if (pNames) + { + USHORT nPos = 0; + if (pNames->SearchName( aName, nPos )) + pRet = (*pNames)[nPos]; + } + } + return pRet; +} + +// XNamed + +rtl::OUString SAL_CALL ScDatabaseRangeObj::getName() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return aName; +} + +void SAL_CALL ScDatabaseRangeObj::setName( const rtl::OUString& aNewName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + ScDBDocFunc aFunc(*pDocShell); + String aNewStr(aNewName); + BOOL bOk = aFunc.RenameDBRange( aName, aNewStr, TRUE ); + if (bOk) + aName = aNewStr; + } +} + +// XDatabaseRange + +table::CellRangeAddress SAL_CALL ScDatabaseRangeObj::getDataArea() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + table::CellRangeAddress aAddress; + ScDBData* pData = GetDBData_Impl(); + if (pData) + { + ScRange aRange; + pData->GetArea(aRange); + aAddress.Sheet = aRange.aStart.Tab(); + aAddress.StartColumn = aRange.aStart.Col(); + aAddress.StartRow = aRange.aStart.Row(); + aAddress.EndColumn = aRange.aEnd.Col(); + aAddress.EndRow = aRange.aEnd.Row(); + } + return aAddress; +} + +void SAL_CALL ScDatabaseRangeObj::setDataArea( const table::CellRangeAddress& aDataArea ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDBData* pData = GetDBData_Impl(); + if ( pDocShell && pData ) + { + ScDBData aNewData( *pData ); + //! MoveTo ??? + aNewData.SetArea( aDataArea.Sheet, (SCCOL)aDataArea.StartColumn, (SCROW)aDataArea.StartRow, + (SCCOL)aDataArea.EndColumn, (SCROW)aDataArea.EndRow ); + ScDBDocFunc aFunc(*pDocShell); + aFunc.ModifyDBData(aNewData, TRUE); + } +} + +uno::Sequence<beans::PropertyValue> SAL_CALL ScDatabaseRangeObj::getSortDescriptor() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScSortParam aParam; + const ScDBData* pData = GetDBData_Impl(); + if (pData) + { + pData->GetSortParam(aParam); + + // im SortDescriptor sind die Fields innerhalb des Bereichs gezaehlt + ScRange aDBRange; + pData->GetArea(aDBRange); + SCCOLROW nFieldStart = aParam.bByRow ? static_cast<SCCOLROW>(aDBRange.aStart.Col()) : static_cast<SCCOLROW>(aDBRange.aStart.Row()); + for (USHORT i=0; i<MAXSORT; i++) + if ( aParam.bDoSort[i] && aParam.nField[i] >= nFieldStart ) + aParam.nField[i] -= nFieldStart; + } + + uno::Sequence<beans::PropertyValue> aSeq( ScSortDescriptor::GetPropertyCount() ); + ScSortDescriptor::FillProperties( aSeq, aParam ); + return aSeq; +} + +void ScDatabaseRangeObj::GetQueryParam(ScQueryParam& rQueryParam) const +{ + const ScDBData* pData = GetDBData_Impl(); + if (pData) + { + pData->GetQueryParam(rQueryParam); + + // im FilterDescriptor sind die Fields innerhalb des Bereichs gezaehlt + ScRange aDBRange; + pData->GetArea(aDBRange); + SCCOLROW nFieldStart = rQueryParam.bByRow ? static_cast<SCCOLROW>(aDBRange.aStart.Col()) : static_cast<SCCOLROW>(aDBRange.aStart.Row()); + SCSIZE nCount = rQueryParam.GetEntryCount(); + for (SCSIZE i=0; i<nCount; i++) + { + ScQueryEntry& rEntry = rQueryParam.GetEntry(i); + if (rEntry.bDoQuery && rEntry.nField >= nFieldStart) + rEntry.nField -= nFieldStart; + } + } +} + +void ScDatabaseRangeObj::SetQueryParam(const ScQueryParam& rQueryParam) +{ + const ScDBData* pData = GetDBData_Impl(); + if (pData) + { + // im FilterDescriptor sind die Fields innerhalb des Bereichs gezaehlt + ScQueryParam aParam(rQueryParam); + ScRange aDBRange; + pData->GetArea(aDBRange); + SCCOLROW nFieldStart = aParam.bByRow ? static_cast<SCCOLROW>(aDBRange.aStart.Col()) : static_cast<SCCOLROW>(aDBRange.aStart.Row()); + + SCSIZE nCount = aParam.GetEntryCount(); + for (SCSIZE i=0; i<nCount; i++) + { + ScQueryEntry& rEntry = aParam.GetEntry(i); + if (rEntry.bDoQuery) + rEntry.nField += nFieldStart; + } + + ScDBData aNewData( *pData ); + aNewData.SetQueryParam(aParam); + aNewData.SetHeader(aParam.bHasHeader); // not in ScDBData::SetQueryParam + ScDBDocFunc aFunc(*pDocShell); + aFunc.ModifyDBData(aNewData, TRUE); + } +} + +uno::Reference<sheet::XSheetFilterDescriptor> SAL_CALL ScDatabaseRangeObj::getFilterDescriptor() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScRangeFilterDescriptor(pDocShell, this); +} + +void ScDatabaseRangeObj::GetSubTotalParam(ScSubTotalParam& rSubTotalParam) const +{ + const ScDBData* pData = GetDBData_Impl(); + if (pData) + { + pData->GetSubTotalParam(rSubTotalParam); + + // im FilterDescriptor sind die Fields innerhalb des Bereichs gezaehlt + ScRange aDBRange; + pData->GetArea(aDBRange); + SCCOL nFieldStart = aDBRange.aStart.Col(); + for (USHORT i=0; i<MAXSUBTOTAL; i++) + { + if ( rSubTotalParam.bGroupActive[i] ) + { + if ( rSubTotalParam.nField[i] >= nFieldStart ) + rSubTotalParam.nField[i] = sal::static_int_cast<SCCOL>( rSubTotalParam.nField[i] - nFieldStart ); + for (SCCOL j=0; j<rSubTotalParam.nSubTotals[i]; j++) + if ( rSubTotalParam.pSubTotals[i][j] >= nFieldStart ) + rSubTotalParam.pSubTotals[i][j] = + sal::static_int_cast<SCCOL>( rSubTotalParam.pSubTotals[i][j] - nFieldStart ); + } + } + } +} + +void ScDatabaseRangeObj::SetSubTotalParam(const ScSubTotalParam& rSubTotalParam) +{ + const ScDBData* pData = GetDBData_Impl(); + if (pData) + { + // im FilterDescriptor sind die Fields innerhalb des Bereichs gezaehlt + ScSubTotalParam aParam(rSubTotalParam); + ScRange aDBRange; + pData->GetArea(aDBRange); + SCCOL nFieldStart = aDBRange.aStart.Col(); + for (USHORT i=0; i<MAXSUBTOTAL; i++) + { + if ( aParam.bGroupActive[i] ) + { + aParam.nField[i] = sal::static_int_cast<SCCOL>( aParam.nField[i] + nFieldStart ); + for (SCCOL j=0; j<aParam.nSubTotals[i]; j++) + aParam.pSubTotals[i][j] = sal::static_int_cast<SCCOL>( aParam.pSubTotals[i][j] + nFieldStart ); + } + } + + ScDBData aNewData( *pData ); + aNewData.SetSubTotalParam(aParam); + ScDBDocFunc aFunc(*pDocShell); + aFunc.ModifyDBData(aNewData, TRUE); + } +} + +uno::Reference<sheet::XSubTotalDescriptor> SAL_CALL ScDatabaseRangeObj::getSubTotalDescriptor() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScRangeSubTotalDescriptor(this); +} + +uno::Sequence<beans::PropertyValue> SAL_CALL ScDatabaseRangeObj::getImportDescriptor() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScImportParam aParam; + const ScDBData* pData = GetDBData_Impl(); + if (pData) + pData->GetImportParam(aParam); + + uno::Sequence<beans::PropertyValue> aSeq( ScImportDescriptor::GetPropertyCount() ); + ScImportDescriptor::FillProperties( aSeq, aParam ); + return aSeq; +} + +// XRefreshable + +void SAL_CALL ScDatabaseRangeObj::refresh() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDBData* pData = GetDBData_Impl(); + if ( pDocShell && pData ) + { + ScDBDocFunc aFunc(*pDocShell); + + // Import zu wiederholen? + BOOL bContinue = TRUE; + ScImportParam aImportParam; + pData->GetImportParam( aImportParam ); + if (aImportParam.bImport && !pData->HasImportSelection()) + { + SCTAB nTab; + SCCOL nDummyCol; + SCROW nDummyRow; + pData->GetArea( nTab, nDummyCol,nDummyRow,nDummyCol,nDummyRow ); + uno::Reference< sdbc::XResultSet > xResultSet; + bContinue = aFunc.DoImport( nTab, aImportParam, xResultSet, NULL, TRUE, FALSE ); //! Api-Flag als Parameter + } + + // interne Operationen (sort, query, subtotal) nur, wenn kein Fehler + if (bContinue) + aFunc.RepeatDB( pData->GetName(), TRUE, TRUE ); + } +} + +void SAL_CALL ScDatabaseRangeObj::addRefreshListener( + const uno::Reference<util::XRefreshListener >& xListener ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<util::XRefreshListener>* pObj = + new uno::Reference<util::XRefreshListener>( xListener ); + aRefreshListeners.Insert( pObj, aRefreshListeners.Count() ); + + // hold one additional ref to keep this object alive as long as there are listeners + if ( aRefreshListeners.Count() == 1 ) + acquire(); +} + +void SAL_CALL ScDatabaseRangeObj::removeRefreshListener( + const uno::Reference<util::XRefreshListener >& xListener ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + USHORT nCount = aRefreshListeners.Count(); + for ( USHORT n=nCount; n--; ) + { + uno::Reference<util::XRefreshListener>* pObj = aRefreshListeners[n]; + if ( *pObj == xListener ) + { + aRefreshListeners.DeleteAndDestroy( n ); + if ( aRefreshListeners.Count() == 0 ) + release(); // release ref for listeners + break; + } + } +} + +void ScDatabaseRangeObj::Refreshed_Impl() +{ + lang::EventObject aEvent; + aEvent.Source = (cppu::OWeakObject*)this; + for ( USHORT n=0; n<aRefreshListeners.Count(); n++ ) + (*aRefreshListeners[n])->refreshed( aEvent ); +} + +// XCellRangeSource + +uno::Reference<table::XCellRange> SAL_CALL ScDatabaseRangeObj::getReferredCells() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScRange aRange; + ScDBData* pData = GetDBData_Impl(); + if ( pData ) + { + //! static Funktion um ScCellObj/ScCellRangeObj zu erzeugen am ScCellRangeObj ??? + + pData->GetArea(aRange); + if ( aRange.aStart == aRange.aEnd ) + return new ScCellObj( pDocShell, aRange.aStart ); + else + return new ScCellRangeObj( pDocShell, aRange ); + } + return NULL; +} + +// XPropertySet + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDatabaseRangeObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef( + new SfxItemPropertySetInfo( aPropSet.getPropertyMap() )); + return aRef; +} + +void SAL_CALL ScDatabaseRangeObj::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDBData* pData = GetDBData_Impl(); + if ( pDocShell && pData ) + { + ScDBData aNewData( *pData ); + BOOL bDo = TRUE; + + String aString(aPropertyName); + if ( aString.EqualsAscii( SC_UNONAME_KEEPFORM ) ) + aNewData.SetKeepFmt( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aString.EqualsAscii( SC_UNONAME_MOVCELLS ) ) + aNewData.SetDoSize( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aString.EqualsAscii( SC_UNONAME_STRIPDAT ) ) + aNewData.SetStripData( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if (aString.EqualsAscii( SC_UNONAME_AUTOFLT )) + { + sal_Bool bAutoFilter(ScUnoHelpFunctions::GetBoolFromAny( aValue )); + aNewData.SetAutoFilter(bAutoFilter); + ScRange aRange; + aNewData.GetArea(aRange); + ScDocument* pDoc = pDocShell->GetDocument(); + if (bAutoFilter && pDoc) + pDoc->ApplyFlagsTab( aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aStart.Row(), + aRange.aStart.Tab(), SC_MF_AUTO ); + else if (!bAutoFilter && pDoc) + pDoc->RemoveFlagsTab(aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aStart.Row(), + aRange.aStart.Tab(), SC_MF_AUTO ); + ScRange aPaintRange(aRange.aStart, aRange.aEnd); + aPaintRange.aEnd.SetRow(aPaintRange.aStart.Row()); + pDocShell->PostPaint(aPaintRange, PAINT_GRID); + } + else if (aString.EqualsAscii( SC_UNONAME_USEFLTCRT )) + { + if (ScUnoHelpFunctions::GetBoolFromAny( aValue )) + { + ScRange aRange; + aNewData.GetAdvancedQuerySource(aRange); + aNewData.SetAdvancedQuerySource(&aRange); + } + else + aNewData.SetAdvancedQuerySource(NULL); + } + else if (aString.EqualsAscii( SC_UNONAME_FLTCRT )) + { + table::CellRangeAddress aRange; + if (aValue >>= aRange) + { + ScRange aCoreRange; + ScUnoConversion::FillScRange(aCoreRange, aRange); + + aNewData.SetAdvancedQuerySource(&aCoreRange); + } + } + else if (aString.EqualsAscii( SC_UNONAME_FROMSELECT )) + { + aNewData.SetImportSelection(::cppu::any2bool(aValue)); + } + else if (aString.EqualsAscii( SC_UNONAME_REFPERIOD )) + { + sal_Int32 nRefresh = 0; + if (aValue >>= nRefresh) + { + ScDocument* pDoc = pDocShell->GetDocument(); + aNewData.SetRefreshDelay(nRefresh); + if (pDoc && pDoc->GetDBCollection()) + { + aNewData.SetRefreshHandler( pDoc->GetDBCollection()->GetRefreshHandler() ); + aNewData.SetRefreshControl( pDoc->GetRefreshTimerControlAddress() ); + } + } + } + else if (aString.EqualsAscii( SC_UNONAME_CONRES )) + { + } + else + bDo = FALSE; + + if (bDo) + { + ScDBDocFunc aFunc(*pDocShell); + aFunc.ModifyDBData(aNewData, TRUE); + } + } +} + +uno::Any SAL_CALL ScDatabaseRangeObj::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Any aRet; + ScDBData* pData = GetDBData_Impl(); + if ( pData ) + { + String aString(aPropertyName); + if ( aString.EqualsAscii( SC_UNONAME_KEEPFORM ) ) + ScUnoHelpFunctions::SetBoolInAny( aRet, pData->IsKeepFmt() ); + else if ( aString.EqualsAscii( SC_UNONAME_MOVCELLS ) ) + ScUnoHelpFunctions::SetBoolInAny( aRet, pData->IsDoSize() ); + else if ( aString.EqualsAscii( SC_UNONAME_STRIPDAT ) ) + ScUnoHelpFunctions::SetBoolInAny( aRet, pData->IsStripData() ); + else if ( aString.EqualsAscii( SC_UNONAME_ISUSER ) ) + { + // all database ranges except "unnamed" are user defined + ScUnoHelpFunctions::SetBoolInAny( aRet, + ( pData->GetName() != ScGlobal::GetRscString(STR_DB_NONAME) ) ); + } + else if ( aString.EqualsAscii( SC_UNO_LINKDISPBIT ) ) + { + // no target bitmaps for individual entries (would be all equal) + // ScLinkTargetTypeObj::SetLinkTargetBitmap( aRet, SC_LINKTARGETTYPE_DBAREA ); + } + else if ( aString.EqualsAscii( SC_UNO_LINKDISPNAME ) ) + aRet <<= rtl::OUString( aName ); + else if (aString.EqualsAscii( SC_UNONAME_AUTOFLT )) + { + sal_Bool bAutoFilter(GetDBData_Impl()->HasAutoFilter()); + + ScUnoHelpFunctions::SetBoolInAny( aRet, bAutoFilter ); + } + else if (aString.EqualsAscii( SC_UNONAME_USEFLTCRT )) + { + ScRange aRange; + sal_Bool bIsAdvancedSource(GetDBData_Impl()->GetAdvancedQuerySource(aRange)); + + ScUnoHelpFunctions::SetBoolInAny( aRet, bIsAdvancedSource ); + } + else if (aString.EqualsAscii( SC_UNONAME_FLTCRT )) + { + table::CellRangeAddress aRange; + ScRange aCoreRange; + if (GetDBData_Impl()->GetAdvancedQuerySource(aCoreRange)) + ScUnoConversion::FillApiRange(aRange, aCoreRange); + + aRet <<= aRange; + } + else if (aString.EqualsAscii( SC_UNONAME_FROMSELECT )) + { + ScUnoHelpFunctions::SetBoolInAny( aRet, GetDBData_Impl()->HasImportSelection() ); + } + else if (aString.EqualsAscii( SC_UNONAME_REFPERIOD )) + { + sal_Int32 nRefresh(GetDBData_Impl()->GetRefreshDelay()); + aRet <<= nRefresh; + } + else if (aString.EqualsAscii( SC_UNONAME_CONRES )) + { + } + else if (aString.EqualsAscii( SC_UNONAME_TOKENINDEX )) + { + // get index for use in formula tokens (read-only) + aRet <<= static_cast<sal_Int32>(GetDBData_Impl()->GetIndex()); + } + } + return aRet; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDatabaseRangeObj ) + +// XServiceInfo + +rtl::OUString SAL_CALL ScDatabaseRangeObj::getImplementationName() throw(uno::RuntimeException) +{ + return rtl::OUString::createFromAscii( "ScDatabaseRangeObj" ); +} + +sal_Bool SAL_CALL ScDatabaseRangeObj::supportsService( const rtl::OUString& rServiceName ) + throw(uno::RuntimeException) +{ + String aServiceStr( rServiceName ); + return aServiceStr.EqualsAscii( SCDATABASERANGEOBJ_SERVICE ) || + aServiceStr.EqualsAscii( SCLINKTARGET_SERVICE ); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScDatabaseRangeObj::getSupportedServiceNames() + throw(uno::RuntimeException) +{ + uno::Sequence<rtl::OUString> aRet(2); + rtl::OUString* pArray = aRet.getArray(); + pArray[0] = rtl::OUString::createFromAscii( SCDATABASERANGEOBJ_SERVICE ); + pArray[1] = rtl::OUString::createFromAscii( SCLINKTARGET_SERVICE ); + return aRet; +} + +//------------------------------------------------------------------------ + +ScDatabaseRangesObj::ScDatabaseRangesObj(ScDocShell* pDocSh) : + pDocShell( pDocSh ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScDatabaseRangesObj::~ScDatabaseRangesObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScDatabaseRangesObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + // Referenz-Update interessiert hier nicht + + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +// XDatabaseRanges + +ScDatabaseRangeObj* ScDatabaseRangesObj::GetObjectByIndex_Impl(USHORT nIndex) +{ + if (pDocShell) + { + ScDBCollection* pNames = pDocShell->GetDocument()->GetDBCollection(); + if (pNames && nIndex < pNames->GetCount()) + return new ScDatabaseRangeObj( pDocShell, (*pNames)[nIndex]->GetName() ); + } + return NULL; +} + +ScDatabaseRangeObj* ScDatabaseRangesObj::GetObjectByName_Impl(const rtl::OUString& aName) +{ + if ( pDocShell && hasByName(aName) ) + { + String aString(aName); + return new ScDatabaseRangeObj( pDocShell, aString ); + } + return NULL; +} + + +void SAL_CALL ScDatabaseRangesObj::addNewByName( const rtl::OUString& aName, + const table::CellRangeAddress& aRange ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + BOOL bDone = FALSE; + if (pDocShell) + { + ScDBDocFunc aFunc(*pDocShell); + + String aString(aName); + ScRange aNameRange( (SCCOL)aRange.StartColumn, (SCROW)aRange.StartRow, aRange.Sheet, + (SCCOL)aRange.EndColumn, (SCROW)aRange.EndRow, aRange.Sheet ); + bDone = aFunc.AddDBRange( aString, aNameRange, TRUE ); + } + if (!bDone) + throw uno::RuntimeException(); // no other exceptions specified +} + +void SAL_CALL ScDatabaseRangesObj::removeByName( const rtl::OUString& aName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + BOOL bDone = FALSE; + if (pDocShell) + { + ScDBDocFunc aFunc(*pDocShell); + String aString(aName); + bDone = aFunc.DeleteDBRange( aString, TRUE ); + } + if (!bDone) + throw uno::RuntimeException(); // no other exceptions specified +} + +// XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScDatabaseRangesObj::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.DatabaseRangesEnumeration"))); +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScDatabaseRangesObj::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + //! "unbenannt" weglassen ? + + if (pDocShell) + { + ScDBCollection* pNames = pDocShell->GetDocument()->GetDBCollection(); + if (pNames) + return pNames->GetCount(); + } + return 0; +} + +uno::Any SAL_CALL ScDatabaseRangesObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<sheet::XDatabaseRange> xRange(GetObjectByIndex_Impl((USHORT)nIndex)); + if (xRange.is()) + return uno::makeAny(xRange); + else + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +uno::Type SAL_CALL ScDatabaseRangesObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((uno::Reference<sheet::XDatabaseRange>*)0); +} + +sal_Bool SAL_CALL ScDatabaseRangesObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +// XNameAccess + +uno::Any SAL_CALL ScDatabaseRangesObj::getByName( const rtl::OUString& aName ) + throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<sheet::XDatabaseRange> xRange(GetObjectByName_Impl(aName)); + if (xRange.is()) + return uno::makeAny(xRange); + else + throw container::NoSuchElementException(); +// return uno::Any(); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScDatabaseRangesObj::getElementNames() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + //! "unbenannt" weglassen ? + + if (pDocShell) + { + ScDBCollection* pNames = pDocShell->GetDocument()->GetDBCollection(); + if (pNames) + { + USHORT nCount = pNames->GetCount(); + String aName; + uno::Sequence<rtl::OUString> aSeq(nCount); + rtl::OUString* pAry = aSeq.getArray(); + for (USHORT i=0; i<nCount; i++) + pAry[i] = (*pNames)[i]->GetName(); + + return aSeq; + } + } + return uno::Sequence<rtl::OUString>(0); +} + +sal_Bool SAL_CALL ScDatabaseRangesObj::hasByName( const rtl::OUString& aName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + //! "unbenannt" weglassen ? + + if (pDocShell) + { + ScDBCollection* pNames = pDocShell->GetDocument()->GetDBCollection(); + if (pNames) + { + String aString(aName); + USHORT nPos = 0; + if (pNames->SearchName( aString, nPos )) + return TRUE; + } + } + return FALSE; +} + +//------------------------------------------------------------------------ + + + + + diff --git a/sc/source/ui/unoobj/defltuno.cxx b/sc/source/ui/unoobj/defltuno.cxx new file mode 100644 index 000000000000..f3f76685e5cb --- /dev/null +++ b/sc/source/ui/unoobj/defltuno.cxx @@ -0,0 +1,387 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + +#include <editeng/memberids.hrc> +#include <svl/smplhint.hxx> +#include <svl/itemprop.hxx> +#include <svx/unomid.hxx> +#include <i18npool/mslangid.hxx> + +#include <com/sun/star/beans/PropertyAttribute.hpp> + +#include "scitems.hxx" +#include "defltuno.hxx" +#include "miscuno.hxx" +#include "docsh.hxx" +#include "docpool.hxx" +#include "unoguard.hxx" +#include "unonames.hxx" +#include "docoptio.hxx" + +#include <limits> + +using namespace ::com::sun::star; + +//------------------------------------------------------------------------ + +const SfxItemPropertyMapEntry* lcl_GetDocDefaultsMap() +{ + static SfxItemPropertyMapEntry aDocDefaultsMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_CFCHARS), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFCHARS), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFCHARS), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNONAME_CFFAMIL), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFFAMIL), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFFAMIL), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNONAME_CFNAME), ATTR_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFNAME), ATTR_CJK_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFNAME), ATTR_CTL_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNONAME_CFPITCH), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFPITCH), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFPITCH), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNONAME_CFSTYLE), ATTR_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFSTYLE), ATTR_CJK_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFSTYLE), ATTR_CTL_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNONAME_CLOCAL), ATTR_FONT_LANGUAGE, &getCppuType((lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNO_CJK_CLOCAL), ATTR_CJK_FONT_LANGUAGE, &getCppuType((lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNO_CTL_CLOCAL), ATTR_CTL_FONT_LANGUAGE, &getCppuType((lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNO_STANDARDDEC), 0, &getCppuType((sal_Int16*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_TABSTOPDIS), 0, &getCppuType((sal_Int32*)0), 0, 0 }, + {0,0,0,0,0,0} + }; + return aDocDefaultsMap_Impl; +} + +inline long TwipsToHMM(long nTwips) { return (nTwips * 127 + 36) / 72; } +inline long HMMToTwips(long nHMM) { return (nHMM * 72 + 63) / 127; } +inline long TwipsToEvenHMM(long nTwips) { return ( (nTwips * 127 + 72) / 144 ) * 2; } + +//------------------------------------------------------------------------ + +SC_SIMPLE_SERVICE_INFO( ScDocDefaultsObj, "ScDocDefaultsObj", "com.sun.star.sheet.Defaults" ) + +//------------------------------------------------------------------------ + +ScDocDefaultsObj::ScDocDefaultsObj(ScDocShell* pDocSh) : + pDocShell( pDocSh ), + aPropertyMap(lcl_GetDocDefaultsMap()) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScDocDefaultsObj::~ScDocDefaultsObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScDocDefaultsObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // document gone + } +} + +void ScDocDefaultsObj::ItemsChanged() +{ + if (pDocShell) + { + //! if not in XML import, adjust row heights + + pDocShell->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID ); + } +} + +// XPropertySet + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScDocDefaultsObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef = new SfxItemPropertySetInfo( + &aPropertyMap ); + return aRef; +} + +void SAL_CALL ScDocDefaultsObj::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if ( !pDocShell ) + throw uno::RuntimeException(); + + const SfxItemPropertySimpleEntry* pEntry = aPropertyMap.getByName( aPropertyName ); + if ( !pEntry ) + throw beans::UnknownPropertyException(); + if(!pEntry->nWID) + { + if(aPropertyName.compareToAscii(SC_UNO_STANDARDDEC) == 0) + { + ScDocument* pDoc = pDocShell->GetDocument(); + if (pDoc) + { + ScDocOptions aDocOpt(pDoc->GetDocOptions()); + sal_Int16 nValue = 0; + if (aValue >>= nValue) + { + aDocOpt.SetStdPrecision(static_cast<sal_uInt16> (nValue)); + pDoc->SetDocOptions(aDocOpt); + } + } + else + throw uno::RuntimeException(); + } + else if (aPropertyName.compareToAscii(SC_UNO_TABSTOPDIS) == 0) + { + ScDocument* pDoc = pDocShell->GetDocument(); + if (pDoc) + { + ScDocOptions aDocOpt(pDoc->GetDocOptions()); + sal_Int32 nValue = 0; + if (aValue >>= nValue) + { + aDocOpt.SetTabDistance(static_cast<sal_uInt16>(HMMToTwips(nValue))); + pDoc->SetDocOptions(aDocOpt); + } + } + else + throw uno::RuntimeException(); + } + } + else if ( pEntry->nWID == ATTR_FONT_LANGUAGE || + pEntry->nWID == ATTR_CJK_FONT_LANGUAGE || + pEntry->nWID == ATTR_CTL_FONT_LANGUAGE ) + { + // for getPropertyValue the PoolDefaults are sufficient, + // but setPropertyValue has to be handled differently + + lang::Locale aLocale; + if ( aValue >>= aLocale ) + { + LanguageType eNew; + if (aLocale.Language.getLength() || aLocale.Country.getLength()) + eNew = MsLangId::convertLocaleToLanguage( aLocale ); + else + eNew = LANGUAGE_NONE; + + ScDocument* pDoc = pDocShell->GetDocument(); + LanguageType eLatin, eCjk, eCtl; + pDoc->GetLanguage( eLatin, eCjk, eCtl ); + + if ( pEntry->nWID == ATTR_CJK_FONT_LANGUAGE ) + eCjk = eNew; + else if ( pEntry->nWID == ATTR_CTL_FONT_LANGUAGE ) + eCtl = eNew; + else + eLatin = eNew; + + pDoc->SetLanguage( eLatin, eCjk, eCtl ); + } + } + else + { + ScDocumentPool* pPool = pDocShell->GetDocument()->GetPool(); + SfxPoolItem* pNewItem = pPool->GetDefaultItem(pEntry->nWID).Clone(); + + if( !pNewItem->PutValue( aValue, pEntry->nMemberId ) ) + throw lang::IllegalArgumentException(); + + pPool->SetPoolDefaultItem( *pNewItem ); + delete pNewItem; // copied in SetPoolDefaultItem + + ItemsChanged(); + } +} + +uno::Any SAL_CALL ScDocDefaultsObj::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + // use pool default if set + + ScUnoGuard aGuard; + + if ( !pDocShell ) + throw uno::RuntimeException(); + + uno::Any aRet; + const SfxItemPropertySimpleEntry* pEntry = aPropertyMap.getByName( aPropertyName ); + if ( !pEntry ) + throw beans::UnknownPropertyException(); + + if (!pEntry->nWID) + { + if(aPropertyName.compareToAscii(SC_UNO_STANDARDDEC) == 0) + { + ScDocument* pDoc = pDocShell->GetDocument(); + if (pDoc) + { + const ScDocOptions& aDocOpt = pDoc->GetDocOptions(); + sal_uInt16 nPrec = aDocOpt.GetStdPrecision(); + // the max value of unsigned 16-bit integer is used as the flag + // value for unlimited precision, c.f. + // SvNumberFormatter::UNLIMITED_PRECISION. + if (nPrec <= ::std::numeric_limits<sal_Int16>::max()) + aRet <<= static_cast<sal_Int16> (nPrec); + } + else + throw uno::RuntimeException(); + } + else if (aPropertyName.compareToAscii(SC_UNO_TABSTOPDIS) == 0) + { + ScDocument* pDoc = pDocShell->GetDocument(); + if (pDoc) + { + const ScDocOptions& aDocOpt = pDoc->GetDocOptions(); + sal_Int32 nValue (TwipsToEvenHMM(aDocOpt.GetTabDistance())); + aRet <<= nValue; + } + else + throw uno::RuntimeException(); + } + } + else + { + ScDocumentPool* pPool = pDocShell->GetDocument()->GetPool(); + const SfxPoolItem& rItem = pPool->GetDefaultItem( pEntry->nWID ); + rItem.QueryValue( aRet, pEntry->nMemberId ); + } + return aRet; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScDocDefaultsObj ) + +// XPropertyState + +beans::PropertyState SAL_CALL ScDocDefaultsObj::getPropertyState( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if ( !pDocShell ) + throw uno::RuntimeException(); + + const SfxItemPropertySimpleEntry* pEntry = aPropertyMap.getByName( aPropertyName ); + if ( !pEntry ) + throw beans::UnknownPropertyException(); + + beans::PropertyState eRet = beans::PropertyState_DEFAULT_VALUE; + + USHORT nWID = pEntry->nWID; + if ( nWID == ATTR_FONT || nWID == ATTR_CJK_FONT || nWID == ATTR_CTL_FONT || !nWID ) + { + // static default for font is system-dependent, + // so font default is always treated as "direct value". + + eRet = beans::PropertyState_DIRECT_VALUE; + } + else + { + // check if pool default is set + + ScDocumentPool* pPool = pDocShell->GetDocument()->GetPool(); + if ( pPool->GetPoolDefaultItem( nWID ) != NULL ) + eRet = beans::PropertyState_DIRECT_VALUE; + } + + return eRet; +} + +uno::Sequence<beans::PropertyState> SAL_CALL ScDocDefaultsObj::getPropertyStates( + const uno::Sequence<rtl::OUString>& aPropertyNames ) + throw(beans::UnknownPropertyException, uno::RuntimeException) +{ + // the simple way: call getPropertyState + + ScUnoGuard aGuard; + const rtl::OUString* pNames = aPropertyNames.getConstArray(); + uno::Sequence<beans::PropertyState> aRet(aPropertyNames.getLength()); + beans::PropertyState* pStates = aRet.getArray(); + for(sal_Int32 i = 0; i < aPropertyNames.getLength(); i++) + pStates[i] = getPropertyState(pNames[i]); + return aRet; +} + +void SAL_CALL ScDocDefaultsObj::setPropertyToDefault( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if ( !pDocShell ) + throw uno::RuntimeException(); + + const SfxItemPropertySimpleEntry* pEntry = aPropertyMap.getByName( aPropertyName ); + if ( !pEntry ) + throw beans::UnknownPropertyException(); + + if (pEntry->nWID) + { + ScDocumentPool* pPool = pDocShell->GetDocument()->GetPool(); + pPool->ResetPoolDefaultItem( pEntry->nWID ); + + ItemsChanged(); + } +} + +uno::Any SAL_CALL ScDocDefaultsObj::getPropertyDefault( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + // always use static default + + ScUnoGuard aGuard; + + if ( !pDocShell ) + throw uno::RuntimeException(); + + const SfxItemPropertySimpleEntry* pEntry = aPropertyMap.getByName( aPropertyName ); + if ( !pEntry ) + throw beans::UnknownPropertyException(); + + uno::Any aRet; + if (pEntry->nWID) + { + ScDocumentPool* pPool = pDocShell->GetDocument()->GetPool(); + const SfxPoolItem* pItem = pPool->GetItem( pEntry->nWID, SFX_ITEMS_STATICDEFAULT ); + if (pItem) + pItem->QueryValue( aRet, pEntry->nMemberId ); + } + return aRet; +} + + diff --git a/sc/source/ui/unoobj/detreg.cxx b/sc/source/ui/unoobj/detreg.cxx new file mode 100644 index 000000000000..e1e77e5deac9 --- /dev/null +++ b/sc/source/ui/unoobj/detreg.cxx @@ -0,0 +1,90 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +#include "scdetect.hxx" +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/registry/XRegistryKey.hpp> +#include <com/sun/star/uno/Sequence.h> +#include <sal/types.h> +#include <rtl/ustring.hxx> + +using ::rtl::OUString; +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; + +extern "C" { + +SAL_DLLPUBLIC_EXPORT void SAL_CALL component_getImplementationEnvironment( + const sal_Char** ppEnvironmentTypeName, + uno_Environment** /* ppEnvironment */ ) +{ + *ppEnvironmentTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME ; +} + +SAL_DLLPUBLIC_EXPORT void* SAL_CALL component_getFactory( const sal_Char* pImplementationName, + void* pServiceManager, + void* /* pRegistryKey */ ) +{ + // Set default return value for this operation - if it failed. + void* pReturn = NULL ; + + if ( + ( pImplementationName != NULL ) && + ( pServiceManager != NULL ) + ) + { + // Define variables which are used in following macros. + Reference< XSingleServiceFactory > xFactory ; + Reference< XMultiServiceFactory > xServiceManager( reinterpret_cast< XMultiServiceFactory* >( pServiceManager ) ) ; + + if( ScFilterDetect::impl_getStaticImplementationName().equalsAscii( pImplementationName ) ) + { + xFactory.set(::cppu::createSingleFactory( xServiceManager, + ScFilterDetect::impl_getStaticImplementationName(), + ScFilterDetect::impl_createInstance, + ScFilterDetect::impl_getStaticSupportedServiceNames() )); + } + + // Factory is valid - service was found. + if ( xFactory.is() ) + { + xFactory->acquire(); + pReturn = xFactory.get(); + } + } + + // Return with result of this operation. + return pReturn ; +} +} // extern "C" + + + diff --git a/sc/source/ui/unoobj/dispuno.cxx b/sc/source/ui/unoobj/dispuno.cxx new file mode 100644 index 000000000000..6c82871d02da --- /dev/null +++ b/sc/source/ui/unoobj/dispuno.cxx @@ -0,0 +1,415 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include <sfx2/viewfrm.hxx> +#include <comphelper/uno3.hxx> +#include <svx/dataaccessdescriptor.hxx> +#include <svl/smplhint.hxx> + +#include <com/sun/star/frame/XDispatchProviderInterception.hpp> +#include <com/sun/star/view/XSelectionSupplier.hpp> +#include <com/sun/star/sdb/CommandType.hpp> + +#include "dispuno.hxx" +#include "unoguard.hxx" +#include "tabvwsh.hxx" +#include "dbdocfun.hxx" +#include "dbcolect.hxx" + +using namespace com::sun::star; + +//------------------------------------------------------------------------ + +const char* cURLInsertColumns = ".uno:DataSourceBrowser/InsertColumns"; //data into text +const char* cURLDocDataSource = ".uno:DataSourceBrowser/DocumentDataSource"; + +//------------------------------------------------------------------------ + +SV_IMPL_PTRARR( XStatusListenerArr_Impl, XStatusListenerPtr ); + +//------------------------------------------------------------------------ + +uno::Reference<view::XSelectionSupplier> lcl_GetSelectionSupplier( SfxViewShell* pViewShell ) +{ + if ( pViewShell ) + { + SfxViewFrame* pViewFrame = pViewShell->GetViewFrame(); + if (pViewFrame) + { + return uno::Reference<view::XSelectionSupplier>( pViewFrame->GetFrame().GetController(), uno::UNO_QUERY ); + } + } + return uno::Reference<view::XSelectionSupplier>(); +} + +//------------------------------------------------------------------------ + + +ScDispatchProviderInterceptor::ScDispatchProviderInterceptor(ScTabViewShell* pViewSh) : + pViewShell( pViewSh ) +{ + if ( pViewShell ) + { + m_xIntercepted.set(uno::Reference<frame::XDispatchProviderInterception>(pViewShell->GetViewFrame()->GetFrame().GetFrameInterface(), uno::UNO_QUERY)); + if (m_xIntercepted.is()) + { + comphelper::increment( m_refCount ); + + m_xIntercepted->registerDispatchProviderInterceptor( + static_cast<frame::XDispatchProviderInterceptor*>(this)); + // this should make us the top-level dispatch-provider for the component, via a call to our + // setDispatchProvider we should have got an fallback for requests we (i.e. our master) cannot fullfill + uno::Reference<lang::XComponent> xInterceptedComponent(m_xIntercepted, uno::UNO_QUERY); + if (xInterceptedComponent.is()) + xInterceptedComponent->addEventListener(static_cast<lang::XEventListener*>(this)); + + comphelper::decrement( m_refCount ); + } + + StartListening(*pViewShell); + } +} + +ScDispatchProviderInterceptor::~ScDispatchProviderInterceptor() +{ + if (pViewShell) + EndListening(*pViewShell); +} + +void ScDispatchProviderInterceptor::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + pViewShell = NULL; +} + +// XDispatchProvider + +uno::Reference<frame::XDispatch> SAL_CALL ScDispatchProviderInterceptor::queryDispatch( + const util::URL& aURL, const rtl::OUString& aTargetFrameName, + sal_Int32 nSearchFlags ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + uno::Reference<frame::XDispatch> xResult; + // create some dispatch ... + if ( pViewShell && ( + !aURL.Complete.compareToAscii(cURLInsertColumns) || + !aURL.Complete.compareToAscii(cURLDocDataSource) ) ) + { + if (!m_xMyDispatch.is()) + m_xMyDispatch = new ScDispatch( pViewShell ); + xResult = m_xMyDispatch; + } + + // ask our slave provider + if (!xResult.is() && m_xSlaveDispatcher.is()) + xResult = m_xSlaveDispatcher->queryDispatch(aURL, aTargetFrameName, nSearchFlags); + + return xResult; +} + +uno::Sequence< uno::Reference<frame::XDispatch> > SAL_CALL + ScDispatchProviderInterceptor::queryDispatches( + const uno::Sequence<frame::DispatchDescriptor>& aDescripts ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + uno::Sequence< uno::Reference< frame::XDispatch> > aReturn(aDescripts.getLength()); + uno::Reference< frame::XDispatch>* pReturn = aReturn.getArray(); + const frame::DispatchDescriptor* pDescripts = aDescripts.getConstArray(); + for (sal_Int16 i=0; i<aDescripts.getLength(); ++i, ++pReturn, ++pDescripts) + { + *pReturn = queryDispatch(pDescripts->FeatureURL, + pDescripts->FrameName, pDescripts->SearchFlags); + } + return aReturn; +} + +// XDispatchProviderInterceptor + +uno::Reference<frame::XDispatchProvider> SAL_CALL + ScDispatchProviderInterceptor::getSlaveDispatchProvider() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return m_xSlaveDispatcher; +} + +void SAL_CALL ScDispatchProviderInterceptor::setSlaveDispatchProvider( + const uno::Reference<frame::XDispatchProvider>& xNewDispatchProvider ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + m_xSlaveDispatcher.set(xNewDispatchProvider); +} + +uno::Reference<frame::XDispatchProvider> SAL_CALL + ScDispatchProviderInterceptor::getMasterDispatchProvider() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return m_xMasterDispatcher; +} + +void SAL_CALL ScDispatchProviderInterceptor::setMasterDispatchProvider( + const uno::Reference<frame::XDispatchProvider>& xNewSupplier ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + m_xMasterDispatcher.set(xNewSupplier); +} + +// XEventListener + +void SAL_CALL ScDispatchProviderInterceptor::disposing( const lang::EventObject& /* Source */ ) + throw(::com::sun::star::uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if (m_xIntercepted.is()) + { + m_xIntercepted->releaseDispatchProviderInterceptor( + static_cast<frame::XDispatchProviderInterceptor*>(this)); + uno::Reference<lang::XComponent> xInterceptedComponent(m_xIntercepted, uno::UNO_QUERY); + if (xInterceptedComponent.is()) + xInterceptedComponent->removeEventListener(static_cast<lang::XEventListener*>(this)); + + m_xMyDispatch = NULL; + } + m_xIntercepted = NULL; +} + +//------------------------------------------------------------------------ + +ScDispatch::ScDispatch(ScTabViewShell* pViewSh) : + pViewShell( pViewSh ), + bListeningToView( FALSE ) +{ + if (pViewShell) + StartListening(*pViewShell); +} + +ScDispatch::~ScDispatch() +{ + if (pViewShell) + EndListening(*pViewShell); + + if (bListeningToView && pViewShell) + { + uno::Reference<view::XSelectionSupplier> xSupplier(lcl_GetSelectionSupplier( pViewShell )); + if ( xSupplier.is() ) + xSupplier->removeSelectionChangeListener(this); + } +} + +void ScDispatch::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + pViewShell = NULL; +} + +// XDispatch + +void SAL_CALL ScDispatch::dispatch( const util::URL& aURL, + const uno::Sequence<beans::PropertyValue>& aArgs ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + BOOL bDone = FALSE; + if ( pViewShell && !aURL.Complete.compareToAscii(cURLInsertColumns) ) + { + ScViewData* pViewData = pViewShell->GetViewData(); + ScAddress aPos( pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo() ); + + ScDBDocFunc aFunc( *pViewData->GetDocShell() ); + bDone = aFunc.DoImportUno( aPos, aArgs ); + } + // cURLDocDataSource is never dispatched + + if (!bDone) + throw uno::RuntimeException(); +} + +void lcl_FillDataSource( frame::FeatureStateEvent& rEvent, const ScImportParam& rParam ) +{ + rEvent.IsEnabled = rParam.bImport; + + ::svx::ODataAccessDescriptor aDescriptor; + if ( rParam.bImport ) + { + sal_Int32 nType = rParam.bSql ? sdb::CommandType::COMMAND : + ( (rParam.nType == ScDbQuery) ? sdb::CommandType::QUERY : + sdb::CommandType::TABLE ); + + aDescriptor.setDataSource(rtl::OUString( rParam.aDBName )); + aDescriptor[svx::daCommand] <<= rtl::OUString( rParam.aStatement ); + aDescriptor[svx::daCommandType] <<= nType; + } + else + { + // descriptor has to be complete anyway + + rtl::OUString aEmpty; + aDescriptor[svx::daDataSource] <<= aEmpty; + aDescriptor[svx::daCommand] <<= aEmpty; + aDescriptor[svx::daCommandType] <<= (sal_Int32)sdb::CommandType::TABLE; + } + rEvent.State <<= aDescriptor.createPropertyValueSequence(); +} + +void SAL_CALL ScDispatch::addStatusListener( + const uno::Reference<frame::XStatusListener>& xListener, + const util::URL& aURL ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if (!pViewShell) + throw uno::RuntimeException(); + + // initial state + frame::FeatureStateEvent aEvent; + aEvent.IsEnabled = sal_True; + aEvent.Source.set(static_cast<cppu::OWeakObject*>(this)); + aEvent.FeatureURL = aURL; + + if ( !aURL.Complete.compareToAscii(cURLDocDataSource) ) + { + uno::Reference<frame::XStatusListener>* pObj = + new uno::Reference<frame::XStatusListener>( xListener ); + aDataSourceListeners.Insert( pObj, aDataSourceListeners.Count() ); + + if (!bListeningToView) + { + uno::Reference<view::XSelectionSupplier> xSupplier(lcl_GetSelectionSupplier( pViewShell )); + if ( xSupplier.is() ) + xSupplier->addSelectionChangeListener(this); + bListeningToView = sal_True; + } + + ScDBData* pDBData = pViewShell->GetDBData(FALSE,SC_DB_OLD); + if ( pDBData ) + pDBData->GetImportParam( aLastImport ); + lcl_FillDataSource( aEvent, aLastImport ); // modifies State, IsEnabled + } + //! else add to listener for "enabled" changes? + + xListener->statusChanged( aEvent ); +} + +void SAL_CALL ScDispatch::removeStatusListener( + const uno::Reference<frame::XStatusListener>& xListener, + const util::URL& aURL ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if ( !aURL.Complete.compareToAscii(cURLDocDataSource) ) + { + USHORT nCount = aDataSourceListeners.Count(); + for ( USHORT n=nCount; n--; ) + { + uno::Reference<frame::XStatusListener> *pObj = aDataSourceListeners[n]; + if ( *pObj == xListener ) + { + aDataSourceListeners.DeleteAndDestroy( n ); + break; + } + } + + if ( aDataSourceListeners.Count() == 0 && pViewShell ) + { + uno::Reference<view::XSelectionSupplier> xSupplier(lcl_GetSelectionSupplier( pViewShell )); + if ( xSupplier.is() ) + xSupplier->removeSelectionChangeListener(this); + bListeningToView = sal_False; + } + } +} + +// XSelectionChangeListener + +void SAL_CALL ScDispatch::selectionChanged( const ::com::sun::star::lang::EventObject& /* aEvent */ ) + throw (::com::sun::star::uno::RuntimeException) +{ + // currently only called for URL cURLDocDataSource + + if ( pViewShell ) + { + ScImportParam aNewImport; + ScDBData* pDBData = pViewShell->GetDBData(FALSE,SC_DB_OLD); + if ( pDBData ) + pDBData->GetImportParam( aNewImport ); + + // notify listeners only if data source has changed + if ( aNewImport.bImport != aLastImport.bImport || + aNewImport.aDBName != aLastImport.aDBName || + aNewImport.aStatement != aLastImport.aStatement || + aNewImport.bSql != aLastImport.bSql || + aNewImport.nType != aLastImport.nType ) + { + frame::FeatureStateEvent aEvent; + aEvent.Source.set(static_cast<cppu::OWeakObject*>(this)); + aEvent.FeatureURL.Complete = rtl::OUString::createFromAscii( cURLDocDataSource ); + + lcl_FillDataSource( aEvent, aNewImport ); // modifies State, IsEnabled + + for ( USHORT n=0; n<aDataSourceListeners.Count(); n++ ) + (*aDataSourceListeners[n])->statusChanged( aEvent ); + + aLastImport = aNewImport; + } + } +} + +// XEventListener + +void SAL_CALL ScDispatch::disposing( const ::com::sun::star::lang::EventObject& rSource ) + throw (::com::sun::star::uno::RuntimeException) +{ + uno::Reference<view::XSelectionSupplier> xSupplier(rSource.Source, uno::UNO_QUERY); + xSupplier->removeSelectionChangeListener(this); + bListeningToView = sal_False; + + lang::EventObject aEvent; + aEvent.Source.set(static_cast<cppu::OWeakObject*>(this)); + for ( USHORT n=0; n<aDataSourceListeners.Count(); n++ ) + (*aDataSourceListeners[n])->disposing( aEvent ); + + pViewShell = NULL; +} + diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx new file mode 100644 index 000000000000..3d3f0f479601 --- /dev/null +++ b/sc/source/ui/unoobj/docuno.cxx @@ -0,0 +1,3776 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +#include "scitems.hxx" +#include <svx/fmdpage.hxx> +#include <svx/fmview.hxx> +#include <svx/svditer.hxx> +#include <svx/svdpage.hxx> +#include <svx/svxids.hrc> +#include <svx/unoshape.hxx> + +#include <svl/numuno.hxx> +#include <svl/smplhint.hxx> +#include <unotools/undoopt.hxx> +#include <unotools/moduleoptions.hxx> +#include <sfx2/printer.hxx> +#include <sfx2/bindings.hxx> +#include <vcl/pdfextoutdevdata.hxx> +#include <vcl/waitobj.hxx> +#include <unotools/charclass.hxx> +#include <tools/multisel.hxx> +#include <tools/resary.hxx> +#include <toolkit/awt/vclxdevice.hxx> + +#include <ctype.h> +#include <float.h> // DBL_MAX + +#include <com/sun/star/util/Date.hpp> +#include <com/sun/star/sheet/XNamedRanges.hpp> +#include <com/sun/star/sheet/XLabelRanges.hpp> +#include <com/sun/star/i18n/XForbiddenCharacters.hpp> +#include <com/sun/star/script/XLibraryContainer.hpp> +#include <com/sun/star/lang/XInitialization.hpp> +#include <com/sun/star/lang/ServiceNotRegisteredException.hpp> +#include <com/sun/star/document/XDocumentEventBroadcaster.hpp> +#include <com/sun/star/script/XInvocation.hpp> +#include <com/sun/star/script/vba/XVBAEventProcessor.hpp> +#include <com/sun/star/reflection/XIdlClassProvider.hpp> +#include <comphelper/processfactory.hxx> + +#include "docuno.hxx" +#include "cellsuno.hxx" +#include "nameuno.hxx" +#include "datauno.hxx" +#include "miscuno.hxx" +#include "notesuno.hxx" +#include "styleuno.hxx" +#include "linkuno.hxx" +#include "servuno.hxx" +#include "targuno.hxx" +#include "convuno.hxx" +#include "optuno.hxx" +#include "forbiuno.hxx" +#include "docsh.hxx" +#include "hints.hxx" +#include "docfunc.hxx" +#include "dociter.hxx" +#include "cell.hxx" +#include "drwlayer.hxx" +#include "rangeutl.hxx" +#include "markdata.hxx" +#include "docoptio.hxx" +#include "unoguard.hxx" +#include "unonames.hxx" +#include "shapeuno.hxx" +#include "viewuno.hxx" +#include "tabvwsh.hxx" +#include "printfun.hxx" +#include "pfuncache.hxx" +#include "scmod.hxx" +#include "rangeutl.hxx" +#include "ViewSettingsSequenceDefines.hxx" +#include "sheetevents.hxx" +#include "sc.hrc" +#include "scresid.hxx" + +using namespace com::sun::star; + +//------------------------------------------------------------------------ + +// alles ohne Which-ID, Map nur fuer PropertySetInfo + +//! umbenennen, sind nicht mehr nur Options +const SfxItemPropertyMapEntry* lcl_GetDocOptPropertyMap() +{ + static SfxItemPropertyMapEntry aDocOptPropertyMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNO_APPLYFMDES), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_AREALINKS), 0, &getCppuType((uno::Reference<sheet::XAreaLinks>*)0), 0, 0}, + {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_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}, + {MAP_CHAR_LEN(SC_UNO_CTL_CLOCAL), 0, &getCppuType((lang::Locale*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_COLLABELRNG), 0, &getCppuType((uno::Reference<sheet::XLabelRanges>*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_DDELINKS), 0, &getCppuType((uno::Reference<container::XNameAccess>*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_DEFTABSTOP), PROP_UNO_DEFTABSTOP, &getCppuType((sal_Int16*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_EXTERNALDOCLINKS), 0, &getCppuType((uno::Reference<sheet::XExternalDocLinks>*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_FORBIDDEN), 0, &getCppuType((uno::Reference<i18n::XForbiddenCharacters>*)0), beans::PropertyAttribute::READONLY, 0}, + {MAP_CHAR_LEN(SC_UNO_HASDRAWPAGES), 0, &getBooleanCppuType(), beans::PropertyAttribute::READONLY, 0}, + {MAP_CHAR_LEN(SC_UNO_IGNORECASE), PROP_UNO_IGNORECASE, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_ITERENABLED), PROP_UNO_ITERENABLED, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_ITERCOUNT), PROP_UNO_ITERCOUNT, &getCppuType((sal_Int32*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_ITEREPSILON), PROP_UNO_ITEREPSILON, &getCppuType((double*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_LOOKUPLABELS), PROP_UNO_LOOKUPLABELS, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_MATCHWHOLE), PROP_UNO_MATCHWHOLE, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_NAMEDRANGES), 0, &getCppuType((uno::Reference<sheet::XNamedRanges>*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_DATABASERNG), 0, &getCppuType((uno::Reference<sheet::XDatabaseRanges>*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_NULLDATE), PROP_UNO_NULLDATE, &getCppuType((util::Date*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_ROWLABELRNG), 0, &getCppuType((uno::Reference<sheet::XLabelRanges>*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SHEETLINKS), 0, &getCppuType((uno::Reference<container::XNameAccess>*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SPELLONLINE), PROP_UNO_SPELLONLINE, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_STANDARDDEC), PROP_UNO_STANDARDDEC, &getCppuType((sal_Int16*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_REGEXENABLED), PROP_UNO_REGEXENABLED, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_RUNTIMEUID), 0, &getCppuType(static_cast< const rtl::OUString * >(0)), beans::PropertyAttribute::READONLY, 0}, + {MAP_CHAR_LEN(SC_UNO_HASVALIDSIGNATURES),0, &getBooleanCppuType(), beans::PropertyAttribute::READONLY, 0}, + {MAP_CHAR_LEN(SC_UNO_ISLOADED), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_ISUNDOENABLED), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_ISADJUSTHEIGHTENABLED), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_ISEXECUTELINKENABLED), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_ISCHANGEREADONLYENABLED), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_REFERENCEDEVICE), 0, &getCppuType((uno::Reference<awt::XDevice>*)0), beans::PropertyAttribute::READONLY, 0}, + {MAP_CHAR_LEN("BuildId"), 0, &::getCppuType(static_cast< const rtl::OUString * >(0)), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_CODENAME), 0, &getCppuType(static_cast< const rtl::OUString * >(0)), 0, 0}, + + {0,0,0,0,0,0} + }; + return aDocOptPropertyMap_Impl; +} + +//! StandardDecimals als Property und vom NumberFormatter ???????? + +const SfxItemPropertyMapEntry* lcl_GetColumnsPropertyMap() +{ + static SfxItemPropertyMapEntry aColumnsPropertyMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_MANPAGE), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_NEWPAGE), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLVIS), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_OWIDTH), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLWID), 0, &getCppuType((sal_Int32*)0), 0, 0 }, + {0,0,0,0,0,0} + }; + return aColumnsPropertyMap_Impl; +} + +const SfxItemPropertyMapEntry* lcl_GetRowsPropertyMap() +{ + static SfxItemPropertyMapEntry aRowsPropertyMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_CELLHGT), 0, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLFILT), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_OHEIGHT), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_MANPAGE), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_NEWPAGE), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLVIS), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLBACK), ATTR_BACKGROUND, &::getCppuType((const sal_Int32*)0), 0, MID_BACK_COLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CELLTRAN), ATTR_BACKGROUND, &::getBooleanCppuType(), 0, MID_GRAPHIC_TRANSPARENT }, + // not sorted, not used with SfxItemPropertyMapEntry::GetByName + {0,0,0,0,0,0} + }; + return aRowsPropertyMap_Impl; +} + +//! move these functions to a header file +inline long TwipsToHMM(long nTwips) { return (nTwips * 127 + 36) / 72; } +inline long HMMToTwips(long nHMM) { return (nHMM * 72 + 63) / 127; } + +//------------------------------------------------------------------------ + +#define SCMODELOBJ_SERVICE "com.sun.star.sheet.SpreadsheetDocument" +#define SCDOCSETTINGS_SERVICE "com.sun.star.sheet.SpreadsheetDocumentSettings" +#define SCDOC_SERVICE "com.sun.star.document.OfficeDocument" + +SC_SIMPLE_SERVICE_INFO( ScAnnotationsObj, "ScAnnotationsObj", "com.sun.star.sheet.CellAnnotations" ) +SC_SIMPLE_SERVICE_INFO( ScDrawPagesObj, "ScDrawPagesObj", "com.sun.star.drawing.DrawPages" ) +SC_SIMPLE_SERVICE_INFO( ScScenariosObj, "ScScenariosObj", "com.sun.star.sheet.Scenarios" ) +SC_SIMPLE_SERVICE_INFO( ScSpreadsheetSettingsObj, "ScSpreadsheetSettingsObj", "com.sun.star.sheet.SpreadsheetDocumentSettings" ) +SC_SIMPLE_SERVICE_INFO( ScTableColumnsObj, "ScTableColumnsObj", "com.sun.star.table.TableColumns" ) +SC_SIMPLE_SERVICE_INFO( ScTableRowsObj, "ScTableRowsObj", "com.sun.star.table.TableRows" ) +SC_SIMPLE_SERVICE_INFO( ScTableSheetsObj, "ScTableSheetsObj", "com.sun.star.sheet.Spreadsheets" ) + +//------------------------------------------------------------------------ + +class ScPrintUIOptions : public vcl::PrinterOptionsHelper +{ +public: + ScPrintUIOptions(); + void SetDefaults(); +}; + +ScPrintUIOptions::ScPrintUIOptions() +{ + const ScPrintOptions& rPrintOpt = SC_MOD()->GetPrintOptions(); + sal_Int32 nContent = rPrintOpt.GetAllSheets() ? 0 : 1; + sal_Bool bSuppress = rPrintOpt.GetSkipEmpty(); + + ResStringArray aStrings( ScResId( SCSTR_PRINT_OPTIONS ) ); + DBG_ASSERT( aStrings.Count() >= 19, "resource incomplete" ); + if( aStrings.Count() < 19 ) // bad resource ? + return; + + m_aUIProperties.realloc( 8 ); + + // create Section for spreadsheet (results in an extra tab page in dialog) + SvtModuleOptions aOpt; + String aAppGroupname( aStrings.GetString( 18 ) ); + aAppGroupname.SearchAndReplace( String( RTL_CONSTASCII_USTRINGPARAM( "%s" ) ), + aOpt.GetModuleName( SvtModuleOptions::E_SCALC ) ); + m_aUIProperties[0].Value = getGroupControlOpt( aAppGroupname, rtl::OUString() ); + + // create subgroup for pages + m_aUIProperties[1].Value = getSubgroupControlOpt( rtl::OUString( aStrings.GetString( 0 ) ), rtl::OUString() ); + + // create a bool option for empty pages + m_aUIProperties[2].Value = getBoolControlOpt( rtl::OUString( aStrings.GetString( 1 ) ), + rtl::OUString( aStrings.GetString( 2 ) ), + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsIncludeEmptyPages" ) ), + ! bSuppress + ); + // create Subgroup for print content + vcl::PrinterOptionsHelper::UIControlOptions aPrintRangeOpt; + aPrintRangeOpt.maGroupHint = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintRange" ) ); + m_aUIProperties[3].Value = getSubgroupControlOpt( rtl::OUString( aStrings.GetString( 6 ) ), + rtl::OUString(), + aPrintRangeOpt + ); + + // create a choice for the content to create + uno::Sequence< rtl::OUString > aChoices( 3 ), aHelpTexts( 3 ); + aChoices[0] = aStrings.GetString( 7 ); + aHelpTexts[0] = aStrings.GetString( 8 ); + aChoices[1] = aStrings.GetString( 9 ); + aHelpTexts[1] = aStrings.GetString( 10 ); + aChoices[2] = aStrings.GetString( 11 ); + aHelpTexts[2] = aStrings.GetString( 12 ); + m_aUIProperties[4].Value = getChoiceControlOpt( rtl::OUString(), + aHelpTexts, + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PrintContent" ) ), + aChoices, + nContent ); + + // create Subgroup for print range + aPrintRangeOpt.mbInternalOnly = sal_True; + m_aUIProperties[5].Value = getSubgroupControlOpt( rtl::OUString( aStrings.GetString( 13 ) ), + rtl::OUString(), + aPrintRangeOpt + ); + + // create a choice for the range to print + rtl::OUString aPrintRangeName( RTL_CONSTASCII_USTRINGPARAM( "PrintRange" ) ); + aChoices.realloc( 2 ); + aHelpTexts.realloc( 2 ); + aChoices[0] = aStrings.GetString( 14 ); + aHelpTexts[0] = aStrings.GetString( 15 ); + aChoices[1] = aStrings.GetString( 16 ); + aHelpTexts[1] = aStrings.GetString( 17 ); + m_aUIProperties[6].Value = getChoiceControlOpt( rtl::OUString(), + aHelpTexts, + aPrintRangeName, + aChoices, + 0 ); + + // create a an Edit dependent on "Pages" selected + vcl::PrinterOptionsHelper::UIControlOptions aPageRangeOpt( aPrintRangeName, 1, sal_True ); + m_aUIProperties[7].Value = getEditControlOpt( rtl::OUString(), + rtl::OUString(), + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "PageRange" ) ), + rtl::OUString(), + aPageRangeOpt + ); + + // "Print only selected sheets" isn't needed because of the "Selected Sheets" choice in "Print content" +#if 0 + // create subgroup for sheets + m_aUIProperties[8].Value = getSubgroupControlOpt( rtl::OUString( aStrings.GetString( 3 ) ), rtl::OUString() ); + + // create a bool option for selected pages only + m_aUIProperties[9].Value = getBoolControlOpt( rtl::OUString( aStrings.GetString( 4 ) ), + rtl::OUString( aStrings.GetString( 5 ) ), + rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "IsOnlySelectedSheets" ) ), + i_bSelectedOnly + ); +#endif +} + +void ScPrintUIOptions::SetDefaults() +{ + // re-initialize the default values from print options + + const ScPrintOptions& rPrintOpt = SC_MOD()->GetPrintOptions(); + sal_Int32 nContent = rPrintOpt.GetAllSheets() ? 0 : 1; + sal_Bool bSuppress = rPrintOpt.GetSkipEmpty(); + + for (sal_Int32 nUIPos=0; nUIPos<m_aUIProperties.getLength(); ++nUIPos) + { + uno::Sequence<beans::PropertyValue> aUIProp; + if ( m_aUIProperties[nUIPos].Value >>= aUIProp ) + { + for (sal_Int32 nPropPos=0; nPropPos<aUIProp.getLength(); ++nPropPos) + { + rtl::OUString aName = aUIProp[nPropPos].Name; + if ( aName.equalsAscii("Property") ) + { + beans::PropertyValue aPropertyValue; + if ( aUIProp[nPropPos].Value >>= aPropertyValue ) + { + if ( aPropertyValue.Name.equalsAscii( "PrintContent" ) ) + { + aPropertyValue.Value <<= nContent; + aUIProp[nPropPos].Value <<= aPropertyValue; + } + else if ( aPropertyValue.Name.equalsAscii( "IsIncludeEmptyPages" ) ) + { + ScUnoHelpFunctions::SetBoolInAny( aPropertyValue.Value, ! bSuppress ); + aUIProp[nPropPos].Value <<= aPropertyValue; + } + } + } + } + m_aUIProperties[nUIPos].Value <<= aUIProp; + } + } +} + +// static +void ScModelObj::CreateAndSet(ScDocShell* pDocSh) +{ + if (pDocSh) + pDocSh->SetBaseModel( new ScModelObj(pDocSh) ); +} + +ScModelObj::ScModelObj( ScDocShell* pDocSh ) : + SfxBaseModel( pDocSh ), + aPropSet( lcl_GetDocOptPropertyMap() ), + pDocShell( pDocSh ), + pPrintFuncCache( NULL ), + pPrinterOptions( NULL ), + maChangesListeners( m_aMutex ) +{ + // pDocShell may be NULL if this is the base of a ScDocOptionsObj + if ( pDocShell ) + { + pDocShell->GetDocument()->AddUnoObject(*this); // SfxModel is derived from SfxListener + } +} + +ScModelObj::~ScModelObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); + + if (xNumberAgg.is()) + xNumberAgg->setDelegator(uno::Reference<uno::XInterface>()); + + delete pPrintFuncCache; + delete pPrinterOptions; +} + +uno::Reference< uno::XAggregation> ScModelObj::GetFormatter() +{ + // pDocShell may be NULL if this is the base of a ScDocOptionsObj + if ( !xNumberAgg.is() && pDocShell ) + { + // setDelegator veraendert den RefCount, darum eine Referenz selber halten + // (direkt am m_refCount, um sich beim release nicht selbst zu loeschen) + comphelper::increment( m_refCount ); + // waehrend des queryInterface braucht man ein Ref auf das + // SvNumberFormatsSupplierObj, sonst wird es geloescht. + uno::Reference<util::XNumberFormatsSupplier> xFormatter(new SvNumberFormatsSupplierObj(pDocShell->GetDocument()->GetFormatTable() )); + { + xNumberAgg.set(uno::Reference<uno::XAggregation>( xFormatter, uno::UNO_QUERY )); + // extra block to force deletion of the temporary before setDelegator + } + + // beim setDelegator darf die zusaetzliche Ref nicht mehr existieren + xFormatter = NULL; + + if (xNumberAgg.is()) + xNumberAgg->setDelegator( (cppu::OWeakObject*)this ); + comphelper::decrement( m_refCount ); + } // if ( !xNumberAgg.is() ) + return xNumberAgg; +} + +ScDocument* ScModelObj::GetDocument() const +{ + if (pDocShell) + return pDocShell->GetDocument(); + return NULL; +} + +SfxObjectShell* ScModelObj::GetEmbeddedObject() const +{ + return pDocShell; +} + +void ScModelObj::UpdateAllRowHeights(const ScMarkData* pTabMark) +{ + if (pDocShell) + pDocShell->UpdateAllRowHeights(pTabMark); +} + +void ScModelObj::BeforeXMLLoading() +{ + if (pDocShell) + pDocShell->BeforeXMLLoading(); +} + +void ScModelObj::AfterXMLLoading(sal_Bool bRet) +{ + if (pDocShell) + pDocShell->AfterXMLLoading(bRet); +} + +ScSheetSaveData* ScModelObj::GetSheetSaveData() +{ + if (pDocShell) + return pDocShell->GetSheetSaveData(); + return NULL; +} + +uno::Any SAL_CALL ScModelObj::queryInterface( const uno::Type& rType ) + throw(uno::RuntimeException) +{ + SC_QUERYINTERFACE( sheet::XSpreadsheetDocument ) + SC_QUERYINTERFACE( document::XActionLockable ) + SC_QUERYINTERFACE( sheet::XCalculatable ) + SC_QUERYINTERFACE( util::XProtectable ) + SC_QUERYINTERFACE( drawing::XDrawPagesSupplier ) + SC_QUERYINTERFACE( sheet::XGoalSeek ) + SC_QUERYINTERFACE( sheet::XConsolidatable ) + SC_QUERYINTERFACE( sheet::XDocumentAuditing ) + SC_QUERYINTERFACE( style::XStyleFamiliesSupplier ) + SC_QUERYINTERFACE( view::XRenderable ) + SC_QUERYINTERFACE( document::XLinkTargetSupplier ) + SC_QUERYINTERFACE( beans::XPropertySet ) + SC_QUERYINTERFACE( lang::XMultiServiceFactory ) + SC_QUERYINTERFACE( lang::XServiceInfo ) + SC_QUERYINTERFACE( util::XChangesNotifier ) + + uno::Any aRet(SfxBaseModel::queryInterface( rType )); + if ( !aRet.hasValue() + && rType != ::getCppuType((uno::Reference< com::sun::star::document::XDocumentEventBroadcaster>*)0) + && rType != ::getCppuType((uno::Reference< com::sun::star::frame::XController>*)0) + && rType != ::getCppuType((uno::Reference< com::sun::star::frame::XFrame>*)0) + && rType != ::getCppuType((uno::Reference< com::sun::star::script::XInvocation>*)0) + && rType != ::getCppuType((uno::Reference< com::sun::star::reflection::XIdlClassProvider>*)0) + && rType != ::getCppuType((uno::Reference< com::sun::star::beans::XFastPropertySet>*)0) + && rType != ::getCppuType((uno::Reference< com::sun::star::awt::XWindow>*)0)) + { + GetFormatter(); + if ( xNumberAgg.is() ) + aRet = xNumberAgg->queryAggregation( rType ); + } + + return aRet; +} + +void SAL_CALL ScModelObj::acquire() throw() +{ + SfxBaseModel::acquire(); +} + +void SAL_CALL ScModelObj::release() throw() +{ + SfxBaseModel::release(); +} + +uno::Sequence<uno::Type> SAL_CALL ScModelObj::getTypes() throw(uno::RuntimeException) +{ + static uno::Sequence<uno::Type> aTypes; + if ( aTypes.getLength() == 0 ) + { + uno::Sequence<uno::Type> aParentTypes(SfxBaseModel::getTypes()); + long nParentLen = aParentTypes.getLength(); + const uno::Type* pParentPtr = aParentTypes.getConstArray(); + + uno::Sequence<uno::Type> aAggTypes; + if ( GetFormatter().is() ) + { + const uno::Type& rProvType = ::getCppuType((uno::Reference<lang::XTypeProvider>*) 0); + uno::Any aNumProv(xNumberAgg->queryAggregation(rProvType)); + if(aNumProv.getValueType() == rProvType) + { + uno::Reference<lang::XTypeProvider> xNumProv( + *(uno::Reference<lang::XTypeProvider>*)aNumProv.getValue()); + aAggTypes = xNumProv->getTypes(); + } + } + long nAggLen = aAggTypes.getLength(); + const uno::Type* pAggPtr = aAggTypes.getConstArray(); + + const long nThisLen = 15; + aTypes.realloc( nParentLen + nAggLen + nThisLen ); + uno::Type* pPtr = aTypes.getArray(); + pPtr[nParentLen + 0] = getCppuType((const uno::Reference<sheet::XSpreadsheetDocument>*)0); + pPtr[nParentLen + 1] = getCppuType((const uno::Reference<document::XActionLockable>*)0); + pPtr[nParentLen + 2] = getCppuType((const uno::Reference<sheet::XCalculatable>*)0); + pPtr[nParentLen + 3] = getCppuType((const uno::Reference<util::XProtectable>*)0); + pPtr[nParentLen + 4] = getCppuType((const uno::Reference<drawing::XDrawPagesSupplier>*)0); + pPtr[nParentLen + 5] = getCppuType((const uno::Reference<sheet::XGoalSeek>*)0); + pPtr[nParentLen + 6] = getCppuType((const uno::Reference<sheet::XConsolidatable>*)0); + pPtr[nParentLen + 7] = getCppuType((const uno::Reference<sheet::XDocumentAuditing>*)0); + pPtr[nParentLen + 8] = getCppuType((const uno::Reference<style::XStyleFamiliesSupplier>*)0); + pPtr[nParentLen + 9] = getCppuType((const uno::Reference<view::XRenderable>*)0); + pPtr[nParentLen +10] = getCppuType((const uno::Reference<document::XLinkTargetSupplier>*)0); + pPtr[nParentLen +11] = getCppuType((const uno::Reference<beans::XPropertySet>*)0); + pPtr[nParentLen +12] = getCppuType((const uno::Reference<lang::XMultiServiceFactory>*)0); + pPtr[nParentLen +13] = getCppuType((const uno::Reference<lang::XServiceInfo>*)0); + pPtr[nParentLen +14] = getCppuType((const uno::Reference<util::XChangesNotifier>*)0); + + long i; + for (i=0; i<nParentLen; i++) + pPtr[i] = pParentPtr[i]; // parent types first + + for (i=0; i<nAggLen; i++) + pPtr[nParentLen+nThisLen+i] = pAggPtr[i]; // aggregated types last + } + return aTypes; +} + +uno::Sequence<sal_Int8> SAL_CALL ScModelObj::getImplementationId() + throw(uno::RuntimeException) +{ + static uno::Sequence< sal_Int8 > aId; + if( aId.getLength() == 0 ) + { + aId.realloc( 16 ); + rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True ); + } + return aId; +} + +void ScModelObj::Notify( SfxBroadcaster& rBC, const SfxHint& rHint ) +{ + // Not interested in reference update hints here + + if ( rHint.ISA( SfxSimpleHint ) ) + { + ULONG nId = ((const SfxSimpleHint&)rHint).GetId(); + if ( nId == SFX_HINT_DYING ) + { + pDocShell = NULL; // has become invalid + if (xNumberAgg.is()) + { + SvNumberFormatsSupplierObj* pNumFmt = + SvNumberFormatsSupplierObj::getImplementation( + uno::Reference<util::XNumberFormatsSupplier>(xNumberAgg, uno::UNO_QUERY) ); + if ( pNumFmt ) + pNumFmt->SetNumberFormatter( NULL ); + } + + DELETEZ( pPrintFuncCache ); // must be deleted because it has a pointer to the DocShell + } + else if ( nId == SFX_HINT_DATACHANGED ) + { + // cached data for rendering become invalid when contents change + // (if a broadcast is added to SetDrawModified, is has to be tested here, too) + + DELETEZ( pPrintFuncCache ); + + // handle "OnCalculate" sheet events (search also for VBA event handlers) + if ( pDocShell && pDocShell->GetDocument()->HasAnySheetEventScript( SC_SHEETEVENT_CALCULATE, true ) ) + HandleCalculateEvents(); + } + } + else if ( rHint.ISA( ScPointerChangedHint ) ) + { + USHORT nFlags = ((const ScPointerChangedHint&)rHint).GetFlags(); + if (nFlags & SC_POINTERCHANGED_NUMFMT) + { + // NumberFormatter-Pointer am Uno-Objekt neu setzen + + if (GetFormatter().is()) + { + SvNumberFormatsSupplierObj* pNumFmt = + SvNumberFormatsSupplierObj::getImplementation( + uno::Reference<util::XNumberFormatsSupplier>(xNumberAgg, uno::UNO_QUERY) ); + if ( pNumFmt && pDocShell ) + pNumFmt->SetNumberFormatter( pDocShell->GetDocument()->GetFormatTable() ); + } + } + } + + // always call parent - SfxBaseModel might need to handle the same hints again + SfxBaseModel::Notify( rBC, rHint ); // SfxBaseModel is derived from SfxListener +} + +// XSpreadsheetDocument + +uno::Reference<sheet::XSpreadsheets> SAL_CALL ScModelObj::getSheets() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + return new ScTableSheetsObj(pDocShell); + return NULL; +} + +// XStyleFamiliesSupplier + +uno::Reference<container::XNameAccess> SAL_CALL ScModelObj::getStyleFamilies() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + return new ScStyleFamiliesObj(pDocShell); + return NULL; +} + +// XRenderable + +OutputDevice* lcl_GetRenderDevice( const uno::Sequence<beans::PropertyValue>& rOptions ) +{ + OutputDevice* pRet = NULL; + const beans::PropertyValue* pPropArray = rOptions.getConstArray(); + long nPropCount = rOptions.getLength(); + for (long i = 0; i < nPropCount; i++) + { + const beans::PropertyValue& rProp = pPropArray[i]; + String aPropName(rProp.Name); + + if (aPropName.EqualsAscii( SC_UNONAME_RENDERDEV )) + { + uno::Reference<awt::XDevice> xRenderDevice(rProp.Value, uno::UNO_QUERY); + if ( xRenderDevice.is() ) + { + VCLXDevice* pDevice = VCLXDevice::GetImplementation( xRenderDevice ); + if ( pDevice ) + { + pRet = pDevice->GetOutputDevice(); + pRet->SetDigitLanguage( SC_MOD()->GetOptDigitLanguage() ); + } + } + } + } + return pRet; +} + +bool lcl_ParseTarget( const String& rTarget, ScRange& rTargetRange, Rectangle& rTargetRect, + bool& rIsSheet, ScDocument* pDoc, SCTAB nSourceTab ) +{ + // test in same order as in SID_CURRENTCELL execute + + ScAddress aAddress; + ScRangeUtil aRangeUtil; + SCTAB nNameTab; + sal_Int32 nNumeric = 0; + + bool bRangeValid = false; + bool bRectValid = false; + + if ( rTargetRange.Parse( rTarget, pDoc ) & SCA_VALID ) + { + bRangeValid = true; // range reference + } + else if ( aAddress.Parse( rTarget, pDoc ) & SCA_VALID ) + { + rTargetRange = aAddress; + bRangeValid = true; // cell reference + } + else if ( aRangeUtil.MakeRangeFromName( rTarget, pDoc, nSourceTab, rTargetRange, RUTL_NAMES ) || + aRangeUtil.MakeRangeFromName( rTarget, pDoc, nSourceTab, rTargetRange, RUTL_DBASE ) ) + { + bRangeValid = true; // named range or database range + } + else if ( ByteString( rTarget, RTL_TEXTENCODING_ASCII_US ).IsNumericAscii() && + ( nNumeric = rTarget.ToInt32() ) > 0 && nNumeric <= MAXROW+1 ) + { + // row number is always mapped to cell A(row) on the same sheet + rTargetRange = ScAddress( 0, (SCROW)(nNumeric-1), nSourceTab ); // target row number is 1-based + bRangeValid = true; // row number + } + else if ( pDoc->GetTable( rTarget, nNameTab ) ) + { + rTargetRange = ScAddress(0,0,nNameTab); + bRangeValid = true; // sheet name + rIsSheet = true; // needs special handling (first page of the sheet) + } + else + { + // look for named drawing object + + ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); + if ( pDrawLayer ) + { + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB i=0; i<nTabCount && !bRangeValid; i++) + { + SdrPage* pPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(i)); + DBG_ASSERT(pPage,"Page ?"); + if (pPage) + { + SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS ); + SdrObject* pObject = aIter.Next(); + while (pObject && !bRangeValid) + { + if ( ScDrawLayer::GetVisibleName( pObject ) == rTarget ) + { + rTargetRect = pObject->GetLogicRect(); // 1/100th mm + rTargetRange = pDoc->GetRange( i, rTargetRect ); // underlying cells + bRangeValid = bRectValid = true; // rectangle is valid + } + pObject = aIter.Next(); + } + } + } + } + } + if ( bRangeValid && !bRectValid ) + { + // get rectangle for cell range + rTargetRect = pDoc->GetMMRect( rTargetRange.aStart.Col(), rTargetRange.aStart.Row(), + rTargetRange.aEnd.Col(), rTargetRange.aEnd.Row(), + rTargetRange.aStart.Tab() ); + } + + return bRangeValid; +} + +BOOL ScModelObj::FillRenderMarkData( const uno::Any& aSelection, + const uno::Sequence< beans::PropertyValue >& rOptions, + ScMarkData& rMark, + ScPrintSelectionStatus& rStatus, String& rPagesStr ) const +{ + DBG_ASSERT( !rMark.IsMarked() && !rMark.IsMultiMarked(), "FillRenderMarkData: MarkData must be empty" ); + DBG_ASSERT( pDocShell, "FillRenderMarkData: DocShell must be set" ); + + BOOL bDone = FALSE; + + uno::Reference<frame::XController> xView; + + // defaults when no options are passed: all sheets, include empty pages + sal_Bool bSelectedSheetsOnly = sal_False; + sal_Bool bIncludeEmptyPages = sal_True; + + bool bHasPrintContent = false; + sal_Int32 nPrintContent = 0; // all sheets / selected sheets / selected cells + sal_Int32 nPrintRange = 0; // all pages / pages + rtl::OUString aPageRange; // "pages" edit value + + for( sal_Int32 i = 0, nLen = rOptions.getLength(); i < nLen; i++ ) + { + if( rOptions[i].Name.equalsAscii( "IsOnlySelectedSheets" ) ) + { + rOptions[i].Value >>= bSelectedSheetsOnly; + } + else if( rOptions[i].Name.equalsAscii( "IsIncludeEmptyPages" ) ) + { + rOptions[i].Value >>= bIncludeEmptyPages; + } + else if( rOptions[i].Name.equalsAscii( "PageRange" ) ) + { + rOptions[i].Value >>= aPageRange; + } + else if( rOptions[i].Name.equalsAscii( "PrintRange" ) ) + { + rOptions[i].Value >>= nPrintRange; + } + else if( rOptions[i].Name.equalsAscii( "PrintContent" ) ) + { + bHasPrintContent = true; + rOptions[i].Value >>= nPrintContent; + } + else if( rOptions[i].Name.equalsAscii( "View" ) ) + { + rOptions[i].Value >>= xView; + } + } + + // "Print Content" selection wins over "Selected Sheets" option + if ( bHasPrintContent ) + bSelectedSheetsOnly = ( nPrintContent != 0 ); + + uno::Reference<uno::XInterface> xInterface(aSelection, uno::UNO_QUERY); + if ( xInterface.is() ) + { + ScCellRangesBase* pSelObj = ScCellRangesBase::getImplementation( xInterface ); + uno::Reference< drawing::XShapes > xShapes( xInterface, uno::UNO_QUERY ); + if ( pSelObj && pSelObj->GetDocShell() == pDocShell ) + { + BOOL bSheet = ( ScTableSheetObj::getImplementation( xInterface ) != NULL ); + BOOL bCursor = pSelObj->IsCursorOnly(); + const ScRangeList& rRanges = pSelObj->GetRangeList(); + + rMark.MarkFromRangeList( rRanges, FALSE ); + rMark.MarkToSimple(); + + if ( rMark.IsMarked() && !rMark.IsMultiMarked() ) + { + // a sheet object is treated like an empty selection: print the used area of the sheet + + if ( bCursor || bSheet ) // nothing selected -> use whole tables + { + rMark.ResetMark(); // doesn't change table selection + rStatus.SetMode( SC_PRINTSEL_CURSOR ); + } + else + rStatus.SetMode( SC_PRINTSEL_RANGE ); + + rStatus.SetRanges( rRanges ); + bDone = TRUE; + } + // multi selection isn't supported + } + else if( xShapes.is() ) + { + //print a selected ole object + uno::Reference< container::XIndexAccess > xIndexAccess( xShapes, uno::UNO_QUERY ); + if( xIndexAccess.is() ) + { + // multi selection isn't supported yet + uno::Reference< drawing::XShape > xShape( xIndexAccess->getByIndex(0), uno::UNO_QUERY ); + SvxShape* pShape = SvxShape::getImplementation( xShape ); + if( pShape ) + { + SdrObject *pSdrObj = pShape->GetSdrObject(); + if( pDocShell ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + if( pDoc && pSdrObj ) + { + Rectangle aObjRect = pSdrObj->GetCurrentBoundRect(); + SCTAB nCurrentTab = ScDocShell::GetCurTab(); + ScRange aRange = pDoc->GetRange( nCurrentTab, aObjRect ); + rMark.SetMarkArea( aRange ); + + if( rMark.IsMarked() && !rMark.IsMultiMarked() ) + { + rStatus.SetMode( SC_PRINTSEL_RANGE_EXCLUSIVELY_OLE_AND_DRAW_OBJECTS ); + bDone = TRUE; + } + } + } + } + } + } + else if ( ScModelObj::getImplementation( xInterface ) == this ) + { + // render the whole document + // -> no selection, all sheets + + SCTAB nTabCount = pDocShell->GetDocument()->GetTableCount(); + for (SCTAB nTab = 0; nTab < nTabCount; nTab++) + rMark.SelectTable( nTab, TRUE ); + rStatus.SetMode( SC_PRINTSEL_DOCUMENT ); + bDone = TRUE; + } + // other selection types aren't supported + } + + // restrict to selected sheets if a view is available + if ( bSelectedSheetsOnly && xView.is() ) + { + ScTabViewObj* pViewObj = ScTabViewObj::getImplementation( xView ); + if (pViewObj) + { + ScTabViewShell* pViewSh = pViewObj->GetViewShell(); + if (pViewSh) + { + const ScMarkData& rViewMark = pViewSh->GetViewData()->GetMarkData(); + SCTAB nTabCount = pDocShell->GetDocument()->GetTableCount(); + for (SCTAB nTab = 0; nTab < nTabCount; nTab++) + if (!rViewMark.GetTableSelect(nTab)) + rMark.SelectTable( nTab, FALSE ); + } + } + } + + ScPrintOptions aNewOptions; + aNewOptions.SetSkipEmpty( !bIncludeEmptyPages ); + aNewOptions.SetAllSheets( !bSelectedSheetsOnly ); + rStatus.SetOptions( aNewOptions ); + + // "PrintRange" enables (1) or disables (0) the "PageRange" edit + if ( nPrintRange == 1 ) + rPagesStr = aPageRange; + else + rPagesStr.Erase(); + + return bDone; +} + + +sal_Int32 SAL_CALL ScModelObj::getRendererCount( const uno::Any& aSelection, + const uno::Sequence<beans::PropertyValue>& rOptions ) + throw (lang::IllegalArgumentException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (!pDocShell) + throw uno::RuntimeException(); + + ScMarkData aMark; + ScPrintSelectionStatus aStatus; + String aPagesStr; + if ( !FillRenderMarkData( aSelection, rOptions, aMark, aStatus, aPagesStr ) ) + return 0; + + // The same ScPrintFuncCache object in pPrintFuncCache is used as long as + // the same selection is used (aStatus) and the document isn't changed + // (pPrintFuncCache is cleared in Notify handler) + + if ( !pPrintFuncCache || !pPrintFuncCache->IsSameSelection( aStatus ) ) + { + delete pPrintFuncCache; + pPrintFuncCache = new ScPrintFuncCache( pDocShell, aMark, aStatus ); + } + sal_Int32 nPages = pPrintFuncCache->GetPageCount(); + + sal_Int32 nSelectCount = nPages; + if ( aPagesStr.Len() ) + { + MultiSelection aPageRanges( aPagesStr ); + aPageRanges.SetTotalRange( Range( 1, nPages ) ); + nSelectCount = aPageRanges.GetSelectCount(); + } + return nSelectCount; +} + +sal_Int32 lcl_GetRendererNum( sal_Int32 nSelRenderer, const String& rPagesStr, sal_Int32 nTotalPages ) +{ + if ( !rPagesStr.Len() ) + return nSelRenderer; + + MultiSelection aPageRanges( rPagesStr ); + aPageRanges.SetTotalRange( Range( 1, nTotalPages ) ); + + sal_Int32 nSelected = aPageRanges.FirstSelected(); + while ( nSelRenderer > 0 ) + { + nSelected = aPageRanges.NextSelected(); + --nSelRenderer; + } + return nSelected - 1; // selection is 1-based +} + +uno::Sequence<beans::PropertyValue> SAL_CALL ScModelObj::getRenderer( sal_Int32 nSelRenderer, + const uno::Any& aSelection, const uno::Sequence<beans::PropertyValue>& rOptions ) + throw (lang::IllegalArgumentException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (!pDocShell) + throw uno::RuntimeException(); + + ScMarkData aMark; + ScPrintSelectionStatus aStatus; + String aPagesStr; + if ( !FillRenderMarkData( aSelection, rOptions, aMark, aStatus, aPagesStr ) ) + throw lang::IllegalArgumentException(); + + if ( !pPrintFuncCache || !pPrintFuncCache->IsSameSelection( aStatus ) ) + { + delete pPrintFuncCache; + pPrintFuncCache = new ScPrintFuncCache( pDocShell, aMark, aStatus ); + } + long nTotalPages = pPrintFuncCache->GetPageCount(); + sal_Int32 nRenderer = lcl_GetRendererNum( nSelRenderer, aPagesStr, nTotalPages ); + if ( nRenderer >= nTotalPages ) + { + if ( nSelRenderer == 0 ) + { + // getRenderer(0) is used to query the settings, so it must always return something + + SCTAB nCurTab = 0; //! use current sheet from view? + ScPrintFunc aDefaultFunc( pDocShell, pDocShell->GetPrinter(), nCurTab ); + Size aTwips = aDefaultFunc.GetPageSize(); + awt::Size aPageSize( TwipsToHMM( aTwips.Width() ), TwipsToHMM( aTwips.Height() ) ); + + uno::Sequence<beans::PropertyValue> aSequence(1); + beans::PropertyValue* pArray = aSequence.getArray(); + pArray[0].Name = rtl::OUString::createFromAscii( SC_UNONAME_PAGESIZE ); + pArray[0].Value <<= aPageSize; + + if( ! pPrinterOptions ) + pPrinterOptions = new ScPrintUIOptions; + else + pPrinterOptions->SetDefaults(); + pPrinterOptions->appendPrintUIOptions( aSequence ); + return aSequence; + } + else + throw lang::IllegalArgumentException(); + } + + // printer is used as device (just for page layout), draw view is not needed + + SCTAB nTab = pPrintFuncCache->GetTabForPage( nRenderer ); + + ScRange aRange; + const ScRange* pSelRange = NULL; + if ( aMark.IsMarked() ) + { + aMark.GetMarkArea( aRange ); + pSelRange = &aRange; + } + ScPrintFunc aFunc( pDocShell, pDocShell->GetPrinter(), nTab, + pPrintFuncCache->GetFirstAttr(nTab), nTotalPages, pSelRange, &aStatus.GetOptions() ); + aFunc.SetRenderFlag( TRUE ); + + Range aPageRange( nRenderer+1, nRenderer+1 ); + MultiSelection aPage( aPageRange ); + aPage.SetTotalRange( Range(0,RANGE_MAX) ); + aPage.Select( aPageRange ); + + long nDisplayStart = pPrintFuncCache->GetDisplayStart( nTab ); + long nTabStart = pPrintFuncCache->GetTabStart( nTab ); + + (void)aFunc.DoPrint( aPage, nTabStart, nDisplayStart, FALSE, NULL, NULL ); + + ScRange aCellRange; + BOOL bWasCellRange = aFunc.GetLastSourceRange( aCellRange ); + Size aTwips = aFunc.GetPageSize(); + awt::Size aPageSize( TwipsToHMM( aTwips.Width() ), TwipsToHMM( aTwips.Height() ) ); + + long nPropCount = bWasCellRange ? 3 : 2; + uno::Sequence<beans::PropertyValue> aSequence(nPropCount); + beans::PropertyValue* pArray = aSequence.getArray(); + pArray[0].Name = rtl::OUString::createFromAscii( SC_UNONAME_PAGESIZE ); + pArray[0].Value <<= aPageSize; + // #i111158# all positions are relative to the whole page, including non-printable area + pArray[1].Name = rtl::OUString::createFromAscii( SC_UNONAME_INC_NP_AREA ); + pArray[1].Value = uno::makeAny( sal_True ); + if ( bWasCellRange ) + { + table::CellRangeAddress aRangeAddress( nTab, + aCellRange.aStart.Col(), aCellRange.aStart.Row(), + aCellRange.aEnd.Col(), aCellRange.aEnd.Row() ); + pArray[2].Name = rtl::OUString::createFromAscii( SC_UNONAME_SOURCERANGE ); + pArray[2].Value <<= aRangeAddress; + } + + #if 0 + const ScPrintOptions& rPrintOpt = + #endif + // FIXME: is this for side effects ? + SC_MOD()->GetPrintOptions(); + if( ! pPrinterOptions ) + pPrinterOptions = new ScPrintUIOptions; + else + pPrinterOptions->SetDefaults(); + pPrinterOptions->appendPrintUIOptions( aSequence ); + return aSequence; +} + +void SAL_CALL ScModelObj::render( sal_Int32 nSelRenderer, const uno::Any& aSelection, + const uno::Sequence<beans::PropertyValue>& rOptions ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (!pDocShell) + throw uno::RuntimeException(); + + ScMarkData aMark; + ScPrintSelectionStatus aStatus; + String aPagesStr; + if ( !FillRenderMarkData( aSelection, rOptions, aMark, aStatus, aPagesStr ) ) + throw lang::IllegalArgumentException(); + + if ( !pPrintFuncCache || !pPrintFuncCache->IsSameSelection( aStatus ) ) + { + delete pPrintFuncCache; + pPrintFuncCache = new ScPrintFuncCache( pDocShell, aMark, aStatus ); + } + long nTotalPages = pPrintFuncCache->GetPageCount(); + sal_Int32 nRenderer = lcl_GetRendererNum( nSelRenderer, aPagesStr, nTotalPages ); + if ( nRenderer >= nTotalPages ) + throw lang::IllegalArgumentException(); + + OutputDevice* pDev = lcl_GetRenderDevice( rOptions ); + if ( !pDev ) + throw lang::IllegalArgumentException(); + + SCTAB nTab = pPrintFuncCache->GetTabForPage( nRenderer ); + ScDocument* pDoc = pDocShell->GetDocument(); + + FmFormView* pDrawView = NULL; + Rectangle aFull( 0, 0, LONG_MAX, LONG_MAX ); + + // #114135# + ScDrawLayer* pModel = pDoc->GetDrawLayer(); + + if( pModel ) + { + pDrawView = new FmFormView( pModel, pDev ); + pDrawView->ShowSdrPage(pDrawView->GetModel()->GetPage(nTab)); + pDrawView->SetPrintPreview( TRUE ); + } + + ScRange aRange; + const ScRange* pSelRange = NULL; + if ( aMark.IsMarked() ) + { + aMark.GetMarkArea( aRange ); + pSelRange = &aRange; + } + + // to increase performance, ScPrintState might be used here for subsequent + // pages of the same sheet + + ScPrintFunc aFunc( pDev, pDocShell, nTab, pPrintFuncCache->GetFirstAttr(nTab), nTotalPages, pSelRange, &aStatus.GetOptions() ); + aFunc.SetDrawView( pDrawView ); + aFunc.SetRenderFlag( TRUE ); + if( aStatus.GetMode() == SC_PRINTSEL_RANGE_EXCLUSIVELY_OLE_AND_DRAW_OBJECTS ) + aFunc.SetExclusivelyDrawOleAndDrawObjects(); + + Range aPageRange( nRenderer+1, nRenderer+1 ); + MultiSelection aPage( aPageRange ); + aPage.SetTotalRange( Range(0,RANGE_MAX) ); + aPage.Select( aPageRange ); + + long nDisplayStart = pPrintFuncCache->GetDisplayStart( nTab ); + long nTabStart = pPrintFuncCache->GetTabStart( nTab ); + + vcl::PDFExtOutDevData* pPDFData = PTR_CAST( vcl::PDFExtOutDevData, pDev->GetExtOutDevData() ); + if ( nRenderer == nTabStart ) + { + // first page of a sheet: add outline item for the sheet name + + if ( pPDFData && pPDFData->GetIsExportBookmarks() ) + { + // the sheet starts at the top of the page + Rectangle aArea( pDev->PixelToLogic( Rectangle( 0,0,0,0 ) ) ); + sal_Int32 nDestID = pPDFData->CreateDest( aArea ); + String aTabName; + pDoc->GetName( nTab, aTabName ); + sal_Int32 nParent = -1; // top-level + pPDFData->CreateOutlineItem( nParent, aTabName, nDestID ); + } + //--->i56629 + // add the named destination stuff + if( pPDFData && pPDFData->GetIsExportNamedDestinations() ) + { + Rectangle aArea( pDev->PixelToLogic( Rectangle( 0,0,0,0 ) ) ); + String aTabName; + pDoc->GetName( nTab, aTabName ); +//need the PDF page number here + pPDFData->CreateNamedDest( aTabName, aArea ); + } + //<---i56629 + } + + (void)aFunc.DoPrint( aPage, nTabStart, nDisplayStart, TRUE, NULL, NULL ); + + // resolve the hyperlinks for PDF export + + if ( pPDFData ) + { + // iterate over the hyperlinks that were output for this page + + std::vector< vcl::PDFExtOutDevBookmarkEntry >& rBookmarks = pPDFData->GetBookmarks(); + std::vector< vcl::PDFExtOutDevBookmarkEntry >::iterator aIter = rBookmarks.begin(); + std::vector< vcl::PDFExtOutDevBookmarkEntry >::iterator aIEnd = rBookmarks.end(); + while ( aIter != aIEnd ) + { + rtl::OUString aBookmark = aIter->aBookmark; + if ( aBookmark.toChar() == (sal_Unicode) '#' ) + { + // try to resolve internal link + + String aTarget( aBookmark.copy( 1 ) ); + + ScRange aTargetRange; + Rectangle aTargetRect; // 1/100th mm + bool bIsSheet = false; + bool bValid = lcl_ParseTarget( aTarget, aTargetRange, aTargetRect, bIsSheet, pDoc, nTab ); + + if ( bValid ) + { + sal_Int32 nPage = -1; + Rectangle aArea; + if ( bIsSheet ) + { + // Get first page for sheet (if nothing from that sheet is printed, + // this page can show a different sheet) + nPage = pPrintFuncCache->GetTabStart( aTargetRange.aStart.Tab() ); + aArea = pDev->PixelToLogic( Rectangle( 0,0,0,0 ) ); + } + else + { + pPrintFuncCache->InitLocations( aMark, pDev ); // does nothing if already initialized + + ScPrintPageLocation aLocation; + if ( pPrintFuncCache->FindLocation( aTargetRange.aStart, aLocation ) ) + { + nPage = aLocation.nPage; + + // get the rectangle of the page's cell range in 1/100th mm + ScRange aLocRange = aLocation.aCellRange; + Rectangle aLocationMM = pDoc->GetMMRect( + aLocRange.aStart.Col(), aLocRange.aStart.Row(), + aLocRange.aEnd.Col(), aLocRange.aEnd.Row(), + aLocRange.aStart.Tab() ); + Rectangle aLocationPixel = aLocation.aRectangle; + + // Scale and move the target rectangle from aLocationMM to aLocationPixel, + // to get the target rectangle in pixels. + + Fraction aScaleX( aLocationPixel.GetWidth(), aLocationMM.GetWidth() ); + Fraction aScaleY( aLocationPixel.GetHeight(), aLocationMM.GetHeight() ); + + long nX1 = aLocationPixel.Left() + (long) + ( Fraction( aTargetRect.Left() - aLocationMM.Left(), 1 ) * aScaleX ); + long nX2 = aLocationPixel.Left() + (long) + ( Fraction( aTargetRect.Right() - aLocationMM.Left(), 1 ) * aScaleX ); + long nY1 = aLocationPixel.Top() + (long) + ( Fraction( aTargetRect.Top() - aLocationMM.Top(), 1 ) * aScaleY ); + long nY2 = aLocationPixel.Top() + (long) + ( Fraction( aTargetRect.Bottom() - aLocationMM.Top(), 1 ) * aScaleY ); + + if ( nX1 > aLocationPixel.Right() ) nX1 = aLocationPixel.Right(); + if ( nX2 > aLocationPixel.Right() ) nX2 = aLocationPixel.Right(); + if ( nY1 > aLocationPixel.Bottom() ) nY1 = aLocationPixel.Bottom(); + if ( nY2 > aLocationPixel.Bottom() ) nY2 = aLocationPixel.Bottom(); + + // The link target area is interpreted using the device's MapMode at + // the time of the CreateDest call, so PixelToLogic can be used here, + // regardless of the MapMode that is actually selected. + + aArea = pDev->PixelToLogic( Rectangle( nX1, nY1, nX2, nY2 ) ); + } + } + + if ( nPage >= 0 ) + pPDFData->SetLinkDest( aIter->nLinkId, pPDFData->CreateDest( aArea, nPage ) ); + } + } + else + { + // external link, use as-is + pPDFData->SetLinkURL( aIter->nLinkId, aBookmark ); + } + aIter++; + } + rBookmarks.clear(); + } + + delete pDrawView; +} + +// XLinkTargetSupplier + +uno::Reference<container::XNameAccess> SAL_CALL ScModelObj::getLinks() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + return new ScLinkTargetTypesObj(pDocShell); + return NULL; +} + +// XActionLockable + +sal_Bool SAL_CALL ScModelObj::isActionLocked() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + BOOL bLocked = FALSE; + if (pDocShell) + bLocked = ( pDocShell->GetLockCount() != 0 ); + return bLocked; +} + +void SAL_CALL ScModelObj::addActionLock() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + pDocShell->LockDocument(); +} + +void SAL_CALL ScModelObj::removeActionLock() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + pDocShell->UnlockDocument(); +} + +void SAL_CALL ScModelObj::setActionLocks( sal_Int16 nLock ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + pDocShell->SetLockCount(nLock); +} + +sal_Int16 SAL_CALL ScModelObj::resetActionLocks() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + USHORT nRet = 0; + if (pDocShell) + { + nRet = pDocShell->GetLockCount(); + pDocShell->SetLockCount(0); + } + return nRet; +} + +void SAL_CALL ScModelObj::lockControllers() throw (::com::sun::star::uno::RuntimeException) +{ + ScUnoGuard aGuard; + SfxBaseModel::lockControllers(); + if (pDocShell) + pDocShell->LockPaint(); +} + +void SAL_CALL ScModelObj::unlockControllers() throw (::com::sun::star::uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (hasControllersLocked()) + { + SfxBaseModel::unlockControllers(); + if (pDocShell) + pDocShell->UnlockPaint(); + } +} + +// XCalculate + +void SAL_CALL ScModelObj::calculate() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + pDocShell->DoRecalc(TRUE); + else + { + DBG_ERROR("keine DocShell"); //! Exception oder so? + } +} + +void SAL_CALL ScModelObj::calculateAll() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + pDocShell->DoHardRecalc(TRUE); + else + { + DBG_ERROR("keine DocShell"); //! Exception oder so? + } +} + +sal_Bool SAL_CALL ScModelObj::isAutomaticCalculationEnabled() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + return pDocShell->GetDocument()->GetAutoCalc(); + + DBG_ERROR("keine DocShell"); //! Exception oder so? + return FALSE; +} + +void SAL_CALL ScModelObj::enableAutomaticCalculation( sal_Bool bEnabled ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + if ( pDoc->GetAutoCalc() != bEnabled ) + { + pDoc->SetAutoCalc( bEnabled ); + pDocShell->SetDocumentModified(); + } + } + else + { + DBG_ERROR("keine DocShell"); //! Exception oder so? + } +} + +// XProtectable + +void SAL_CALL ScModelObj::protect( const rtl::OUString& aPassword ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + // #i108245# if already protected, don't change anything + if ( pDocShell && !pDocShell->GetDocument()->IsDocProtected() ) + { + String aString(aPassword); + + ScDocFunc aFunc(*pDocShell); + aFunc.Protect( TABLEID_DOC, aString, TRUE ); + } +} + +void SAL_CALL ScModelObj::unprotect( const rtl::OUString& aPassword ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + String aString(aPassword); + + ScDocFunc aFunc(*pDocShell); + BOOL bDone = aFunc.Unprotect( TABLEID_DOC, aString, TRUE ); + if (!bDone) + throw lang::IllegalArgumentException(); + } +} + +sal_Bool SAL_CALL ScModelObj::isProtected() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + return pDocShell->GetDocument()->IsDocProtected(); + + DBG_ERROR("keine DocShell"); //! Exception oder so? + return FALSE; +} + +// XDrawPagesSupplier + +uno::Reference<drawing::XDrawPages> SAL_CALL ScModelObj::getDrawPages() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + return new ScDrawPagesObj(pDocShell); + + DBG_ERROR("keine DocShell"); //! Exception oder so? + return NULL; +} + +#if 0 +// XPrintable + +rtl::OUString ScModelObj::getPrinterName(void) const +{ + ScUnoGuard aGuard; + if (pDocShell) + { + SfxPrinter* pPrinter = pDocShell->GetPrinter(); + if (pPrinter) + return pPrinter->GetName(); + } + + DBG_ERROR("getPrinterName: keine DocShell oder kein Printer"); + return rtl::OUString(); +} + +void ScModelObj::setPrinterName(const rtl::OUString& PrinterName) +{ + ScUnoGuard aGuard; + // Drucker setzen - wie in SfxViewShell::ExecPrint_Impl + + if (pDocShell) + { + SfxPrinter* pPrinter = pDocShell->GetPrinter(); + if (pPrinter) + { + String aString(PrinterName); + SfxPrinter* pNewPrinter = new SfxPrinter( pPrinter->GetOptions().Clone(), aString ); + if (pNewPrinter->IsKnown()) + pDocShell->SetPrinter( pNewPrinter, SFX_PRINTER_PRINTER ); + else + delete pNewPrinter; + } + } +} + +XPropertySetRef ScModelObj::createPrintOptions(void) +{ + ScUnoGuard aGuard; + return new ScPrintSettingsObj; //! ScPrintSettingsObj implementieren! +} + +void ScModelObj::print(const XPropertySetRef& xOptions) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + //! xOptions auswerten (wie denn?) + + //! muss noch + } +} +#endif + +// XGoalSeek + +sheet::GoalResult SAL_CALL ScModelObj::seekGoal( + const table::CellAddress& aFormulaPosition, + const table::CellAddress& aVariablePosition, + const ::rtl::OUString& aGoalValue ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + sheet::GoalResult aResult; + aResult.Divergence = DBL_MAX; // nichts gefunden + if (pDocShell) + { + WaitObject aWait( pDocShell->GetActiveDialogParent() ); + String aGoalString(aGoalValue); + ScDocument* pDoc = pDocShell->GetDocument(); + double fValue = 0.0; + BOOL bFound = pDoc->Solver( + (SCCOL)aFormulaPosition.Column, (SCROW)aFormulaPosition.Row, aFormulaPosition.Sheet, + (SCCOL)aVariablePosition.Column, (SCROW)aVariablePosition.Row, aVariablePosition.Sheet, + aGoalString, fValue ); + aResult.Result = fValue; + if (bFound) + aResult.Divergence = 0.0; //! das ist gelogen + } + return aResult; +} + +// XConsolidatable + +uno::Reference<sheet::XConsolidationDescriptor> SAL_CALL ScModelObj::createConsolidationDescriptor( + sal_Bool bEmpty ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScConsolidationDescriptor* pNew = new ScConsolidationDescriptor; + if ( pDocShell && !bEmpty ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + const ScConsolidateParam* pParam = pDoc->GetConsolidateDlgData(); + if (pParam) + pNew->SetParam( *pParam ); + } + return pNew; +} + +void SAL_CALL ScModelObj::consolidate( + const uno::Reference<sheet::XConsolidationDescriptor>& xDescriptor ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + // das koennte theoretisch ein fremdes Objekt sein, also nur das + // oeffentliche XConsolidationDescriptor Interface benutzen, um + // die Daten in ein ScConsolidationDescriptor Objekt zu kopieren: + //! wenn es schon ein ScConsolidationDescriptor ist, direkt per getImplementation? + + ScConsolidationDescriptor aImpl; + aImpl.setFunction( xDescriptor->getFunction() ); + aImpl.setSources( xDescriptor->getSources() ); + aImpl.setStartOutputPosition( xDescriptor->getStartOutputPosition() ); + aImpl.setUseColumnHeaders( xDescriptor->getUseColumnHeaders() ); + aImpl.setUseRowHeaders( xDescriptor->getUseRowHeaders() ); + aImpl.setInsertLinks( xDescriptor->getInsertLinks() ); + + if (pDocShell) + { + const ScConsolidateParam& rParam = aImpl.GetParam(); + pDocShell->DoConsolidate( rParam, TRUE ); + pDocShell->GetDocument()->SetConsolidateDlgData( &rParam ); + } +} + +// XDocumentAuditing + +void SAL_CALL ScModelObj::refreshArrows() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + ScDocFunc aFunc(*pDocShell); + aFunc.DetectiveRefresh(); + } +} + +// XViewDataSupplier +uno::Reference< container::XIndexAccess > SAL_CALL ScModelObj::getViewData( ) + throw (uno::RuntimeException) +{ + uno::Reference < container::XIndexAccess > xRet( SfxBaseModel::getViewData() ); + + if( !xRet.is() ) + { + ScUnoGuard aGuard; + if (pDocShell && pDocShell->GetCreateMode() == SFX_CREATE_MODE_EMBEDDED) + { + xRet.set(uno::Reference < container::XIndexAccess >::query(::comphelper::getProcessServiceFactory()->createInstance(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.document.IndexedPropertyValues"))))); + + uno::Reference < container::XIndexContainer > xCont( xRet, uno::UNO_QUERY ); + DBG_ASSERT( xCont.is(), "ScModelObj::getViewData() failed for OLE object" ); + if( xCont.is() ) + { + uno::Sequence< beans::PropertyValue > aSeq; + aSeq.realloc(1); + String sName; + pDocShell->GetDocument()->GetName( pDocShell->GetDocument()->GetVisibleTab(), sName ); + rtl::OUString sOUName(sName); + aSeq[0].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_ACTIVETABLE)); + aSeq[0].Value <<= sOUName; + xCont->insertByIndex( 0, uno::makeAny( aSeq ) ); + } + } + } + + return xRet; +} + +// XPropertySet (Doc-Optionen) +//! auch an der Applikation anbieten? + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScModelObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef( + new SfxItemPropertySetInfo( aPropSet.getPropertyMap() )); + return aRef; +} + +void SAL_CALL ScModelObj::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aString(aPropertyName); + + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + const ScDocOptions& rOldOpt = pDoc->GetDocOptions(); + ScDocOptions aNewOpt = rOldOpt; + + BOOL bOpt = ScDocOptionsHelper::setPropertyValue( aNewOpt, *aPropSet.getPropertyMap(), aPropertyName, aValue ); + if (bOpt) + { + // done... + } + else if ( aString.EqualsAscii( SC_UNONAME_CLOCAL ) ) + { + lang::Locale aLocale; + if ( aValue >>= aLocale ) + { + LanguageType eLatin, eCjk, eCtl; + pDoc->GetLanguage( eLatin, eCjk, eCtl ); + eLatin = ScUnoConversion::GetLanguage(aLocale); + pDoc->SetLanguage( eLatin, eCjk, eCtl ); + } + } + else if ( aString.EqualsAscii( SC_UNO_CODENAME ) ) + { + rtl::OUString sCodeName; + if ( aValue >>= sCodeName ) + pDoc->SetCodeName( sCodeName ); + } + else if ( aString.EqualsAscii( SC_UNO_CJK_CLOCAL ) ) + { + lang::Locale aLocale; + if ( aValue >>= aLocale ) + { + LanguageType eLatin, eCjk, eCtl; + pDoc->GetLanguage( eLatin, eCjk, eCtl ); + eCjk = ScUnoConversion::GetLanguage(aLocale); + pDoc->SetLanguage( eLatin, eCjk, eCtl ); + } + } + else if ( aString.EqualsAscii( SC_UNO_CTL_CLOCAL ) ) + { + lang::Locale aLocale; + if ( aValue >>= aLocale ) + { + LanguageType eLatin, eCjk, eCtl; + pDoc->GetLanguage( eLatin, eCjk, eCtl ); + eCtl = ScUnoConversion::GetLanguage(aLocale); + pDoc->SetLanguage( eLatin, eCjk, eCtl ); + } + } + else if ( aString.EqualsAscii( SC_UNO_APPLYFMDES ) ) + { + // model is created if not there + ScDrawLayer* pModel = pDocShell->MakeDrawLayer(); + pModel->SetOpenInDesignMode( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + + SfxBindings* pBindings = pDocShell->GetViewBindings(); + if (pBindings) + pBindings->Invalidate( SID_FM_OPEN_READONLY ); + } + else if ( aString.EqualsAscii( SC_UNO_AUTOCONTFOC ) ) + { + // model is created if not there + ScDrawLayer* pModel = pDocShell->MakeDrawLayer(); + pModel->SetAutoControlFocus( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + + SfxBindings* pBindings = pDocShell->GetViewBindings(); + if (pBindings) + pBindings->Invalidate( SID_FM_AUTOCONTROLFOCUS ); + } + else if ( aString.EqualsAscii( SC_UNO_ISLOADED ) ) + { + pDocShell->SetEmpty( !ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + } + else if ( aString.EqualsAscii( SC_UNO_ISUNDOENABLED ) ) + { + BOOL bUndoEnabled = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + pDoc->EnableUndo( bUndoEnabled ); + USHORT nCount = ( bUndoEnabled ? + static_cast< USHORT >( SvtUndoOptions().GetUndoCount() ) : 0 ); + pDocShell->GetUndoManager()->SetMaxUndoActionCount( nCount ); + } + else if ( aString.EqualsAscii( SC_UNO_ISADJUSTHEIGHTENABLED ) ) + { + bool bOldAdjustHeightEnabled = pDoc->IsAdjustHeightEnabled(); + bool bAdjustHeightEnabled = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + if( bOldAdjustHeightEnabled != bAdjustHeightEnabled ) + { + pDoc->EnableAdjustHeight( bAdjustHeightEnabled ); + if( bAdjustHeightEnabled ) + pDocShell->UpdateAllRowHeights(); + } + } + else if ( aString.EqualsAscii( SC_UNO_ISEXECUTELINKENABLED ) ) + { + pDoc->EnableExecuteLink( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + } + else if ( aString.EqualsAscii( SC_UNO_ISCHANGEREADONLYENABLED ) ) + { + pDoc->EnableChangeReadOnly( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + } + else if ( aString.EqualsAscii( "BuildId" ) ) + { + aValue >>= maBuildId; + } + else if ( aString.EqualsAscii( "SavedObject" ) ) // set from chart after saving + { + rtl::OUString aObjName; + aValue >>= aObjName; + if ( aObjName.getLength() ) + pDoc->RestoreChartListener( aObjName ); + } + + if ( aNewOpt != rOldOpt ) + { + pDoc->SetDocOptions( aNewOpt ); + // Don't recalculate while loading XML, when the formula text is stored. + // Recalculation after loading is handled separately. + //! Recalc only for options that need it? + if ( !pDoc->IsImportingXML() ) + pDocShell->DoHardRecalc( TRUE ); + pDocShell->SetDocumentModified(); + } + } +} + +uno::Any SAL_CALL ScModelObj::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aString(aPropertyName); + uno::Any aRet; + + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + const ScDocOptions& rOpt = pDoc->GetDocOptions(); + aRet = ScDocOptionsHelper::getPropertyValue( rOpt, *aPropSet.getPropertyMap(), aPropertyName ); + if ( aRet.hasValue() ) + { + // done... + } + else if ( aString.EqualsAscii( SC_UNONAME_CLOCAL ) ) + { + LanguageType eLatin, eCjk, eCtl; + pDoc->GetLanguage( eLatin, eCjk, eCtl ); + + lang::Locale aLocale; + ScUnoConversion::FillLocale( aLocale, eLatin ); + aRet <<= aLocale; + } + else if ( aString.EqualsAscii( SC_UNO_CODENAME ) ) + { + rtl::OUString sCodeName = pDoc->GetCodeName(); + aRet <<= sCodeName; + } + + else if ( aString.EqualsAscii( SC_UNO_CJK_CLOCAL ) ) + { + LanguageType eLatin, eCjk, eCtl; + pDoc->GetLanguage( eLatin, eCjk, eCtl ); + + lang::Locale aLocale; + ScUnoConversion::FillLocale( aLocale, eCjk ); + aRet <<= aLocale; + } + else if ( aString.EqualsAscii( SC_UNO_CTL_CLOCAL ) ) + { + LanguageType eLatin, eCjk, eCtl; + pDoc->GetLanguage( eLatin, eCjk, eCtl ); + + lang::Locale aLocale; + ScUnoConversion::FillLocale( aLocale, eCtl ); + aRet <<= aLocale; + } + else if ( aString.EqualsAscii( SC_UNO_NAMEDRANGES ) ) + { + aRet <<= uno::Reference<sheet::XNamedRanges>(new ScNamedRangesObj( pDocShell )); + } + else if ( aString.EqualsAscii( SC_UNO_DATABASERNG ) ) + { + aRet <<= uno::Reference<sheet::XDatabaseRanges>(new ScDatabaseRangesObj( pDocShell )); + } + else if ( aString.EqualsAscii( SC_UNO_COLLABELRNG ) ) + { + aRet <<= uno::Reference<sheet::XLabelRanges>(new ScLabelRangesObj( pDocShell, TRUE )); + } + else if ( aString.EqualsAscii( SC_UNO_ROWLABELRNG ) ) + { + aRet <<= uno::Reference<sheet::XLabelRanges>(new ScLabelRangesObj( pDocShell, FALSE )); + } + else if ( aString.EqualsAscii( SC_UNO_AREALINKS ) ) + { + aRet <<= uno::Reference<sheet::XAreaLinks>(new ScAreaLinksObj( pDocShell )); + } + else if ( aString.EqualsAscii( SC_UNO_DDELINKS ) ) + { + aRet <<= uno::Reference<container::XNameAccess>(new ScDDELinksObj( pDocShell )); + } + else if ( aString.EqualsAscii( SC_UNO_EXTERNALDOCLINKS ) ) + { + aRet <<= uno::Reference<sheet::XExternalDocLinks>(new ScExternalDocLinksObj(pDocShell)); + } + else if ( aString.EqualsAscii( SC_UNO_SHEETLINKS ) ) + { + aRet <<= uno::Reference<container::XNameAccess>(new ScSheetLinksObj( pDocShell )); + } + else if ( aString.EqualsAscii( SC_UNO_APPLYFMDES ) ) + { + // default for no model is TRUE + ScDrawLayer* pModel = pDoc->GetDrawLayer(); + sal_Bool bOpenInDesign = pModel ? pModel->GetOpenInDesignMode() : sal_True; + ScUnoHelpFunctions::SetBoolInAny( aRet, bOpenInDesign ); + } + else if ( aString.EqualsAscii( SC_UNO_AUTOCONTFOC ) ) + { + // default for no model is FALSE + ScDrawLayer* pModel = pDoc->GetDrawLayer(); + sal_Bool bAutoControlFocus = pModel ? pModel->GetAutoControlFocus() : sal_False; + ScUnoHelpFunctions::SetBoolInAny( aRet, bAutoControlFocus ); + } + else if ( aString.EqualsAscii( SC_UNO_FORBIDDEN ) ) + { + aRet <<= uno::Reference<i18n::XForbiddenCharacters>(new ScForbiddenCharsObj( pDocShell )); + } + else if ( aString.EqualsAscii( SC_UNO_HASDRAWPAGES ) ) + { + ScUnoHelpFunctions::SetBoolInAny( aRet, (pDocShell->GetDocument()->GetDrawLayer() != 0) ); + } + else if ( aString.EqualsAscii( SC_UNO_BASICLIBRARIES ) ) + { + aRet <<= pDocShell->GetBasicContainer(); + } + else if ( aString.EqualsAscii( SC_UNO_DIALOGLIBRARIES ) ) + { + aRet <<= pDocShell->GetDialogContainer(); + } + else if ( aString.EqualsAscii( SC_UNO_RUNTIMEUID ) ) + { + aRet <<= getRuntimeUID(); + } + else if ( aString.EqualsAscii( SC_UNO_HASVALIDSIGNATURES ) ) + { + aRet <<= hasValidSignatures(); + } + else if ( aString.EqualsAscii( SC_UNO_ISLOADED ) ) + { + ScUnoHelpFunctions::SetBoolInAny( aRet, !pDocShell->IsEmpty() ); + } + else if ( aString.EqualsAscii( SC_UNO_ISUNDOENABLED ) ) + { + ScUnoHelpFunctions::SetBoolInAny( aRet, pDoc->IsUndoEnabled() ); + } + else if ( aString.EqualsAscii( SC_UNO_ISADJUSTHEIGHTENABLED ) ) + { + ScUnoHelpFunctions::SetBoolInAny( aRet, pDoc->IsAdjustHeightEnabled() ); + } + else if ( aString.EqualsAscii( SC_UNO_ISEXECUTELINKENABLED ) ) + { + ScUnoHelpFunctions::SetBoolInAny( aRet, pDoc->IsExecuteLinkEnabled() ); + } + else if ( aString.EqualsAscii( SC_UNO_ISCHANGEREADONLYENABLED ) ) + { + ScUnoHelpFunctions::SetBoolInAny( aRet, pDoc->IsChangeReadOnlyEnabled() ); + } + else if ( aString.EqualsAscii( SC_UNO_REFERENCEDEVICE ) ) + { + VCLXDevice* pXDev = new VCLXDevice(); + pXDev->SetOutputDevice( pDoc->GetRefDevice() ); + aRet <<= uno::Reference< awt::XDevice >( pXDev ); + } + else if ( aString.EqualsAscii( "BuildId" ) ) + { + aRet <<= maBuildId; + } + else if ( aString.EqualsAscii( "InternalDocument" ) ) + { + ScUnoHelpFunctions::SetBoolInAny( aRet, (pDocShell->GetCreateMode() == SFX_CREATE_MODE_INTERNAL) ); + } + } + + return aRet; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScModelObj ) + +// XMultiServiceFactory + +uno::Reference<uno::XInterface> SAL_CALL ScModelObj::createInstance( + const rtl::OUString& aServiceSpecifier ) + throw(uno::Exception, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<uno::XInterface> xRet; + String aNameStr(aServiceSpecifier); + USHORT nType = ScServiceProvider::GetProviderType(aNameStr); + if ( nType != SC_SERVICE_INVALID ) + { + // drawing layer tables must be kept as long as the model is alive + // return stored instance if already set + switch ( nType ) + { + case SC_SERVICE_GRADTAB: xRet.set(xDrawGradTab); break; + case SC_SERVICE_HATCHTAB: xRet.set(xDrawHatchTab); break; + case SC_SERVICE_BITMAPTAB: xRet.set(xDrawBitmapTab); break; + case SC_SERVICE_TRGRADTAB: xRet.set(xDrawTrGradTab); break; + case SC_SERVICE_MARKERTAB: xRet.set(xDrawMarkerTab); break; + case SC_SERVICE_DASHTAB: xRet.set(xDrawDashTab); break; + case SC_SERVICE_CHDATAPROV: xRet.set(xChartDataProv); break; + } + + // #i64497# If a chart is in a temporary document during clipoard paste, + // there should be no data provider, so that own data is used + bool bCreate = + ! ( nType == SC_SERVICE_CHDATAPROV && + ( pDocShell->GetCreateMode() == SFX_CREATE_MODE_INTERNAL )); + // this should never happen, i.e. the temporary document should never be + // loaded, becuase this unlinks the data + OSL_ASSERT( bCreate ); + + if ( !xRet.is() && bCreate ) + { + xRet.set(ScServiceProvider::MakeInstance( nType, pDocShell )); + + // store created instance + switch ( nType ) + { + case SC_SERVICE_GRADTAB: xDrawGradTab.set(xRet); break; + case SC_SERVICE_HATCHTAB: xDrawHatchTab.set(xRet); break; + case SC_SERVICE_BITMAPTAB: xDrawBitmapTab.set(xRet); break; + case SC_SERVICE_TRGRADTAB: xDrawTrGradTab.set(xRet); break; + case SC_SERVICE_MARKERTAB: xDrawMarkerTab.set(xRet); break; + case SC_SERVICE_DASHTAB: xDrawDashTab.set(xRet); break; + case SC_SERVICE_CHDATAPROV: xChartDataProv.set(xRet); break; + } + } + } + else + { + // alles was ich nicht kenn, werf ich der SvxFmMSFactory an den Hals, + // da wird dann 'ne Exception geworfen, wenn's nicht passt... + + try + { + xRet.set(SvxFmMSFactory::createInstance(aServiceSpecifier)); + // extra block to force deletion of the temporary before ScShapeObj ctor (setDelegator) + } + catch ( lang::ServiceNotRegisteredException & ) + { + } + + // #96117# if the drawing factory created a shape, a ScShapeObj has to be used + // to support own properties like ImageMap: + + uno::Reference<drawing::XShape> xShape( xRet, uno::UNO_QUERY ); + if ( xShape.is() ) + { + xRet.clear(); // for aggregation, xShape must be the object's only ref + new ScShapeObj( xShape ); // aggregates object and modifies xShape + xRet.set(xShape); + } + } + return xRet; +} + +uno::Reference<uno::XInterface> SAL_CALL ScModelObj::createInstanceWithArguments( + const rtl::OUString& ServiceSpecifier, + const uno::Sequence<uno::Any>& aArgs ) + throw(uno::Exception, uno::RuntimeException) +{ + //! unterscheiden zwischen eigenen Services und denen vom Drawing-Layer? + + ScUnoGuard aGuard; + uno::Reference<uno::XInterface> xInt(createInstance(ServiceSpecifier)); + + if ( aArgs.getLength() ) + { + // used only for cell value binding so far - it can be initialized after creating + + uno::Reference<lang::XInitialization> xInit( xInt, uno::UNO_QUERY ); + if ( xInit.is() ) + xInit->initialize( aArgs ); + } + + return xInt; +} + +uno::Sequence<rtl::OUString> SAL_CALL ScModelObj::getAvailableServiceNames() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + //! warum sind die Parameter bei concatServiceNames nicht const ??? + //! return concatServiceNames( ScServiceProvider::GetAllServiceNames(), + //! SvxFmMSFactory::getAvailableServiceNames() ); + + uno::Sequence<rtl::OUString> aMyServices(ScServiceProvider::GetAllServiceNames()); + uno::Sequence<rtl::OUString> aDrawServices(SvxFmMSFactory::getAvailableServiceNames()); + + return concatServiceNames( aMyServices, aDrawServices ); +} + +// XServiceInfo + +rtl::OUString SAL_CALL ScModelObj::getImplementationName() throw(uno::RuntimeException) +{ + return rtl::OUString::createFromAscii( "ScModelObj" ); +} + +sal_Bool SAL_CALL ScModelObj::supportsService( const rtl::OUString& rServiceName ) + throw(uno::RuntimeException) +{ + String aServiceStr(rServiceName); + return aServiceStr.EqualsAscii( SCMODELOBJ_SERVICE ) || + aServiceStr.EqualsAscii( SCDOCSETTINGS_SERVICE ) || + aServiceStr.EqualsAscii( SCDOC_SERVICE ); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScModelObj::getSupportedServiceNames() + throw(uno::RuntimeException) +{ + uno::Sequence<rtl::OUString> aRet(2); + rtl::OUString* pArray = aRet.getArray(); + pArray[0] = rtl::OUString::createFromAscii( SCMODELOBJ_SERVICE ); + pArray[1] = rtl::OUString::createFromAscii( SCDOCSETTINGS_SERVICE ); + return aRet; +} + +// XUnoTunnel + +sal_Int64 SAL_CALL ScModelObj::getSomething( + const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); + } + + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( SfxObjectShell::getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(pDocShell )); + } + + // aggregated number formats supplier has XUnoTunnel, too + // interface from aggregated object must be obtained via queryAggregation + + sal_Int64 nRet = SfxBaseModel::getSomething( rId ); + if ( nRet ) + return nRet; + + if ( GetFormatter().is() ) + { + const uno::Type& rTunnelType = ::getCppuType((uno::Reference<lang::XUnoTunnel>*) 0); + uno::Any aNumTunnel(xNumberAgg->queryAggregation(rTunnelType)); + if(aNumTunnel.getValueType() == rTunnelType) + { + uno::Reference<lang::XUnoTunnel> xTunnelAgg( + *(uno::Reference<lang::XUnoTunnel>*)aNumTunnel.getValue()); + return xTunnelAgg->getSomething( rId ); + } + } + + return 0; +} + +// static +const uno::Sequence<sal_Int8>& ScModelObj::getUnoTunnelId() +{ + static uno::Sequence<sal_Int8> * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +// static +ScModelObj* ScModelObj::getImplementation( const uno::Reference<uno::XInterface> xObj ) +{ + ScModelObj* pRet = NULL; + uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); + if (xUT.is()) + pRet = reinterpret_cast<ScModelObj*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId()))); + return pRet; +} + +// XChangesNotifier + +void ScModelObj::addChangesListener( const uno::Reference< util::XChangesListener >& aListener ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + maChangesListeners.addInterface( aListener ); +} + +void ScModelObj::removeChangesListener( const uno::Reference< util::XChangesListener >& aListener ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + maChangesListeners.removeInterface( aListener ); +} + +bool ScModelObj::HasChangesListeners() const +{ + if ( maChangesListeners.getLength() > 0 ) + return true; + + // "change" event set in any sheet? + return pDocShell && pDocShell->GetDocument()->HasAnySheetEventScript(SC_SHEETEVENT_CHANGE); +} + +void ScModelObj::NotifyChanges( const ::rtl::OUString& rOperation, const ScRangeList& rRanges, + const uno::Sequence< beans::PropertyValue >& rProperties ) +{ + if ( pDocShell && HasChangesListeners() ) + { + util::ChangesEvent aEvent; + aEvent.Source.set( static_cast< cppu::OWeakObject* >( this ) ); + aEvent.Base <<= aEvent.Source; + + ULONG nRangeCount = rRanges.Count(); + aEvent.Changes.realloc( static_cast< sal_Int32 >( nRangeCount ) ); + for ( ULONG nIndex = 0; nIndex < nRangeCount; ++nIndex ) + { + uno::Reference< table::XCellRange > xRangeObj; + + ScRange aRange( *rRanges.GetObject( nIndex ) ); + if ( aRange.aStart == aRange.aEnd ) + { + xRangeObj.set( new ScCellObj( pDocShell, aRange.aStart ) ); + } + else + { + xRangeObj.set( new ScCellRangeObj( pDocShell, aRange ) ); + } + + util::ElementChange& rChange = aEvent.Changes[ static_cast< sal_Int32 >( nIndex ) ]; + rChange.Accessor <<= rOperation; + rChange.Element <<= rProperties; + rChange.ReplacedElement <<= xRangeObj; + } + + ::cppu::OInterfaceIteratorHelper aIter( maChangesListeners ); + while ( aIter.hasMoreElements() ) + { + try + { + static_cast< util::XChangesListener* >( aIter.next() )->changesOccurred( aEvent ); + } + catch( uno::Exception& ) + { + } + } + } + + // handle sheet events + //! separate method with ScMarkData? Then change HasChangesListeners back. + if ( rOperation.compareToAscii("cell-change") == 0 && pDocShell ) + { + ScMarkData aMarkData; + aMarkData.MarkFromRangeList( rRanges, FALSE ); + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab = 0; nTab < nTabCount; nTab++) + if (aMarkData.GetTableSelect(nTab)) + { + const ScSheetEvents* pEvents = pDoc->GetSheetEvents(nTab); + if (pEvents) + { + const rtl::OUString* pScript = pEvents->GetScript(SC_SHEETEVENT_CHANGE); + if (pScript) + { + ScRangeList aTabRanges; // collect ranges on this sheet + ULONG nRangeCount = rRanges.Count(); + for ( ULONG nIndex = 0; nIndex < nRangeCount; ++nIndex ) + { + ScRange aRange( *rRanges.GetObject( nIndex ) ); + if ( aRange.aStart.Tab() == nTab ) + aTabRanges.Append( aRange ); + } + ULONG nTabRangeCount = aTabRanges.Count(); + if ( nTabRangeCount > 0 ) + { + uno::Reference<uno::XInterface> xTarget; + if ( nTabRangeCount == 1 ) + { + ScRange aRange( *aTabRanges.GetObject( 0 ) ); + if ( aRange.aStart == aRange.aEnd ) + xTarget.set( static_cast<cppu::OWeakObject*>( new ScCellObj( pDocShell, aRange.aStart ) ) ); + else + xTarget.set( static_cast<cppu::OWeakObject*>( new ScCellRangeObj( pDocShell, aRange ) ) ); + } + else + xTarget.set( static_cast<cppu::OWeakObject*>( new ScCellRangesObj( pDocShell, aTabRanges ) ) ); + + uno::Sequence<uno::Any> aParams(1); + aParams[0] <<= xTarget; + + uno::Any aRet; + uno::Sequence<sal_Int16> aOutArgsIndex; + uno::Sequence<uno::Any> aOutArgs; + + /*ErrCode eRet =*/ pDocShell->CallXScript( *pScript, aParams, aRet, aOutArgsIndex, aOutArgs ); + } + } + } + } + } +} + +void ScModelObj::HandleCalculateEvents() +{ + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + // don't call events before the document is visible + // (might also set a flag on SFX_EVENT_LOADFINISHED and only disable while loading) + if ( pDoc->IsDocVisible() ) + { + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab = 0; nTab < nTabCount; nTab++) + { + if (pDoc->HasCalcNotification(nTab)) + { + if (const ScSheetEvents* pEvents = pDoc->GetSheetEvents( nTab )) + { + if (const rtl::OUString* pScript = pEvents->GetScript(SC_SHEETEVENT_CALCULATE)) + { + uno::Any aRet; + uno::Sequence<uno::Any> aParams; + uno::Sequence<sal_Int16> aOutArgsIndex; + uno::Sequence<uno::Any> aOutArgs; + pDocShell->CallXScript( *pScript, aParams, aRet, aOutArgsIndex, aOutArgs ); + } + } + + try + { + uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( pDoc->GetVbaEventProcessor(), uno::UNO_SET_THROW ); + uno::Sequence< uno::Any > aArgs( 1 ); + aArgs[ 0 ] <<= nTab; + xVbaEvents->processVbaEvent( ScSheetEvents::GetVbaSheetEventId( SC_SHEETEVENT_CALCULATE ), aArgs ); + } + catch( uno::Exception& ) + { + } + } + } + } + pDoc->ResetCalcNotifications(); + } +} + +//------------------------------------------------------------------------ + +ScDrawPagesObj::ScDrawPagesObj(ScDocShell* pDocSh) : + pDocShell( pDocSh ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScDrawPagesObj::~ScDrawPagesObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScDrawPagesObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + // Referenz-Update interessiert hier nicht + + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +uno::Reference<drawing::XDrawPage> ScDrawPagesObj::GetObjectByIndex_Impl(INT32 nIndex) const +{ + if (pDocShell) + { + ScDrawLayer* pDrawLayer = pDocShell->MakeDrawLayer(); + DBG_ASSERT(pDrawLayer,"kann Draw-Layer nicht anlegen"); + if ( pDrawLayer && nIndex >= 0 && nIndex < pDocShell->GetDocument()->GetTableCount() ) + { + SdrPage* pPage = pDrawLayer->GetPage((USHORT)nIndex); + DBG_ASSERT(pPage,"Draw-Page nicht gefunden"); + if (pPage) + { + return uno::Reference<drawing::XDrawPage> (pPage->getUnoPage(), uno::UNO_QUERY); + } + } + } + return NULL; +} + +// XDrawPages + +uno::Reference<drawing::XDrawPage> SAL_CALL ScDrawPagesObj::insertNewByIndex( sal_Int32 nPos ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<drawing::XDrawPage> xRet; + if (pDocShell) + { + String aNewName; + pDocShell->GetDocument()->CreateValidTabName(aNewName); + ScDocFunc aFunc(*pDocShell); + if ( aFunc.InsertTable( (SCTAB)nPos, aNewName, TRUE, TRUE ) ) + xRet.set(GetObjectByIndex_Impl( nPos )); + } + return xRet; +} + +void SAL_CALL ScDrawPagesObj::remove( const uno::Reference<drawing::XDrawPage>& xPage ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + SvxDrawPage* pImp = SvxDrawPage::getImplementation( xPage ); + if ( pDocShell && pImp ) + { + SdrPage* pPage = pImp->GetSdrPage(); + if (pPage) + { + SCTAB nPageNum = static_cast<SCTAB>(pPage->GetPageNum()); + ScDocFunc aFunc(*pDocShell); + aFunc.DeleteTable( nPageNum, TRUE, TRUE ); + } + } +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScDrawPagesObj::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + return pDocShell->GetDocument()->GetTableCount(); + return 0; +} + +uno::Any SAL_CALL ScDrawPagesObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<drawing::XDrawPage> xPage(GetObjectByIndex_Impl(nIndex)); + if (xPage.is()) + return uno::makeAny(xPage); + else + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +uno::Type SAL_CALL ScDrawPagesObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((uno::Reference<drawing::XDrawPage>*)0); +} + +sal_Bool SAL_CALL ScDrawPagesObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +//------------------------------------------------------------------------ + +ScTableSheetsObj::ScTableSheetsObj(ScDocShell* pDocSh) : + pDocShell( pDocSh ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScTableSheetsObj::~ScTableSheetsObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScTableSheetsObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + // Referenz-Update interessiert hier nicht + + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +// XSpreadsheets + +ScTableSheetObj* ScTableSheetsObj::GetObjectByIndex_Impl(sal_Int32 nIndex) const +{ + if ( pDocShell && nIndex >= 0 && nIndex < pDocShell->GetDocument()->GetTableCount() ) + return new ScTableSheetObj( pDocShell, static_cast<SCTAB>(nIndex) ); + + return NULL; +} + +ScTableSheetObj* ScTableSheetsObj::GetObjectByName_Impl(const rtl::OUString& aName) const +{ + if (pDocShell) + { + SCTAB nIndex; + String aString(aName); + if ( pDocShell->GetDocument()->GetTable( aString, nIndex ) ) + return new ScTableSheetObj( pDocShell, nIndex ); + } + return NULL; +} + +void SAL_CALL ScTableSheetsObj::insertNewByName( const rtl::OUString& aName, sal_Int16 nPosition ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + BOOL bDone = FALSE; + if (pDocShell) + { + String aNamStr(aName); + ScDocFunc aFunc(*pDocShell); + bDone = aFunc.InsertTable( nPosition, aNamStr, TRUE, TRUE ); + } + if (!bDone) + throw uno::RuntimeException(); // no other exceptions specified +} + +void SAL_CALL ScTableSheetsObj::moveByName( const rtl::OUString& aName, sal_Int16 nDestination ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + BOOL bDone = FALSE; + if (pDocShell) + { + String aNamStr(aName); + SCTAB nSource; + if ( pDocShell->GetDocument()->GetTable( aNamStr, nSource ) ) + bDone = pDocShell->MoveTable( nSource, nDestination, FALSE, TRUE ); + } + if (!bDone) + throw uno::RuntimeException(); // no other exceptions specified +} + +void SAL_CALL ScTableSheetsObj::copyByName( const rtl::OUString& aName, + const rtl::OUString& aCopy, sal_Int16 nDestination ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + BOOL bDone = FALSE; + if (pDocShell) + { + String aNamStr(aName); + String aNewStr(aCopy); + SCTAB nSource; + if ( pDocShell->GetDocument()->GetTable( aNamStr, nSource ) ) + { + bDone = pDocShell->MoveTable( nSource, nDestination, TRUE, TRUE ); + if (bDone) + { + // #i92477# any index past the last sheet means "append" in MoveTable + SCTAB nResultTab = static_cast<SCTAB>(nDestination); + SCTAB nTabCount = pDocShell->GetDocument()->GetTableCount(); // count after copying + if (nResultTab >= nTabCount) + nResultTab = nTabCount - 1; + + ScDocFunc aFunc(*pDocShell); + bDone = aFunc.RenameTable( nResultTab, aNewStr, TRUE, TRUE ); + } + } + } + if (!bDone) + throw uno::RuntimeException(); // no other exceptions specified +} + +void SAL_CALL ScTableSheetsObj::insertByName( const rtl::OUString& aName, const uno::Any& aElement ) + throw(lang::IllegalArgumentException, container::ElementExistException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + BOOL bDone = FALSE; + BOOL bIllArg = FALSE; + + //! Type of aElement can be some specific interface instead of XInterface + + if ( pDocShell ) + { + uno::Reference<uno::XInterface> xInterface(aElement, uno::UNO_QUERY); + if ( xInterface.is() ) + { + ScTableSheetObj* pSheetObj = ScTableSheetObj::getImplementation( xInterface ); + if ( pSheetObj && !pSheetObj->GetDocShell() ) // noch nicht eingefuegt? + { + ScDocument* pDoc = pDocShell->GetDocument(); + String aNamStr(aName); + SCTAB nDummy; + if ( pDoc->GetTable( aNamStr, nDummy ) ) + { + // name already exists + throw container::ElementExistException(); + } + else + { + SCTAB nPosition = pDoc->GetTableCount(); + ScDocFunc aFunc(*pDocShell); + bDone = aFunc.InsertTable( nPosition, aNamStr, TRUE, TRUE ); + if (bDone) + pSheetObj->InitInsertSheet( pDocShell, nPosition ); + // Dokument und neuen Range am Objekt setzen + } + } + else + bIllArg = TRUE; + } + else + bIllArg = TRUE; + } + + if (!bDone) + { + if (bIllArg) + throw lang::IllegalArgumentException(); + else + throw uno::RuntimeException(); // ElementExistException is handled above + } +} + +void SAL_CALL ScTableSheetsObj::replaceByName( const rtl::OUString& aName, const uno::Any& aElement ) + throw(lang::IllegalArgumentException, container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + BOOL bDone = FALSE; + BOOL bIllArg = FALSE; + + //! Type of aElement can be some specific interface instead of XInterface + + if ( pDocShell ) + { + uno::Reference<uno::XInterface> xInterface(aElement, uno::UNO_QUERY); + if ( xInterface.is() ) + { + ScTableSheetObj* pSheetObj = ScTableSheetObj::getImplementation( xInterface ); + if ( pSheetObj && !pSheetObj->GetDocShell() ) // noch nicht eingefuegt? + { + String aNamStr(aName); + SCTAB nPosition; + if ( pDocShell->GetDocument()->GetTable( aNamStr, nPosition ) ) + { + ScDocFunc aFunc(*pDocShell); + if ( aFunc.DeleteTable( nPosition, TRUE, TRUE ) ) + { + // InsertTable kann jetzt eigentlich nicht schiefgehen... + bDone = aFunc.InsertTable( nPosition, aNamStr, TRUE, TRUE ); + if (bDone) + pSheetObj->InitInsertSheet( pDocShell, nPosition ); + } + } + else + { + // not found + throw container::NoSuchElementException(); + } + } + else + bIllArg = TRUE; + } + else + bIllArg = TRUE; + } + + if (!bDone) + { + if (bIllArg) + throw lang::IllegalArgumentException(); + else + throw uno::RuntimeException(); // NoSuchElementException is handled above + } +} + +void SAL_CALL ScTableSheetsObj::removeByName( const rtl::OUString& aName ) + throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + BOOL bDone = FALSE; + if (pDocShell) + { + SCTAB nIndex; + String aString(aName); + if ( pDocShell->GetDocument()->GetTable( aString, nIndex ) ) + { + ScDocFunc aFunc(*pDocShell); + bDone = aFunc.DeleteTable( nIndex, TRUE, TRUE ); + } + else + { + // not found + throw container::NoSuchElementException(); + } + } + + if (!bDone) + throw uno::RuntimeException(); // NoSuchElementException is handled above +} + +// XCellRangesAccess + +uno::Reference< table::XCell > SAL_CALL ScTableSheetsObj::getCellByPosition( sal_Int32 nColumn, sal_Int32 nRow, sal_Int32 nSheet ) + throw (lang::IndexOutOfBoundsException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<table::XCellRange> xSheet(static_cast<ScCellRangeObj*>(GetObjectByIndex_Impl((USHORT)nSheet))); + if (! xSheet.is()) + throw lang::IndexOutOfBoundsException(); + + return xSheet->getCellByPosition(nColumn, nRow); +} + +uno::Reference< table::XCellRange > SAL_CALL ScTableSheetsObj::getCellRangeByPosition( sal_Int32 nLeft, sal_Int32 nTop, sal_Int32 nRight, sal_Int32 nBottom, sal_Int32 nSheet ) + throw (lang::IndexOutOfBoundsException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<table::XCellRange> xSheet(static_cast<ScCellRangeObj*>(GetObjectByIndex_Impl((USHORT)nSheet))); + if (! xSheet.is()) + throw lang::IndexOutOfBoundsException(); + + return xSheet->getCellRangeByPosition(nLeft, nTop, nRight, nBottom); +} + +uno::Sequence < uno::Reference< table::XCellRange > > SAL_CALL ScTableSheetsObj::getCellRangesByName( const rtl::OUString& aRange ) + throw (lang::IllegalArgumentException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Sequence < uno::Reference < table::XCellRange > > xRet; + + ScRangeList aRangeList; + ScDocument* pDoc = pDocShell->GetDocument(); + if (ScRangeStringConverter::GetRangeListFromString( aRangeList, aRange, pDoc, ::formula::FormulaGrammar::CONV_OOO, ';' )) + { + sal_Int32 nCount = aRangeList.Count(); + if (nCount) + { + xRet.realloc(nCount); + for( sal_Int32 nIndex = 0; nIndex < nCount; nIndex++ ) + { + const ScRange* pRange = aRangeList.GetObject( nIndex ); + if( pRange ) + xRet[nIndex] = new ScCellRangeObj(pDocShell, *pRange); + } + } + else + throw lang::IllegalArgumentException(); + } + else + throw lang::IllegalArgumentException(); + return xRet; +} + +// XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScTableSheetsObj::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.SpreadsheetsEnumeration"))); +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScTableSheetsObj::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + return pDocShell->GetDocument()->GetTableCount(); + return 0; +} + +uno::Any SAL_CALL ScTableSheetsObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<sheet::XSpreadsheet> xSheet(GetObjectByIndex_Impl(nIndex)); + if (xSheet.is()) + return uno::makeAny(xSheet); + else + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +uno::Type SAL_CALL ScTableSheetsObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((uno::Reference<sheet::XSpreadsheet>*)0); +} + +sal_Bool SAL_CALL ScTableSheetsObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +// XNameAccess + +uno::Any SAL_CALL ScTableSheetsObj::getByName( const rtl::OUString& aName ) + throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<sheet::XSpreadsheet> xSheet(GetObjectByName_Impl(aName)); + if (xSheet.is()) + return uno::makeAny(xSheet); + else + throw container::NoSuchElementException(); +// return uno::Any(); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScTableSheetsObj::getElementNames() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB nCount = pDoc->GetTableCount(); + String aName; + uno::Sequence<rtl::OUString> aSeq(nCount); + rtl::OUString* pAry = aSeq.getArray(); + for (SCTAB i=0; i<nCount; i++) + { + pDoc->GetName( i, aName ); + pAry[i] = aName; + } + return aSeq; + } + return uno::Sequence<rtl::OUString>(); +} + +sal_Bool SAL_CALL ScTableSheetsObj::hasByName( const rtl::OUString& aName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + SCTAB nIndex; + if ( pDocShell->GetDocument()->GetTable( String(aName), nIndex ) ) + return TRUE; + } + return FALSE; +} + +//------------------------------------------------------------------------ + +ScTableColumnsObj::ScTableColumnsObj(ScDocShell* pDocSh, SCTAB nT, SCCOL nSC, SCCOL nEC) : + pDocShell( pDocSh ), + nTab ( nT ), + nStartCol( nSC ), + nEndCol ( nEC ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScTableColumnsObj::~ScTableColumnsObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScTableColumnsObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( ScUpdateRefHint ) ) + { +// const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint; + + //! Referenz-Update fuer Tab und Start/Ende + } + else if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +// XTableColumns + +ScTableColumnObj* ScTableColumnsObj::GetObjectByIndex_Impl(sal_Int32 nIndex) const +{ + SCCOL nCol = static_cast<SCCOL>(nIndex) + nStartCol; + if ( pDocShell && nCol <= nEndCol ) + return new ScTableColumnObj( pDocShell, nCol, nTab ); + + return NULL; // falscher Index +} + +ScTableColumnObj* ScTableColumnsObj::GetObjectByName_Impl(const rtl::OUString& aName) const +{ + SCCOL nCol = 0; + String aString(aName); + if ( ::AlphaToCol( nCol, aString) ) + if ( pDocShell && nCol >= nStartCol && nCol <= nEndCol ) + return new ScTableColumnObj( pDocShell, nCol, nTab ); + + return NULL; +} + +void SAL_CALL ScTableColumnsObj::insertByIndex( sal_Int32 nPosition, sal_Int32 nCount ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + BOOL bDone = FALSE; + if ( pDocShell && nCount > 0 && nPosition >= 0 && nStartCol+nPosition <= nEndCol && + nStartCol+nPosition+nCount-1 <= MAXCOL ) + { + ScDocFunc aFunc(*pDocShell); + ScRange aRange( (SCCOL)(nStartCol+nPosition), 0, nTab, + (SCCOL)(nStartCol+nPosition+nCount-1), MAXROW, nTab ); + bDone = aFunc.InsertCells( aRange, NULL, INS_INSCOLS, TRUE, TRUE ); + } + if (!bDone) + throw uno::RuntimeException(); // no other exceptions specified +} + +void SAL_CALL ScTableColumnsObj::removeByIndex( sal_Int32 nIndex, sal_Int32 nCount ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + BOOL bDone = FALSE; + // Der zu loeschende Bereich muss innerhalb des Objekts liegen + if ( pDocShell && nCount > 0 && nIndex >= 0 && nStartCol+nIndex+nCount-1 <= nEndCol ) + { + ScDocFunc aFunc(*pDocShell); + ScRange aRange( (SCCOL)(nStartCol+nIndex), 0, nTab, + (SCCOL)(nStartCol+nIndex+nCount-1), MAXROW, nTab ); + bDone = aFunc.DeleteCells( aRange, NULL, DEL_DELCOLS, TRUE, TRUE ); + } + if (!bDone) + throw uno::RuntimeException(); // no other exceptions specified +} + +// XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScTableColumnsObj::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.table.TableColumnsEnumeration"))); +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScTableColumnsObj::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return nEndCol - nStartCol + 1; +} + +uno::Any SAL_CALL ScTableColumnsObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<table::XCellRange> xColumn(GetObjectByIndex_Impl(nIndex)); + if (xColumn.is()) + return uno::makeAny(xColumn); + else + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +uno::Type SAL_CALL ScTableColumnsObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((uno::Reference<table::XCellRange>*)0); +} + +sal_Bool SAL_CALL ScTableColumnsObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +uno::Any SAL_CALL ScTableColumnsObj::getByName( const rtl::OUString& aName ) + throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<table::XCellRange> xColumn(GetObjectByName_Impl(aName)); + if (xColumn.is()) + return uno::makeAny(xColumn); + else + throw container::NoSuchElementException(); +// return uno::Any(); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScTableColumnsObj::getElementNames() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + SCCOL nCount = nEndCol - nStartCol + 1; + uno::Sequence<rtl::OUString> aSeq(nCount); + rtl::OUString* pAry = aSeq.getArray(); + for (SCCOL i=0; i<nCount; i++) + pAry[i] = ::ScColToAlpha( nStartCol + i ); + + return aSeq; +} + +sal_Bool SAL_CALL ScTableColumnsObj::hasByName( const rtl::OUString& aName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + SCCOL nCol = 0; + String aString(aName); + if ( ::AlphaToCol( nCol, aString) ) + if ( pDocShell && nCol >= nStartCol && nCol <= nEndCol ) + return TRUE; + + return FALSE; // nicht gefunden +} + +// XPropertySet + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTableColumnsObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef( + new SfxItemPropertySetInfo( lcl_GetColumnsPropertyMap() )); + return aRef; +} + +void SAL_CALL ScTableColumnsObj::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (!pDocShell) + throw uno::RuntimeException(); + + ScDocFunc aFunc(*pDocShell); + SCCOLROW nColArr[2]; + nColArr[0] = nStartCol; + nColArr[1] = nEndCol; + String aNameString(aPropertyName); + + if ( aNameString.EqualsAscii( SC_UNONAME_CELLWID ) ) + { + sal_Int32 nNewWidth = 0; + if ( aValue >>= nNewWidth ) + aFunc.SetWidthOrHeight( TRUE, 1, nColArr, nTab, SC_SIZE_ORIGINAL, + (USHORT)HMMToTwips(nNewWidth), TRUE, TRUE ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_CELLVIS ) ) + { + BOOL bVis = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + ScSizeMode eMode = bVis ? SC_SIZE_SHOW : SC_SIZE_DIRECT; + aFunc.SetWidthOrHeight( TRUE, 1, nColArr, nTab, eMode, 0, TRUE, TRUE ); + // SC_SIZE_DIRECT with size 0: hide + } + else if ( aNameString.EqualsAscii( SC_UNONAME_OWIDTH ) ) + { + BOOL bOpt = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + if (bOpt) + aFunc.SetWidthOrHeight( TRUE, 1, nColArr, nTab, + SC_SIZE_OPTIMAL, STD_EXTRA_WIDTH, TRUE, TRUE ); + // FALSE for columns currently has no effect + } + else if ( aNameString.EqualsAscii( SC_UNONAME_NEWPAGE ) || aNameString.EqualsAscii( SC_UNONAME_MANPAGE ) ) + { + //! single function to set/remove all breaks? + BOOL bSet = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + for (SCCOL nCol=nStartCol; nCol<=nEndCol; nCol++) + if (bSet) + aFunc.InsertPageBreak( TRUE, ScAddress(nCol,0,nTab), TRUE, TRUE, TRUE ); + else + aFunc.RemovePageBreak( TRUE, ScAddress(nCol,0,nTab), TRUE, TRUE, TRUE ); + } +} + +uno::Any SAL_CALL ScTableColumnsObj::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (!pDocShell) + throw uno::RuntimeException(); + + ScDocument* pDoc = pDocShell->GetDocument(); + String aNameString(aPropertyName); + uno::Any aAny; + + //! loop over all columns for current state? + + if ( aNameString.EqualsAscii( SC_UNONAME_CELLWID ) ) + { + // for hidden column, return original height + USHORT nWidth = pDoc->GetOriginalWidth( nStartCol, nTab ); + aAny <<= (sal_Int32)TwipsToHMM(nWidth); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_CELLVIS ) ) + { + SCCOL nLastCol; + bool bVis = !pDoc->ColHidden(nStartCol, nTab, nLastCol); + ScUnoHelpFunctions::SetBoolInAny( aAny, bVis ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_OWIDTH ) ) + { + BOOL bOpt = !(pDoc->GetColFlags( nStartCol, nTab ) & CR_MANUALSIZE); + ScUnoHelpFunctions::SetBoolInAny( aAny, bOpt ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_NEWPAGE ) ) + { + ScBreakType nBreak = pDoc->HasColBreak(nStartCol, nTab); + ScUnoHelpFunctions::SetBoolInAny( aAny, nBreak ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_MANPAGE ) ) + { + ScBreakType nBreak = pDoc->HasColBreak(nStartCol, nTab); + ScUnoHelpFunctions::SetBoolInAny( aAny, (nBreak & BREAK_MANUAL) ); + } + + return aAny; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScTableColumnsObj ) + +//------------------------------------------------------------------------ + +ScTableRowsObj::ScTableRowsObj(ScDocShell* pDocSh, SCTAB nT, SCROW nSR, SCROW nER) : + pDocShell( pDocSh ), + nTab ( nT ), + nStartRow( nSR ), + nEndRow ( nER ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScTableRowsObj::~ScTableRowsObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScTableRowsObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( ScUpdateRefHint ) ) + { +// const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint; + + //! Referenz-Update fuer Tab und Start/Ende + } + else if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +// XTableRows + +ScTableRowObj* ScTableRowsObj::GetObjectByIndex_Impl(sal_Int32 nIndex) const +{ + SCROW nRow = static_cast<SCROW>(nIndex) + nStartRow; + if ( pDocShell && nRow <= nEndRow ) + return new ScTableRowObj( pDocShell, nRow, nTab ); + + return NULL; // falscher Index +} + +void SAL_CALL ScTableRowsObj::insertByIndex( sal_Int32 nPosition, sal_Int32 nCount ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + BOOL bDone = FALSE; + if ( pDocShell && nCount > 0 && nPosition >= 0 && nStartRow+nPosition <= nEndRow && + nStartRow+nPosition+nCount-1 <= MAXROW ) + { + ScDocFunc aFunc(*pDocShell); + ScRange aRange( 0, (SCROW)(nStartRow+nPosition), nTab, + MAXCOL, (SCROW)(nStartRow+nPosition+nCount-1), nTab ); + bDone = aFunc.InsertCells( aRange, NULL, INS_INSROWS, TRUE, TRUE ); + } + if (!bDone) + throw uno::RuntimeException(); // no other exceptions specified +} + +void SAL_CALL ScTableRowsObj::removeByIndex( sal_Int32 nIndex, sal_Int32 nCount ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + BOOL bDone = FALSE; + // Der zu loeschende Bereich muss innerhalb des Objekts liegen + if ( pDocShell && nCount > 0 && nIndex >= 0 && nStartRow+nIndex+nCount-1 <= nEndRow ) + { + ScDocFunc aFunc(*pDocShell); + ScRange aRange( 0, (SCROW)(nStartRow+nIndex), nTab, + MAXCOL, (SCROW)(nStartRow+nIndex+nCount-1), nTab ); + bDone = aFunc.DeleteCells( aRange, NULL, DEL_DELROWS, TRUE, TRUE ); + } + if (!bDone) + throw uno::RuntimeException(); // no other exceptions specified +} + +// XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScTableRowsObj::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.table.TableRowsEnumeration"))); +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScTableRowsObj::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return nEndRow - nStartRow + 1; +} + +uno::Any SAL_CALL ScTableRowsObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<table::XCellRange> xRow(GetObjectByIndex_Impl(nIndex)); + if (xRow.is()) + return uno::makeAny(xRow); + else + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +uno::Type SAL_CALL ScTableRowsObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((uno::Reference<table::XCellRange>*)0); +} + +sal_Bool SAL_CALL ScTableRowsObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +// XPropertySet + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTableRowsObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef( + new SfxItemPropertySetInfo( lcl_GetRowsPropertyMap() )); + return aRef; +} + +void SAL_CALL ScTableRowsObj::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (!pDocShell) + throw uno::RuntimeException(); + + ScDocFunc aFunc(*pDocShell); + ScDocument* pDoc = pDocShell->GetDocument(); + SCCOLROW nRowArr[2]; + nRowArr[0] = nStartRow; + nRowArr[1] = nEndRow; + String aNameString(aPropertyName); + + if ( aNameString.EqualsAscii( SC_UNONAME_OHEIGHT ) ) + { + sal_Int32 nNewHeight = 0; + if ( pDoc->IsImportingXML() && ( aValue >>= nNewHeight ) ) + { + // used to set the stored row height for rows with optimal height when loading. + + // TODO: It's probably cleaner to use a different property name + // for this. + pDoc->SetRowHeightOnly( nStartRow, nEndRow, nTab, (USHORT)HMMToTwips(nNewHeight) ); + } + else + { + BOOL bOpt = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + if (bOpt) + aFunc.SetWidthOrHeight( FALSE, 1, nRowArr, nTab, SC_SIZE_OPTIMAL, 0, TRUE, TRUE ); + else + { + //! manually set old heights again? + } + } + } + else if ( aNameString.EqualsAscii( SC_UNONAME_CELLHGT ) ) + { + sal_Int32 nNewHeight = 0; + if ( aValue >>= nNewHeight ) + aFunc.SetWidthOrHeight( FALSE, 1, nRowArr, nTab, SC_SIZE_ORIGINAL, + (USHORT)HMMToTwips(nNewHeight), TRUE, TRUE ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_CELLVIS ) ) + { + BOOL bVis = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + ScSizeMode eMode = bVis ? SC_SIZE_SHOW : SC_SIZE_DIRECT; + aFunc.SetWidthOrHeight( FALSE, 1, nRowArr, nTab, eMode, 0, TRUE, TRUE ); + // SC_SIZE_DIRECT with size 0: hide + } + else if ( aNameString.EqualsAscii( SC_UNONAME_CELLFILT ) ) + { + //! undo etc. + if (ScUnoHelpFunctions::GetBoolFromAny( aValue )) + pDoc->SetRowFiltered(nStartRow, nEndRow, nTab, true); + else + pDoc->SetRowFiltered(nStartRow, nEndRow, nTab, false); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_NEWPAGE) || aNameString.EqualsAscii( SC_UNONAME_MANPAGE) ) + { + //! single function to set/remove all breaks? + BOOL bSet = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + for (SCROW nRow=nStartRow; nRow<=nEndRow; nRow++) + if (bSet) + aFunc.InsertPageBreak( FALSE, ScAddress(0,nRow,nTab), TRUE, TRUE, TRUE ); + else + aFunc.RemovePageBreak( FALSE, ScAddress(0,nRow,nTab), TRUE, TRUE, TRUE ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_CELLBACK ) || aNameString.EqualsAscii( SC_UNONAME_CELLTRAN ) ) + { + // #i57867# Background color is specified for row styles in the file format, + // so it has to be supported along with the row properties (import only). + + // Use ScCellRangeObj to set the property for all cells in the rows + // (this means, the "row attribute" must be set before individual cell attributes). + + ScRange aRange( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab ); + uno::Reference<beans::XPropertySet> xRangeObj = new ScCellRangeObj( pDocShell, aRange ); + xRangeObj->setPropertyValue( aPropertyName, aValue ); + } +} + +uno::Any SAL_CALL ScTableRowsObj::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (!pDocShell) + throw uno::RuntimeException(); + + ScDocument* pDoc = pDocShell->GetDocument(); + String aNameString(aPropertyName); + uno::Any aAny; + + //! loop over all rows for current state? + + if ( aNameString.EqualsAscii( SC_UNONAME_CELLHGT ) ) + { + // for hidden row, return original height + USHORT nHeight = pDoc->GetOriginalHeight( nStartRow, nTab ); + aAny <<= (sal_Int32)TwipsToHMM(nHeight); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_CELLVIS ) ) + { + SCROW nLastRow; + bool bVis = !pDoc->RowHidden(nStartRow, nTab, nLastRow); + ScUnoHelpFunctions::SetBoolInAny( aAny, bVis ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_CELLFILT ) ) + { + bool bVis = pDoc->RowFiltered(nStartRow, nTab); + ScUnoHelpFunctions::SetBoolInAny( aAny, bVis ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_OHEIGHT ) ) + { + BOOL bOpt = !(pDoc->GetRowFlags( nStartRow, nTab ) & CR_MANUALSIZE); + ScUnoHelpFunctions::SetBoolInAny( aAny, bOpt ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_NEWPAGE ) ) + { + ScBreakType nBreak = pDoc->HasRowBreak(nStartRow, nTab); + ScUnoHelpFunctions::SetBoolInAny( aAny, nBreak ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_MANPAGE ) ) + { + ScBreakType nBreak = pDoc->HasRowBreak(nStartRow, nTab); + ScUnoHelpFunctions::SetBoolInAny( aAny, (nBreak & BREAK_MANUAL) ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_CELLBACK ) || aNameString.EqualsAscii( SC_UNONAME_CELLTRAN ) ) + { + // Use ScCellRangeObj to get the property from the cell range + // (for completeness only, this is not used by the XML filter). + + ScRange aRange( 0, nStartRow, nTab, MAXCOL, nEndRow, nTab ); + uno::Reference<beans::XPropertySet> xRangeObj = new ScCellRangeObj( pDocShell, aRange ); + aAny = xRangeObj->getPropertyValue( aPropertyName ); + } + + return aAny; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScTableRowsObj ) + +//------------------------------------------------------------------------ + +//UNUSED2008-05 ScSpreadsheetSettingsObj::ScSpreadsheetSettingsObj(ScDocShell* pDocSh) : +//UNUSED2008-05 pDocShell( pDocSh ) +//UNUSED2008-05 { +//UNUSED2008-05 pDocShell->GetDocument()->AddUnoObject(*this); +//UNUSED2008-05 } + +ScSpreadsheetSettingsObj::~ScSpreadsheetSettingsObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScSpreadsheetSettingsObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + // Referenz-Update interessiert hier nicht + + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +// XPropertySet + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScSpreadsheetSettingsObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + //! muss noch + return NULL; +} + +void SAL_CALL ScSpreadsheetSettingsObj::setPropertyValue( + const rtl::OUString& /* aPropertyName */, const uno::Any& /* aValue */ ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + //! muss noch +} + +uno::Any SAL_CALL ScSpreadsheetSettingsObj::getPropertyValue( const rtl::OUString& /* aPropertyName */ ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + //! muss noch + return uno::Any(); +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScSpreadsheetSettingsObj ) + +//------------------------------------------------------------------------ + +ScAnnotationsObj::ScAnnotationsObj(ScDocShell* pDocSh, SCTAB nT) : + pDocShell( pDocSh ), + nTab( nT ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScAnnotationsObj::~ScAnnotationsObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScAnnotationsObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + //! nTab bei Referenz-Update anpassen!!! + + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +bool ScAnnotationsObj::GetAddressByIndex_Impl( sal_Int32 nIndex, ScAddress& rPos ) const +{ + if (pDocShell) + { + sal_Int32 nFound = 0; + ScDocument* pDoc = pDocShell->GetDocument(); + ScCellIterator aCellIter( pDoc, 0,0, nTab, MAXCOL,MAXROW, nTab ); + for( ScBaseCell* pCell = aCellIter.GetFirst(); pCell; pCell = aCellIter.GetNext() ) + { + if (pCell->HasNote()) + { + if (nFound == nIndex) + { + rPos = ScAddress( aCellIter.GetCol(), aCellIter.GetRow(), aCellIter.GetTab() ); + return true; + } + ++nFound; + } + } + } + return false; +} + +ScAnnotationObj* ScAnnotationsObj::GetObjectByIndex_Impl( sal_Int32 nIndex ) const +{ + if (pDocShell) + { + ScAddress aPos; + if ( GetAddressByIndex_Impl( nIndex, aPos ) ) + return new ScAnnotationObj( pDocShell, aPos ); + } + return NULL; +} + +// XSheetAnnotations + +void SAL_CALL ScAnnotationsObj::insertNew( + const table::CellAddress& aPosition, const ::rtl::OUString& rText ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + DBG_ASSERT( aPosition.Sheet == nTab, "addAnnotation mit falschem Sheet" ); + ScAddress aPos( (SCCOL)aPosition.Column, (SCROW)aPosition.Row, nTab ); + + ScDocFunc aFunc( *pDocShell ); + aFunc.ReplaceNote( aPos, rText, 0, 0, TRUE ); + } +} + +void SAL_CALL ScAnnotationsObj::removeByIndex( sal_Int32 nIndex ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + ScAddress aPos; + if ( GetAddressByIndex_Impl( nIndex, aPos ) ) + { + ScMarkData aMarkData; + aMarkData.SelectTable( aPos.Tab(), TRUE ); + aMarkData.SetMultiMarkArea( ScRange(aPos) ); + + ScDocFunc aFunc(*pDocShell); + aFunc.DeleteContents( aMarkData, IDF_NOTE, TRUE, TRUE ); + } + } +} + +// XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScAnnotationsObj::createEnumeration() + throw(uno::RuntimeException) +{ + //! iterate directly (more efficiently)? + + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.CellAnnotationsEnumeration"))); +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScAnnotationsObj::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ULONG nCount = 0; + if (pDocShell) + { + ScCellIterator aCellIter( pDocShell->GetDocument(), 0,0, nTab, MAXCOL,MAXROW, nTab ); + for( ScBaseCell* pCell = aCellIter.GetFirst(); pCell; pCell = aCellIter.GetNext() ) + if (pCell->HasNote()) + ++nCount; + } + return nCount; +} + +uno::Any SAL_CALL ScAnnotationsObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<sheet::XSheetAnnotation> xAnnotation(GetObjectByIndex_Impl(nIndex)); + if (xAnnotation.is()) + return uno::makeAny(xAnnotation); + else + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +uno::Type SAL_CALL ScAnnotationsObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((uno::Reference<sheet::XSheetAnnotation>*)0); +} + +sal_Bool SAL_CALL ScAnnotationsObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +//------------------------------------------------------------------------ + +ScScenariosObj::ScScenariosObj(ScDocShell* pDocSh, SCTAB nT) : + pDocShell( pDocSh ), + nTab ( nT ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScScenariosObj::~ScScenariosObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScScenariosObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( ScUpdateRefHint ) ) + { +// const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint; + + //! Referenz-Update fuer Tab und Start/Ende + } + else if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +// XScenarios + +BOOL ScScenariosObj::GetScenarioIndex_Impl( const rtl::OUString& rName, SCTAB& rIndex ) +{ + //! Case-insensitiv ???? + + if ( pDocShell ) + { + String aString(rName); + + String aTabName; + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB nCount = (SCTAB)getCount(); + for (SCTAB i=0; i<nCount; i++) + if (pDoc->GetName( nTab+i+1, aTabName )) + if ( aTabName == aString ) + { + rIndex = i; + return TRUE; + } + } + + return FALSE; +} + +ScTableSheetObj* ScScenariosObj::GetObjectByIndex_Impl(sal_Int32 nIndex) +{ + USHORT nCount = (USHORT)getCount(); + if ( pDocShell && nIndex >= 0 && nIndex < nCount ) + return new ScTableSheetObj( pDocShell, nTab+static_cast<SCTAB>(nIndex)+1 ); + + return NULL; // kein Dokument oder falscher Index +} + +ScTableSheetObj* ScScenariosObj::GetObjectByName_Impl(const rtl::OUString& aName) +{ + SCTAB nIndex; + if ( pDocShell && GetScenarioIndex_Impl( aName, nIndex ) ) + return new ScTableSheetObj( pDocShell, nTab+nIndex+1 ); + + return NULL; // nicht gefunden +} + +void SAL_CALL ScScenariosObj::addNewByName( const rtl::OUString& aName, + const uno::Sequence<table::CellRangeAddress>& aRanges, + const rtl::OUString& aComment ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( pDocShell ) + { + ScMarkData aMarkData; + aMarkData.SelectTable( nTab, TRUE ); + + USHORT nRangeCount = (USHORT)aRanges.getLength(); + if (nRangeCount) + { + const table::CellRangeAddress* pAry = aRanges.getConstArray(); + for (USHORT i=0; i<nRangeCount; i++) + { + DBG_ASSERT( pAry[i].Sheet == nTab, "addScenario mit falscher Tab" ); + ScRange aRange( (SCCOL)pAry[i].StartColumn, (SCROW)pAry[i].StartRow, nTab, + (SCCOL)pAry[i].EndColumn, (SCROW)pAry[i].EndRow, nTab ); + + aMarkData.SetMultiMarkArea( aRange ); + } + } + + String aNameStr(aName); + String aCommStr(aComment); + + Color aColor( COL_LIGHTGRAY ); // Default + USHORT nFlags = SC_SCENARIO_SHOWFRAME | SC_SCENARIO_PRINTFRAME | SC_SCENARIO_TWOWAY | SC_SCENARIO_PROTECT; + + pDocShell->MakeScenario( nTab, aNameStr, aCommStr, aColor, nFlags, aMarkData ); + } +} + +void SAL_CALL ScScenariosObj::removeByName( const rtl::OUString& aName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + SCTAB nIndex; + if ( pDocShell && GetScenarioIndex_Impl( aName, nIndex ) ) + { + ScDocFunc aFunc(*pDocShell); + aFunc.DeleteTable( nTab+nIndex+1, TRUE, TRUE ); + } +} + +// XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScScenariosObj::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.ScenariosEnumeration"))); +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScScenariosObj::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + SCTAB nCount = 0; + if ( pDocShell ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + if (!pDoc->IsScenario(nTab)) + { + SCTAB nTabCount = pDoc->GetTableCount(); + SCTAB nNext = nTab + 1; + while (nNext < nTabCount && pDoc->IsScenario(nNext)) + { + ++nCount; + ++nNext; + } + } + } + return nCount; +} + +uno::Any SAL_CALL ScScenariosObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<sheet::XScenario> xScen(GetObjectByIndex_Impl(nIndex)); + if (xScen.is()) + return uno::makeAny(xScen); + else + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +uno::Type SAL_CALL ScScenariosObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((uno::Reference<sheet::XScenario>*)0); +} + +sal_Bool SAL_CALL ScScenariosObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +uno::Any SAL_CALL ScScenariosObj::getByName( const rtl::OUString& aName ) + throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<sheet::XScenario> xScen(GetObjectByName_Impl(aName)); + if (xScen.is()) + return uno::makeAny(xScen); + else + throw container::NoSuchElementException(); +// return uno::Any(); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScScenariosObj::getElementNames() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + SCTAB nCount = (SCTAB)getCount(); + uno::Sequence<rtl::OUString> aSeq(nCount); + + if ( pDocShell ) // sonst ist auch Count = 0 + { + String aTabName; + ScDocument* pDoc = pDocShell->GetDocument(); + rtl::OUString* pAry = aSeq.getArray(); + for (SCTAB i=0; i<nCount; i++) + if (pDoc->GetName( nTab+i+1, aTabName )) + pAry[i] = aTabName; + } + + return aSeq; +} + +sal_Bool SAL_CALL ScScenariosObj::hasByName( const rtl::OUString& aName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + SCTAB nIndex; + return GetScenarioIndex_Impl( aName, nIndex ); +} + + + + + diff --git a/sc/source/ui/unoobj/drdefuno.cxx b/sc/source/ui/unoobj/drdefuno.cxx new file mode 100644 index 000000000000..52fce55dfc58 --- /dev/null +++ b/sc/source/ui/unoobj/drdefuno.cxx @@ -0,0 +1,83 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include "drdefuno.hxx" +#include "docsh.hxx" +#include "drwlayer.hxx" + +using namespace ::com::sun::star; + +//------------------------------------------------------------------------ + +ScDrawDefaultsObj::ScDrawDefaultsObj(ScDocShell* pDocSh) : + SvxUnoDrawPool( NULL ), + pDocShell( pDocSh ) +{ + // SvxUnoDrawPool is initialized without model, + // draw layer is created on demand in getModelPool + + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScDrawDefaultsObj::~ScDrawDefaultsObj() throw () +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScDrawDefaultsObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // document gone + } +} + +SfxItemPool* ScDrawDefaultsObj::getModelPool( sal_Bool bReadOnly ) throw() +{ + SfxItemPool* pRet = NULL; + if ( pDocShell ) + { + ScDrawLayer* pModel = bReadOnly ? + pDocShell->GetDocument()->GetDrawLayer() : + pDocShell->MakeDrawLayer(); + if ( pModel ) + pRet = &pModel->GetItemPool(); + } + if ( !pRet ) + pRet = SvxUnoDrawPool::getModelPool( bReadOnly ); // uses default pool + + return pRet; +} + + diff --git a/sc/source/ui/unoobj/editsrc.cxx b/sc/source/ui/unoobj/editsrc.cxx new file mode 100644 index 000000000000..7febe374d0d9 --- /dev/null +++ b/sc/source/ui/unoobj/editsrc.cxx @@ -0,0 +1,373 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +#include "editsrc.hxx" + +#include "scitems.hxx" +#include <editeng/eeitem.hxx> +#include <editeng/unofored.hxx> +#include <svx/svdpage.hxx> +#include <svx/svditer.hxx> +#include <svx/svdocapt.hxx> +#include <editeng/outlobj.hxx> +#include <editeng/editobj.hxx> +#include <editeng/outliner.hxx> +#include "textuno.hxx" +#include "editutil.hxx" +#include "docsh.hxx" +#include "docfunc.hxx" +#include "hints.hxx" +#include "patattr.hxx" +#include "unoguard.hxx" +#include "drwlayer.hxx" +#include "userdat.hxx" +#include "postit.hxx" +#include "AccessibleText.hxx" + +//------------------------------------------------------------------------ + +TYPEINIT1( ScHeaderFooterChangedHint, SfxHint ); + +ScHeaderFooterChangedHint::ScHeaderFooterChangedHint(USHORT nP) : + nPart( nP ) +{ +} + +ScHeaderFooterChangedHint::~ScHeaderFooterChangedHint() +{ +} + +//------------------------------------------------------------------------ + +ScSharedHeaderFooterEditSource::ScSharedHeaderFooterEditSource( ScHeaderFooterTextData* pData ) : + pTextData( pData ) +{ + // pTextData is held by the ScHeaderFooterTextObj. + // Text range and cursor keep a reference to their parent text, so the text object is + // always alive and the TextData is valid as long as there are children. +} + +ScSharedHeaderFooterEditSource::~ScSharedHeaderFooterEditSource() +{ +} + +SvxEditSource* ScSharedHeaderFooterEditSource::Clone() const +{ + return new ScSharedHeaderFooterEditSource( pTextData ); +} + +SvxTextForwarder* ScSharedHeaderFooterEditSource::GetTextForwarder() +{ + return pTextData->GetTextForwarder(); +} + +void ScSharedHeaderFooterEditSource::UpdateData() +{ + pTextData->UpdateData(); +} + +ScEditEngineDefaulter* ScSharedHeaderFooterEditSource::GetEditEngine() +{ + return pTextData->GetEditEngine(); +} + +//------------------------------------------------------------------------ + +// each ScHeaderFooterEditSource object has its own ScHeaderFooterTextData + +ScHeaderFooterEditSource::ScHeaderFooterEditSource( ScHeaderFooterContentObj* pContent, + USHORT nP ) : + ScSharedHeaderFooterEditSource( new ScHeaderFooterTextData( *pContent, nP ) ) +{ +} + +ScHeaderFooterEditSource::ScHeaderFooterEditSource( ScHeaderFooterContentObj& rContent, + USHORT nP ) : + ScSharedHeaderFooterEditSource( new ScHeaderFooterTextData( rContent, nP ) ) +{ +} + +ScHeaderFooterEditSource::~ScHeaderFooterEditSource() +{ + delete GetTextData(); // not accessed in ScSharedHeaderFooterEditSource dtor +} + +SvxEditSource* ScHeaderFooterEditSource::Clone() const +{ + const ScHeaderFooterTextData* pData = GetTextData(); + return new ScHeaderFooterEditSource( pData->GetContentObj(), pData->GetPart() ); +} + +//------------------------------------------------------------------------ + +ScSharedCellEditSource::ScSharedCellEditSource( ScCellTextData* pData ) : + pCellTextData( pData ) +{ + // pCellTextData is part of the ScCellTextObj. + // Text range and cursor keep a reference to their parent text, so the text object is + // always alive and the CellTextData is valid as long as there are children. +} + +ScSharedCellEditSource::~ScSharedCellEditSource() +{ +} + +SvxEditSource* ScSharedCellEditSource::Clone() const +{ + return new ScSharedCellEditSource( pCellTextData ); +} + +SvxTextForwarder* ScSharedCellEditSource::GetTextForwarder() +{ + return pCellTextData->GetTextForwarder(); +} + +void ScSharedCellEditSource::UpdateData() +{ + pCellTextData->UpdateData(); +} + +void ScSharedCellEditSource::SetDoUpdateData(sal_Bool bValue) +{ + pCellTextData->SetDoUpdate(bValue); +} + +sal_Bool ScSharedCellEditSource::IsDirty() const +{ + return pCellTextData->IsDirty(); +} + +ScEditEngineDefaulter* ScSharedCellEditSource::GetEditEngine() +{ + return pCellTextData->GetEditEngine(); +} + +//------------------------------------------------------------------------ + +// each ScCellEditSource object has its own ScCellTextData + +ScCellEditSource::ScCellEditSource( ScDocShell* pDocSh, const ScAddress& rP ) : + ScSharedCellEditSource( new ScCellTextData( pDocSh, rP ) ) +{ +} + +ScCellEditSource::~ScCellEditSource() +{ + delete GetCellTextData(); // not accessed in ScSharedCellEditSource dtor +} + +SvxEditSource* ScCellEditSource::Clone() const +{ + const ScCellTextData* pData = GetCellTextData(); + return new ScCellEditSource( pData->GetDocShell(), pData->GetCellPos() ); +} + +//------------------------------------------------------------------------ + +ScAnnotationEditSource::ScAnnotationEditSource(ScDocShell* pDocSh, const ScAddress& rP) : + pDocShell( pDocSh ), + aCellPos( rP ), + pEditEngine( NULL ), + pForwarder( NULL ), + bDataValid( FALSE ) +{ + if (pDocShell) + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScAnnotationEditSource::~ScAnnotationEditSource() +{ + ScUnoGuard aGuard; // needed for EditEngine dtor + + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); + + delete pForwarder; + delete pEditEngine; +} + +SvxEditSource* ScAnnotationEditSource::Clone() const +{ + return new ScAnnotationEditSource( pDocShell, aCellPos ); +} + +SdrObject* ScAnnotationEditSource::GetCaptionObj() +{ + ScPostIt* pNote = pDocShell->GetDocument()->GetNote( aCellPos ); + return pNote ? pNote->GetOrCreateCaption( aCellPos ) : 0; +} + +SvxTextForwarder* ScAnnotationEditSource::GetTextForwarder() +{ + if (!pEditEngine) + { + // Notizen haben keine Felder + if ( pDocShell ) + { + pEditEngine = new ScNoteEditEngine( pDocShell->GetDocument()->GetNoteEngine() ); + } + else + { + SfxItemPool* pEnginePool = EditEngine::CreatePool(); + pEnginePool->FreezeIdRanges(); + pEditEngine = new ScEditEngineDefaulter( pEnginePool, TRUE ); + } + pForwarder = new SvxEditEngineForwarder(*pEditEngine); + } + + if (bDataValid) + return pForwarder; + + if ( pDocShell ) + if ( ScPostIt* pNote = pDocShell->GetDocument()->GetNote( aCellPos ) ) + if ( const EditTextObject* pEditObj = pNote->GetEditTextObject() ) + pEditEngine->SetText( *pEditObj ); // incl. Umbrueche + + bDataValid = TRUE; + return pForwarder; +} + +void ScAnnotationEditSource::UpdateData() +{ + if ( pDocShell && pEditEngine ) + { + ScDocShellModificator aModificator( *pDocShell ); + + if( SdrObject* pObj = GetCaptionObj() ) + { + EditTextObject* pEditObj = pEditEngine->CreateTextObject(); + OutlinerParaObject* pOPO = new OutlinerParaObject( *pEditObj ); + delete pEditObj; + pOPO->SetOutlinerMode( OUTLINERMODE_TEXTOBJECT ); + pObj->NbcSetOutlinerParaObject( pOPO ); + pObj->ActionChanged(); + } + + //! Undo !!! + + aModificator.SetDocumentModified(); + + // bDataValid wird bei SetDocumentModified zurueckgesetzt + } +} + +void ScAnnotationEditSource::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( ScUpdateRefHint ) ) + { +// const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint; + + //! Ref-Update + } + else if ( rHint.ISA( SfxSimpleHint ) ) + { + ULONG nId = ((const SfxSimpleHint&)rHint).GetId(); + if ( nId == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + + DELETEZ( pForwarder ); + DELETEZ( pEditEngine ); // EditEngine uses document's pool + } + else if ( nId == SFX_HINT_DATACHANGED ) + bDataValid = FALSE; // Text muss neu geholt werden + } +} + +//------------------------------------------------------------------------ + +ScSimpleEditSource::ScSimpleEditSource( SvxTextForwarder* pForw ) : + pForwarder( pForw ) +{ + // The same forwarder (and EditEngine) is shared by all children of the same Text object. + // Text range and cursor keep a reference to their parent text, so the text object is + // always alive and the forwarder is valid as long as there are children. +} + +ScSimpleEditSource::~ScSimpleEditSource() +{ +} + +SvxEditSource* ScSimpleEditSource::Clone() const +{ + return new ScSimpleEditSource( pForwarder ); +} + +SvxTextForwarder* ScSimpleEditSource::GetTextForwarder() +{ + return pForwarder; +} + +void ScSimpleEditSource::UpdateData() +{ + // nothing +} + +//------------------------------------------------------------------------ + +ScAccessibilityEditSource::ScAccessibilityEditSource( ::std::auto_ptr < ScAccessibleTextData > pAccessibleCellTextData ) + : mpAccessibleTextData(pAccessibleCellTextData) +{ +} + +ScAccessibilityEditSource::~ScAccessibilityEditSource() +{ +} + +SvxEditSource* ScAccessibilityEditSource::Clone() const +{ + return new ScAccessibilityEditSource(::std::auto_ptr < ScAccessibleTextData > (mpAccessibleTextData->Clone())); +} + +SvxTextForwarder* ScAccessibilityEditSource::GetTextForwarder() +{ + return mpAccessibleTextData->GetTextForwarder(); +} + +SvxViewForwarder* ScAccessibilityEditSource::GetViewForwarder() +{ + return mpAccessibleTextData->GetViewForwarder(); +} + +SvxEditViewForwarder* ScAccessibilityEditSource::GetEditViewForwarder( sal_Bool bCreate ) +{ + return mpAccessibleTextData->GetEditViewForwarder(bCreate); +} + +void ScAccessibilityEditSource::UpdateData() +{ + mpAccessibleTextData->UpdateData(); +} + +SfxBroadcaster& ScAccessibilityEditSource::GetBroadcaster() const +{ + return mpAccessibleTextData->GetBroadcaster(); +} + diff --git a/sc/source/ui/unoobj/eventuno.cxx b/sc/source/ui/unoobj/eventuno.cxx new file mode 100755 index 000000000000..d7de00f4cc56 --- /dev/null +++ b/sc/source/ui/unoobj/eventuno.cxx @@ -0,0 +1,201 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2008 by Sun Microsystems, Inc. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * $RCSfile: tokenuno.cxx,v $ + * $Revision: 1.6.108.8 $ + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +#include "eventuno.hxx" +#include "miscuno.hxx" +#include "unoguard.hxx" +#include "docsh.hxx" +#include "sheetevents.hxx" +#include "unonames.hxx" + +using namespace ::com::sun::star; + +//------------------------------------------------------------------------ + +SC_SIMPLE_SERVICE_INFO( ScSheetEventsObj, "ScSheetEventsObj", "com.sun.star.document.Events" ) + +//------------------------------------------------------------------------ + +ScSheetEventsObj::ScSheetEventsObj(ScDocShell* pDocSh, SCTAB nT) : + mpDocShell( pDocSh ), + mnTab( nT ) +{ + mpDocShell->GetDocument()->AddUnoObject(*this); +} + +ScSheetEventsObj::~ScSheetEventsObj() +{ + if (mpDocShell) + mpDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScSheetEventsObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + //! reference update + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + mpDocShell = NULL; + } +} + +sal_Int32 lcl_GetEventFromName( const rtl::OUString& aName ) +{ + for (sal_Int32 nEvent=0; nEvent<SC_SHEETEVENT_COUNT; ++nEvent) + if ( aName == ScSheetEvents::GetEventName(nEvent) ) + return nEvent; + + return -1; // not found +} + +// XNameReplace + +void SAL_CALL ScSheetEventsObj::replaceByName( const rtl::OUString& aName, const uno::Any& aElement ) + throw(lang::IllegalArgumentException, container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (!mpDocShell) + throw uno::RuntimeException(); + + sal_Int32 nEvent = lcl_GetEventFromName(aName); + if (nEvent < 0) + throw container::NoSuchElementException(); + + ScSheetEvents aNewEvents; + const ScSheetEvents* pOldEvents = mpDocShell->GetDocument()->GetSheetEvents(mnTab); + if (pOldEvents) + aNewEvents = *pOldEvents; + + rtl::OUString aScript; + if ( aElement.hasValue() ) // empty Any -> reset event + { + uno::Sequence<beans::PropertyValue> aPropSeq; + if ( aElement >>= aPropSeq ) + { + sal_Int32 nPropCount = aPropSeq.getLength(); + for (sal_Int32 nPos=0; nPos<nPropCount; ++nPos) + { + const beans::PropertyValue& rProp = aPropSeq[nPos]; + if ( rProp.Name.compareToAscii( SC_UNO_EVENTTYPE ) == 0 ) + { + rtl::OUString aEventType; + if ( rProp.Value >>= aEventType ) + { + // only "Script" is supported + if ( aEventType.compareToAscii( SC_UNO_SCRIPT ) != 0 ) + throw lang::IllegalArgumentException(); + } + } + else if ( rProp.Name.compareToAscii( SC_UNO_SCRIPT ) == 0 ) + rProp.Value >>= aScript; + } + } + } + if (aScript.getLength()) + aNewEvents.SetScript( nEvent, &aScript ); + else + aNewEvents.SetScript( nEvent, NULL ); // reset + + mpDocShell->GetDocument()->SetSheetEvents( mnTab, &aNewEvents ); + mpDocShell->SetDocumentModified(); +} + +// XNameAccess + +uno::Any SAL_CALL ScSheetEventsObj::getByName( const rtl::OUString& aName ) + throw(container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + sal_Int32 nEvent = lcl_GetEventFromName(aName); + if (nEvent < 0) + throw container::NoSuchElementException(); + + const rtl::OUString* pScript = NULL; + if (mpDocShell) + { + const ScSheetEvents* pEvents = mpDocShell->GetDocument()->GetSheetEvents(mnTab); + if (pEvents) + pScript = pEvents->GetScript(nEvent); + } + + uno::Any aRet; + if (pScript) + { + uno::Sequence<beans::PropertyValue> aPropSeq( 2 ); + aPropSeq[0] = beans::PropertyValue( + rtl::OUString::createFromAscii("EventType"), -1, + uno::makeAny( rtl::OUString::createFromAscii("Script") ), beans::PropertyState_DIRECT_VALUE ); + aPropSeq[1] = beans::PropertyValue( + rtl::OUString::createFromAscii("Script"), -1, + uno::makeAny( *pScript ), beans::PropertyState_DIRECT_VALUE ); + aRet <<= aPropSeq; + } + // empty Any if nothing was set + return aRet; +} + +uno::Sequence<rtl::OUString> SAL_CALL ScSheetEventsObj::getElementNames() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Sequence<rtl::OUString> aNames(SC_SHEETEVENT_COUNT); + for (sal_Int32 nEvent=0; nEvent<SC_SHEETEVENT_COUNT; ++nEvent) + aNames[nEvent] = ScSheetEvents::GetEventName(nEvent); + return aNames; +} + +sal_Bool SAL_CALL ScSheetEventsObj::hasByName( const ::rtl::OUString& aName ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + sal_Int32 nEvent = lcl_GetEventFromName(aName); + return (nEvent >= 0); +} + +// XElementAccess + +uno::Type SAL_CALL ScSheetEventsObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((uno::Sequence<beans::PropertyValue>*)0); +} + +sal_Bool SAL_CALL ScSheetEventsObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (mpDocShell) + return sal_True; + return sal_False; +} + + + diff --git a/sc/source/ui/unoobj/fielduno.cxx b/sc/source/ui/unoobj/fielduno.cxx new file mode 100644 index 000000000000..8e3e39d07ef4 --- /dev/null +++ b/sc/source/ui/unoobj/fielduno.cxx @@ -0,0 +1,1549 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" +#include <svl/smplhint.hxx> + + +#include <editeng/eeitem.hxx> + +#include <editeng/editeng.hxx> +#include <editeng/editobj.hxx> +#include <editeng/flditem.hxx> +#include <rtl/uuid.h> + +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/text/TextContentAnchorType.hpp> +#include <com/sun/star/text/WrapTextMode.hpp> +#include <com/sun/star/text/FilenameDisplayFormat.hpp> + +#include "fielduno.hxx" +#include "textuno.hxx" +#include "miscuno.hxx" +#include "docsh.hxx" +#include "hints.hxx" +#include "editsrc.hxx" +#include "cellsuno.hxx" +#include "servuno.hxx" // fuer IDs +#include "unoguard.hxx" +#include "unonames.hxx" +#include "editutil.hxx" + +using namespace com::sun::star; + +//------------------------------------------------------------------------ + +// alles ohne Which-ID, Map nur fuer PropertySetInfo + +const SfxItemPropertySet* lcl_GetURLPropertySet() +{ + static SfxItemPropertyMapEntry aURLPropertyMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_ANCTYPE), 0, &getCppuType((text::TextContentAnchorType*)0), beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_ANCTYPES), 0, &getCppuType((uno::Sequence<text::TextContentAnchorType>*)0), beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_REPR), 0, &getCppuType((rtl::OUString*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_TARGET), 0, &getCppuType((rtl::OUString*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_TEXTWRAP), 0, &getCppuType((text::WrapTextMode*)0), beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_URL), 0, &getCppuType((rtl::OUString*)0), 0, 0}, + {0,0,0,0,0,0} + }; + static SfxItemPropertySet aURLPropertySet_Impl( aURLPropertyMap_Impl ); + return &aURLPropertySet_Impl; +} + +const SfxItemPropertySet* lcl_GetHeaderFieldPropertySet() +{ + static SfxItemPropertyMapEntry aHeaderFieldPropertyMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_ANCTYPE), 0, &getCppuType((text::TextContentAnchorType*)0), beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_ANCTYPES), 0, &getCppuType((uno::Sequence<text::TextContentAnchorType>*)0), beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_TEXTWRAP), 0, &getCppuType((text::WrapTextMode*)0), beans::PropertyAttribute::READONLY, 0 }, + {0,0,0,0,0,0} + }; + static SfxItemPropertySet aHeaderFieldPropertySet_Impl( aHeaderFieldPropertyMap_Impl ); + return &aHeaderFieldPropertySet_Impl; +} + +const SfxItemPropertySet* lcl_GetFileFieldPropertySet() +{ + static SfxItemPropertyMapEntry aFileFieldPropertyMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_ANCTYPE), 0, &getCppuType((text::TextContentAnchorType*)0), beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_ANCTYPES), 0, &getCppuType((uno::Sequence<text::TextContentAnchorType>*)0), beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_FILEFORM), 0, &getCppuType((sal_Int16*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_TEXTWRAP), 0, &getCppuType((text::WrapTextMode*)0), beans::PropertyAttribute::READONLY, 0 }, + {0,0,0,0,0,0} + }; + static SfxItemPropertySet aFileFieldPropertySet_Impl( aFileFieldPropertyMap_Impl ); + return &aFileFieldPropertySet_Impl; +} + +//------------------------------------------------------------------------ + +#define SCTEXTFIELD_SERVICE "com.sun.star.text.TextField" +#define SCTEXTCONTENT_SERVICE "com.sun.star.text.TextContent" + +SC_SIMPLE_SERVICE_INFO( ScCellFieldsObj, "ScCellFieldsObj", "com.sun.star.text.TextFields" ) +SC_SIMPLE_SERVICE_INFO( ScHeaderFieldsObj, "ScHeaderFieldsObj", "com.sun.star.text.TextFields" ) + +//------------------------------------------------------------------------ + +// ScUnoEditEngine nur um aus einer EditEngine die Felder herauszubekommen... + +enum ScUnoCollectMode +{ + SC_UNO_COLLECT_NONE, + SC_UNO_COLLECT_COUNT, + SC_UNO_COLLECT_FINDINDEX, + SC_UNO_COLLECT_FINDPOS +}; + +class ScUnoEditEngine : public ScEditEngineDefaulter +{ + ScUnoCollectMode eMode; + USHORT nFieldCount; + TypeId aFieldType; + SvxFieldData* pFound; // lokale Kopie + USHORT nFieldPar; + xub_StrLen nFieldPos; + USHORT nFieldIndex; + +public: + ScUnoEditEngine(ScEditEngineDefaulter* pSource); + ~ScUnoEditEngine(); + + //! nPos should be xub_StrLen + virtual String CalcFieldValue( const SvxFieldItem& rField, USHORT nPara, USHORT nPos, + Color*& rTxtColor, Color*& rFldColor ); + + USHORT CountFields(TypeId aType); + SvxFieldData* FindByIndex(USHORT nIndex, TypeId aType); + SvxFieldData* FindByPos(USHORT nPar, xub_StrLen nPos, TypeId aType); + + USHORT GetFieldPar() const { return nFieldPar; } + xub_StrLen GetFieldPos() const { return nFieldPos; } +}; + +ScUnoEditEngine::ScUnoEditEngine(ScEditEngineDefaulter* pSource) : + ScEditEngineDefaulter( *pSource ), + eMode( SC_UNO_COLLECT_NONE ), + nFieldCount( 0 ), + aFieldType( NULL ), + pFound( NULL ) +{ + if (pSource) + { + EditTextObject* pData = pSource->CreateTextObject(); + SetText( *pData ); + delete pData; + } +} + +ScUnoEditEngine::~ScUnoEditEngine() +{ + delete pFound; +} + +String ScUnoEditEngine::CalcFieldValue( const SvxFieldItem& rField, + USHORT nPara, USHORT nPos, Color*& rTxtColor, Color*& rFldColor ) +{ + String aRet(EditEngine::CalcFieldValue( rField, nPara, nPos, rTxtColor, rFldColor )); + if (eMode != SC_UNO_COLLECT_NONE) + { + const SvxFieldData* pFieldData = rField.GetField(); + if ( pFieldData ) + { + if ( !aFieldType || pFieldData->Type() == aFieldType ) + { + if ( eMode == SC_UNO_COLLECT_FINDINDEX && !pFound && nFieldCount == nFieldIndex ) + { + pFound = pFieldData->Clone(); + nFieldPar = nPara; + nFieldPos = nPos; + } + if ( eMode == SC_UNO_COLLECT_FINDPOS && !pFound && + nPara == nFieldPar && nPos == nFieldPos ) + { + pFound = pFieldData->Clone(); + nFieldIndex = nFieldCount; + } + ++nFieldCount; + } + } + } + return aRet; +} + +USHORT ScUnoEditEngine::CountFields(TypeId aType) +{ + eMode = SC_UNO_COLLECT_COUNT; + aFieldType = aType; + nFieldCount = 0; + UpdateFields(); + aFieldType = NULL; + eMode = SC_UNO_COLLECT_NONE; + + return nFieldCount; +} + +SvxFieldData* ScUnoEditEngine::FindByIndex(USHORT nIndex, TypeId aType) +{ + eMode = SC_UNO_COLLECT_FINDINDEX; + nFieldIndex = nIndex; + aFieldType = aType; + nFieldCount = 0; + UpdateFields(); + aFieldType = NULL; + eMode = SC_UNO_COLLECT_NONE; + + return pFound; +} + +SvxFieldData* ScUnoEditEngine::FindByPos(USHORT nPar, xub_StrLen nPos, TypeId aType) +{ + eMode = SC_UNO_COLLECT_FINDPOS; + nFieldPar = nPar; + nFieldPos = nPos; + aFieldType = aType; + nFieldCount = 0; + UpdateFields(); + aFieldType = NULL; + eMode = SC_UNO_COLLECT_NONE; + + return pFound; +} + +//------------------------------------------------------------------------ + +ScCellFieldsObj::ScCellFieldsObj(ScDocShell* pDocSh, const ScAddress& rPos) : + pDocShell( pDocSh ), + aCellPos( rPos ), + mpRefreshListeners( NULL ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); + + pEditSource = new ScCellEditSource( pDocShell, aCellPos ); +} + +ScCellFieldsObj::~ScCellFieldsObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); + + delete pEditSource; + + // increment refcount to prevent double call off dtor + osl_incrementInterlockedCount( &m_refCount ); + + if (mpRefreshListeners) + { + lang::EventObject aEvent; + aEvent.Source.set(static_cast<cppu::OWeakObject*>(this)); + if (mpRefreshListeners) + { + mpRefreshListeners->disposeAndClear(aEvent); + DELETEZ( mpRefreshListeners ); + } + } +} + +void ScCellFieldsObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( ScUpdateRefHint ) ) + { +// const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint; + + //! Ref-Update + } + else if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } + + // EditSource hat sich selber als Listener angemeldet +} + +// XIndexAccess (via XTextFields) + +ScCellFieldObj* ScCellFieldsObj::GetObjectByIndex_Impl(INT32 Index) const +{ + //! Feld-Funktionen muessen an den Forwarder !!! + ScEditEngineDefaulter* pEditEngine = ((ScCellEditSource*)pEditSource)->GetEditEngine(); + ScUnoEditEngine aTempEngine(pEditEngine); + + if ( aTempEngine.FindByIndex( (USHORT)Index, NULL ) ) // in der Zelle ist der Typ egal + { + USHORT nPar = aTempEngine.GetFieldPar(); + xub_StrLen nPos = aTempEngine.GetFieldPos(); + ESelection aSelection( nPar, nPos, nPar, nPos+1 ); // Feld ist 1 Zeichen + return new ScCellFieldObj( pDocShell, aCellPos, aSelection ); + } + return NULL; +} + +sal_Int32 SAL_CALL ScCellFieldsObj::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + //! Feld-Funktionen muessen an den Forwarder !!! + ScEditEngineDefaulter* pEditEngine = ((ScCellEditSource*)pEditSource)->GetEditEngine(); + ScUnoEditEngine aTempEngine(pEditEngine); + + return aTempEngine.CountFields(NULL); // Felder zaehlen, in Zelle ist der Typ egal +} + +uno::Any SAL_CALL ScCellFieldsObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<text::XTextField> xField(GetObjectByIndex_Impl(nIndex)); + if (xField.is()) + return uno::makeAny(xField); + else + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +uno::Type SAL_CALL ScCellFieldsObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((uno::Reference<text::XTextField>*)0); +} + +sal_Bool SAL_CALL ScCellFieldsObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +uno::Reference<container::XEnumeration> SAL_CALL ScCellFieldsObj::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.TextFieldEnumeration"))); +} + +void SAL_CALL ScCellFieldsObj::addContainerListener( + const uno::Reference<container::XContainerListener>& /* xListener */ ) + throw(uno::RuntimeException) +{ + DBG_ERROR("not implemented"); +} + +void SAL_CALL ScCellFieldsObj::removeContainerListener( + const uno::Reference<container::XContainerListener>& /* xListener */ ) + throw(uno::RuntimeException) +{ + DBG_ERROR("not implemented"); +} + +// XRefreshable +void SAL_CALL ScCellFieldsObj::refresh( ) + throw (uno::RuntimeException) +{ + if (mpRefreshListeners) + { + // Call all listeners. + uno::Sequence< uno::Reference< uno::XInterface > > aListeners(mpRefreshListeners->getElements()); + sal_uInt32 nLength(aListeners.getLength()); + if (nLength) + { + const uno::Reference< uno::XInterface >* pInterfaces = aListeners.getConstArray(); + if (pInterfaces) + { + lang::EventObject aEvent; + aEvent.Source.set(uno::Reference< util::XRefreshable >(const_cast<ScCellFieldsObj*>(this))); + sal_uInt32 i(0); + while (i < nLength) + { + try + { + while(i < nLength) + { + static_cast< util::XRefreshListener* >(pInterfaces->get())->refreshed(aEvent); + ++pInterfaces; + ++i; + } + } + catch(uno::RuntimeException&) + { +// DBG_ERROR("a object is gone without to remove from Broadcaster"); + ++pInterfaces; + ++i; + } + } + } + } + } +} + +void SAL_CALL ScCellFieldsObj::addRefreshListener( const uno::Reference< util::XRefreshListener >& xListener ) + throw (uno::RuntimeException) +{ + if (xListener.is()) + { + ScUnoGuard aGuard; + if (!mpRefreshListeners) + mpRefreshListeners = new cppu::OInterfaceContainerHelper(aMutex); + mpRefreshListeners->addInterface(xListener); + } +} + +void SAL_CALL ScCellFieldsObj::removeRefreshListener( const uno::Reference<util::XRefreshListener >& xListener ) + throw (uno::RuntimeException) +{ + if (xListener.is()) + { + ScUnoGuard aGuard; + if (mpRefreshListeners) + mpRefreshListeners->removeInterface(xListener); + } +} + +//------------------------------------------------------------------------ + +// Default-ctor wird fuer SMART_REFLECTION_IMPLEMENTATION gebraucht + + +//UNUSED2008-05 ScCellFieldObj::ScCellFieldObj() : +//UNUSED2008-05 OComponentHelper( getMutex() ), +//UNUSED2008-05 aPropSet( lcl_GetURLPropertyMap() ), +//UNUSED2008-05 pDocShell( NULL ) +//UNUSED2008-05 { +//UNUSED2008-05 pEditSource = NULL; +//UNUSED2008-05 } + +ScCellFieldObj::ScCellFieldObj(ScDocShell* pDocSh, const ScAddress& rPos, + const ESelection& rSel) : + OComponentHelper( getMutex() ), + pPropSet( lcl_GetURLPropertySet() ), + pDocShell( pDocSh ), + aCellPos( rPos ), + aSelection( rSel ) +{ + // pDocShell ist Null, wenn per ServiceProvider erzeugt + + if (pDocShell) + { + pDocShell->GetDocument()->AddUnoObject(*this); + pEditSource = new ScCellEditSource( pDocShell, aCellPos ); + } + else + pEditSource = NULL; +} + +uno::Any SAL_CALL ScCellFieldObj::queryAggregation( const uno::Type& rType ) + throw(uno::RuntimeException) +{ + SC_QUERYINTERFACE( text::XTextField ) + SC_QUERYINTERFACE( text::XTextContent ) // parent of XTextField + SC_QUERYINTERFACE( beans::XPropertySet ) + SC_QUERYINTERFACE( lang::XUnoTunnel ) + SC_QUERYINTERFACE( lang::XServiceInfo ) + + return OComponentHelper::queryAggregation( rType ); // XComponent +} + +uno::Sequence<uno::Type> SAL_CALL ScCellFieldObj::getTypes() throw(uno::RuntimeException) +{ + static uno::Sequence<uno::Type> aTypes; + if ( aTypes.getLength() == 0 ) + { + uno::Sequence<uno::Type> aParentTypes(OComponentHelper::getTypes()); + long nParentLen = aParentTypes.getLength(); + const uno::Type* pParentPtr = aParentTypes.getConstArray(); + + aTypes.realloc( nParentLen + 4 ); + uno::Type* pPtr = aTypes.getArray(); + pPtr[nParentLen + 0] = getCppuType((const uno::Reference<text::XTextField>*)0); + pPtr[nParentLen + 1] = getCppuType((const uno::Reference<beans::XPropertySet>*)0); + pPtr[nParentLen + 2] = getCppuType((const uno::Reference<lang::XUnoTunnel>*)0); + pPtr[nParentLen + 3] = getCppuType((const uno::Reference<lang::XServiceInfo>*)0); + + for (long i=0; i<nParentLen; i++) + pPtr[i] = pParentPtr[i]; // parent types first + } + return aTypes; +} + +uno::Sequence<sal_Int8> SAL_CALL ScCellFieldObj::getImplementationId() + throw(uno::RuntimeException) +{ + static uno::Sequence< sal_Int8 > aId; + if( aId.getLength() == 0 ) + { + aId.realloc( 16 ); + rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True ); + } + return aId; +} + +uno::Any SAL_CALL ScCellFieldObj::queryInterface( const uno::Type& rType ) + throw(uno::RuntimeException) +{ + return OComponentHelper::queryInterface( rType ); +} + +void SAL_CALL ScCellFieldObj::acquire() throw() +{ + OComponentHelper::acquire(); +} + +void SAL_CALL ScCellFieldObj::release() throw() +{ + OComponentHelper::release(); +} + +void ScCellFieldObj::InitDoc( ScDocShell* pDocSh, const ScAddress& rPos, + const ESelection& rSel ) +{ + if ( pDocSh && !pEditSource ) + { + aCellPos = rPos; + aSelection = rSel; + pDocShell = pDocSh; + + pDocShell->GetDocument()->AddUnoObject(*this); + pEditSource = new ScCellEditSource( pDocShell, aCellPos ); + } +} + +ScCellFieldObj::~ScCellFieldObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); + + delete pEditSource; +} + +void ScCellFieldObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + //! Updates fuer aSelection (muessen erst noch erzeugt werden) !!!!!! + + if ( rHint.ISA( ScUpdateRefHint ) ) + { +// const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint; + + //! Ref-Update + } + else if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } + + // EditSource hat sich selber als Listener angemeldet +} + +// per getImplementation gerufen: + +SvxFieldItem ScCellFieldObj::CreateFieldItem() +{ + DBG_ASSERT( !pEditSource, "CreateFieldItem mit eingefuegtem Feld" ); + + SvxURLField aField; + aField.SetFormat(SVXURLFORMAT_APPDEFAULT); + aField.SetURL( aUrl ); + aField.SetRepresentation( aRepresentation ); + aField.SetTargetFrame( aTarget ); + return SvxFieldItem( aField, EE_FEATURE_FIELD ); +} + +void ScCellFieldObj::DeleteField() +{ + if (pEditSource) + { + SvxTextForwarder* pForwarder = pEditSource->GetTextForwarder(); +// pEditEngine->QuickDelete( aSelection ); + pForwarder->QuickInsertText( String(), aSelection ); + pEditSource->UpdateData(); + + aSelection.nEndPara = aSelection.nStartPara; + aSelection.nEndPos = aSelection.nStartPos; + + //! Broadcast, um Selektion in anderen Objekten anzupassen + //! (auch bei anderen Aktionen) + } +} + +// XTextField + +rtl::OUString SAL_CALL ScCellFieldObj::getPresentation( sal_Bool bShowCommand ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aRet; + + if (pEditSource) + { + //! Feld-Funktionen muessen an den Forwarder !!! + ScEditEngineDefaulter* pEditEngine = ((ScCellEditSource*)pEditSource)->GetEditEngine(); + ScUnoEditEngine aTempEngine(pEditEngine); + + // Typ egal (in Zellen gibts nur URLs) + SvxFieldData* pField = aTempEngine.FindByPos( aSelection.nStartPara, aSelection.nStartPos, 0 ); + DBG_ASSERT(pField,"getPresentation: Feld nicht gefunden"); + if (pField) + { + SvxURLField* pURL = (SvxURLField*)pField; + if (bShowCommand) + aRet = pURL->GetURL(); + else + aRet = pURL->GetRepresentation(); + } + } + + return aRet; +} + +// XTextContent + +void SAL_CALL ScCellFieldObj::attach( const uno::Reference<text::XTextRange>& xTextRange ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (xTextRange.is()) + { + uno::Reference<text::XText> xText(xTextRange->getText()); + if (xText.is()) + { + xText->insertTextContent( xTextRange, this, TRUE ); + } + } +} + +uno::Reference<text::XTextRange> SAL_CALL ScCellFieldObj::getAnchor() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + return new ScCellObj( pDocShell, aCellPos ); + return NULL; +} + +// XComponent + +void SAL_CALL ScCellFieldObj::dispose() throw(uno::RuntimeException) +{ + OComponentHelper::dispose(); +} + +void SAL_CALL ScCellFieldObj::addEventListener( + const uno::Reference<lang::XEventListener>& xListener ) + throw(uno::RuntimeException) +{ + OComponentHelper::addEventListener( xListener ); +} + +void SAL_CALL ScCellFieldObj::removeEventListener( + const uno::Reference<lang::XEventListener>& xListener ) + throw(uno::RuntimeException) +{ + OComponentHelper::removeEventListener( xListener ); +} + +// XPropertySet + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScCellFieldObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef = pPropSet->getPropertySetInfo(); + return aRef; +} + +void SAL_CALL ScCellFieldObj::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aNameString(aPropertyName); + rtl::OUString aStrVal; + if (pEditSource) + { + //! Feld-Funktionen muessen an den Forwarder !!! + ScEditEngineDefaulter* pEditEngine = ((ScCellEditSource*)pEditSource)->GetEditEngine(); + ScUnoEditEngine aTempEngine(pEditEngine); + + // Typ egal (in Zellen gibts nur URLs) + SvxFieldData* pField = aTempEngine.FindByPos( aSelection.nStartPara, aSelection.nStartPos, 0 ); + DBG_ASSERT(pField,"setPropertyValue: Feld nicht gefunden"); + if (pField) + { + SvxURLField* pURL = (SvxURLField*)pField; // ist eine Kopie in der ScUnoEditEngine + + BOOL bOk = TRUE; + if ( aNameString.EqualsAscii( SC_UNONAME_URL ) ) + { + if (aValue >>= aStrVal) + pURL->SetURL( aStrVal ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_REPR ) ) + { + if (aValue >>= aStrVal) + pURL->SetRepresentation( aStrVal ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_TARGET ) ) + { + if (aValue >>= aStrVal) + pURL->SetTargetFrame( aStrVal ); + } + else + bOk = FALSE; + + if (bOk) + { + pEditEngine->QuickInsertField( SvxFieldItem(*pField, EE_FEATURE_FIELD), aSelection ); + pEditSource->UpdateData(); + } + } + } + else // noch nicht eingefuegt + { + if ( aNameString.EqualsAscii( SC_UNONAME_URL ) ) + { + if (aValue >>= aStrVal) + aUrl = String( aStrVal ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_REPR ) ) + { + if (aValue >>= aStrVal) + aRepresentation = String( aStrVal ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_TARGET ) ) + { + if (aValue >>= aStrVal) + aTarget = String( aStrVal ); + } + } +} + +uno::Any SAL_CALL ScCellFieldObj::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Any aRet; + String aNameString(aPropertyName); + + // anchor type is always "as character", text wrap always "none" + + if ( aNameString.EqualsAscii( SC_UNONAME_ANCTYPE ) ) + aRet <<= text::TextContentAnchorType_AS_CHARACTER; + else if ( aNameString.EqualsAscii( SC_UNONAME_ANCTYPES ) ) + { + uno::Sequence<text::TextContentAnchorType> aSeq(1); + aSeq[0] = text::TextContentAnchorType_AS_CHARACTER; + aRet <<= aSeq; + } + else if ( aNameString.EqualsAscii( SC_UNONAME_TEXTWRAP ) ) + aRet <<= text::WrapTextMode_NONE; + else if (pEditSource) + { + //! Feld-Funktionen muessen an den Forwarder !!! + ScEditEngineDefaulter* pEditEngine = ((ScCellEditSource*)pEditSource)->GetEditEngine(); + ScUnoEditEngine aTempEngine(pEditEngine); + + // Typ egal (in Zellen gibts nur URLs) + SvxFieldData* pField = aTempEngine.FindByPos( aSelection.nStartPara, aSelection.nStartPos, 0 ); + DBG_ASSERT(pField,"getPropertyValue: Feld nicht gefunden"); + if (pField) + { + SvxURLField* pURL = (SvxURLField*)pField; + + if ( aNameString.EqualsAscii( SC_UNONAME_URL ) ) + aRet <<= rtl::OUString( pURL->GetURL() ); + else if ( aNameString.EqualsAscii( SC_UNONAME_REPR ) ) + aRet <<= rtl::OUString( pURL->GetRepresentation() ); + else if ( aNameString.EqualsAscii( SC_UNONAME_TARGET ) ) + aRet <<= rtl::OUString( pURL->GetTargetFrame() ); + } + } + else // noch nicht eingefuegt + { + if ( aNameString.EqualsAscii( SC_UNONAME_URL ) ) + aRet <<= rtl::OUString( aUrl ); + else if ( aNameString.EqualsAscii( SC_UNONAME_REPR ) ) + aRet <<= rtl::OUString( aRepresentation ); + else if ( aNameString.EqualsAscii( SC_UNONAME_TARGET ) ) + aRet <<= rtl::OUString( aTarget ); + } + return aRet; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScCellFieldObj ) + +// XUnoTunnel + +sal_Int64 SAL_CALL ScCellFieldObj::getSomething( + const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); + } + return 0; +} + +// static +const uno::Sequence<sal_Int8>& ScCellFieldObj::getUnoTunnelId() +{ + static uno::Sequence<sal_Int8> * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +// static +ScCellFieldObj* ScCellFieldObj::getImplementation( + const uno::Reference<text::XTextContent> xObj ) +{ + ScCellFieldObj* pRet = NULL; + uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); + if (xUT.is()) + pRet = reinterpret_cast<ScCellFieldObj*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId()))); + return pRet; +} + +// XServiceInfo + +rtl::OUString SAL_CALL ScCellFieldObj::getImplementationName() throw(uno::RuntimeException) +{ + return rtl::OUString::createFromAscii( "ScCellFieldObj" ); +} + +sal_Bool SAL_CALL ScCellFieldObj::supportsService( const rtl::OUString& rServiceName ) + throw(uno::RuntimeException) +{ + String aServiceStr( rServiceName ); + return aServiceStr.EqualsAscii( SCTEXTFIELD_SERVICE ) || + aServiceStr.EqualsAscii( SCTEXTCONTENT_SERVICE ); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScCellFieldObj::getSupportedServiceNames() + throw(uno::RuntimeException) +{ + uno::Sequence<rtl::OUString> aRet(2); + rtl::OUString* pArray = aRet.getArray(); + pArray[0] = rtl::OUString::createFromAscii( SCTEXTFIELD_SERVICE ); + pArray[1] = rtl::OUString::createFromAscii( SCTEXTCONTENT_SERVICE ); + return aRet; +} + +//------------------------------------------------------------------------ + +ScHeaderFieldsObj::ScHeaderFieldsObj(ScHeaderFooterContentObj* pContent, USHORT nP, USHORT nT) : + pContentObj( pContent ), + nPart( nP ), + nType( nT ), + mpRefreshListeners( NULL ) +{ + DBG_ASSERT( pContentObj, "ScHeaderFieldsObj ohne Objekt?" ); + + if (pContentObj) + { + pContentObj->acquire(); // darf nicht wegkommen + pEditSource = new ScHeaderFooterEditSource( pContentObj, nPart ); + } + else + pEditSource = NULL; +} + +ScHeaderFieldsObj::~ScHeaderFieldsObj() +{ + delete pEditSource; + + if (pContentObj) + pContentObj->release(); + + // increment refcount to prevent double call off dtor + osl_incrementInterlockedCount( &m_refCount ); + + if (mpRefreshListeners) + { + lang::EventObject aEvent; + aEvent.Source = static_cast<cppu::OWeakObject*>(this); + if (mpRefreshListeners) + { + mpRefreshListeners->disposeAndClear(aEvent); + DELETEZ( mpRefreshListeners ); + } + } +} + +// XIndexAccess (via XTextFields) + +ScHeaderFieldObj* ScHeaderFieldsObj::GetObjectByIndex_Impl(INT32 Index) const +{ + //! Feld-Funktionen muessen an den Forwarder !!! + ScEditEngineDefaulter* pEditEngine = ((ScHeaderFooterEditSource*)pEditSource)->GetEditEngine(); + ScUnoEditEngine aTempEngine(pEditEngine); + + TypeId aTypeId = NULL; + switch (nType) + { + case SC_SERVICE_PAGEFIELD: aTypeId = TYPE(SvxPageField); break; + case SC_SERVICE_PAGESFIELD: aTypeId = TYPE(SvxPagesField); break; + case SC_SERVICE_DATEFIELD: aTypeId = TYPE(SvxDateField); break; + case SC_SERVICE_TIMEFIELD: aTypeId = TYPE(SvxTimeField); break; + case SC_SERVICE_TITLEFIELD: aTypeId = TYPE(SvxFileField); break; + case SC_SERVICE_FILEFIELD: aTypeId = TYPE(SvxExtFileField); break; + case SC_SERVICE_SHEETFIELD: aTypeId = TYPE(SvxTableField); break; + // bei SC_SERVICE_INVALID bleibt TypeId Null + } + SvxFieldData* pData = aTempEngine.FindByIndex( (USHORT)Index, aTypeId ); + if ( pData ) + { + USHORT nPar = aTempEngine.GetFieldPar(); + xub_StrLen nPos = aTempEngine.GetFieldPos(); + + USHORT nFieldType = nType; + if ( nFieldType == SC_SERVICE_INVALID ) + { + if ( pData->ISA( SvxPageField ) ) nFieldType = SC_SERVICE_PAGEFIELD; + else if ( pData->ISA( SvxPagesField ) ) nFieldType = SC_SERVICE_PAGESFIELD; + else if ( pData->ISA( SvxDateField ) ) nFieldType = SC_SERVICE_DATEFIELD; + else if ( pData->ISA( SvxTimeField ) ) nFieldType = SC_SERVICE_TIMEFIELD; + else if ( pData->ISA( SvxFileField ) ) nFieldType = SC_SERVICE_TITLEFIELD; + else if ( pData->ISA( SvxExtFileField ) ) nFieldType = SC_SERVICE_FILEFIELD; + else if ( pData->ISA( SvxTableField ) ) nFieldType = SC_SERVICE_SHEETFIELD; + } + + ESelection aSelection( nPar, nPos, nPar, nPos+1 ); // Field is 1 character + return new ScHeaderFieldObj( pContentObj, nPart, nFieldType, aSelection ); + } + return NULL; +} + +sal_Int32 SAL_CALL ScHeaderFieldsObj::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + //! Feld-Funktionen muessen an den Forwarder !!! + ScEditEngineDefaulter* pEditEngine = ((ScHeaderFooterEditSource*)pEditSource)->GetEditEngine(); + ScUnoEditEngine aTempEngine(pEditEngine); + + TypeId aTypeId = NULL; + switch (nType) + { + case SC_SERVICE_PAGEFIELD: aTypeId = TYPE(SvxPageField); break; + case SC_SERVICE_PAGESFIELD: aTypeId = TYPE(SvxPagesField); break; + case SC_SERVICE_DATEFIELD: aTypeId = TYPE(SvxDateField); break; + case SC_SERVICE_TIMEFIELD: aTypeId = TYPE(SvxTimeField); break; + case SC_SERVICE_TITLEFIELD: aTypeId = TYPE(SvxFileField); break; + case SC_SERVICE_FILEFIELD: aTypeId = TYPE(SvxExtFileField); break; + case SC_SERVICE_SHEETFIELD: aTypeId = TYPE(SvxTableField); break; + } + return aTempEngine.CountFields(aTypeId); // Felder zaehlen +} + +uno::Any SAL_CALL ScHeaderFieldsObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<text::XTextField> xField(GetObjectByIndex_Impl(nIndex)); + if (xField.is()) + return uno::makeAny(xField); + else + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +uno::Type SAL_CALL ScHeaderFieldsObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((uno::Reference<text::XTextField>*)0); +} + +sal_Bool SAL_CALL ScHeaderFieldsObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +uno::Reference<container::XEnumeration> SAL_CALL ScHeaderFieldsObj::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.text.TextFieldEnumeration"))); +} + +void SAL_CALL ScHeaderFieldsObj::addContainerListener( + const uno::Reference<container::XContainerListener>& /* xListener */ ) + throw(uno::RuntimeException) +{ + DBG_ERROR("not implemented"); +} + +void SAL_CALL ScHeaderFieldsObj::removeContainerListener( + const uno::Reference<container::XContainerListener>& /* xListener */ ) + throw(uno::RuntimeException) +{ + DBG_ERROR("not implemented"); +} + +// XRefreshable +void SAL_CALL ScHeaderFieldsObj::refresh( ) + throw (uno::RuntimeException) +{ + if (mpRefreshListeners) + { + // Call all listeners. + uno::Sequence< uno::Reference< uno::XInterface > > aListeners(mpRefreshListeners->getElements()); + sal_uInt32 nLength(aListeners.getLength()); + if (nLength) + { + const uno::Reference< uno::XInterface >* pInterfaces = aListeners.getConstArray(); + if (pInterfaces) + { + lang::EventObject aEvent; + aEvent.Source.set(uno::Reference< util::XRefreshable >(const_cast<ScHeaderFieldsObj*>(this))); + sal_uInt32 i(0); + while (i < nLength) + { + try + { + while(i < nLength) + { + static_cast< util::XRefreshListener* >(pInterfaces->get())->refreshed(aEvent); + ++pInterfaces; + ++i; + } + } + catch(uno::RuntimeException&) + { +// DBG_ERROR("a object is gone without to remove from Broadcaster"); + ++pInterfaces; + ++i; + } + } + } + } + } +} + +void SAL_CALL ScHeaderFieldsObj::addRefreshListener( const uno::Reference< util::XRefreshListener >& xListener ) + throw (uno::RuntimeException) +{ + if (xListener.is()) + { + ScUnoGuard aGuard; + if (!mpRefreshListeners) + mpRefreshListeners = new cppu::OInterfaceContainerHelper(aMutex); + mpRefreshListeners->addInterface(xListener); + } +} + +void SAL_CALL ScHeaderFieldsObj::removeRefreshListener( const uno::Reference<util::XRefreshListener >& xListener ) + throw (uno::RuntimeException) +{ + if (xListener.is()) + { + ScUnoGuard aGuard; + if (mpRefreshListeners) + mpRefreshListeners->removeInterface(xListener); + } +} + +//------------------------------------------------------------------------ + +SvxFileFormat lcl_UnoToSvxFileFormat( sal_Int16 nUnoValue ) +{ + switch( nUnoValue ) + { + case text::FilenameDisplayFormat::FULL: return SVXFILEFORMAT_FULLPATH; + case text::FilenameDisplayFormat::PATH: return SVXFILEFORMAT_PATH; + case text::FilenameDisplayFormat::NAME: return SVXFILEFORMAT_NAME; +// case text::FilenameDisplayFormat::NAME_AND_EXT: + default: + return SVXFILEFORMAT_NAME_EXT; + } +} + +sal_Int16 lcl_SvxToUnoFileFormat( SvxFileFormat nSvxValue ) +{ + switch( nSvxValue ) + { + case SVXFILEFORMAT_NAME_EXT: return text::FilenameDisplayFormat::NAME_AND_EXT; + case SVXFILEFORMAT_FULLPATH: return text::FilenameDisplayFormat::FULL; + case SVXFILEFORMAT_PATH: return text::FilenameDisplayFormat::PATH; +// case SVXFILEFORMAT_NAME: + default: + return text::FilenameDisplayFormat::NAME; + } +} + + +// Default-ctor wird fuer SMART_REFLECTION_IMPLEMENTATION gebraucht +//UNUSED2008-05 ScHeaderFieldObj::ScHeaderFieldObj() : +//UNUSED2008-05 OComponentHelper( getMutex() ), +//UNUSED2008-05 aPropSet( lcl_GetHeaderFieldPropertyMap() ), +//UNUSED2008-05 pContentObj( NULL ), +//UNUSED2008-05 nPart( 0 ), +//UNUSED2008-05 nType( 0 ), +//UNUSED2008-05 nFileFormat( SVXFILEFORMAT_NAME_EXT ) +//UNUSED2008-05 { +//UNUSED2008-05 pEditSource = NULL; +//UNUSED2008-05 } + +ScHeaderFieldObj::ScHeaderFieldObj(ScHeaderFooterContentObj* pContent, USHORT nP, + USHORT nT, const ESelection& rSel) : + OComponentHelper( getMutex() ), + pPropSet( (nT == SC_SERVICE_FILEFIELD) ? lcl_GetFileFieldPropertySet() : lcl_GetHeaderFieldPropertySet() ), + pContentObj( pContent ), + nPart( nP ), + nType( nT ), + aSelection( rSel ), + nFileFormat( SVXFILEFORMAT_NAME_EXT ) +{ + // pContent ist Null, wenn per ServiceProvider erzeugt + + if (pContentObj) + { + pContentObj->acquire(); // darf nicht wegkommen + pEditSource = new ScHeaderFooterEditSource( pContentObj, nPart ); + } + else + pEditSource = NULL; +} + +uno::Any SAL_CALL ScHeaderFieldObj::queryAggregation( const uno::Type& rType ) + throw(uno::RuntimeException) +{ + SC_QUERYINTERFACE( text::XTextField ) + SC_QUERYINTERFACE( text::XTextContent ) // parent of XTextField + SC_QUERYINTERFACE( beans::XPropertySet ) + SC_QUERYINTERFACE( lang::XUnoTunnel ) + SC_QUERYINTERFACE( lang::XServiceInfo ) + + return OComponentHelper::queryAggregation( rType ); // XComponent +} + +uno::Sequence<uno::Type> SAL_CALL ScHeaderFieldObj::getTypes() throw(uno::RuntimeException) +{ + static uno::Sequence<uno::Type> aTypes; + if ( aTypes.getLength() == 0 ) + { + uno::Sequence<uno::Type> aParentTypes(OComponentHelper::getTypes()); + long nParentLen = aParentTypes.getLength(); + const uno::Type* pParentPtr = aParentTypes.getConstArray(); + + aTypes.realloc( nParentLen + 4 ); + uno::Type* pPtr = aTypes.getArray(); + pPtr[nParentLen + 0] = getCppuType((const uno::Reference<text::XTextField>*)0); + pPtr[nParentLen + 1] = getCppuType((const uno::Reference<beans::XPropertySet>*)0); + pPtr[nParentLen + 2] = getCppuType((const uno::Reference<lang::XUnoTunnel>*)0); + pPtr[nParentLen + 3] = getCppuType((const uno::Reference<lang::XServiceInfo>*)0); + + for (long i=0; i<nParentLen; i++) + pPtr[i] = pParentPtr[i]; // parent types first + } + return aTypes; +} + +uno::Sequence<sal_Int8> SAL_CALL ScHeaderFieldObj::getImplementationId() + throw(uno::RuntimeException) +{ + static uno::Sequence< sal_Int8 > aId; + if( aId.getLength() == 0 ) + { + aId.realloc( 16 ); + rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True ); + } + return aId; +} + +uno::Any SAL_CALL ScHeaderFieldObj::queryInterface( const uno::Type& rType ) + throw(uno::RuntimeException) +{ + return OComponentHelper::queryInterface( rType ); +} + +void SAL_CALL ScHeaderFieldObj::acquire() throw() +{ + OComponentHelper::acquire(); +} + +void SAL_CALL ScHeaderFieldObj::release() throw() +{ + OComponentHelper::release(); +} + +void ScHeaderFieldObj::InitDoc( ScHeaderFooterContentObj* pContent, USHORT nP, + const ESelection& rSel ) +{ + if ( pContent && !pEditSource ) + { + DBG_ASSERT( !pContentObj, "ContentObj, aber kein EditSource?" ); + + aSelection = rSel; + nPart = nP; + pContentObj = pContent; + + pContentObj->acquire(); // darf nicht wegkommen + pEditSource = new ScHeaderFooterEditSource( pContentObj, nPart ); + } +} + +ScHeaderFieldObj::~ScHeaderFieldObj() +{ + delete pEditSource; + + if (pContentObj) + pContentObj->release(); +} + +// per getImplementation gerufen: + +SvxFieldItem ScHeaderFieldObj::CreateFieldItem() +{ + DBG_ASSERT( !pEditSource, "CreateFieldItem mit eingefuegtem Feld" ); + + switch (nType) + { + case SC_SERVICE_PAGEFIELD: + { + SvxPageField aField; + return SvxFieldItem( aField, EE_FEATURE_FIELD ); + } + case SC_SERVICE_PAGESFIELD: + { + SvxPagesField aField; + return SvxFieldItem( aField, EE_FEATURE_FIELD ); + } + case SC_SERVICE_DATEFIELD: + { + SvxDateField aField; + return SvxFieldItem( aField, EE_FEATURE_FIELD ); + } + case SC_SERVICE_TIMEFIELD: + { + SvxTimeField aField; + return SvxFieldItem( aField, EE_FEATURE_FIELD ); + } + case SC_SERVICE_TITLEFIELD: + { + SvxFileField aField; + return SvxFieldItem( aField, EE_FEATURE_FIELD ); + } + case SC_SERVICE_FILEFIELD: + { + SvxExtFileField aField; + aField.SetFormat( (SvxFileFormat) nFileFormat ); + return SvxFieldItem( aField, EE_FEATURE_FIELD ); + } + case SC_SERVICE_SHEETFIELD: + { + SvxTableField aField; + return SvxFieldItem( aField, EE_FEATURE_FIELD ); + } + } + + return SvxFieldItem( SvxFieldData(), EE_FEATURE_FIELD ); +} + +void ScHeaderFieldObj::DeleteField() +{ + if (pEditSource) + { + SvxTextForwarder* pForwarder = pEditSource->GetTextForwarder(); +// pEditEngine->QuickDelete( aSelection ); + pForwarder->QuickInsertText( String(), aSelection ); + pEditSource->UpdateData(); + + aSelection.nEndPara = aSelection.nStartPara; + aSelection.nEndPos = aSelection.nStartPos; + + //! Broadcast, um Selektion in anderen Objekten anzupassen + //! (auch bei anderen Aktionen) + } +} + +// XTextField + +rtl::OUString SAL_CALL ScHeaderFieldObj::getPresentation( sal_Bool /* bShowCommand */ ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aRet; + + if (pEditSource) + { + // Feld von der EditEngine formatieren lassen, bShowCommand gibt's nicht + + SvxTextForwarder* pForwarder = pEditSource->GetTextForwarder(); + aRet = pForwarder->GetText( aSelection ); + } + + return aRet; +} + +// XTextContent + +void SAL_CALL ScHeaderFieldObj::attach( const uno::Reference<text::XTextRange>& xTextRange ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (xTextRange.is()) + { + uno::Reference<text::XText> xText(xTextRange->getText()); + if (xText.is()) + { + xText->insertTextContent( xTextRange, this, TRUE ); + } + } +} + +uno::Reference<text::XTextRange> SAL_CALL ScHeaderFieldObj::getAnchor() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pContentObj) + { + uno::Reference<text::XText> xText; + if ( nPart == SC_HDFT_LEFT ) + xText = pContentObj->getLeftText(); + else if (nPart == SC_HDFT_CENTER) + xText = pContentObj->getCenterText(); + else + xText = pContentObj->getRightText(); + return uno::Reference<text::XTextRange>( xText, uno::UNO_QUERY ); + } + return NULL; +} + +// XComponent + +void SAL_CALL ScHeaderFieldObj::dispose() throw(uno::RuntimeException) +{ + OComponentHelper::dispose(); +} + +void SAL_CALL ScHeaderFieldObj::addEventListener( + const uno::Reference<lang::XEventListener>& xListener ) + throw(uno::RuntimeException) +{ + OComponentHelper::addEventListener( xListener ); +} + +void SAL_CALL ScHeaderFieldObj::removeEventListener( + const uno::Reference<lang::XEventListener>& xListener ) + throw(uno::RuntimeException) +{ + OComponentHelper::removeEventListener( xListener ); +} + +// XPropertySet + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScHeaderFieldObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (nType == SC_SERVICE_FILEFIELD) + { + // file field has different properties + static uno::Reference<beans::XPropertySetInfo> aFileFieldInfo = pPropSet->getPropertySetInfo(); + return aFileFieldInfo; + } + else + { + static uno::Reference<beans::XPropertySetInfo> aRef = pPropSet->getPropertySetInfo(); + return aRef; + } +} + +void SAL_CALL ScHeaderFieldObj::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aNameString(aPropertyName); + if ( nType == SC_SERVICE_FILEFIELD && aNameString.EqualsAscii( SC_UNONAME_FILEFORM ) ) + { + sal_Int16 nIntVal = 0; + if ( aValue >>= nIntVal ) + { + SvxFileFormat eFormat = lcl_UnoToSvxFileFormat( nIntVal ); + if (pEditSource) + { + ScEditEngineDefaulter* pEditEngine = ((ScHeaderFooterEditSource*)pEditSource)->GetEditEngine(); + ScUnoEditEngine aTempEngine(pEditEngine); + SvxFieldData* pField = aTempEngine.FindByPos( + aSelection.nStartPara, aSelection.nStartPos, TYPE(SvxExtFileField) ); + DBG_ASSERT(pField,"setPropertyValue: Field not found"); + if (pField) + { + SvxExtFileField* pExtFile = (SvxExtFileField*)pField; // local to the ScUnoEditEngine + pExtFile->SetFormat( eFormat ); + pEditEngine->QuickInsertField( SvxFieldItem(*pField, EE_FEATURE_FIELD), aSelection ); + pEditSource->UpdateData(); + } + } + else + nFileFormat = sal::static_int_cast<sal_Int16>(eFormat); // not inserted yet - store value + } + } +} + +uno::Any SAL_CALL ScHeaderFieldObj::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + + //! Properties? + uno::Any aRet; + String aNameString(aPropertyName); + + // anchor type is always "as character", text wrap always "none" + + if ( aNameString.EqualsAscii( SC_UNONAME_ANCTYPE ) ) + aRet <<= text::TextContentAnchorType_AS_CHARACTER; + else if ( aNameString.EqualsAscii( SC_UNONAME_ANCTYPES ) ) + { + uno::Sequence<text::TextContentAnchorType> aSeq(1); + aSeq[0] = text::TextContentAnchorType_AS_CHARACTER; + aRet <<= aSeq; + } + else if ( aNameString.EqualsAscii( SC_UNONAME_TEXTWRAP ) ) + aRet <<= text::WrapTextMode_NONE; + else if ( nType == SC_SERVICE_FILEFIELD && aNameString.EqualsAscii( SC_UNONAME_FILEFORM ) ) + { + SvxFileFormat eFormat = SVXFILEFORMAT_NAME_EXT; + if (pEditSource) + { + ScEditEngineDefaulter* pEditEngine = ((ScHeaderFooterEditSource*)pEditSource)->GetEditEngine(); + ScUnoEditEngine aTempEngine(pEditEngine); + SvxFieldData* pField = aTempEngine.FindByPos( + aSelection.nStartPara, aSelection.nStartPos, TYPE(SvxExtFileField) ); + DBG_ASSERT(pField,"setPropertyValue: Field not found"); + if (pField) + { + const SvxExtFileField* pExtFile = (const SvxExtFileField*)pField; + eFormat = pExtFile->GetFormat(); + } + } + else + eFormat = (SvxFileFormat) nFileFormat; // not inserted yet - use stored value + + sal_Int16 nIntVal = lcl_SvxToUnoFileFormat( eFormat ); + aRet <<= nIntVal; + } + + return aRet; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScHeaderFieldObj ) + +// XUnoTunnel + +sal_Int64 SAL_CALL ScHeaderFieldObj::getSomething( + const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); + } + return 0; +} + +// static +const uno::Sequence<sal_Int8>& ScHeaderFieldObj::getUnoTunnelId() +{ + static uno::Sequence<sal_Int8> * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +// static +ScHeaderFieldObj* ScHeaderFieldObj::getImplementation( + const uno::Reference<text::XTextContent> xObj ) +{ + ScHeaderFieldObj* pRet = NULL; + uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); + if (xUT.is()) + pRet = reinterpret_cast<ScHeaderFieldObj*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId()))); + return pRet; +} + +// XServiceInfo + +rtl::OUString SAL_CALL ScHeaderFieldObj::getImplementationName() throw(uno::RuntimeException) +{ + return rtl::OUString::createFromAscii( "ScHeaderFieldObj" ); +} + +sal_Bool SAL_CALL ScHeaderFieldObj::supportsService( const rtl::OUString& rServiceName ) + throw(uno::RuntimeException) +{ + String aServiceStr( rServiceName ); + return aServiceStr.EqualsAscii( SCTEXTFIELD_SERVICE ) || + aServiceStr.EqualsAscii( SCTEXTCONTENT_SERVICE ); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScHeaderFieldObj::getSupportedServiceNames() + throw(uno::RuntimeException) +{ + uno::Sequence<rtl::OUString> aRet(2); + rtl::OUString* pArray = aRet.getArray(); + pArray[0] = rtl::OUString::createFromAscii( SCTEXTFIELD_SERVICE ); + pArray[1] = rtl::OUString::createFromAscii( SCTEXTCONTENT_SERVICE ); + return aRet; +} + +//------------------------------------------------------------------------ + + + + diff --git a/sc/source/ui/unoobj/filtuno.cxx b/sc/source/ui/unoobj/filtuno.cxx new file mode 100644 index 000000000000..efe804784a40 --- /dev/null +++ b/sc/source/ui/unoobj/filtuno.cxx @@ -0,0 +1,317 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include <com/sun/star/ui/dialogs/ExecutableDialogResults.hpp> +#include <tools/urlobj.hxx> +#include <vcl/msgbox.hxx> +#include <unotools/ucbstreamhelper.hxx> + +#include "editutil.hxx" +#include "filtuno.hxx" +#include "miscuno.hxx" +#include "unoguard.hxx" +#include "scdll.hxx" +#include "imoptdlg.hxx" +#include "asciiopt.hxx" +#include "docsh.hxx" +#include "globstr.hrc" + + +#include "sc.hrc" //CHINA001 +#include "scabstdlg.hxx" //CHINA001 +#include "i18npool/lang.h" + +#include <memory> + +using namespace ::com::sun::star; +using ::rtl::OUStringBuffer; + +//------------------------------------------------------------------------ + +#define SCFILTEROPTIONSOBJ_SERVICE "com.sun.star.ui.dialogs.FilterOptionsDialog" +#define SCFILTEROPTIONSOBJ_IMPLNAME "com.sun.star.comp.Calc.FilterOptionsDialog" + +SC_SIMPLE_SERVICE_INFO( ScFilterOptionsObj, SCFILTEROPTIONSOBJ_IMPLNAME, SCFILTEROPTIONSOBJ_SERVICE ) + +#define SC_UNONAME_FILENAME "URL" +#define SC_UNONAME_FILTERNAME "FilterName" +#define SC_UNONAME_FILTEROPTIONS "FilterOptions" +#define SC_UNONAME_INPUTSTREAM "InputStream" + +//------------------------------------------------------------------------ + +ScFilterOptionsObj::ScFilterOptionsObj() : + bExport( sal_False ) +{ +} + +ScFilterOptionsObj::~ScFilterOptionsObj() +{ +} + +// stuff for exService_... + +uno::Reference<uno::XInterface> SAL_CALL ScFilterOptionsObj_CreateInstance( + const uno::Reference<lang::XMultiServiceFactory>& ) +{ + ScUnoGuard aGuard; + ScDLL::Init(); + return (::cppu::OWeakObject*) new ScFilterOptionsObj; +} + +rtl::OUString ScFilterOptionsObj::getImplementationName_Static() +{ + return rtl::OUString::createFromAscii( SCFILTEROPTIONSOBJ_IMPLNAME ); +} + +uno::Sequence<rtl::OUString> ScFilterOptionsObj::getSupportedServiceNames_Static() +{ + uno::Sequence<rtl::OUString> aRet(1); + rtl::OUString* pArray = aRet.getArray(); + pArray[0] = rtl::OUString::createFromAscii( SCFILTEROPTIONSOBJ_SERVICE ); + return aRet; +} + +// XPropertyAccess + +uno::Sequence<beans::PropertyValue> SAL_CALL ScFilterOptionsObj::getPropertyValues() throw(uno::RuntimeException) +{ + uno::Sequence<beans::PropertyValue> aRet(1); + beans::PropertyValue* pArray = aRet.getArray(); + + pArray[0].Name = rtl::OUString::createFromAscii( SC_UNONAME_FILTEROPTIONS ); + pArray[0].Value <<= aFilterOptions; + + return aRet; +} + +void SAL_CALL ScFilterOptionsObj::setPropertyValues( const uno::Sequence<beans::PropertyValue>& aProps ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException) +{ + const beans::PropertyValue* pPropArray = aProps.getConstArray(); + long nPropCount = aProps.getLength(); + for (long i = 0; i < nPropCount; i++) + { + const beans::PropertyValue& rProp = pPropArray[i]; + String aPropName(rProp.Name); + + if ( aPropName.EqualsAscii( SC_UNONAME_FILENAME ) ) + rProp.Value >>= aFileName; + else if ( aPropName.EqualsAscii( SC_UNONAME_FILTERNAME ) ) + rProp.Value >>= aFilterName; + else if ( aPropName.EqualsAscii( SC_UNONAME_FILTEROPTIONS ) ) + rProp.Value >>= aFilterOptions; + else if ( aPropName.EqualsAscii( SC_UNONAME_INPUTSTREAM ) ) + rProp.Value >>= xInputStream; + } +} + +// XExecutableDialog + +void SAL_CALL ScFilterOptionsObj::setTitle( const ::rtl::OUString& /* aTitle */ ) throw(uno::RuntimeException) +{ + // not used +} + +sal_Int16 SAL_CALL ScFilterOptionsObj::execute() throw(uno::RuntimeException) +{ + sal_Int16 nRet = ui::dialogs::ExecutableDialogResults::CANCEL; + + String aFilterString( aFilterName ); + + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!"); + + if ( !bExport && aFilterString == ScDocShell::GetAsciiFilterName() ) + { + // ascii import is special... + + INetURLObject aURL( aFileName ); + String aExt(aURL.getExtension()); + String aPrivDatName(aURL.getName()); + sal_Unicode cAsciiDel; + if (aExt.EqualsIgnoreCaseAscii("CSV")) + cAsciiDel = ','; + else + cAsciiDel = '\t'; + + SvStream* pInStream = NULL; + if ( xInputStream.is() ) + pInStream = utl::UcbStreamHelper::CreateStream( xInputStream ); + + //CHINA001 ScImportAsciiDlg* pDlg = new ScImportAsciiDlg( NULL, aPrivDatName, pInStream, cAsciiDel ); + AbstractScImportAsciiDlg* pDlg = pFact->CreateScImportAsciiDlg( NULL, aPrivDatName, pInStream, RID_SCDLG_ASCII, cAsciiDel); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + if ( pDlg->Execute() == RET_OK ) + { + ScAsciiOptions aOptions; + pDlg->GetOptions( aOptions ); + pDlg->SaveParameters(); + aFilterOptions = aOptions.WriteToString(); + nRet = ui::dialogs::ExecutableDialogResults::OK; + } + delete pDlg; + delete pInStream; + } + else if ( aFilterString == ScDocShell::GetWebQueryFilterName() || aFilterString == ScDocShell::GetHtmlFilterName() ) + { + if (bExport) + nRet = ui::dialogs::ExecutableDialogResults::OK; // export HTML without dialog + else + { + // HTML import. + ::std::auto_ptr<AbstractScTextImportOptionsDlg> pDlg( + pFact->CreateScTextImportOptionsDlg(NULL, RID_SCDLG_TEXT_IMPORT_OPTIONS)); + + if (pDlg->Execute() == RET_OK) + { + LanguageType eLang = pDlg->GetLanguageType(); + OUStringBuffer aBuf; + + aBuf.append(String::CreateFromInt32(static_cast<sal_Int32>(eLang))); + aBuf.append(sal_Unicode(' ')); + aBuf.append(pDlg->IsDateConversionSet() ? sal_Unicode('1') : sal_Unicode('0')); + aFilterOptions = aBuf.makeStringAndClear(); + nRet = ui::dialogs::ExecutableDialogResults::OK; + } + } + } + else + { + sal_Bool bMultiByte = sal_True; + sal_Bool bDBEnc = sal_False; + sal_Bool bAscii = sal_False; + + sal_Unicode cStrDel = '"'; + sal_Unicode cAsciiDel = ';'; + rtl_TextEncoding eEncoding = RTL_TEXTENCODING_DONTKNOW; + + String aTitle; + + if ( aFilterString == ScDocShell::GetAsciiFilterName() ) + { + // ascii export (import is handled above) + + INetURLObject aURL( aFileName ); + String aExt(aURL.getExtension()); + if (aExt.EqualsIgnoreCaseAscii("CSV")) + cAsciiDel = ','; + else + cAsciiDel = '\t'; + + aTitle = ScGlobal::GetRscString( STR_EXPORT_ASCII ); + bAscii = sal_True; + } + else if ( aFilterString == ScDocShell::GetLotusFilterName() ) + { + // lotus is only imported + DBG_ASSERT( !bExport, "Filter Options for Lotus Export is not implemented" ); + + aTitle = ScGlobal::GetRscString( STR_IMPORT_LOTUS ); + eEncoding = RTL_TEXTENCODING_IBM_437; + } + else if ( aFilterString == ScDocShell::GetDBaseFilterName() ) + { + if ( bExport ) + { + // dBase export + aTitle = ScGlobal::GetRscString( STR_EXPORT_DBF ); + } + else + { + // dBase import + aTitle = ScGlobal::GetRscString( STR_IMPORT_DBF ); + } + // common for dBase import/export + eEncoding = RTL_TEXTENCODING_IBM_850; + bDBEnc = sal_True; + } + else if ( aFilterString == ScDocShell::GetDifFilterName() ) + { + if ( bExport ) + { + // DIF export + aTitle = ScGlobal::GetRscString( STR_EXPORT_DIF ); + } + else + { + // DIF import + aTitle = ScGlobal::GetRscString( STR_IMPORT_DIF ); + } + // common for DIF import/export + eEncoding = RTL_TEXTENCODING_MS_1252; + } + + ScImportOptions aOptions( cAsciiDel, cStrDel, eEncoding); +//CHINA001 ScImportOptionsDlg* pDlg = new ScImportOptionsDlg( NULL, bAscii, +//CHINA001 &aOptions, &aTitle, bMultiByte, bDBEnc, +//CHINA001 !bExport ); +//CHINA001 + + AbstractScImportOptionsDlg* pDlg = pFact->CreateScImportOptionsDlg( NULL, RID_SCDLG_IMPORTOPT, + bAscii, &aOptions, &aTitle, bMultiByte, bDBEnc, + !bExport); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + if ( pDlg->Execute() == RET_OK ) + { + pDlg->GetImportOptions( aOptions ); + if ( bAscii ) + aFilterOptions = aOptions.BuildString(); + else + aFilterOptions = aOptions.aStrFont; + nRet = ui::dialogs::ExecutableDialogResults::OK; + } + delete pDlg; + } + + xInputStream.clear(); // don't hold the stream longer than necessary + + return nRet; +} + +// XImporter + +void SAL_CALL ScFilterOptionsObj::setTargetDocument( const uno::Reference<lang::XComponent>& /* xDoc */ ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + bExport = sal_False; +} + +// XExporter + +void SAL_CALL ScFilterOptionsObj::setSourceDocument( const uno::Reference<lang::XComponent>& /* xDoc */ ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + bExport = sal_True; +} + diff --git a/sc/source/ui/unoobj/fmtuno.cxx b/sc/source/ui/unoobj/fmtuno.cxx new file mode 100644 index 000000000000..392533c7cf93 --- /dev/null +++ b/sc/source/ui/unoobj/fmtuno.cxx @@ -0,0 +1,1066 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include <tools/debug.hxx> +#include <rtl/uuid.h> + +#include <com/sun/star/sheet/ValidationAlertStyle.hpp> +#include <com/sun/star/sheet/ValidationType.hpp> +#include <com/sun/star/sheet/TableValidationVisibility.hpp> + +#include "fmtuno.hxx" +#include "miscuno.hxx" +#include "validat.hxx" +#include "document.hxx" +#include "unoguard.hxx" +#include "unonames.hxx" +#include "styleuno.hxx" // ScStyleNameConversion +#include "tokenarray.hxx" +#include "tokenuno.hxx" + +using namespace ::com::sun::star; +using namespace ::formula; + +//------------------------------------------------------------------------ + +// Map nur fuer PropertySetInfo + +const SfxItemPropertyMapEntry* lcl_GetValidatePropertyMap() +{ + static SfxItemPropertyMapEntry aValidatePropertyMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_ERRALSTY), 0, &getCppuType((sheet::ValidationAlertStyle*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_ERRMESS), 0, &getCppuType((rtl::OUString*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_ERRTITLE), 0, &getCppuType((rtl::OUString*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_IGNOREBL), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_INPMESS), 0, &getCppuType((rtl::OUString*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_INPTITLE), 0, &getCppuType((rtl::OUString*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_SHOWERR), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_SHOWINP), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_SHOWLIST), 0, &getCppuType((sal_Int16*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNONAME_TYPE), 0, &getCppuType((sheet::ValidationType*)0), 0, 0}, + {0,0,0,0,0,0} + }; + return aValidatePropertyMap_Impl; +} + +//------------------------------------------------------------------------ + +SC_SIMPLE_SERVICE_INFO( ScTableConditionalEntry, "ScTableConditionalEntry", "com.sun.star.sheet.TableConditionalEntry" ) +SC_SIMPLE_SERVICE_INFO( ScTableConditionalFormat, "ScTableConditionalFormat", "com.sun.star.sheet.TableConditionalFormat" ) +SC_SIMPLE_SERVICE_INFO( ScTableValidationObj, "ScTableValidationObj", "com.sun.star.sheet.TableValidation" ) + +//------------------------------------------------------------------------ + +sheet::ConditionOperator lcl_ConditionModeToOperator( ScConditionMode eMode ) +{ + sheet::ConditionOperator eOper = sheet::ConditionOperator_NONE; + switch (eMode) + { + case SC_COND_EQUAL: eOper = sheet::ConditionOperator_EQUAL; break; + case SC_COND_LESS: eOper = sheet::ConditionOperator_LESS; break; + case SC_COND_GREATER: eOper = sheet::ConditionOperator_GREATER; break; + case SC_COND_EQLESS: eOper = sheet::ConditionOperator_LESS_EQUAL; break; + case SC_COND_EQGREATER: eOper = sheet::ConditionOperator_GREATER_EQUAL; break; + case SC_COND_NOTEQUAL: eOper = sheet::ConditionOperator_NOT_EQUAL; break; + case SC_COND_BETWEEN: eOper = sheet::ConditionOperator_BETWEEN; break; + case SC_COND_NOTBETWEEN: eOper = sheet::ConditionOperator_NOT_BETWEEN; break; + case SC_COND_DIRECT: eOper = sheet::ConditionOperator_FORMULA; break; + default: + { + // added to avoid warnings + } + } + return eOper; +} + +ScConditionMode lcl_ConditionOperatorToMode( sheet::ConditionOperator eOper ) +{ + ScConditionMode eMode = SC_COND_NONE; + switch (eOper) + { + case sheet::ConditionOperator_EQUAL: eMode = SC_COND_EQUAL; break; + case sheet::ConditionOperator_LESS: eMode = SC_COND_LESS; break; + case sheet::ConditionOperator_GREATER: eMode = SC_COND_GREATER; break; + case sheet::ConditionOperator_LESS_EQUAL: eMode = SC_COND_EQLESS; break; + case sheet::ConditionOperator_GREATER_EQUAL: eMode = SC_COND_EQGREATER; break; + case sheet::ConditionOperator_NOT_EQUAL: eMode = SC_COND_NOTEQUAL; break; + case sheet::ConditionOperator_BETWEEN: eMode = SC_COND_BETWEEN; break; + case sheet::ConditionOperator_NOT_BETWEEN: eMode = SC_COND_NOTBETWEEN; break; + case sheet::ConditionOperator_FORMULA: eMode = SC_COND_DIRECT; break; + default: + { + // added to avoid warnings + } + } + return eMode; +} + +//------------------------------------------------------------------------ + +ScCondFormatEntryItem::ScCondFormatEntryItem() : + meGrammar1( FormulaGrammar::GRAM_UNSPECIFIED ), + meGrammar2( FormulaGrammar::GRAM_UNSPECIFIED ), + meMode( SC_COND_NONE ) +{ +} + +//------------------------------------------------------------------------ + +ScTableConditionalFormat::ScTableConditionalFormat( + ScDocument* pDoc, ULONG nKey, FormulaGrammar::Grammar eGrammar) +{ + // Eintrag aus dem Dokument lesen... + + if ( pDoc && nKey ) + { + ScConditionalFormatList* pList = pDoc->GetCondFormList(); + if (pList) + { + const ScConditionalFormat* pFormat = pList->GetFormat( nKey ); + if (pFormat) + { + // During save to XML. + if (pDoc->IsInExternalReferenceMarking()) + pFormat->MarkUsedExternalReferences(); + + USHORT nEntryCount = pFormat->Count(); + for (USHORT i=0; i<nEntryCount; i++) + { + ScCondFormatEntryItem aItem; + const ScCondFormatEntry* pFormatEntry = pFormat->GetEntry(i); + aItem.meMode = pFormatEntry->GetOperation(); + aItem.maPos = pFormatEntry->GetValidSrcPos(); + aItem.maExpr1 = pFormatEntry->GetExpression(aItem.maPos, 0, 0, eGrammar); + aItem.maExpr2 = pFormatEntry->GetExpression(aItem.maPos, 1, 0, eGrammar); + aItem.meGrammar1 = aItem.meGrammar2 = eGrammar; + aItem.maStyle = pFormatEntry->GetStyle(); + + AddEntry_Impl(aItem); + } + } + } + } +} + +namespace { + +FormulaGrammar::Grammar lclResolveGrammar( FormulaGrammar::Grammar eExtGrammar, FormulaGrammar::Grammar eIntGrammar ) +{ + if( eExtGrammar != FormulaGrammar::GRAM_UNSPECIFIED ) + return eExtGrammar; + OSL_ENSURE( eIntGrammar != FormulaGrammar::GRAM_UNSPECIFIED, "lclResolveGrammar - unspecified grammar, using GRAM_PODF_A1" ); + return (eIntGrammar == FormulaGrammar::GRAM_UNSPECIFIED) ? FormulaGrammar::GRAM_PODF_A1 : eIntGrammar; +} + +} // namespace + +void ScTableConditionalFormat::FillFormat( ScConditionalFormat& rFormat, + ScDocument* pDoc, FormulaGrammar::Grammar eGrammar) const +{ + // ScConditionalFormat = Core-Struktur, muss leer sein + + DBG_ASSERT( rFormat.IsEmpty(), "FillFormat: Format nicht leer" ); + USHORT nCount = (USHORT)aEntries.Count(); + for (USHORT i=0; i<nCount; i++) + { + ScTableConditionalEntry* pEntry = (ScTableConditionalEntry*)aEntries.GetObject(i); + if ( !pEntry ) + continue; + + ScCondFormatEntryItem aData; + pEntry->GetData(aData); + + FormulaGrammar::Grammar eGrammar1 = lclResolveGrammar( eGrammar, aData.meGrammar1 ); + FormulaGrammar::Grammar eGrammar2 = lclResolveGrammar( eGrammar, aData.meGrammar2 ); + + ScCondFormatEntry aCoreEntry( aData.meMode, aData.maExpr1, aData.maExpr2, + pDoc, aData.maPos, aData.maStyle, aData.maExprNmsp1, aData.maExprNmsp2, eGrammar1, eGrammar2 ); + + if ( aData.maPosStr.Len() ) + aCoreEntry.SetSrcString( aData.maPosStr ); + + if ( aData.maTokens1.getLength() ) + { + ScTokenArray aTokenArray; + if ( ScTokenConversion::ConvertToTokenArray(*pDoc, aTokenArray, aData.maTokens1) ) + aCoreEntry.SetFormula1(aTokenArray); + } + + if ( aData.maTokens2.getLength() ) + { + ScTokenArray aTokenArray; + if ( ScTokenConversion::ConvertToTokenArray(*pDoc, aTokenArray, aData.maTokens2) ) + aCoreEntry.SetFormula2(aTokenArray); + } + rFormat.AddEntry( aCoreEntry ); + } +} + +ScTableConditionalFormat::~ScTableConditionalFormat() +{ + ScTableConditionalEntry* pEntry; + aEntries.First(); + while ( ( pEntry = (ScTableConditionalEntry*)aEntries.Remove() ) != NULL ) + pEntry->release(); +} + +void ScTableConditionalFormat::AddEntry_Impl(const ScCondFormatEntryItem& aEntry) +{ + ScTableConditionalEntry* pNew = new ScTableConditionalEntry(this, aEntry); + pNew->acquire(); + aEntries.Insert( pNew, LIST_APPEND ); +} + +void ScTableConditionalFormat::DataChanged() +{ + // wenn's mal das "lebende Objekt" ist, muss hier was passieren... +} + +// XSheetConditionalFormat + +ScTableConditionalEntry* ScTableConditionalFormat::GetObjectByIndex_Impl(USHORT nIndex) const +{ + return (ScTableConditionalEntry*)aEntries.GetObject(nIndex); +} + +void SAL_CALL ScTableConditionalFormat::addNew( + const uno::Sequence<beans::PropertyValue >& aConditionalEntry ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScCondFormatEntryItem aEntry; + aEntry.meMode = SC_COND_NONE; + + const beans::PropertyValue* pPropArray = aConditionalEntry.getConstArray(); + long nPropCount = aConditionalEntry.getLength(); + for (long i = 0; i < nPropCount; i++) + { + const beans::PropertyValue& rProp = pPropArray[i]; + + if ( rProp.Name.equalsAscii( SC_UNONAME_OPERATOR ) ) + { + sheet::ConditionOperator eOper = (sheet::ConditionOperator) + ScUnoHelpFunctions::GetEnumFromAny( rProp.Value ); + aEntry.meMode = lcl_ConditionOperatorToMode( eOper ); + } + else if ( rProp.Name.equalsAscii( SC_UNONAME_FORMULA1 ) ) + { + rtl::OUString aStrVal; + uno::Sequence<sheet::FormulaToken> aTokens; + if ( rProp.Value >>= aStrVal ) + aEntry.maExpr1 = aStrVal; + else if ( rProp.Value >>= aTokens ) + { + aEntry.maExpr1.Erase(); + aEntry.maTokens1 = aTokens; + } + } + else if ( rProp.Name.equalsAscii( SC_UNONAME_FORMULA2 ) ) + { + rtl::OUString aStrVal; + uno::Sequence<sheet::FormulaToken> aTokens; + if ( rProp.Value >>= aStrVal ) + aEntry.maExpr2 = aStrVal; + else if ( rProp.Value >>= aTokens ) + { + aEntry.maExpr2.Erase(); + aEntry.maTokens2 = aTokens; + } + } + else if ( rProp.Name.equalsAscii( SC_UNONAME_SOURCEPOS ) ) + { + table::CellAddress aAddress; + if ( rProp.Value >>= aAddress ) + aEntry.maPos = ScAddress( (SCCOL)aAddress.Column, (SCROW)aAddress.Row, aAddress.Sheet ); + } + else if ( rProp.Name.equalsAscii( SC_UNONAME_SOURCESTR ) ) + { + rtl::OUString aStrVal; + if ( rProp.Value >>= aStrVal ) + aEntry.maPosStr = String( aStrVal ); + } + else if ( rProp.Name.equalsAscii( SC_UNONAME_STYLENAME ) ) + { + rtl::OUString aStrVal; + if ( rProp.Value >>= aStrVal ) + aEntry.maStyle = ScStyleNameConversion::ProgrammaticToDisplayName( + aStrVal, SFX_STYLE_FAMILY_PARA ); + } + else if ( rProp.Name.equalsAscii( SC_UNONAME_FORMULANMSP1 ) ) + { + rtl::OUString aStrVal; + if ( rProp.Value >>= aStrVal ) + aEntry.maExprNmsp1 = aStrVal; + } + else if ( rProp.Name.equalsAscii( SC_UNONAME_FORMULANMSP2 ) ) + { + rtl::OUString aStrVal; + if ( rProp.Value >>= aStrVal ) + aEntry.maExprNmsp2 = aStrVal; + } + else if ( rProp.Name.equalsAscii( SC_UNONAME_GRAMMAR1 ) ) + { + sal_Int32 nVal = 0; + if ( rProp.Value >>= nVal ) + aEntry.meGrammar1 = static_cast< FormulaGrammar::Grammar >( nVal ); + } + else if ( rProp.Name.equalsAscii( SC_UNONAME_GRAMMAR2 ) ) + { + sal_Int32 nVal = 0; + if ( rProp.Value >>= nVal ) + aEntry.meGrammar2 = static_cast< FormulaGrammar::Grammar >( nVal ); + } + else + { + DBG_ERROR("falsche Property"); + //! Exception... + } + } + + AddEntry_Impl(aEntry); + DataChanged(); +} + +void SAL_CALL ScTableConditionalFormat::removeByIndex( sal_Int32 nIndex ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScTableConditionalEntry* pEntry = (ScTableConditionalEntry*)aEntries.GetObject(nIndex); + if (pEntry) + { + aEntries.Remove(pEntry); + pEntry->release(); + DataChanged(); + } +} + +void SAL_CALL ScTableConditionalFormat::clear() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScTableConditionalEntry* pEntry; + aEntries.First(); + while ( ( pEntry = (ScTableConditionalEntry*)aEntries.Remove() ) != NULL ) + pEntry->release(); + + DataChanged(); +} + +// XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScTableConditionalFormat::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.TableConditionalEntryEnumeration"))); +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScTableConditionalFormat::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return aEntries.Count(); +} + +uno::Any SAL_CALL ScTableConditionalFormat::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<sheet::XSheetConditionalEntry> xEntry(GetObjectByIndex_Impl((USHORT)nIndex)); + if (xEntry.is()) + return uno::makeAny(xEntry); + else + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +uno::Type SAL_CALL ScTableConditionalFormat::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((uno::Reference<sheet::XSheetConditionalEntry>*)0); +} + +sal_Bool SAL_CALL ScTableConditionalFormat::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +// conditional format entries have no real names +// -> generate name from index + +rtl::OUString lcl_GetEntryNameFromIndex( sal_Int32 nIndex ) +{ + rtl::OUString aRet( RTL_CONSTASCII_USTRINGPARAM( "Entry" ) ); + aRet += rtl::OUString::valueOf( nIndex ); + return aRet; +} + +uno::Any SAL_CALL ScTableConditionalFormat::getByName( const rtl::OUString& aName ) + throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + uno::Reference<sheet::XSheetConditionalEntry> xEntry; + long nCount = aEntries.Count(); + for (long i=0; i<nCount; i++) + if ( aName == lcl_GetEntryNameFromIndex(i) ) + { + xEntry.set(GetObjectByIndex_Impl((USHORT)i)); + break; + } + + if (xEntry.is()) + return uno::makeAny(xEntry); + else + throw container::NoSuchElementException(); +// return uno::Any(); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScTableConditionalFormat::getElementNames() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + long nCount = aEntries.Count(); + uno::Sequence<rtl::OUString> aNames(nCount); + rtl::OUString* pArray = aNames.getArray(); + for (long i=0; i<nCount; i++) + pArray[i] = lcl_GetEntryNameFromIndex(i); + + return aNames; +} + +sal_Bool SAL_CALL ScTableConditionalFormat::hasByName( const rtl::OUString& aName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + long nCount = aEntries.Count(); + for (long i=0; i<nCount; i++) + if ( aName == lcl_GetEntryNameFromIndex(i) ) + return TRUE; + + return FALSE; +} + +// XUnoTunnel + +sal_Int64 SAL_CALL ScTableConditionalFormat::getSomething( + const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); + } + return 0; +} + +// static +const uno::Sequence<sal_Int8>& ScTableConditionalFormat::getUnoTunnelId() +{ + static uno::Sequence<sal_Int8> * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +// static +ScTableConditionalFormat* ScTableConditionalFormat::getImplementation( + const uno::Reference<sheet::XSheetConditionalEntries> xObj ) +{ + ScTableConditionalFormat* pRet = NULL; + uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); + if (xUT.is()) + pRet = reinterpret_cast<ScTableConditionalFormat*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId()))); + return pRet; +} + +//------------------------------------------------------------------------ + +//UNUSED2008-05 ScTableConditionalEntry::ScTableConditionalEntry() : +//UNUSED2008-05 pParent( NULL ) +//UNUSED2008-05 { +//UNUSED2008-05 } + +ScTableConditionalEntry::ScTableConditionalEntry(ScTableConditionalFormat* pPar, + const ScCondFormatEntryItem& aItem) : + pParent( pPar ), + aData( aItem ) +{ + if (pParent) + pParent->acquire(); +} + +ScTableConditionalEntry::~ScTableConditionalEntry() +{ + if (pParent) + pParent->release(); +} + +void ScTableConditionalEntry::GetData(ScCondFormatEntryItem& rData) const +{ + rData = aData; +} + +// XSheetCondition + +sheet::ConditionOperator SAL_CALL ScTableConditionalEntry::getOperator() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return lcl_ConditionModeToOperator( aData.meMode ); +} + +void SAL_CALL ScTableConditionalEntry::setOperator( sheet::ConditionOperator nOperator ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + aData.meMode = lcl_ConditionOperatorToMode( nOperator ); + if (pParent) + pParent->DataChanged(); +} + +rtl::OUString SAL_CALL ScTableConditionalEntry::getFormula1() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return aData.maExpr1; +} + +void SAL_CALL ScTableConditionalEntry::setFormula1( const rtl::OUString& aFormula1 ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + aData.maExpr1 = String( aFormula1 ); + if (pParent) + pParent->DataChanged(); +} + +rtl::OUString SAL_CALL ScTableConditionalEntry::getFormula2() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return aData.maExpr2; +} + +void SAL_CALL ScTableConditionalEntry::setFormula2( const rtl::OUString& aFormula2 ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + aData.maExpr2 = String( aFormula2 ); + if (pParent) + pParent->DataChanged(); +} + +table::CellAddress SAL_CALL ScTableConditionalEntry::getSourcePosition() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + table::CellAddress aRet; + aRet.Column = aData.maPos.Col(); + aRet.Row = aData.maPos.Row(); + aRet.Sheet = aData.maPos.Tab(); + return aRet; +} + +void SAL_CALL ScTableConditionalEntry::setSourcePosition( const table::CellAddress& aSourcePosition ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + aData.maPos.Set( (SCCOL)aSourcePosition.Column, (SCROW)aSourcePosition.Row, aSourcePosition.Sheet ); + if (pParent) + pParent->DataChanged(); +} + +// XSheetConditionalEntry + +rtl::OUString SAL_CALL ScTableConditionalEntry::getStyleName() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ScStyleNameConversion::DisplayToProgrammaticName( aData.maStyle, SFX_STYLE_FAMILY_PARA ); +} + +void SAL_CALL ScTableConditionalEntry::setStyleName( const rtl::OUString& aStyleName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + aData.maStyle = ScStyleNameConversion::ProgrammaticToDisplayName( aStyleName, SFX_STYLE_FAMILY_PARA ); + if (pParent) + pParent->DataChanged(); +} + +//------------------------------------------------------------------------ + +ScTableValidationObj::ScTableValidationObj(ScDocument* pDoc, ULONG nKey, + const formula::FormulaGrammar::Grammar eGrammar) : + aPropSet( lcl_GetValidatePropertyMap() ) +{ + // Eintrag aus dem Dokument lesen... + + BOOL bFound = FALSE; + if ( pDoc && nKey ) + { + const ScValidationData* pData = pDoc->GetValidationEntry( nKey ); + if (pData) + { + nMode = sal::static_int_cast<USHORT>( pData->GetOperation() ); + aSrcPos = pData->GetValidSrcPos(); // #b4974740# valid pos for expressions + aExpr1 = pData->GetExpression( aSrcPos, 0, 0, eGrammar ); + aExpr2 = pData->GetExpression( aSrcPos, 1, 0, eGrammar ); + meGrammar1 = meGrammar2 = eGrammar; + nValMode = sal::static_int_cast<USHORT>( pData->GetDataMode() ); + bIgnoreBlank = pData->IsIgnoreBlank(); + nShowList = pData->GetListType(); + bShowInput = pData->GetInput( aInputTitle, aInputMessage ); + ScValidErrorStyle eStyle; + bShowError = pData->GetErrMsg( aErrorTitle, aErrorMessage, eStyle ); + nErrorStyle = sal::static_int_cast<USHORT>( eStyle ); + + // During save to XML, sheet::ValidationType_ANY formulas are not + // saved, even if in the list, see + // ScMyValidationsContainer::GetCondition(), so shall not mark + // anything in use. + if (nValMode != SC_VALID_ANY && pDoc->IsInExternalReferenceMarking()) + pData->MarkUsedExternalReferences(); + + bFound = TRUE; + } + } + if (!bFound) + ClearData_Impl(); // Defaults +} + +ScValidationData* ScTableValidationObj::CreateValidationData( ScDocument* pDoc, + formula::FormulaGrammar::Grammar eGrammar ) const +{ + // ScValidationData = Core-Struktur + + FormulaGrammar::Grammar eGrammar1 = lclResolveGrammar( eGrammar, meGrammar1 ); + FormulaGrammar::Grammar eGrammar2 = lclResolveGrammar( eGrammar, meGrammar2 ); + + ScValidationData* pRet = new ScValidationData( (ScValidationMode)nValMode, + (ScConditionMode)nMode, + aExpr1, aExpr2, pDoc, aSrcPos, + maExprNmsp1, maExprNmsp2, + eGrammar1, eGrammar2 ); + pRet->SetIgnoreBlank(bIgnoreBlank); + pRet->SetListType(nShowList); + + if ( aTokens1.getLength() ) + { + ScTokenArray aTokenArray; + if ( ScTokenConversion::ConvertToTokenArray(*pDoc, aTokenArray, aTokens1) ) + pRet->SetFormula1(aTokenArray); + } + + if ( aTokens2.getLength() ) + { + ScTokenArray aTokenArray; + if ( ScTokenConversion::ConvertToTokenArray(*pDoc, aTokenArray, aTokens2) ) + pRet->SetFormula2(aTokenArray); + } + + // set strings for error / input even if disabled (and disable afterwards) + pRet->SetInput( aInputTitle, aInputMessage ); + if (!bShowInput) + pRet->ResetInput(); + pRet->SetError( aErrorTitle, aErrorMessage, (ScValidErrorStyle)nErrorStyle ); + if (!bShowError) + pRet->ResetError(); + + if ( aPosString.Len() ) + pRet->SetSrcString( aPosString ); + + return pRet; +} + +void ScTableValidationObj::ClearData_Impl() +{ + nMode = SC_COND_NONE; + nValMode = SC_VALID_ANY; + bIgnoreBlank = TRUE; + nShowList = sheet::TableValidationVisibility::UNSORTED; + bShowInput = FALSE; + bShowError = FALSE; + nErrorStyle = SC_VALERR_STOP; + aSrcPos.Set(0,0,0); + aExpr1.Erase(); + aExpr2.Erase(); + maExprNmsp1.Erase(); + maExprNmsp2.Erase(); + meGrammar1 = meGrammar2 = FormulaGrammar::GRAM_UNSPECIFIED; // will be overriden when needed + aInputTitle.Erase(); + aInputMessage.Erase(); + aErrorTitle.Erase(); + aErrorMessage.Erase(); +} + +ScTableValidationObj::~ScTableValidationObj() +{ +} + +void ScTableValidationObj::DataChanged() +{ + // wenn's mal das "lebende Objekt" ist, muss hier was passieren... +} + +// XSheetCondition + +sheet::ConditionOperator SAL_CALL ScTableValidationObj::getOperator() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return lcl_ConditionModeToOperator( (ScConditionMode)nMode ); +} + +void SAL_CALL ScTableValidationObj::setOperator( sheet::ConditionOperator nOperator ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + nMode = sal::static_int_cast<USHORT>( lcl_ConditionOperatorToMode( nOperator ) ); + DataChanged(); +} + +rtl::OUString SAL_CALL ScTableValidationObj::getFormula1() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return aExpr1; +} + +void SAL_CALL ScTableValidationObj::setFormula1( const rtl::OUString& aFormula1 ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + aExpr1 = String( aFormula1 ); + DataChanged(); +} + +rtl::OUString SAL_CALL ScTableValidationObj::getFormula2() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return aExpr2; +} + +void SAL_CALL ScTableValidationObj::setFormula2( const rtl::OUString& aFormula2 ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + aExpr2 = String( aFormula2 ); + DataChanged(); +} + +table::CellAddress SAL_CALL ScTableValidationObj::getSourcePosition() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + table::CellAddress aRet; + aRet.Column = aSrcPos.Col(); + aRet.Row = aSrcPos.Row(); + aRet.Sheet = aSrcPos.Tab(); + return aRet; +} + +void SAL_CALL ScTableValidationObj::setSourcePosition( const table::CellAddress& aSourcePosition ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + aSrcPos.Set( (SCCOL)aSourcePosition.Column, (SCROW)aSourcePosition.Row, aSourcePosition.Sheet ); + DataChanged(); +} + +uno::Sequence<sheet::FormulaToken> SAL_CALL ScTableValidationObj::getTokens( sal_Int32 nIndex ) + throw(uno::RuntimeException,lang::IndexOutOfBoundsException) +{ + ScUnoGuard aGuard; + if (nIndex >= 2 || nIndex < 0) + throw lang::IndexOutOfBoundsException(); + + return nIndex == 0 ? aTokens1 : aTokens2; +} + +void SAL_CALL ScTableValidationObj::setTokens( sal_Int32 nIndex, const uno::Sequence<sheet::FormulaToken>& aTokens ) + throw(uno::RuntimeException,lang::IndexOutOfBoundsException) +{ + ScUnoGuard aGuard; + if (nIndex >= 2 || nIndex < 0) + throw lang::IndexOutOfBoundsException(); + + if (nIndex == 0) + { + aTokens1 = aTokens; + aExpr1.Erase(); + } + else if (nIndex == 1) + { + aTokens2 = aTokens; + aExpr2.Erase(); + } +} + +sal_Int32 SAL_CALL ScTableValidationObj::getCount() throw(uno::RuntimeException) +{ + return 2; +} + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTableValidationObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef( + new SfxItemPropertySetInfo( aPropSet.getPropertyMap() )); + return aRef; +} + +void SAL_CALL ScTableValidationObj::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aString(aPropertyName); + + if ( aString.EqualsAscii( SC_UNONAME_SHOWINP ) ) bShowInput = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + else if ( aString.EqualsAscii( SC_UNONAME_SHOWERR ) ) bShowError = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + else if ( aString.EqualsAscii( SC_UNONAME_IGNOREBL ) ) bIgnoreBlank = ScUnoHelpFunctions::GetBoolFromAny( aValue ); + else if ( aString.EqualsAscii( SC_UNONAME_SHOWLIST ) ) aValue >>= nShowList; + else if ( aString.EqualsAscii( SC_UNONAME_INPTITLE ) ) + { + rtl::OUString aStrVal; + if ( aValue >>= aStrVal ) + aInputTitle = String( aStrVal ); + } + else if ( aString.EqualsAscii( SC_UNONAME_INPMESS ) ) + { + rtl::OUString aStrVal; + if ( aValue >>= aStrVal ) + aInputMessage = String( aStrVal ); + } + else if ( aString.EqualsAscii( SC_UNONAME_ERRTITLE ) ) + { + rtl::OUString aStrVal; + if ( aValue >>= aStrVal ) + aErrorTitle = String( aStrVal ); + } + else if ( aString.EqualsAscii( SC_UNONAME_ERRMESS ) ) + { + rtl::OUString aStrVal; + if ( aValue >>= aStrVal ) + aErrorMessage = String( aStrVal ); + } + else if ( aString.EqualsAscii( SC_UNONAME_TYPE ) ) + { + sheet::ValidationType eType = (sheet::ValidationType) + ScUnoHelpFunctions::GetEnumFromAny( aValue ); + switch (eType) + { + case sheet::ValidationType_ANY: nValMode = SC_VALID_ANY; break; + case sheet::ValidationType_WHOLE: nValMode = SC_VALID_WHOLE; break; + case sheet::ValidationType_DECIMAL: nValMode = SC_VALID_DECIMAL; break; + case sheet::ValidationType_DATE: nValMode = SC_VALID_DATE; break; + case sheet::ValidationType_TIME: nValMode = SC_VALID_TIME; break; + case sheet::ValidationType_TEXT_LEN: nValMode = SC_VALID_TEXTLEN; break; + case sheet::ValidationType_LIST: nValMode = SC_VALID_LIST; break; + case sheet::ValidationType_CUSTOM: nValMode = SC_VALID_CUSTOM; break; + default: + { + // added to avoid warnings + } + } + } + else if ( aString.EqualsAscii( SC_UNONAME_ERRALSTY ) ) + { + sheet::ValidationAlertStyle eStyle = (sheet::ValidationAlertStyle) + ScUnoHelpFunctions::GetEnumFromAny( aValue ); + switch (eStyle) + { + case sheet::ValidationAlertStyle_STOP: nErrorStyle = SC_VALERR_STOP; break; + case sheet::ValidationAlertStyle_WARNING: nErrorStyle = SC_VALERR_WARNING; break; + case sheet::ValidationAlertStyle_INFO: nErrorStyle = SC_VALERR_INFO; break; + case sheet::ValidationAlertStyle_MACRO: nErrorStyle = SC_VALERR_MACRO; break; + default: + { + // added to avoid warnings + } + } + } + else if ( aString.EqualsAscii( SC_UNONAME_SOURCESTR ) ) + { + // internal - only for XML filter, not in PropertySetInfo, only set + + rtl::OUString aStrVal; + if ( aValue >>= aStrVal ) + aPosString = String( aStrVal ); + } + else if ( aString.EqualsAscii( SC_UNONAME_FORMULANMSP1 ) ) + { + // internal - only for XML filter, not in PropertySetInfo, only set + + rtl::OUString aStrVal; + if ( aValue >>= aStrVal ) + maExprNmsp1 = aStrVal; + } + else if ( aString.EqualsAscii( SC_UNONAME_FORMULANMSP2 ) ) + { + // internal - only for XML filter, not in PropertySetInfo, only set + + rtl::OUString aStrVal; + if ( aValue >>= aStrVal ) + maExprNmsp2 = aStrVal; + } + else if ( aString.EqualsAscii( SC_UNONAME_GRAMMAR1 ) ) + { + // internal - only for XML filter, not in PropertySetInfo, only set + + sal_Int32 nVal = 0; + if ( aValue >>= nVal ) + meGrammar1 = static_cast< FormulaGrammar::Grammar >(nVal); + } + else if ( aString.EqualsAscii( SC_UNONAME_GRAMMAR2 ) ) + { + // internal - only for XML filter, not in PropertySetInfo, only set + + sal_Int32 nVal = 0; + if ( aValue >>= nVal ) + meGrammar2 = static_cast< FormulaGrammar::Grammar >(nVal); + } + + DataChanged(); +} + +uno::Any SAL_CALL ScTableValidationObj::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aString(aPropertyName); + uno::Any aRet; + + if ( aString.EqualsAscii( SC_UNONAME_SHOWINP ) ) ScUnoHelpFunctions::SetBoolInAny( aRet, bShowInput ); + else if ( aString.EqualsAscii( SC_UNONAME_SHOWERR ) ) ScUnoHelpFunctions::SetBoolInAny( aRet, bShowError ); + else if ( aString.EqualsAscii( SC_UNONAME_IGNOREBL ) ) ScUnoHelpFunctions::SetBoolInAny( aRet, bIgnoreBlank ); + else if ( aString.EqualsAscii( SC_UNONAME_SHOWLIST ) ) aRet <<= nShowList; + else if ( aString.EqualsAscii( SC_UNONAME_INPTITLE ) ) aRet <<= rtl::OUString( aInputTitle ); + else if ( aString.EqualsAscii( SC_UNONAME_INPMESS ) ) aRet <<= rtl::OUString( aInputMessage ); + else if ( aString.EqualsAscii( SC_UNONAME_ERRTITLE ) ) aRet <<= rtl::OUString( aErrorTitle ); + else if ( aString.EqualsAscii( SC_UNONAME_ERRMESS ) ) aRet <<= rtl::OUString( aErrorMessage ); + else if ( aString.EqualsAscii( SC_UNONAME_TYPE ) ) + { + sheet::ValidationType eType = sheet::ValidationType_ANY; + switch (nValMode) + { + case SC_VALID_ANY: eType = sheet::ValidationType_ANY; break; + case SC_VALID_WHOLE: eType = sheet::ValidationType_WHOLE; break; + case SC_VALID_DECIMAL: eType = sheet::ValidationType_DECIMAL; break; + case SC_VALID_DATE: eType = sheet::ValidationType_DATE; break; + case SC_VALID_TIME: eType = sheet::ValidationType_TIME; break; + case SC_VALID_TEXTLEN: eType = sheet::ValidationType_TEXT_LEN; break; + case SC_VALID_LIST: eType = sheet::ValidationType_LIST; break; + case SC_VALID_CUSTOM: eType = sheet::ValidationType_CUSTOM; break; + } + aRet <<= eType; + } + else if ( aString.EqualsAscii( SC_UNONAME_ERRALSTY ) ) + { + sheet::ValidationAlertStyle eStyle = sheet::ValidationAlertStyle_STOP; + switch (nErrorStyle) + { + case SC_VALERR_STOP: eStyle = sheet::ValidationAlertStyle_STOP; break; + case SC_VALERR_WARNING: eStyle = sheet::ValidationAlertStyle_WARNING; break; + case SC_VALERR_INFO: eStyle = sheet::ValidationAlertStyle_INFO; break; + case SC_VALERR_MACRO: eStyle = sheet::ValidationAlertStyle_MACRO; break; + } + aRet <<= eStyle; + } + + return aRet; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScTableValidationObj ) + +// XUnoTunnel + +sal_Int64 SAL_CALL ScTableValidationObj::getSomething( + const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); + } + return 0; +} + +// static +const uno::Sequence<sal_Int8>& ScTableValidationObj::getUnoTunnelId() +{ + static uno::Sequence<sal_Int8> * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +// static +ScTableValidationObj* ScTableValidationObj::getImplementation( + const uno::Reference<beans::XPropertySet> xObj ) +{ + ScTableValidationObj* pRet = NULL; + uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); + if (xUT.is()) + pRet = reinterpret_cast<ScTableValidationObj*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId()))); + return pRet; +} + +//------------------------------------------------------------------------ + + + + diff --git a/sc/source/ui/unoobj/forbiuno.cxx b/sc/source/ui/unoobj/forbiuno.cxx new file mode 100644 index 000000000000..2807a12f7dac --- /dev/null +++ b/sc/source/ui/unoobj/forbiuno.cxx @@ -0,0 +1,93 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include <editeng/forbiddencharacterstable.hxx> + +#include "forbiuno.hxx" +#include "docsh.hxx" + +using namespace ::com::sun::star; + +//------------------------------------------------------------------------ + +vos::ORef<SvxForbiddenCharactersTable> lcl_GetForbidden( ScDocShell* pDocSh ) +{ + vos::ORef<SvxForbiddenCharactersTable> xRet; + if ( pDocSh ) + { + ScDocument* pDoc = pDocSh->GetDocument(); + xRet = pDoc->GetForbiddenCharacters(); + if ( !xRet.isValid() ) + { + // create an empty SvxForbiddenCharactersTable for SvxUnoForbiddenCharsTable, + // so changes can be stored. + + xRet = new SvxForbiddenCharactersTable( pDoc->GetServiceManager() ); + pDoc->SetForbiddenCharacters( xRet ); + } + } + return xRet; +} + +ScForbiddenCharsObj::ScForbiddenCharsObj( ScDocShell* pDocSh ) : + SvxUnoForbiddenCharsTable( lcl_GetForbidden( pDocSh ) ), + pDocShell( pDocSh ) +{ + if (pDocShell) + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScForbiddenCharsObj::~ScForbiddenCharsObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScForbiddenCharsObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // document gone + } +} + +void ScForbiddenCharsObj::onChange() +{ + if (pDocShell) + { + pDocShell->GetDocument()->SetForbiddenCharacters( mxForbiddenChars ); + pDocShell->PostPaintGridAll(); + pDocShell->SetDocumentModified(); + } +} + diff --git a/sc/source/ui/unoobj/funcuno.cxx b/sc/source/ui/unoobj/funcuno.cxx new file mode 100644 index 000000000000..7012b477050c --- /dev/null +++ b/sc/source/ui/unoobj/funcuno.cxx @@ -0,0 +1,745 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include <tools/debug.hxx> +#include <sfx2/app.hxx> +#include <svl/itemprop.hxx> + +#include "scitems.hxx" +#include "funcuno.hxx" +#include "miscuno.hxx" +#include "cellsuno.hxx" +#include "unoguard.hxx" +#include "scdll.hxx" +#include "document.hxx" +#include "compiler.hxx" +#include "formula/errorcodes.hxx" +#include "callform.hxx" +#include "addincol.hxx" +#include "rangeseq.hxx" +#include "cell.hxx" +#include "docoptio.hxx" +#include "optuno.hxx" +#include <docuno.hxx> +// for lcl_CopyData: +#include "markdata.hxx" +#include "patattr.hxx" +#include "docpool.hxx" +#include "attrib.hxx" +#include "clipparam.hxx" +#include "dociter.hxx" + +using namespace com::sun::star; + +//------------------------------------------------------------------------ + +// registered as implementation for service FunctionAccess, +// also supports service SpreadsheetDocumentSettings (to set null date etc.) + +#define SCFUNCTIONACCESS_SERVICE "com.sun.star.sheet.FunctionAccess" +#define SCDOCSETTINGS_SERVICE "com.sun.star.sheet.SpreadsheetDocumentSettings" + +//------------------------------------------------------------------------ + +// helper to use cached document if not in use, temporary document otherwise + +class ScTempDocSource +{ +private: + ScTempDocCache& rCache; + ScDocument* pTempDoc; + + static ScDocument* CreateDocument(); // create and initialize doc + +public: + ScTempDocSource( ScTempDocCache& rDocCache ); + ~ScTempDocSource(); + + ScDocument* GetDocument(); +}; + +//------------------------------------------------------------------------ + +// static +ScDocument* ScTempDocSource::CreateDocument() +{ + ScDocument* pDoc = new ScDocument; // SCDOCMODE_DOCUMENT + pDoc->MakeTable( 0 ); + return pDoc; +} + +ScTempDocSource::ScTempDocSource( ScTempDocCache& rDocCache ) : + rCache( rDocCache ), + pTempDoc( NULL ) +{ + if ( rCache.IsInUse() ) + pTempDoc = CreateDocument(); + else + { + rCache.SetInUse( TRUE ); + if ( !rCache.GetDocument() ) + rCache.SetDocument( CreateDocument() ); + } +} + +ScTempDocSource::~ScTempDocSource() +{ + if ( pTempDoc ) + delete pTempDoc; + else + rCache.SetInUse( FALSE ); +} + +ScDocument* ScTempDocSource::GetDocument() +{ + if ( pTempDoc ) + return pTempDoc; + else + return rCache.GetDocument(); +} + +//------------------------------------------------------------------------ + +ScTempDocCache::ScTempDocCache() : + pDoc( NULL ), + bInUse( FALSE ) +{ +} + +ScTempDocCache::~ScTempDocCache() +{ + DBG_ASSERT( !bInUse, "ScTempDocCache dtor: bInUse" ); + delete pDoc; +} + +void ScTempDocCache::SetDocument( ScDocument* pNew ) +{ + DBG_ASSERT( !pDoc, "ScTempDocCache::SetDocument: already set" ); + pDoc = pNew; +} + +void ScTempDocCache::Clear() +{ + DBG_ASSERT( !bInUse, "ScTempDocCache::Clear: bInUse" ); + delete pDoc; + pDoc = NULL; +} + +//------------------------------------------------------------------------ + +// copy results from one document into another +//! merge this with ScAreaLink::Refresh +//! copy directly without a clipboard document? + +BOOL lcl_CopyData( ScDocument* pSrcDoc, const ScRange& rSrcRange, + ScDocument* pDestDoc, const ScAddress& rDestPos ) +{ + SCTAB nSrcTab = rSrcRange.aStart.Tab(); + SCTAB nDestTab = rDestPos.Tab(); + + ScRange aNewRange( rDestPos, ScAddress( + rSrcRange.aEnd.Col() - rSrcRange.aStart.Col() + rDestPos.Col(), + rSrcRange.aEnd.Row() - rSrcRange.aStart.Row() + rDestPos.Row(), + nDestTab ) ); + + ScDocument* pClipDoc = new ScDocument( SCDOCMODE_CLIP ); + ScMarkData aSourceMark; + aSourceMark.SelectOneTable( nSrcTab ); // for CopyToClip + aSourceMark.SetMarkArea( rSrcRange ); + ScClipParam aClipParam(rSrcRange, false); + pSrcDoc->CopyToClip(aClipParam, pClipDoc, &aSourceMark, false); + + if ( pClipDoc->HasAttrib( 0,0,nSrcTab, MAXCOL,MAXROW,nSrcTab, + HASATTR_MERGED | HASATTR_OVERLAPPED ) ) + { + ScPatternAttr aPattern( pSrcDoc->GetPool() ); + aPattern.GetItemSet().Put( ScMergeAttr() ); // Defaults + aPattern.GetItemSet().Put( ScMergeFlagAttr() ); + pClipDoc->ApplyPatternAreaTab( 0,0, MAXCOL,MAXROW, nSrcTab, aPattern ); + } + + // If the range contains formula cells with default number format, + // apply a number format for the formula result + ScCellIterator aIter( pClipDoc, rSrcRange ); + ScBaseCell* pCell = aIter.GetFirst(); + while (pCell) + { + if (pCell->GetCellType() == CELLTYPE_FORMULA) + { + ScAddress aCellPos = aIter.GetPos(); + sal_uInt32 nFormat = pClipDoc->GetNumberFormat(aCellPos); + if ( (nFormat % SV_COUNTRY_LANGUAGE_OFFSET) == 0 ) + { + ScFormulaCell* pFCell = static_cast<ScFormulaCell*>(pCell); + USHORT nErrCode = pFCell->GetErrCode(); + if ( nErrCode == 0 && pFCell->IsValue() ) + { + sal_uInt32 nNewFormat = pFCell->GetStandardFormat( *pClipDoc->GetFormatTable(), nFormat ); + if ( nNewFormat != nFormat ) + pClipDoc->ApplyAttr( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab(), + SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) ); + } + } + } + pCell = aIter.GetNext(); + } + + ScMarkData aDestMark; + aDestMark.SelectOneTable( nDestTab ); + aDestMark.SetMarkArea( aNewRange ); + pDestDoc->CopyFromClip( aNewRange, aDestMark, IDF_ALL & ~IDF_FORMULA, NULL, pClipDoc, FALSE ); + + delete pClipDoc; + return TRUE; +} + +//------------------------------------------------------------------------ + +ScFunctionAccess::ScFunctionAccess() : + pOptions( NULL ), + aPropertyMap( ScDocOptionsHelper::GetPropertyMap() ), + mbArray( true ), // default according to behaviour of older Office versions + mbValid( true ) +{ + StartListening( *SFX_APP() ); // for SFX_HINT_DEINITIALIZING +} + +ScFunctionAccess::~ScFunctionAccess() +{ + delete pOptions; +} + +void ScFunctionAccess::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA(SfxSimpleHint) && + ((SfxSimpleHint&)rHint).GetId() == SFX_HINT_DEINITIALIZING ) + { + // document must not be used anymore + aDocCache.Clear(); + mbValid = false; + } +} + +// stuff for exService_... + +uno::Reference<uno::XInterface> SAL_CALL ScFunctionAccess_CreateInstance( + const uno::Reference<lang::XMultiServiceFactory>& ) +{ + ScUnoGuard aGuard; + ScDLL::Init(); + static uno::Reference< uno::XInterface > xInst((::cppu::OWeakObject*) new ScFunctionAccess); + return xInst; +} + +rtl::OUString ScFunctionAccess::getImplementationName_Static() +{ + return rtl::OUString::createFromAscii( "stardiv.StarCalc.ScFunctionAccess" ); +} + +uno::Sequence<rtl::OUString> ScFunctionAccess::getSupportedServiceNames_Static() +{ + uno::Sequence<rtl::OUString> aRet(1); + rtl::OUString* pArray = aRet.getArray(); + pArray[0] = rtl::OUString::createFromAscii( SCFUNCTIONACCESS_SERVICE ); + return aRet; +} + +// XServiceInfo + +rtl::OUString SAL_CALL ScFunctionAccess::getImplementationName() throw(uno::RuntimeException) +{ + return rtl::OUString::createFromAscii( "ScFunctionAccess" ); +} + +sal_Bool SAL_CALL ScFunctionAccess::supportsService( const rtl::OUString& rServiceName ) + throw(uno::RuntimeException) +{ + String aServiceStr(rServiceName); + return aServiceStr.EqualsAscii( SCFUNCTIONACCESS_SERVICE ) || + aServiceStr.EqualsAscii( SCDOCSETTINGS_SERVICE ); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScFunctionAccess::getSupportedServiceNames() + throw(uno::RuntimeException) +{ + uno::Sequence<rtl::OUString> aRet(2); + rtl::OUString* pArray = aRet.getArray(); + pArray[0] = rtl::OUString::createFromAscii( SCFUNCTIONACCESS_SERVICE ); + pArray[1] = rtl::OUString::createFromAscii( SCDOCSETTINGS_SERVICE ); + return aRet; +} + +// XPropertySet (document settings) + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScFunctionAccess::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef( + new SfxItemPropertySetInfo( &aPropertyMap )); + return aRef; +} + +void SAL_CALL ScFunctionAccess::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsArrayFunction" ) ) ) + { + if( !(aValue >>= mbArray) ) + throw lang::IllegalArgumentException(); + } + else + { + if ( !pOptions ) + pOptions = new ScDocOptions(); + + // options aren't initialized from configuration - always get the same default behaviour + + BOOL bDone = ScDocOptionsHelper::setPropertyValue( *pOptions, aPropertyMap, aPropertyName, aValue ); + if (!bDone) + throw beans::UnknownPropertyException(); + } +} + +uno::Any SAL_CALL ScFunctionAccess::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "IsArrayFunction" ) ) ) + return uno::Any( mbArray ); + + if ( !pOptions ) + pOptions = new ScDocOptions(); + + // options aren't initialized from configuration - always get the same default behaviour + + return ScDocOptionsHelper::getPropertyValue( *pOptions, aPropertyMap, aPropertyName ); +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScFunctionAccess ) + +// XFunctionAccess + +BOOL lcl_AddFunctionToken( ScTokenArray& rArray, const rtl::OUString& rName,const ScCompiler& rCompiler ) +{ + // function names are always case-insensitive + String aUpper( ScGlobal::pCharClass->upper( rName ) ); + + // same options as in ScCompiler::IsOpCode: + // 1. built-in function name + + OpCode eOp = rCompiler.GetEnglishOpCode( aUpper ); + if ( eOp != ocNone ) + { + rArray.AddOpCode( eOp ); + return TRUE; + } + + // 2. old add in functions + + USHORT nIndex; + if ( ScGlobal::GetFuncCollection()->SearchFunc( aUpper, nIndex ) ) + { + rArray.AddExternal( aUpper.GetBuffer() ); + return TRUE; + } + + // 3. new (uno) add in functions + + String aIntName(ScGlobal::GetAddInCollection()->FindFunction( aUpper, FALSE )); + if (aIntName.Len()) + { + rArray.AddExternal( aIntName.GetBuffer() ); // international name + return TRUE; + } + + return FALSE; // no valid function name +} + +void lcl_AddRef( ScTokenArray& rArray, long nStartRow, long nColCount, long nRowCount ) +{ + ScComplexRefData aRef; + aRef.InitFlags(); + aRef.Ref1.nTab = 0; + aRef.Ref2.nTab = 0; + aRef.Ref1.nCol = 0; + aRef.Ref1.nRow = (SCROW) nStartRow; + aRef.Ref2.nCol = (SCCOL) (nColCount - 1); + aRef.Ref2.nRow = (SCROW) (nStartRow + nRowCount - 1); + rArray.AddDoubleReference(aRef); +} + +class SimpleVisitor +{ +protected: + bool mbArgError; + ScDocument* mpDoc; +public: + SimpleVisitor( ScDocument* pDoc ) : mbArgError( false ), mpDoc( pDoc ) {} + // could possibly just get away with JUST the following overload + // 1) virtual void visitElem( long& nCol, long& nRow, const double& elem ) + // 2) virtual void visitElem( long& nCol, long& nRow, const rtl::OUString& elem ) + // 3) virtual void visitElem( long& nCol, long& nRow, const uno::Any& elem ) + // the other types methods are here just to reflect the orig code and for + // completeness. + + void visitElem( long nCol, long nRow, const sal_Int16& elem ) + { + mpDoc->SetValue( (SCCOL) nCol, (SCROW) nRow, 0, elem ); + } + void visitElem( long nCol, long nRow, const sal_Int32& elem ) + { + mpDoc->SetValue( (SCCOL) nCol, (SCROW) nRow, 0, elem ); + } + void visitElem( long nCol, long nRow, const double& elem ) + { + mpDoc->SetValue( (SCCOL) nCol, (SCROW) nRow, 0, elem ); + } + void visitElem( long nCol, long nRow, const rtl::OUString& elem ) + { + if ( elem.getLength() ) + mpDoc->PutCell( (SCCOL) nCol, (SCROW) nRow, 0, + new ScStringCell( elem ) ); + } + void visitElem( long nCol, long nRow, const uno::Any& rElement ) + { + uno::TypeClass eElemClass = rElement.getValueTypeClass(); + if ( eElemClass == uno::TypeClass_VOID ) + { + // leave empty + } + else if ( eElemClass == uno::TypeClass_BYTE || + eElemClass == uno::TypeClass_SHORT || + eElemClass == uno::TypeClass_UNSIGNED_SHORT || + eElemClass == uno::TypeClass_LONG || + eElemClass == uno::TypeClass_UNSIGNED_LONG || + eElemClass == uno::TypeClass_FLOAT || + eElemClass == uno::TypeClass_DOUBLE ) + { + // #87871# accept integer types because Basic passes a floating point + // variable as byte, short or long if it's an integer number. + double fVal(0.0); + rElement >>= fVal; + visitElem( nCol, nRow, fVal ); + } + else if ( eElemClass == uno::TypeClass_STRING ) + { + rtl::OUString aUStr; + rElement >>= aUStr; + visitElem( nCol, nRow, aUStr ); + } + else + mbArgError = true; + } + bool hasArgError() { return mbArgError; } +}; + +template< class seq > +class SequencesContainer +{ + uno::Sequence< uno::Sequence< seq > > maSeq; + + long& mrDocRow; + bool mbOverflow; + bool mbArgError; + ScDocument* mpDoc; + ScTokenArray& mrTokenArr; + +public: + SequencesContainer( const uno::Any& rArg, ScTokenArray& rTokenArr, long& rDocRow, ScDocument* pDoc ) : + mrDocRow( rDocRow ), mbOverflow(false), mbArgError(false), mpDoc( pDoc ), mrTokenArr( rTokenArr ) + { + rArg >>= maSeq; + } + + void process() + { + SimpleVisitor aVisitor(mpDoc); + long nStartRow = mrDocRow; + long nRowCount = maSeq.getLength(); + long nMaxColCount = 0; + const uno::Sequence< seq >* pRowArr = maSeq.getConstArray(); + for ( long nRow=0; nRow<nRowCount; nRow++ ) + { + long nColCount = pRowArr[nRow].getLength(); + if ( nColCount > nMaxColCount ) + nMaxColCount = nColCount; + const seq* pColArr = pRowArr[nRow].getConstArray(); + for (long nCol=0; nCol<nColCount; nCol++) + if ( nCol <= MAXCOL && mrDocRow <= MAXROW ) + aVisitor.visitElem( nCol, mrDocRow, pColArr[ nCol ] ); + else + mbOverflow=true; + mrDocRow++; + } + mbArgError = aVisitor.hasArgError(); + if ( nRowCount && nMaxColCount && !mbOverflow ) + lcl_AddRef( mrTokenArr, nStartRow, nMaxColCount, nRowCount ); + } + bool getOverflow() { return mbOverflow; } + bool getArgError() { return mbArgError; } +}; + +template <class T> +class ArrayOfArrayProc +{ +public: +static void processSequences( ScDocument* pDoc, const uno::Any& rArg, ScTokenArray& rTokenArr, + long& rDocRow, BOOL& rArgErr, BOOL& rOverflow ) +{ + SequencesContainer< T > aContainer( rArg, rTokenArr, rDocRow, pDoc ); + aContainer.process(); + rArgErr = aContainer.getArgError(); + rOverflow = aContainer.getOverflow(); +} +}; + +uno::Any SAL_CALL ScFunctionAccess::callFunction( const rtl::OUString& aName, + const uno::Sequence<uno::Any>& aArguments ) + throw(container::NoSuchElementException, lang::IllegalArgumentException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if (!mbValid) + throw uno::RuntimeException(); + + // use cached document if not in use, temporary document otherwise + // (deleted in ScTempDocSource dtor) + ScTempDocSource aSource( aDocCache ); + ScDocument* pDoc = aSource.GetDocument(); + const static SCTAB nTempSheet = 1; + // Create an extra tab to contain the Function Cell + // this will allow full rows to be used. + if ( !pDoc->HasTable( nTempSheet ) ) + pDoc->MakeTable( nTempSheet ); + + /// TODO: check + ScAddress aAdr; + ScCompiler aCompiler(pDoc,aAdr); + aCompiler.SetGrammar(pDoc->GetGrammar()); + //if (!ScCompiler::IsInitialized()) + // ScCompiler::InitSymbolsEnglish(); + + // + // find function + // + + ScTokenArray aTokenArr; + if ( !lcl_AddFunctionToken( aTokenArr, aName,aCompiler ) ) + { + // function not found + throw container::NoSuchElementException(); + } + + // + // set options (null date, etc.) + // + + if ( pOptions ) + pDoc->SetDocOptions( *pOptions ); + + // + // add arguments to token array + // + + BOOL bArgErr = FALSE; + BOOL bOverflow = FALSE; + long nDocRow = 0; + long nArgCount = aArguments.getLength(); + const uno::Any* pArgArr = aArguments.getConstArray(); + + aTokenArr.AddOpCode(ocOpen); + for (long nPos=0; nPos<nArgCount; nPos++) + { + if ( nPos > 0 ) + aTokenArr.AddOpCode(ocSep); + + const uno::Any& rArg = pArgArr[nPos]; + + uno::TypeClass eClass = rArg.getValueTypeClass(); + uno::Type aType = rArg.getValueType(); + if ( eClass == uno::TypeClass_BYTE || + eClass == uno::TypeClass_BOOLEAN || + eClass == uno::TypeClass_SHORT || + eClass == uno::TypeClass_UNSIGNED_SHORT || + eClass == uno::TypeClass_LONG || + eClass == uno::TypeClass_UNSIGNED_LONG || + eClass == uno::TypeClass_FLOAT || + eClass == uno::TypeClass_DOUBLE ) + { + // #87871# accept integer types because Basic passes a floating point + // variable as byte, short or long if it's an integer number. + double fVal = 0; + rArg >>= fVal; + aTokenArr.AddDouble( fVal ); + } + else if ( eClass == uno::TypeClass_STRING ) + { + rtl::OUString aUStr; + rArg >>= aUStr; + String aStr( aUStr ); + aTokenArr.AddString( aStr.GetBuffer() ); + } + else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<sal_Int16> > *)0 ) ) ) + { + ArrayOfArrayProc<sal_Int16>::processSequences( pDoc, rArg, aTokenArr, nDocRow, bArgErr, bOverflow ); + } + else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<sal_Int32> > *)0 ) ) ) + { + ArrayOfArrayProc<sal_Int32>::processSequences( pDoc, rArg, aTokenArr, nDocRow, bArgErr, bOverflow ); + } + else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<double> > *)0 ) ) ) + { + ArrayOfArrayProc<double>::processSequences( pDoc, rArg, aTokenArr, nDocRow, bArgErr, bOverflow ); + } + else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<rtl::OUString> > *)0 ) ) ) + { + ArrayOfArrayProc<rtl::OUString>::processSequences( pDoc, rArg, aTokenArr, nDocRow, bArgErr, bOverflow ); + } + else if ( aType.equals( getCppuType( (uno::Sequence< uno::Sequence<uno::Any> > *)0 ) ) ) + { + ArrayOfArrayProc<uno::Any>::processSequences( pDoc, rArg, aTokenArr, nDocRow, bArgErr, bOverflow ); + } + else if ( aType.equals( getCppuType( (uno::Reference<table::XCellRange>*)0 ) ) ) + { + // currently, only our own cell ranges are supported + + uno::Reference<table::XCellRange> xRange(rArg, uno::UNO_QUERY); + ScCellRangesBase* pImpl = ScCellRangesBase::getImplementation( xRange ); + if ( pImpl ) + { + ScDocument* pSrcDoc = pImpl->GetDocument(); + const ScRangeList& rRanges = pImpl->GetRangeList(); + if ( pSrcDoc && rRanges.Count() == 1 ) + { + ScRange aSrcRange = *rRanges.GetObject(0); + + long nStartRow = nDocRow; + long nColCount = aSrcRange.aEnd.Col() - aSrcRange.aStart.Col() + 1; + long nRowCount = aSrcRange.aEnd.Row() - aSrcRange.aStart.Row() + 1; + + if ( nStartRow + nRowCount > MAXROWCOUNT ) + bOverflow = TRUE; + else + { + // copy data + if ( !lcl_CopyData( pSrcDoc, aSrcRange, pDoc, ScAddress( 0, (SCROW)nDocRow, 0 ) ) ) + bOverflow = TRUE; + } + + nDocRow += nRowCount; + if ( !bOverflow ) + lcl_AddRef( aTokenArr, nStartRow, nColCount, nRowCount ); + } + else + bArgErr = TRUE; + } + else + bArgErr = TRUE; + } + else + bArgErr = TRUE; // invalid type + } + aTokenArr.AddOpCode(ocClose); + aTokenArr.AddOpCode(ocStop); + + // + // execute formula + // + + uno::Any aRet; + if ( !bArgErr && !bOverflow && nDocRow <= MAXROWCOUNT ) + { + ScAddress aFormulaPos( 0, 0, nTempSheet ); + // GRAM_PODF_A1 doesn't really matter for the token array but fits with + // other API compatibility grammars. + ScFormulaCell* pFormula = new ScFormulaCell( pDoc, aFormulaPos, + &aTokenArr, formula::FormulaGrammar::GRAM_PODF_A1, (BYTE)(mbArray ? MM_FORMULA : MM_NONE) ); + pDoc->PutCell( aFormulaPos, pFormula ); //! necessary? + + // call GetMatrix before GetErrCode because GetMatrix always recalculates + // if there is no matrix result + + const ScMatrix* pMat = mbArray ? pFormula->GetMatrix() : 0; + USHORT nErrCode = pFormula->GetErrCode(); + if ( nErrCode == 0 ) + { + if ( pMat ) + { + // array result + ScRangeToSequence::FillMixedArray( aRet, pMat ); + } + else if ( pFormula->IsValue() ) + { + // numeric value + aRet <<= (double) pFormula->GetValue(); + } + else + { + // string result + String aStrVal; + pFormula->GetString( aStrVal ); + aRet <<= rtl::OUString( aStrVal ); + } + } + else if ( nErrCode == NOTAVAILABLE ) + { + // #N/A: leave result empty, no exception + } + else + { + // any other error: IllegalArgumentException + bArgErr = TRUE; + } + + pDoc->DeleteAreaTab( 0, 0, MAXCOL, MAXROW, 0, IDF_ALL ); + pDoc->DeleteAreaTab( 0, 0, 0, 0, nTempSheet, IDF_ALL ); + } + + if (bOverflow) + throw uno::RuntimeException(); + + if (bArgErr) + throw lang::IllegalArgumentException(); + + return aRet; +} + + diff --git a/sc/source/ui/unoobj/linkuno.cxx b/sc/source/ui/unoobj/linkuno.cxx new file mode 100644 index 000000000000..a119eda13a32 --- /dev/null +++ b/sc/source/ui/unoobj/linkuno.cxx @@ -0,0 +1,1821 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include <svl/smplhint.hxx> +#include <sfx2/linkmgr.hxx> + +#include "linkuno.hxx" +#include "miscuno.hxx" +#include "convuno.hxx" +#include "docsh.hxx" +#include "docfunc.hxx" +#include "collect.hxx" +#include "tablink.hxx" +#include "arealink.hxx" +#include "unoguard.hxx" +#include "hints.hxx" +#include "unonames.hxx" +#include "rangeseq.hxx" +#include "token.hxx" + +#include <vector> +#include <climits> + +using namespace com::sun::star; +using namespace formula; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::UNO_QUERY; +using ::com::sun::star::uno::UNO_QUERY_THROW; +using ::com::sun::star::lang::IllegalArgumentException; +using ::com::sun::star::uno::RuntimeException; +using ::rtl::OUString; +using ::std::vector; + +//------------------------------------------------------------------------ + +// fuer Sheet- und Area-Links benutzt: +const SfxItemPropertyMapEntry* lcl_GetSheetLinkMap() +{ + static SfxItemPropertyMapEntry aSheetLinkMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_FILTER), 0, &getCppuType((rtl::OUString*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_FILTOPT), 0, &getCppuType((rtl::OUString*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_LINKURL), 0, &getCppuType((rtl::OUString*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_REFDELAY), 0, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_REFPERIOD), 0, &getCppuType((sal_Int32*)0), 0, 0 }, + {0,0,0,0,0,0} + }; + return aSheetLinkMap_Impl; +} + +//------------------------------------------------------------------------ + +SV_IMPL_PTRARR( XRefreshListenerArr_Impl, XRefreshListenerPtr ); + +SC_SIMPLE_SERVICE_INFO( ScAreaLinkObj, "ScAreaLinkObj", "com.sun.star.sheet.CellAreaLink" ) +SC_SIMPLE_SERVICE_INFO( ScAreaLinksObj, "ScAreaLinksObj", "com.sun.star.sheet.CellAreaLinks" ) +SC_SIMPLE_SERVICE_INFO( ScDDELinkObj, "ScDDELinkObj", "com.sun.star.sheet.DDELink" ) +SC_SIMPLE_SERVICE_INFO( ScDDELinksObj, "ScDDELinksObj", "com.sun.star.sheet.DDELinks" ) +SC_SIMPLE_SERVICE_INFO( ScSheetLinkObj, "ScSheetLinkObj", "com.sun.star.sheet.SheetLink" ) +SC_SIMPLE_SERVICE_INFO( ScSheetLinksObj, "ScSheetLinksObj", "com.sun.star.sheet.SheetLinks" ) + +//------------------------------------------------------------------------ + +ScSheetLinkObj::ScSheetLinkObj(ScDocShell* pDocSh, const String& rName) : + aPropSet( lcl_GetSheetLinkMap() ), + pDocShell( pDocSh ), + aFileName( rName ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScSheetLinkObj::~ScSheetLinkObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScSheetLinkObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + //! notify if links in document are changed + // UpdateRef is not needed here + + if ( rHint.ISA( SfxSimpleHint ) ) + { + if ( ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + pDocShell = NULL; // pointer is invalid + } + else if ( rHint.ISA( ScLinkRefreshedHint ) ) + { + const ScLinkRefreshedHint& rLH = (const ScLinkRefreshedHint&) rHint; + if ( rLH.GetLinkType() == SC_LINKREFTYPE_SHEET && rLH.GetUrl() == aFileName ) + Refreshed_Impl(); + } +} + +ScTableLink* ScSheetLinkObj::GetLink_Impl() const +{ + if (pDocShell) + { + sfx2::LinkManager* pLinkManager = pDocShell->GetDocument()->GetLinkManager(); + USHORT nCount = pLinkManager->GetLinks().Count(); + for (USHORT i=0; i<nCount; i++) + { + ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[i]; + if (pBase->ISA(ScTableLink)) + { + ScTableLink* pTabLink = (ScTableLink*)pBase; + if ( pTabLink->GetFileName() == aFileName ) + return pTabLink; + } + } + } + return NULL; // nicht gefunden +} + +// XNamed + +rtl::OUString SAL_CALL ScSheetLinkObj::getName() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getFileName(); // Name ist der Dateiname (URL) +} + +void SAL_CALL ScSheetLinkObj::setName( const rtl::OUString& aName ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + setFileName(aName); // Name ist der Dateiname (URL) +} + +// XRefreshable + +void SAL_CALL ScSheetLinkObj::refresh() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScTableLink* pLink = GetLink_Impl(); + if (pLink) + pLink->Refresh( pLink->GetFileName(), pLink->GetFilterName(), NULL, pLink->GetRefreshDelay() ); +} + +void SAL_CALL ScSheetLinkObj::addRefreshListener( + const uno::Reference<util::XRefreshListener >& xListener ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<util::XRefreshListener>* pObj = + new uno::Reference<util::XRefreshListener>( xListener ); + aRefreshListeners.Insert( pObj, aRefreshListeners.Count() ); + + // hold one additional ref to keep this object alive as long as there are listeners + if ( aRefreshListeners.Count() == 1 ) + acquire(); +} + +void SAL_CALL ScSheetLinkObj::removeRefreshListener( + const uno::Reference<util::XRefreshListener >& xListener ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + USHORT nCount = aRefreshListeners.Count(); + for ( USHORT n=nCount; n--; ) + { + uno::Reference<util::XRefreshListener>* pObj = aRefreshListeners[n]; + if ( *pObj == xListener ) + { + aRefreshListeners.DeleteAndDestroy( n ); + if ( aRefreshListeners.Count() == 0 ) + release(); // release ref for listeners + break; + } + } +} + +void ScSheetLinkObj::Refreshed_Impl() +{ + lang::EventObject aEvent; + aEvent.Source.set((cppu::OWeakObject*)this); + for ( USHORT n=0; n<aRefreshListeners.Count(); n++ ) + (*aRefreshListeners[n])->refreshed( aEvent ); +} + +void ScSheetLinkObj::ModifyRefreshDelay_Impl( sal_Int32 nRefresh ) +{ + ScTableLink* pLink = GetLink_Impl(); + if( pLink ) + pLink->SetRefreshDelay( (ULONG) nRefresh ); +} + +// XPropertySet + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScSheetLinkObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef( + new SfxItemPropertySetInfo( aPropSet.getPropertyMap() )); + return aRef; +} + +void SAL_CALL ScSheetLinkObj::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aNameString(aPropertyName); + rtl::OUString aValStr; + if ( aNameString.EqualsAscii( SC_UNONAME_LINKURL ) ) + { + if ( aValue >>= aValStr ) + setFileName( aValStr ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_FILTER ) ) + { + if ( aValue >>= aValStr ) + setFilter( aValStr ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_FILTOPT ) ) + { + if ( aValue >>= aValStr ) + setFilterOptions( aValStr ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_REFPERIOD ) ) + { + sal_Int32 nRefresh = 0; + if ( aValue >>= nRefresh ) + setRefreshDelay( nRefresh ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_REFDELAY ) ) + { + sal_Int32 nRefresh = 0; + if ( aValue >>= nRefresh ) + setRefreshDelay( nRefresh ); + } +} + +uno::Any SAL_CALL ScSheetLinkObj::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aNameString(aPropertyName); + uno::Any aRet; + if ( aNameString.EqualsAscii( SC_UNONAME_LINKURL ) ) + aRet <<= getFileName(); + else if ( aNameString.EqualsAscii( SC_UNONAME_FILTER ) ) + aRet <<= getFilter(); + else if ( aNameString.EqualsAscii( SC_UNONAME_FILTOPT ) ) + aRet <<= getFilterOptions(); + else if ( aNameString.EqualsAscii( SC_UNONAME_REFPERIOD ) ) + aRet <<= getRefreshDelay(); + else if ( aNameString.EqualsAscii( SC_UNONAME_REFDELAY ) ) + aRet <<= getRefreshDelay(); + return aRet; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScSheetLinkObj ) + +// internal: + +rtl::OUString ScSheetLinkObj::getFileName(void) const +{ + ScUnoGuard aGuard; + return aFileName; +} + +void ScSheetLinkObj::setFileName(const rtl::OUString& rNewName) +{ + ScUnoGuard aGuard; + ScTableLink* pLink = GetLink_Impl(); + if (pLink) + { + // pLink->Refresh mit neuem Dateinamen bringt sfx2::LinkManager durcheinander + // darum per Hand die Tabellen umsetzen und Link per UpdateLinks neu erzeugen + + String aNewStr(ScGlobal::GetAbsDocName( String(rNewName), pDocShell )); + + // zuerst Tabellen umsetzen + + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab=0; nTab<nTabCount; nTab++) + if ( pDoc->IsLinked(nTab) && pDoc->GetLinkDoc(nTab) == aFileName ) // alte Datei + pDoc->SetLink( nTab, pDoc->GetLinkMode(nTab), aNewStr, + pDoc->GetLinkFlt(nTab), pDoc->GetLinkOpt(nTab), + pDoc->GetLinkTab(nTab), + pDoc->GetLinkRefreshDelay(nTab) ); // nur Datei aendern + + // Links updaten + //! Undo !!! + + pLink = NULL; // wird bei UpdateLinks ungueltig + pDocShell->UpdateLinks(); // alter Link raus, evtl. neuen Link anlegen + + // Daten kopieren + + aFileName = aNewStr; + pLink = GetLink_Impl(); // neuer Link mit neuem Namen + if (pLink) + pLink->Update(); // inkl. Paint & Undo fuer Daten + } +} + +rtl::OUString ScSheetLinkObj::getFilter(void) const +{ + ScUnoGuard aGuard; + rtl::OUString aRet; + ScTableLink* pLink = GetLink_Impl(); + if (pLink) + aRet = pLink->GetFilterName(); + return aRet; +} + +void ScSheetLinkObj::setFilter(const rtl::OUString& Filter) +{ + ScUnoGuard aGuard; + ScTableLink* pLink = GetLink_Impl(); + if (pLink) + { + String aFilterStr(Filter); + pLink->Refresh( aFileName, aFilterStr, NULL, pLink->GetRefreshDelay() ); + } +} + +rtl::OUString ScSheetLinkObj::getFilterOptions(void) const +{ + ScUnoGuard aGuard; + rtl::OUString aRet; + ScTableLink* pLink = GetLink_Impl(); + if (pLink) + aRet = pLink->GetOptions(); + return aRet; +} + +void ScSheetLinkObj::setFilterOptions(const rtl::OUString& FilterOptions) +{ + ScUnoGuard aGuard; + ScTableLink* pLink = GetLink_Impl(); + if (pLink) + { + String aOptStr(FilterOptions); + pLink->Refresh( aFileName, pLink->GetFilterName(), &aOptStr, pLink->GetRefreshDelay() ); + } +} + +sal_Int32 ScSheetLinkObj::getRefreshDelay(void) const +{ + ScUnoGuard aGuard; + sal_Int32 nRet = 0; + ScTableLink* pLink = GetLink_Impl(); + if (pLink) + nRet = (sal_Int32) pLink->GetRefreshDelay(); + return nRet; +} + +void ScSheetLinkObj::setRefreshDelay(sal_Int32 nRefreshDelay) +{ + ScUnoGuard aGuard; + ModifyRefreshDelay_Impl( nRefreshDelay ); +} + +//------------------------------------------------------------------------ + +ScSheetLinksObj::ScSheetLinksObj(ScDocShell* pDocSh) : + pDocShell( pDocSh ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScSheetLinksObj::~ScSheetLinksObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScSheetLinksObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + // Referenz-Update interessiert hier nicht + + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +// XSheetLinks + +ScSheetLinkObj* ScSheetLinksObj::GetObjectByIndex_Impl(INT32 nIndex) +{ + if (pDocShell) + { + INT32 nCount = 0; + ScStrCollection aNames; // um doppelte wegzulassen + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab=0; nTab<nTabCount; nTab++) + if (pDoc->IsLinked(nTab)) + { + String aLinkDoc = pDoc->GetLinkDoc( nTab ); + StrData* pData = new StrData(aLinkDoc); + if (aNames.Insert(pData)) + { + if ( nCount == nIndex ) + return new ScSheetLinkObj( pDocShell, aLinkDoc ); + ++nCount; + } + else + delete pData; + } + } + return NULL; // kein Dokument oder Index zu gross +} + +ScSheetLinkObj* ScSheetLinksObj::GetObjectByName_Impl(const rtl::OUString& aName) +{ + // Name ist der Dateiname + + if (pDocShell) + { + String aNameStr(aName); + + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab=0; nTab<nTabCount; nTab++) + if (pDoc->IsLinked(nTab)) + { + //! case-insensitiv ??? + String aLinkDoc = pDoc->GetLinkDoc( nTab ); + if ( aLinkDoc == aNameStr ) + return new ScSheetLinkObj( pDocShell, aNameStr ); + } + } + + return NULL; +} + +// XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScSheetLinksObj::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.SheetLinksEnumeration"))); +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScSheetLinksObj::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + INT32 nCount = 0; + if (pDocShell) + { + ScStrCollection aNames; // um doppelte wegzulassen + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab=0; nTab<nTabCount; nTab++) + if (pDoc->IsLinked(nTab)) + { + String aLinkDoc(pDoc->GetLinkDoc( nTab )); + StrData* pData = new StrData(aLinkDoc); + if (aNames.Insert(pData)) + ++nCount; + else + delete pData; + } + } + return nCount; +} + +uno::Any SAL_CALL ScSheetLinksObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<beans::XPropertySet> xLink(GetObjectByIndex_Impl(nIndex)); + if (xLink.is()) + return uno::makeAny(xLink); + else + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +uno::Type SAL_CALL ScSheetLinksObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((uno::Reference<beans::XPropertySet>*)0); +} + +sal_Bool SAL_CALL ScSheetLinksObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +uno::Any SAL_CALL ScSheetLinksObj::getByName( const rtl::OUString& aName ) + throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<beans::XPropertySet> xLink(GetObjectByName_Impl(aName)); + if (xLink.is()) + return uno::makeAny(xLink); + else + throw container::NoSuchElementException(); +// return uno::Any(); +} + +sal_Bool SAL_CALL ScSheetLinksObj::hasByName( const rtl::OUString& aName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + // Name ist der Dateiname + + if (pDocShell) + { + String aNameStr(aName); + + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB nTabCount = pDoc->GetTableCount(); + for (SCTAB nTab=0; nTab<nTabCount; nTab++) + if (pDoc->IsLinked(nTab)) + { + //! case-insensitiv ??? + String aLinkDoc(pDoc->GetLinkDoc( nTab )); + if ( aLinkDoc == aNameStr ) + return TRUE; + } + } + return FALSE; +} + +uno::Sequence<rtl::OUString> SAL_CALL ScSheetLinksObj::getElementNames() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + // Name ist der Dateiname + + if (pDocShell) + { + ScStrCollection aNames; // um doppelte wegzulassen + ScDocument* pDoc = pDocShell->GetDocument(); + SCTAB nTabCount = pDoc->GetTableCount(); + String aName; + + INT32 nLinkCount = getCount(); + uno::Sequence<rtl::OUString> aSeq(nLinkCount); + rtl::OUString* pAry = aSeq.getArray(); + USHORT nPos = 0; + for (SCTAB nTab=0; nTab<nTabCount; nTab++) + { + if (pDoc->IsLinked(nTab)) + { + String aLinkDoc(pDoc->GetLinkDoc( nTab )); + StrData* pData = new StrData(aLinkDoc); + if (aNames.Insert(pData)) + pAry[nPos++] = aLinkDoc; + else + delete pData; + } + } + DBG_ASSERT( nPos==nLinkCount, "verzaehlt" ); + return aSeq; + } + return uno::Sequence<rtl::OUString>(); +} + +//------------------------------------------------------------------------ + +ScAreaLink* lcl_GetAreaLink( ScDocShell* pDocShell, USHORT nPos ) +{ + if (pDocShell) + { + sfx2::LinkManager* pLinkManager = pDocShell->GetDocument()->GetLinkManager(); + USHORT nTotalCount = pLinkManager->GetLinks().Count(); + USHORT nAreaCount = 0; + for (USHORT i=0; i<nTotalCount; i++) + { + ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[i]; + if (pBase->ISA(ScAreaLink)) + { + if ( nAreaCount == nPos ) + return (ScAreaLink*)pBase; + ++nAreaCount; + } + } + } + return NULL; // nicht gefunden +} + +ScAreaLinkObj::ScAreaLinkObj(ScDocShell* pDocSh, USHORT nP) : + aPropSet( lcl_GetSheetLinkMap() ), + pDocShell( pDocSh ), + nPos( nP ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScAreaLinkObj::~ScAreaLinkObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScAreaLinkObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + //! notify if links in document are changed + // UpdateRef is not needed here + + if ( rHint.ISA( SfxSimpleHint ) ) + { + if ( ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + pDocShell = NULL; // pointer is invalid + } + else if ( rHint.ISA( ScLinkRefreshedHint ) ) + { + const ScLinkRefreshedHint& rLH = (const ScLinkRefreshedHint&) rHint; + if ( rLH.GetLinkType() == SC_LINKREFTYPE_AREA ) + { + // get this link to compare dest position + ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); + if ( pLink && pLink->GetDestArea().aStart == rLH.GetDestPos() ) + Refreshed_Impl(); + } + } +} + +// XFileLink + +void ScAreaLinkObj::Modify_Impl( const rtl::OUString* pNewFile, const rtl::OUString* pNewFilter, + const rtl::OUString* pNewOptions, const rtl::OUString* pNewSource, + const table::CellRangeAddress* pNewDest ) +{ + ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); + if (pLink) + { + String aFile (pLink->GetFile()); + String aFilter (pLink->GetFilter()); + String aOptions (pLink->GetOptions()); + String aSource (pLink->GetSource()); + ScRange aDest (pLink->GetDestArea()); + ULONG nRefresh = pLink->GetRefreshDelay(); + + //! Undo fuer Loeschen + //! Undo zusammenfassen + + sfx2::LinkManager* pLinkManager = pDocShell->GetDocument()->GetLinkManager(); + pLinkManager->Remove( pLink ); + pLink = NULL; // bei Remove geloescht + + BOOL bFitBlock = TRUE; // verschieben, wenn durch Update Groesse geaendert + if (pNewFile) + { + aFile = String( *pNewFile ); + aFile = ScGlobal::GetAbsDocName( aFile, pDocShell ); //! in InsertAreaLink? + } + if (pNewFilter) + aFilter = String( *pNewFilter ); + if (pNewOptions) + aOptions = String( *pNewOptions ); + if (pNewSource) + aSource = String( *pNewSource ); + if (pNewDest) + { + ScUnoConversion::FillScRange( aDest, *pNewDest ); + bFitBlock = FALSE; // neuer Bereich angegeben -> keine Inhalte verschieben + } + + ScDocFunc aFunc(*pDocShell); + aFunc.InsertAreaLink( aFile, aFilter, aOptions, aSource, aDest, nRefresh, bFitBlock, TRUE ); + } +} + +void ScAreaLinkObj::ModifyRefreshDelay_Impl( sal_Int32 nRefresh ) +{ + ScAreaLink* pLink = lcl_GetAreaLink( pDocShell, nPos ); + if( pLink ) + pLink->SetRefreshDelay( (ULONG) nRefresh ); +} + +// XRefreshable + +void SAL_CALL ScAreaLinkObj::refresh() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); + if (pLink) + pLink->Refresh( pLink->GetFile(), pLink->GetFilter(), pLink->GetSource(), pLink->GetRefreshDelay() ); +} + +void SAL_CALL ScAreaLinkObj::addRefreshListener( + const uno::Reference<util::XRefreshListener >& xListener ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<util::XRefreshListener>* pObj = + new uno::Reference<util::XRefreshListener>( xListener ); + aRefreshListeners.Insert( pObj, aRefreshListeners.Count() ); + + // hold one additional ref to keep this object alive as long as there are listeners + if ( aRefreshListeners.Count() == 1 ) + acquire(); +} + +void SAL_CALL ScAreaLinkObj::removeRefreshListener( + const uno::Reference<util::XRefreshListener >& xListener ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + USHORT nCount = aRefreshListeners.Count(); + for ( USHORT n=nCount; n--; ) + { + uno::Reference<util::XRefreshListener>* pObj = aRefreshListeners[n]; + if ( *pObj == xListener ) + { + aRefreshListeners.DeleteAndDestroy( n ); + if ( aRefreshListeners.Count() == 0 ) + release(); // release ref for listeners + break; + } + } +} + +void ScAreaLinkObj::Refreshed_Impl() +{ + lang::EventObject aEvent; + aEvent.Source.set((cppu::OWeakObject*)this); + for ( USHORT n=0; n<aRefreshListeners.Count(); n++ ) + (*aRefreshListeners[n])->refreshed( aEvent ); +} + +// XPropertySet + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScAreaLinkObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef( + new SfxItemPropertySetInfo( aPropSet.getPropertyMap() )); + return aRef; +} + +void SAL_CALL ScAreaLinkObj::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aNameString(aPropertyName); + rtl::OUString aValStr; + if ( aNameString.EqualsAscii( SC_UNONAME_LINKURL ) ) + { + if ( aValue >>= aValStr ) + setFileName( aValStr ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_FILTER ) ) + { + if ( aValue >>= aValStr ) + setFilter( aValStr ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_FILTOPT ) ) + { + if ( aValue >>= aValStr ) + setFilterOptions( aValStr ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_REFPERIOD ) ) + { + sal_Int32 nRefresh = 0; + if ( aValue >>= nRefresh ) + setRefreshDelay( nRefresh ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_REFDELAY ) ) + { + sal_Int32 nRefresh = 0; + if ( aValue >>= nRefresh ) + setRefreshDelay( nRefresh ); + } +} + +uno::Any SAL_CALL ScAreaLinkObj::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aNameString(aPropertyName); + uno::Any aRet; + if ( aNameString.EqualsAscii( SC_UNONAME_LINKURL ) ) + aRet <<= getFileName(); + else if ( aNameString.EqualsAscii( SC_UNONAME_FILTER ) ) + aRet <<= getFilter(); + else if ( aNameString.EqualsAscii( SC_UNONAME_FILTOPT ) ) + aRet <<= getFilterOptions(); + else if ( aNameString.EqualsAscii( SC_UNONAME_REFPERIOD ) ) + aRet <<= getRefreshDelay(); + else if ( aNameString.EqualsAscii( SC_UNONAME_REFDELAY ) ) + aRet <<= getRefreshDelay(); + return aRet; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScAreaLinkObj ) + +// internal: + +rtl::OUString ScAreaLinkObj::getFileName(void) const +{ + ScUnoGuard aGuard; + rtl::OUString aRet; + ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); + if (pLink) + aRet = pLink->GetFile(); + return aRet; +} + +void ScAreaLinkObj::setFileName(const rtl::OUString& rNewName) +{ + ScUnoGuard aGuard; + Modify_Impl( &rNewName, NULL, NULL, NULL, NULL ); +} + +rtl::OUString ScAreaLinkObj::getFilter(void) const +{ + ScUnoGuard aGuard; + rtl::OUString aRet; + ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); + if (pLink) + aRet = pLink->GetFilter(); + return aRet; +} + +void ScAreaLinkObj::setFilter(const rtl::OUString& Filter) +{ + ScUnoGuard aGuard; + Modify_Impl( NULL, &Filter, NULL, NULL, NULL ); +} + +rtl::OUString ScAreaLinkObj::getFilterOptions(void) const +{ + ScUnoGuard aGuard; + rtl::OUString aRet; + ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); + if (pLink) + aRet = pLink->GetOptions(); + return aRet; +} + +void ScAreaLinkObj::setFilterOptions(const rtl::OUString& FilterOptions) +{ + ScUnoGuard aGuard; + Modify_Impl( NULL, NULL, &FilterOptions, NULL, NULL ); +} + +sal_Int32 ScAreaLinkObj::getRefreshDelay(void) const +{ + ScUnoGuard aGuard; + sal_Int32 nRet = 0; + ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); + if (pLink) + nRet = (sal_Int32) pLink->GetRefreshDelay(); + return nRet; +} + +void ScAreaLinkObj::setRefreshDelay(sal_Int32 nRefreshDelay) +{ + ScUnoGuard aGuard; + ModifyRefreshDelay_Impl( nRefreshDelay ); +} + +// XAreaLink + +rtl::OUString SAL_CALL ScAreaLinkObj::getSourceArea() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + rtl::OUString aRet; + ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); + if (pLink) + aRet = pLink->GetSource(); + return aRet; +} + +void SAL_CALL ScAreaLinkObj::setSourceArea( const rtl::OUString& aSourceArea ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + Modify_Impl( NULL, NULL, NULL, &aSourceArea, NULL ); +} + +table::CellRangeAddress SAL_CALL ScAreaLinkObj::getDestArea() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + table::CellRangeAddress aRet; + ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, nPos); + if (pLink) + ScUnoConversion::FillApiRange( aRet, pLink->GetDestArea() ); + return aRet; +} + +void SAL_CALL ScAreaLinkObj::setDestArea( const table::CellRangeAddress& aDestArea ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + Modify_Impl( NULL, NULL, NULL, NULL, &aDestArea ); +} + +//------------------------------------------------------------------------ + +ScAreaLinksObj::ScAreaLinksObj(ScDocShell* pDocSh) : + pDocShell( pDocSh ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScAreaLinksObj::~ScAreaLinksObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScAreaLinksObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + // Referenz-Update interessiert hier nicht + + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +// XAreaLinks + +ScAreaLinkObj* ScAreaLinksObj::GetObjectByIndex_Impl(INT32 nIndex) +{ + if ( pDocShell && nIndex >= 0 && nIndex < getCount() ) + return new ScAreaLinkObj( pDocShell, (USHORT)nIndex ); + + return NULL; // nicht gefunden +} + +void SAL_CALL ScAreaLinksObj::insertAtPosition( const table::CellAddress& aDestPos, + const rtl::OUString& aFileName, + const rtl::OUString& aSourceArea, + const rtl::OUString& aFilter, + const rtl::OUString& aFilterOptions ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + String aFileStr (aFileName); + String aFilterStr (aFilter); + String aOptionStr (aFilterOptions); + String aSourceStr (aSourceArea); + ScAddress aDestAddr( (SCCOL)aDestPos.Column, (SCROW)aDestPos.Row, aDestPos.Sheet ); + + aFileStr = ScGlobal::GetAbsDocName( aFileStr, pDocShell ); //! in InsertAreaLink ??? + + ScDocFunc aFunc(*pDocShell); + aFunc.InsertAreaLink( aFileStr, aFilterStr, aOptionStr, + aSourceStr, ScRange(aDestAddr), + 0, FALSE, TRUE ); // keine Inhalte verschieben + } +} + +void SAL_CALL ScAreaLinksObj::removeByIndex( sal_Int32 nIndex ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScAreaLink* pLink = lcl_GetAreaLink(pDocShell, (USHORT)nIndex); + if (pLink) + { + //! SetAddUndo oder so + + sfx2::LinkManager* pLinkManager = pDocShell->GetDocument()->GetLinkManager(); + pLinkManager->Remove( pLink ); + } +} + +// XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScAreaLinksObj::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.CellAreaLinksEnumeration"))); +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScAreaLinksObj::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + INT32 nAreaCount = 0; + if (pDocShell) + { + sfx2::LinkManager* pLinkManager = pDocShell->GetDocument()->GetLinkManager(); + USHORT nTotalCount = pLinkManager->GetLinks().Count(); + for (USHORT i=0; i<nTotalCount; i++) + { + ::sfx2::SvBaseLink* pBase = *pLinkManager->GetLinks()[i]; + if (pBase->ISA(ScAreaLink)) + ++nAreaCount; + } + } + return nAreaCount; +} + +uno::Any SAL_CALL ScAreaLinksObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<sheet::XAreaLink> xLink(GetObjectByIndex_Impl(nIndex)); + if (xLink.is()) + return uno::makeAny(xLink); + else + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +uno::Type SAL_CALL ScAreaLinksObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((uno::Reference<sheet::XAreaLink>*)0); +} + +sal_Bool SAL_CALL ScAreaLinksObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +//------------------------------------------------------------------------ + +ScDDELinkObj::ScDDELinkObj(ScDocShell* pDocSh, const String& rA, + const String& rT, const String& rI) : + pDocShell( pDocSh ), + aAppl( rA ), + aTopic( rT ), + aItem( rI ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScDDELinkObj::~ScDDELinkObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScDDELinkObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + //! notify if links in document are changed + // UpdateRef is not needed here + + if ( rHint.ISA( SfxSimpleHint ) ) + { + if ( ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + pDocShell = NULL; // pointer is invalid + } + else if ( rHint.ISA( ScLinkRefreshedHint ) ) + { + const ScLinkRefreshedHint& rLH = (const ScLinkRefreshedHint&) rHint; + if ( rLH.GetLinkType() == SC_LINKREFTYPE_DDE && + rLH.GetDdeAppl() == aAppl && + rLH.GetDdeTopic() == aTopic && + rLH.GetDdeItem() == aItem ) //! mode is ignored + Refreshed_Impl(); + } +} + +// XNamed + +String lcl_BuildDDEName( const String& rAppl, const String& rTopic, const String& rItem ) +{ + // Appl|Topic!Item (wie Excel) + String aRet = rAppl; + aRet += '|'; + aRet += rTopic; + aRet += '!'; + aRet += rItem; + return aRet; +} + +rtl::OUString SAL_CALL ScDDELinkObj::getName() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return lcl_BuildDDEName( aAppl, aTopic, aItem ); +} + +void SAL_CALL ScDDELinkObj::setName( const rtl::OUString& /* aName */ ) throw(uno::RuntimeException) +{ + // name can't be changed (formulas wouldn't find the link) + throw uno::RuntimeException(); +} + +// XDDELink + +rtl::OUString SAL_CALL ScDDELinkObj::getApplication() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + //! Test, ob Link noch im Dokument enthalten? + + return aAppl; +} + +rtl::OUString SAL_CALL ScDDELinkObj::getTopic() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + //! Test, ob Link noch im Dokument enthalten? + + return aTopic; +} + +rtl::OUString SAL_CALL ScDDELinkObj::getItem() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + //! Test, ob Link noch im Dokument enthalten? + + return aItem; +} + +// XRefreshable + +void SAL_CALL ScDDELinkObj::refresh() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + (void)pDoc->UpdateDdeLink( aAppl, aTopic, aItem ); + //! Fehler abfragen + } +} + +void SAL_CALL ScDDELinkObj::addRefreshListener( + const uno::Reference<util::XRefreshListener >& xListener ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<util::XRefreshListener>* pObj = + new uno::Reference<util::XRefreshListener>( xListener ); + aRefreshListeners.Insert( pObj, aRefreshListeners.Count() ); + + // hold one additional ref to keep this object alive as long as there are listeners + if ( aRefreshListeners.Count() == 1 ) + acquire(); +} + +void SAL_CALL ScDDELinkObj::removeRefreshListener( + const uno::Reference<util::XRefreshListener >& xListener ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + USHORT nCount = aRefreshListeners.Count(); + for ( USHORT n=nCount; n--; ) + { + uno::Reference<util::XRefreshListener>* pObj = aRefreshListeners[n]; + if ( *pObj == xListener ) + { + aRefreshListeners.DeleteAndDestroy( n ); + if ( aRefreshListeners.Count() == 0 ) + release(); // release ref for listeners + break; + } + } +} + +// XDDELinkResults + +uno::Sequence< uno::Sequence< uno::Any > > ScDDELinkObj::getResults( ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Sequence< uno::Sequence< uno::Any > > aReturn; + bool bSuccess = false; + + if ( pDocShell ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + if ( pDoc ) + { + USHORT nPos = 0; + if ( pDoc->FindDdeLink( aAppl, aTopic, aItem, SC_DDE_IGNOREMODE, nPos ) ) + { + const ScMatrix* pMatrix = pDoc->GetDdeLinkResultMatrix( nPos ); + if ( pMatrix ) + { + uno::Any aAny; + if ( ScRangeToSequence::FillMixedArray( aAny, pMatrix, true ) ) + { + aAny >>= aReturn; + } + } + bSuccess = true; + } + } + } + + if ( !bSuccess ) + { + throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "ScDDELinkObj::getResults: failed to get results!" ) ), + uno::Reference< uno::XInterface >() ); + } + + return aReturn; +} + +void ScDDELinkObj::setResults( const uno::Sequence< uno::Sequence< uno::Any > >& aResults ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + bool bSuccess = false; + + if ( pDocShell ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + if ( pDoc ) + { + USHORT nPos = 0; + if ( pDoc->FindDdeLink( aAppl, aTopic, aItem, SC_DDE_IGNOREMODE, nPos ) ) + { + uno::Any aAny; + aAny <<= aResults; + ScMatrixRef xMatrix = ScSequenceToMatrix::CreateMixedMatrix( aAny ); + bSuccess = pDoc->SetDdeLinkResultMatrix( nPos, xMatrix ); + } + } + } + + if ( !bSuccess ) + { + throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "ScDDELinkObj::setResults: failed to set results!" ) ), + uno::Reference< uno::XInterface >() ); + } +} + +void ScDDELinkObj::Refreshed_Impl() +{ + lang::EventObject aEvent; + aEvent.Source.set((cppu::OWeakObject*)this); + for ( USHORT n=0; n<aRefreshListeners.Count(); n++ ) + (*aRefreshListeners[n])->refreshed( aEvent ); +} + +//------------------------------------------------------------------------ + +ScDDELinksObj::ScDDELinksObj(ScDocShell* pDocSh) : + pDocShell( pDocSh ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScDDELinksObj::~ScDDELinksObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScDDELinksObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + // Referenz-Update interessiert hier nicht + + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +// XDDELinks + +ScDDELinkObj* ScDDELinksObj::GetObjectByIndex_Impl(INT32 nIndex) +{ + if (pDocShell) + { + String aAppl, aTopic, aItem; + if ( nIndex <= USHRT_MAX && + pDocShell->GetDocument()->GetDdeLinkData( (USHORT)nIndex, aAppl, aTopic, aItem ) ) + return new ScDDELinkObj( pDocShell, aAppl, aTopic, aItem ); + } + return NULL; +} + +ScDDELinkObj* ScDDELinksObj::GetObjectByName_Impl(const rtl::OUString& aName) +{ + if (pDocShell) + { + String aNamStr(aName); + String aAppl, aTopic, aItem; + + ScDocument* pDoc = pDocShell->GetDocument(); + USHORT nCount = pDoc->GetDdeLinkCount(); + for (USHORT i=0; i<nCount; i++) + { + pDoc->GetDdeLinkData( i, aAppl, aTopic, aItem ); + if ( lcl_BuildDDEName(aAppl, aTopic, aItem) == aNamStr ) + return new ScDDELinkObj( pDocShell, aAppl, aTopic, aItem ); + } + } + return NULL; +} + +// XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScDDELinksObj::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.DDELinksEnumeration"))); +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScDDELinksObj::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + INT32 nAreaCount = 0; + if (pDocShell) + nAreaCount = pDocShell->GetDocument()->GetDdeLinkCount(); + return nAreaCount; +} + +uno::Any SAL_CALL ScDDELinksObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<sheet::XDDELink> xLink(GetObjectByIndex_Impl(nIndex)); + if (xLink.is()) + return uno::makeAny(xLink); + else + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +uno::Type SAL_CALL ScDDELinksObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((uno::Reference<sheet::XDDELink>*)0); +} + +sal_Bool SAL_CALL ScDDELinksObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +uno::Any SAL_CALL ScDDELinksObj::getByName( const rtl::OUString& aName ) + throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<sheet::XDDELink> xLink(GetObjectByName_Impl(aName)); + if (xLink.is()) + return uno::makeAny(xLink); + else + throw container::NoSuchElementException(); +// return uno::Any(); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScDDELinksObj::getElementNames() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + String aAppl, aTopic, aItem; + + ScDocument* pDoc = pDocShell->GetDocument(); + USHORT nCount = pDoc->GetDdeLinkCount(); + uno::Sequence<rtl::OUString> aSeq(nCount); + rtl::OUString* pAry = aSeq.getArray(); + + for (USHORT i=0; i<nCount; i++) + { + pDoc->GetDdeLinkData( i, aAppl, aTopic, aItem ); + pAry[i] = lcl_BuildDDEName(aAppl, aTopic, aItem); + } + return aSeq; + } + return uno::Sequence<rtl::OUString>(); +} + +sal_Bool SAL_CALL ScDDELinksObj::hasByName( const rtl::OUString& aName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + String aNamStr(aName); + String aAppl, aTopic, aItem; + + ScDocument* pDoc = pDocShell->GetDocument(); + USHORT nCount = pDoc->GetDdeLinkCount(); + for (USHORT i=0; i<nCount; i++) + { + pDoc->GetDdeLinkData( i, aAppl, aTopic, aItem ); + if ( lcl_BuildDDEName(aAppl, aTopic, aItem) == aNamStr ) + return TRUE; + } + } + return FALSE; +} + +// XDDELinks + +uno::Reference< sheet::XDDELink > ScDDELinksObj::addDDELink( + const ::rtl::OUString& aApplication, const ::rtl::OUString& aTopic, + const ::rtl::OUString& aItem, ::com::sun::star::sheet::DDELinkMode nMode ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference< sheet::XDDELink > xLink; + + if ( pDocShell ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + if ( pDoc ) + { + BYTE nMod = SC_DDE_DEFAULT; + switch ( nMode ) + { + case sheet::DDELinkMode_DEFAULT: + { + nMod = SC_DDE_DEFAULT; + } + break; + case sheet::DDELinkMode_ENGLISH: + { + nMod = SC_DDE_ENGLISH; + } + break; + case sheet::DDELinkMode_TEXT: + { + nMod = SC_DDE_TEXT; + } + break; + default: + { + } + break; + } + + if ( pDoc->CreateDdeLink( aApplication, aTopic, aItem, nMod ) ) + { + const ::rtl::OUString aName( lcl_BuildDDEName( aApplication, aTopic, aItem ) ); + xLink.set( GetObjectByName_Impl( aName ) ); + } + } + } + + if ( !xLink.is() ) + { + throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( + "ScDDELinksObj::addDDELink: cannot add DDE link!" ) ), + uno::Reference< uno::XInterface >() ); + } + + return xLink; +} + +// ============================================================================ + +ScExternalSheetCacheObj::ScExternalSheetCacheObj(ScExternalRefCache::TableTypeRef pTable, size_t nIndex) : + mpTable(pTable), + mnIndex(nIndex) +{ +} + +ScExternalSheetCacheObj::~ScExternalSheetCacheObj() +{ +} + +void SAL_CALL ScExternalSheetCacheObj::setCellValue(sal_Int32 nCol, sal_Int32 nRow, const Any& rValue) + throw (IllegalArgumentException, RuntimeException) +{ + ScUnoGuard aGuard; + if (nRow < 0 || nCol < 0) + throw IllegalArgumentException(); + + ScExternalRefCache::TokenRef pToken; + double fVal = 0.0; + OUString aVal; + if (rValue >>= fVal) + pToken.reset(new FormulaDoubleToken(fVal)); + else if (rValue >>= aVal) + pToken.reset(new FormulaStringToken(aVal)); + else + // unidentified value type. + return; + + mpTable->setCell(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), pToken); +} + +Any SAL_CALL ScExternalSheetCacheObj::getCellValue(sal_Int32 nCol, sal_Int32 nRow) + throw (IllegalArgumentException, RuntimeException) +{ + ScUnoGuard aGuard; + if (nRow < 0 || nCol < 0) + throw IllegalArgumentException(); + + FormulaToken* pToken = mpTable->getCell(static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow)).get(); + if (!pToken) + throw IllegalArgumentException(); + + Any aValue; + switch (pToken->GetType()) + { + case svDouble: + { + double fVal = pToken->GetDouble(); + aValue <<= fVal; + } + break; + case svString: + { + OUString aVal = pToken->GetString(); + aValue <<= aVal; + } + break; + default: + throw IllegalArgumentException(); + } + return aValue; +} + +Sequence< sal_Int32 > SAL_CALL ScExternalSheetCacheObj::getAllRows() + throw (RuntimeException) +{ + ScUnoGuard aGuard; + vector<SCROW> aRows; + mpTable->getAllRows(aRows); + size_t nSize = aRows.size(); + Sequence<sal_Int32> aRowsSeq(nSize); + for (size_t i = 0; i < nSize; ++i) + aRowsSeq[i] = aRows[i]; + + return aRowsSeq; +} + +Sequence< sal_Int32 > SAL_CALL ScExternalSheetCacheObj::getAllColumns(sal_Int32 nRow) + throw (IllegalArgumentException, RuntimeException) +{ + ScUnoGuard aGuard; + if (nRow < 0) + throw IllegalArgumentException(); + + vector<SCCOL> aCols; + mpTable->getAllCols(static_cast<SCROW>(nRow), aCols); + size_t nSize = aCols.size(); + Sequence<sal_Int32> aColsSeq(nSize); + for (size_t i = 0; i < nSize; ++i) + aColsSeq[i] = aCols[i]; + + return aColsSeq; +} + +sal_Int32 SAL_CALL ScExternalSheetCacheObj::getTokenIndex() + throw (RuntimeException) +{ + return static_cast< sal_Int32 >( mnIndex ); +} + +// ============================================================================ + +ScExternalDocLinkObj::ScExternalDocLinkObj(ScExternalRefManager* pRefMgr, sal_uInt16 nFileId) : + mpRefMgr(pRefMgr), mnFileId(nFileId) +{ +} + +ScExternalDocLinkObj::~ScExternalDocLinkObj() +{ +} + +Reference< sheet::XExternalSheetCache > SAL_CALL ScExternalDocLinkObj::addSheetCache( + const OUString& aSheetName, sal_Bool bDynamicCache ) + throw (RuntimeException) +{ + ScUnoGuard aGuard; + size_t nIndex = 0; + ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aSheetName, true, &nIndex); + if (!bDynamicCache) + // Set the whole table cached to prevent access to the source document. + pTable->setWholeTableCached(); + + Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(pTable, nIndex)); + return aSheetCache; +} + +Any SAL_CALL ScExternalDocLinkObj::getByName(const::rtl::OUString &aName) + throw (container::NoSuchElementException, lang::WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + size_t nIndex = 0; + ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, aName, false, &nIndex); + if (!pTable) + throw container::NoSuchElementException(); + + Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(pTable, nIndex)); + + Any aAny; + aAny <<= aSheetCache; + return aAny; +} + +Sequence< OUString > SAL_CALL ScExternalDocLinkObj::getElementNames() + throw (RuntimeException) +{ + ScUnoGuard aGuard; + vector<String> aTabNames; + mpRefMgr->getAllCachedTableNames(mnFileId, aTabNames); + size_t n = aTabNames.size(); + Sequence<OUString> aSeq(n); + for (size_t i = 0; i < n; ++i) + aSeq[i] = aTabNames[i]; + return aSeq; +} + +sal_Bool SAL_CALL ScExternalDocLinkObj::hasByName(const OUString &aName) + throw (RuntimeException) +{ + ScUnoGuard aGuard; + return static_cast<sal_Bool>(mpRefMgr->hasCacheTable(mnFileId, aName)); +} + +sal_Int32 SAL_CALL ScExternalDocLinkObj::getCount() + throw (RuntimeException) +{ + ScUnoGuard aGuard; + return static_cast<sal_Int32>(mpRefMgr->getCacheTableCount(mnFileId)); +} + +Any SAL_CALL ScExternalDocLinkObj::getByIndex(sal_Int32 nIndex) + throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + size_t nTabCount = mpRefMgr->getCacheTableCount(mnFileId); + if (nIndex < 0 || nIndex >= static_cast<sal_Int32>(nTabCount)) + throw lang::IndexOutOfBoundsException(); + + ScExternalRefCache::TableTypeRef pTable = mpRefMgr->getCacheTable(mnFileId, static_cast<size_t>(nIndex)); + if (!pTable) + throw lang::IndexOutOfBoundsException(); + + Reference< sheet::XExternalSheetCache > aSheetCache(new ScExternalSheetCacheObj(pTable, nIndex)); + + Any aAny; + aAny <<= aSheetCache; + return aAny; +} + +Reference< container::XEnumeration > SAL_CALL ScExternalDocLinkObj::createEnumeration() + throw (RuntimeException) +{ + ScUnoGuard aGuard; + Reference< container::XEnumeration > aRef( + new ScIndexEnumeration(this, OUString::createFromAscii( + "com.sun.star.sheet.ExternalDocLink"))); + return aRef; +} + +uno::Type SAL_CALL ScExternalDocLinkObj::getElementType() + throw (RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType(static_cast<Reference<sheet::XExternalDocLink>*>(0)); +} + +sal_Bool SAL_CALL ScExternalDocLinkObj::hasElements() + throw (RuntimeException) +{ + ScUnoGuard aGuard; + return static_cast<sal_Bool>(mpRefMgr->getCacheTableCount(mnFileId) > 0); +} + +sal_Int32 SAL_CALL ScExternalDocLinkObj::getTokenIndex() + throw (RuntimeException) +{ + return static_cast<sal_Int32>(mnFileId); +} + +// ============================================================================ + +ScExternalDocLinksObj::ScExternalDocLinksObj(ScDocShell* pDocShell) : + mpDocShell(pDocShell), + mpRefMgr(pDocShell->GetDocument()->GetExternalRefManager()) +{ +} + +ScExternalDocLinksObj::~ScExternalDocLinksObj() +{ +} + +Reference< sheet::XExternalDocLink > SAL_CALL ScExternalDocLinksObj::addDocLink( + const OUString& aDocName ) + throw (RuntimeException) +{ + ScUnoGuard aGuard; + sal_uInt16 nFileId = mpRefMgr->getExternalFileId(aDocName); + Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpRefMgr, nFileId)); + return aDocLink; +} + +Any SAL_CALL ScExternalDocLinksObj::getByName(const::rtl::OUString &aName) + throw (container::NoSuchElementException, lang::WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + if (!mpRefMgr->hasExternalFile(aName)) + throw container::NoSuchElementException(); + + sal_uInt16 nFileId = mpRefMgr->getExternalFileId(aName); + Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpRefMgr, nFileId)); + + Any aAny; + aAny <<= aDocLink; + return aAny; +} + +Sequence< OUString > SAL_CALL ScExternalDocLinksObj::getElementNames() + throw (RuntimeException) +{ + ScUnoGuard aGuard; + sal_uInt16 n = mpRefMgr->getExternalFileCount(); + Sequence<OUString> aSeq(n); + for (sal_uInt16 i = 0; i < n; ++i) + { + const String* pName = mpRefMgr->getExternalFileName(i); + aSeq[i] = pName ? *pName : EMPTY_STRING; + } + + return aSeq; +} + +sal_Bool SAL_CALL ScExternalDocLinksObj::hasByName(const OUString &aName) + throw (RuntimeException) +{ + ScUnoGuard aGuard; + return mpRefMgr->hasExternalFile(aName); +} + +sal_Int32 SAL_CALL ScExternalDocLinksObj::getCount() + throw (RuntimeException) +{ + ScUnoGuard aGuard; + return mpRefMgr->getExternalFileCount(); +} + +Any SAL_CALL ScExternalDocLinksObj::getByIndex(sal_Int32 nIndex) + throw (lang::IndexOutOfBoundsException, lang::WrappedTargetException, RuntimeException) +{ + ScUnoGuard aGuard; + if (nIndex > ::std::numeric_limits<sal_uInt16>::max() || nIndex < ::std::numeric_limits<sal_uInt16>::min()) + throw lang::IndexOutOfBoundsException(); + + sal_uInt16 nFileId = static_cast<sal_uInt16>(nIndex); + + if (!mpRefMgr->hasExternalFile(nFileId)) + throw lang::IndexOutOfBoundsException(); + + Reference< sheet::XExternalDocLink > aDocLink(new ScExternalDocLinkObj(mpRefMgr, nFileId)); + Any aAny; + aAny <<= aDocLink; + return aAny; +} + +Reference< container::XEnumeration > SAL_CALL ScExternalDocLinksObj::createEnumeration() + throw (RuntimeException) +{ + ScUnoGuard aGuard; + Reference< container::XEnumeration > aRef( + new ScIndexEnumeration(this, OUString::createFromAscii( + "com.sun.star.sheet.ExternalDocLinks"))); + return aRef; +} + +uno::Type SAL_CALL ScExternalDocLinksObj::getElementType() + throw (RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType(static_cast<Reference<sheet::XExternalDocLinks>*>(0)); +} + +sal_Bool SAL_CALL ScExternalDocLinksObj::hasElements() + throw (RuntimeException) +{ + ScUnoGuard aGuard; + return mpRefMgr->getExternalFileCount() > 0; +} + diff --git a/sc/source/ui/unoobj/listenercalls.cxx b/sc/source/ui/unoobj/listenercalls.cxx new file mode 100644 index 000000000000..9abc8e0ab826 --- /dev/null +++ b/sc/source/ui/unoobj/listenercalls.cxx @@ -0,0 +1,89 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include <com/sun/star/util/XModifyListener.hpp> +#include <tools/debug.hxx> + +#include "listenercalls.hxx" + +using namespace com::sun::star; + +//------------------------------------------------------------------------ + +ScUnoListenerCalls::ScUnoListenerCalls() +{ +} + +ScUnoListenerCalls::~ScUnoListenerCalls() +{ + DBG_ASSERT( aEntries.empty(), "unhandled listener calls remaining" ); +} + +void ScUnoListenerCalls::Add( const uno::Reference<util::XModifyListener>& rListener, + const lang::EventObject& rEvent ) +{ + if ( rListener.is() ) + aEntries.push_back( ScUnoListenerEntry( rListener, rEvent ) ); +} + +void ScUnoListenerCalls::ExecuteAndClear() +{ + // Execute all stored calls and remove them from the list. + // During each modified() call, Add may be called again. + // These new calls are executed here, too. + + if (!aEntries.empty()) + { + std::list<ScUnoListenerEntry>::iterator aItr(aEntries.begin()); + std::list<ScUnoListenerEntry>::iterator aEndItr(aEntries.end()); + while ( aItr != aEndItr ) + { + ScUnoListenerEntry aEntry = *aItr; + try + { + aEntry.xListener->modified( aEntry.aEvent ); + } + catch ( uno::RuntimeException ) + { + // the listener is an external object and may throw a RuntimeException + // for reasons we don't know + } + + // New calls that are added during the modified() call are appended to the end + // of aEntries, so the loop will catch them, too (as long as erase happens + // after modified). + + aItr = aEntries.erase(aItr); + } + } +} + diff --git a/sc/source/ui/unoobj/makefile.mk b/sc/source/ui/unoobj/makefile.mk new file mode 100644 index 000000000000..36c3493ceefc --- /dev/null +++ b/sc/source/ui/unoobj/makefile.mk @@ -0,0 +1,120 @@ +#************************************************************************* +# +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# Copyright 2000, 2010 Oracle and/or its affiliates. +# +# OpenOffice.org - a multi-platform office productivity suite +# +# This file is part of OpenOffice.org. +# +# OpenOffice.org is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License version 3 +# only, as published by the Free Software Foundation. +# +# OpenOffice.org is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License version 3 for more details +# (a copy is included in the LICENSE file that accompanied this code). +# +# You should have received a copy of the GNU Lesser General Public License +# version 3 along with OpenOffice.org. If not, see +# <http://www.openoffice.org/license.html> +# for a copy of the LGPLv3 License. +# +#************************************************************************* + +PRJ=..$/..$/.. + +PRJNAME=sc +TARGET=unoobj + +LIBTARGET=NO +ENABLE_EXCEPTIONS=TRUE + +# --- Settings ----------------------------------------------------- + +.INCLUDE : scpre.mk +.INCLUDE : settings.mk +.INCLUDE : sc.mk +.INCLUDE : $(PRJ)$/util$/makefile.pmk + +# --- Files -------------------------------------------------------- +SLO1FILES = \ + $(SLO)$/docuno.obj \ + $(SLO)$/servuno.obj \ + $(SLO)$/defltuno.obj \ + $(SLO)$/drdefuno.obj \ + $(SLO)$/cellsuno.obj \ + $(SLO)$/tokenuno.obj \ + $(SLO)$/textuno.obj \ + $(SLO)$/notesuno.obj \ + $(SLO)$/cursuno.obj \ + $(SLO)$/srchuno.obj \ + $(SLO)$/fielduno.obj \ + $(SLO)$/miscuno.obj \ + $(SLO)$/optuno.obj \ + $(SLO)$/appluno.obj \ + $(SLO)$/funcuno.obj \ + $(SLO)$/nameuno.obj \ + $(SLO)$/viewuno.obj \ + $(SLO)$/dispuno.obj \ + $(SLO)$/datauno.obj \ + $(SLO)$/dapiuno.obj \ + $(SLO)$/chartuno.obj \ + $(SLO)$/chart2uno.obj \ + $(SLO)$/shapeuno.obj \ + $(SLO)$/pageuno.obj \ + $(SLO)$/forbiuno.obj \ + $(SLO)$/styleuno.obj \ + $(SLO)$/afmtuno.obj \ + $(SLO)$/fmtuno.obj \ + $(SLO)$/linkuno.obj \ + $(SLO)$/targuno.obj \ + $(SLO)$/convuno.obj \ + $(SLO)$/editsrc.obj \ + $(SLO)$/unoguard.obj \ + $(SLO)$/confuno.obj \ + $(SLO)$/filtuno.obj \ + $(SLO)$/unodoc.obj \ + $(SLO)$/addruno.obj \ + $(SLO)$/eventuno.obj \ + $(SLO)$/listenercalls.obj \ + $(SLO)$/cellvaluebinding.obj \ + $(SLO)$/celllistsource.obj \ + $(SLO)$/warnpassword.obj \ + $(SLO)$/unoreflist.obj \ + $(SLO)$/ChartRangeSelectionListener.obj + +SLO2FILES = \ + $(SLO)$/scdetect.obj \ + $(SLO)$/detreg.obj + +SLOFILES = \ + $(SLO1FILES) \ + $(SLO2FILES) + +LIB1TARGET = \ + $(SLB)$/$(TARGET).lib + +LIB1OBJFILES = \ + $(SLO1FILES) + +.IF "$(OS)$(COM)$(CPUNAME)"=="LINUXGCCSPARC" +NOOPTFILES= \ + $(SLO)$/cellsuno.obj +.ENDIF + +# Work around bug in gcc 4.2 / 4.3, see +# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=35182 +.IF "$(COM)"=="GCC" +NOOPTFILES+= \ + $(SLO)$/chart2uno.obj +.ENDIF + + +# --- Tagets ------------------------------------------------------- + +.INCLUDE : target.mk + diff --git a/sc/source/ui/unoobj/miscuno.cxx b/sc/source/ui/unoobj/miscuno.cxx new file mode 100644 index 000000000000..4fdac0288796 --- /dev/null +++ b/sc/source/ui/unoobj/miscuno.cxx @@ -0,0 +1,424 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include <tools/debug.hxx> + +#include "miscuno.hxx" +#include "unoguard.hxx" + +using namespace com::sun::star; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Any; +using ::rtl::OUString; + +//------------------------------------------------------------------------ + +//UNUSED2008-05 SC_SIMPLE_SERVICE_INFO( ScEmptyEnumeration, "ScEmptyEnumeration", "stardiv.unknown" ) +//UNUSED2008-05 SC_SIMPLE_SERVICE_INFO( ScEmptyEnumerationAccess, "ScEmptyEnumerationAccess", "stardiv.unknown" ) +//UNUSED2008-05 SC_SIMPLE_SERVICE_INFO( ScIndexEnumeration, "ScIndexEnumeration", "stardiv.unknown" ) +//UNUSED2008-05 SC_SIMPLE_SERVICE_INFO( ScPrintSettingsObj, "ScPrintSettingsObj", "stardiv.unknown" ) + +SC_SIMPLE_SERVICE_INFO( ScNameToIndexAccess, "ScNameToIndexAccess", "stardiv.unknown" ) + +//------------------------------------------------------------------------ + +// static +uno::Reference<uno::XInterface> ScUnoHelpFunctions::AnyToInterface( const uno::Any& rAny ) +{ + if ( rAny.getValueTypeClass() == uno::TypeClass_INTERFACE ) + { + return uno::Reference<uno::XInterface>(rAny, uno::UNO_QUERY); + } + return uno::Reference<uno::XInterface>(); //! Exception? +} + +// static +sal_Bool ScUnoHelpFunctions::GetBoolProperty( const uno::Reference<beans::XPropertySet>& xProp, + const rtl::OUString& rName, sal_Bool bDefault ) +{ + sal_Bool bRet = bDefault; + if ( xProp.is() ) + { + try + { + uno::Any aAny(xProp->getPropertyValue( rName )); + //! type conversion??? + // operator >>= shouldn't be used for bool (?) + if ( aAny.getValueTypeClass() == uno::TypeClass_BOOLEAN ) + { + //! safe way to get bool value from any??? + bRet = *(sal_Bool*)aAny.getValue(); + } + } + catch(uno::Exception&) + { + // keep default + } + } + return bRet; +} + +// static +sal_Int32 ScUnoHelpFunctions::GetLongProperty( const uno::Reference<beans::XPropertySet>& xProp, + const rtl::OUString& rName, long nDefault ) +{ + sal_Int32 nRet = nDefault; + if ( xProp.is() ) + { + try + { + //! type conversion??? + xProp->getPropertyValue( rName ) >>= nRet; + } + catch(uno::Exception&) + { + // keep default + } + } + return nRet; +} + +// static +sal_Int32 ScUnoHelpFunctions::GetEnumProperty( const uno::Reference<beans::XPropertySet>& xProp, + const rtl::OUString& rName, long nDefault ) +{ + sal_Int32 nRet = nDefault; + if ( xProp.is() ) + { + try + { + uno::Any aAny(xProp->getPropertyValue( rName )); + + if ( aAny.getValueTypeClass() == uno::TypeClass_ENUM ) + { + //! get enum value from any??? + nRet = *(sal_Int32*)aAny.getValue(); + } + else + { + //! type conversion??? + aAny >>= nRet; + } + } + catch(uno::Exception&) + { + // keep default + } + } + return nRet; +} + +// static +OUString ScUnoHelpFunctions::GetStringProperty( + const Reference<beans::XPropertySet>& xProp, const OUString& rName, const OUString& rDefault ) +{ + OUString aRet = rDefault; + if (!xProp.is()) + return aRet; + + try + { + Any any = xProp->getPropertyValue(rName); + any >>= aRet; + } + catch (const uno::Exception&) + { + } + + return aRet; +} + +// static +sal_Bool ScUnoHelpFunctions::GetBoolFromAny( const uno::Any& aAny ) +{ + if ( aAny.getValueTypeClass() == uno::TypeClass_BOOLEAN ) + return *(sal_Bool*)aAny.getValue(); + return FALSE; +} + +// static +sal_Int16 ScUnoHelpFunctions::GetInt16FromAny( const uno::Any& aAny ) +{ + sal_Int16 nRet = 0; + if ( aAny >>= nRet ) + return nRet; + return 0; +} + +// static +sal_Int32 ScUnoHelpFunctions::GetInt32FromAny( const uno::Any& aAny ) +{ + sal_Int32 nRet = 0; + if ( aAny >>= nRet ) + return nRet; + return 0; +} + +// static +sal_Int32 ScUnoHelpFunctions::GetEnumFromAny( const uno::Any& aAny ) +{ + sal_Int32 nRet = 0; + if ( aAny.getValueTypeClass() == uno::TypeClass_ENUM ) + nRet = *(sal_Int32*)aAny.getValue(); + else + aAny >>= nRet; + return nRet; +} + +// static +void ScUnoHelpFunctions::SetBoolInAny( uno::Any& rAny, sal_Bool bValue ) +{ + rAny.setValue( &bValue, getBooleanCppuType() ); +} + +// static +void ScUnoHelpFunctions::SetOptionalPropertyValue( + Reference<beans::XPropertySet>& rPropSet, const sal_Char* pPropName, const Any& rVal ) +{ + try + { + rPropSet->setPropertyValue(OUString::createFromAscii(pPropName), rVal); + } + catch (const beans::UnknownPropertyException&) + { + // ignored - not supported. + } +} + +//------------------------------------------------------------------------ + +ScIndexEnumeration::ScIndexEnumeration(const uno::Reference<container::XIndexAccess>& rInd, + const rtl::OUString& rServiceName) : + xIndex( rInd ), + sServiceName(rServiceName), + nPos( 0 ) +{ +} + +ScIndexEnumeration::~ScIndexEnumeration() +{ +} + +// XEnumeration + +sal_Bool SAL_CALL ScIndexEnumeration::hasMoreElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( nPos < xIndex->getCount() ); +} + +uno::Any SAL_CALL ScIndexEnumeration::nextElement() throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Any aReturn; + try + { + aReturn = xIndex->getByIndex(nPos++); + } + catch (lang::IndexOutOfBoundsException&) + { + throw container::NoSuchElementException(); + } + return aReturn; +} + +::rtl::OUString SAL_CALL ScIndexEnumeration::getImplementationName() + throw(::com::sun::star::uno::RuntimeException) +{ + return ::rtl::OUString::createFromAscii("ScIndexEnumeration"); +} + +sal_Bool SAL_CALL ScIndexEnumeration::supportsService( const ::rtl::OUString& ServiceName ) + throw(::com::sun::star::uno::RuntimeException) +{ + return sServiceName == ServiceName; +} + +::com::sun::star::uno::Sequence< ::rtl::OUString > + SAL_CALL ScIndexEnumeration::getSupportedServiceNames(void) + throw(::com::sun::star::uno::RuntimeException) +{ + ::com::sun::star::uno::Sequence< ::rtl::OUString > aRet(1); + ::rtl::OUString* pArray = aRet.getArray(); + pArray[0] = sServiceName; + return aRet; +} + +//------------------------------------------------------------------------ + +//UNUSED2008-05 ScEmptyEnumerationAccess::ScEmptyEnumerationAccess() +//UNUSED2008-05 { +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 ScEmptyEnumerationAccess::~ScEmptyEnumerationAccess() +//UNUSED2008-05 { +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 // XEnumerationAccess +//UNUSED2008-05 +//UNUSED2008-05 uno::Reference<container::XEnumeration> SAL_CALL ScEmptyEnumerationAccess::createEnumeration() +//UNUSED2008-05 throw(uno::RuntimeException) +//UNUSED2008-05 { +//UNUSED2008-05 ScUnoGuard aGuard; +//UNUSED2008-05 return new ScEmptyEnumeration; +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 uno::Type SAL_CALL ScEmptyEnumerationAccess::getElementType() throw(uno::RuntimeException) +//UNUSED2008-05 { +//UNUSED2008-05 ScUnoGuard aGuard; +//UNUSED2008-05 return getCppuType((uno::Reference<uno::XInterface>*)0); // or what? +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 sal_Bool SAL_CALL ScEmptyEnumerationAccess::hasElements() throw(uno::RuntimeException) +//UNUSED2008-05 { +//UNUSED2008-05 return FALSE; +//UNUSED2008-05 } + +//------------------------------------------------------------------------ + +//UNUSED2008-05 ScEmptyEnumeration::ScEmptyEnumeration() +//UNUSED2008-05 { +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 ScEmptyEnumeration::~ScEmptyEnumeration() +//UNUSED2008-05 { +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 // XEnumeration +//UNUSED2008-05 +//UNUSED2008-05 sal_Bool SAL_CALL ScEmptyEnumeration::hasMoreElements() throw(uno::RuntimeException) +//UNUSED2008-05 { +//UNUSED2008-05 ScUnoGuard aGuard; +//UNUSED2008-05 return FALSE; +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 uno::Any SAL_CALL ScEmptyEnumeration::nextElement() throw(container::NoSuchElementException, +//UNUSED2008-05 lang::WrappedTargetException, uno::RuntimeException) +//UNUSED2008-05 { +//UNUSED2008-05 ScUnoGuard aGuard; +//UNUSED2008-05 return uno::Any(); +//UNUSED2008-05 } + +//------------------------------------------------------------------------ + +ScNameToIndexAccess::ScNameToIndexAccess( const com::sun::star::uno::Reference< + com::sun::star::container::XNameAccess>& rNameObj ) : + xNameAccess( rNameObj ) +{ + //! test for XIndexAccess interface at rNameObj, use that instead! + + if ( xNameAccess.is() ) + aNames = xNameAccess->getElementNames(); +} + +ScNameToIndexAccess::~ScNameToIndexAccess() +{ +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScNameToIndexAccess::getCount( ) throw(::com::sun::star::uno::RuntimeException) +{ + return aNames.getLength(); +} + +::com::sun::star::uno::Any SAL_CALL ScNameToIndexAccess::getByIndex( sal_Int32 nIndex ) + throw(::com::sun::star::lang::IndexOutOfBoundsException, + ::com::sun::star::lang::WrappedTargetException, + ::com::sun::star::uno::RuntimeException) +{ + if ( xNameAccess.is() && nIndex >= 0 && nIndex < aNames.getLength() ) + return xNameAccess->getByName( aNames.getConstArray()[nIndex] ); + + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +// XElementAccess + +::com::sun::star::uno::Type SAL_CALL ScNameToIndexAccess::getElementType( ) + throw(::com::sun::star::uno::RuntimeException) +{ + if ( xNameAccess.is() ) + return xNameAccess->getElementType(); + else + return uno::Type(); +} + +sal_Bool SAL_CALL ScNameToIndexAccess::hasElements( ) throw(::com::sun::star::uno::RuntimeException) +{ + return getCount() > 0; +} + +//------------------------------------------------------------------------ + +//UNUSED2008-05 ScPrintSettingsObj::ScPrintSettingsObj() +//UNUSED2008-05 { +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 ScPrintSettingsObj::~ScPrintSettingsObj() +//UNUSED2008-05 { +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 // XPropertySet +//UNUSED2008-05 +//UNUSED2008-05 uno::Reference<beans::XPropertySetInfo> SAL_CALL ScPrintSettingsObj::getPropertySetInfo() +//UNUSED2008-05 throw(uno::RuntimeException) +//UNUSED2008-05 { +//UNUSED2008-05 return NULL; +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 void SAL_CALL ScPrintSettingsObj::setPropertyValue( +//UNUSED2008-05 const rtl::OUString& /* aPropertyName */, const uno::Any& /* aValue */ ) +//UNUSED2008-05 throw(beans::UnknownPropertyException, beans::PropertyVetoException, +//UNUSED2008-05 lang::IllegalArgumentException, lang::WrappedTargetException, +//UNUSED2008-05 uno::RuntimeException) +//UNUSED2008-05 { +//UNUSED2008-05 //! later... +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 uno::Any SAL_CALL ScPrintSettingsObj::getPropertyValue( const rtl::OUString& /* aPropertyName */ ) +//UNUSED2008-05 throw(beans::UnknownPropertyException, lang::WrappedTargetException, +//UNUSED2008-05 uno::RuntimeException) +//UNUSED2008-05 { +//UNUSED2008-05 //! later... +//UNUSED2008-05 return uno::Any(); +//UNUSED2008-05 } +//UNUSED2008-05 +//UNUSED2008-05 SC_IMPL_DUMMY_PROPERTY_LISTENER( ScPrintSettingsObj ) + + +//------------------------------------------------------------------------ + + + diff --git a/sc/source/ui/unoobj/nameuno.cxx b/sc/source/ui/unoobj/nameuno.cxx new file mode 100644 index 000000000000..75686df460d6 --- /dev/null +++ b/sc/source/ui/unoobj/nameuno.cxx @@ -0,0 +1,1131 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include <svl/smplhint.hxx> + +#include <com/sun/star/sheet/NamedRangeFlag.hpp> +#include <com/sun/star/awt/XBitmap.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> + +using namespace ::com::sun::star; + + +#include "nameuno.hxx" +#include "miscuno.hxx" +#include "cellsuno.hxx" +#include "convuno.hxx" +#include "targuno.hxx" +#include "tokenuno.hxx" +#include "tokenarray.hxx" +#include "docsh.hxx" +#include "docfunc.hxx" +#include "rangenam.hxx" +//CHINA001 #include "namecrea.hxx" // NAME_TOP etc. +#include "unoguard.hxx" +#include "unonames.hxx" + +#include "scui_def.hxx" //CHINA001 + +//------------------------------------------------------------------------ + +const SfxItemPropertyMapEntry* lcl_GetNamedRangeMap() +{ + static SfxItemPropertyMapEntry aNamedRangeMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNO_LINKDISPBIT), 0, &getCppuType((uno::Reference<awt::XBitmap>*)0), beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNO_LINKDISPNAME), 0, &getCppuType((rtl::OUString*)0), beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_TOKENINDEX), 0, &getCppuType((sal_Int32*)0), beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_ISSHAREDFMLA), 0, &getBooleanCppuType(), 0, 0 }, + {0,0,0,0,0,0} + }; + return aNamedRangeMap_Impl; +} + +//------------------------------------------------------------------------ + +#define SCNAMEDRANGEOBJ_SERVICE "com.sun.star.sheet.NamedRange" + +SC_SIMPLE_SERVICE_INFO( ScLabelRangeObj, "ScLabelRangeObj", "com.sun.star.sheet.LabelRange" ) +SC_SIMPLE_SERVICE_INFO( ScLabelRangesObj, "ScLabelRangesObj", "com.sun.star.sheet.LabelRanges" ) +SC_SIMPLE_SERVICE_INFO( ScNamedRangesObj, "ScNamedRangesObj", "com.sun.star.sheet.NamedRanges" ) + +//------------------------------------------------------------------------ + +sal_Bool lcl_UserVisibleName( const ScRangeData* pData ) +{ + //! als Methode an ScRangeData + + return ( pData && !pData->HasType( RT_DATABASE ) && !pData->HasType( RT_SHARED ) ); +} + +//------------------------------------------------------------------------ + +ScNamedRangeObj::ScNamedRangeObj(ScDocShell* pDocSh, const String& rNm) : + pDocShell( pDocSh ), + aName( rNm ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScNamedRangeObj::~ScNamedRangeObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScNamedRangeObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + // Ref-Update interessiert nicht + + if ( rHint.ISA( SfxSimpleHint ) && ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + pDocShell = NULL; // ungueltig geworden +} + +// Hilfsfuntionen + +ScRangeData* ScNamedRangeObj::GetRangeData_Impl() +{ + ScRangeData* pRet = NULL; + if (pDocShell) + { + ScRangeName* pNames = pDocShell->GetDocument()->GetRangeName(); + if (pNames) + { + sal_uInt16 nPos = 0; + if (pNames->SearchName( aName, nPos )) + { + pRet = (*pNames)[nPos]; + pRet->ValidateTabRefs(); // adjust relative tab refs to valid tables + } + } + } + return pRet; +} + +// sheet::XNamedRange + +void ScNamedRangeObj::Modify_Impl( const String* pNewName, const ScTokenArray* pNewTokens, const String* pNewContent, + const ScAddress* pNewPos, const sal_uInt16* pNewType, + const formula::FormulaGrammar::Grammar eGrammar ) +{ + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScRangeName* pNames = pDoc->GetRangeName(); + if (pNames) + { + sal_uInt16 nPos = 0; + if (pNames->SearchName( aName, nPos )) + { + ScRangeName* pNewRanges = new ScRangeName( *pNames ); + ScRangeData* pOld = (*pNames)[nPos]; + + String aInsName(pOld->GetName()); + if (pNewName) + aInsName = *pNewName; + String aContent; // Content string based => + pOld->GetSymbol( aContent, eGrammar); // no problems with changed positions and such. + if (pNewContent) + aContent = *pNewContent; + ScAddress aPos(pOld->GetPos()); + if (pNewPos) + aPos = *pNewPos; + sal_uInt16 nType = pOld->GetType(); + if (pNewType) + nType = *pNewType; + + ScRangeData* pNew = NULL; + if ( pNewTokens ) + pNew = new ScRangeData( pDoc, aInsName, *pNewTokens, aPos, nType ); + else + pNew = new ScRangeData( pDoc, aInsName, aContent, aPos, nType, eGrammar ); + pNew->SetIndex( pOld->GetIndex() ); + + pNewRanges->AtFree( nPos ); + if ( pNewRanges->Insert(pNew) ) + { + ScDocFunc aFunc(*pDocShell); + aFunc.SetNewRangeNames( pNewRanges, sal_True ); + + aName = aInsName; //! broadcast? + } + else + { + delete pNew; //! uno::Exception/Fehler oder so + delete pNewRanges; + } + } + } + } +} + + +rtl::OUString SAL_CALL ScNamedRangeObj::getName() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return aName; +} + +void SAL_CALL ScNamedRangeObj::setName( const rtl::OUString& aNewName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + //! Formeln anpassen ????? + + String aNewStr(aNewName); + // GRAM_PODF_A1 for API compatibility. + Modify_Impl( &aNewStr, NULL, NULL, NULL, NULL,formula::FormulaGrammar::GRAM_PODF_A1 ); + + if ( aName != aNewStr ) // some error occured... + throw uno::RuntimeException(); // no other exceptions specified +} + +rtl::OUString SAL_CALL ScNamedRangeObj::getContent() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aContent; + ScRangeData* pData = GetRangeData_Impl(); + if (pData) + // GRAM_PODF_A1 for API compatibility. + pData->GetSymbol( aContent,formula::FormulaGrammar::GRAM_PODF_A1); + return aContent; +} + +void SAL_CALL ScNamedRangeObj::setContent( const rtl::OUString& aContent ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aContStr(aContent); + // GRAM_PODF_A1 for API compatibility. + Modify_Impl( NULL, NULL, &aContStr, NULL, NULL,formula::FormulaGrammar::GRAM_PODF_A1 ); +} + +void ScNamedRangeObj::SetContentWithGrammar( const ::rtl::OUString& aContent, + const formula::FormulaGrammar::Grammar eGrammar ) + throw(::com::sun::star::uno::RuntimeException) +{ + String aContStr(aContent); + Modify_Impl( NULL, NULL, &aContStr, NULL, NULL, eGrammar ); +} + +table::CellAddress SAL_CALL ScNamedRangeObj::getReferencePosition() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScAddress aPos; + ScRangeData* pData = GetRangeData_Impl(); + if (pData) + aPos = pData->GetPos(); + table::CellAddress aAddress; + aAddress.Column = aPos.Col(); + aAddress.Row = aPos.Row(); + aAddress.Sheet = aPos.Tab(); + if (pDocShell) + { + SCTAB nDocTabs = pDocShell->GetDocument()->GetTableCount(); + if ( aAddress.Sheet >= nDocTabs && nDocTabs > 0 ) + { + // Even after ValidateTabRefs, the position can be invalid if + // the content points to preceding tables. The resulting string + // is invalid in any case, so the position is just shifted. + aAddress.Sheet = nDocTabs - 1; + } + } + return aAddress; +} + +void SAL_CALL ScNamedRangeObj::setReferencePosition( const table::CellAddress& aReferencePosition ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScAddress aPos( (SCCOL)aReferencePosition.Column, (SCROW)aReferencePosition.Row, aReferencePosition.Sheet ); + // GRAM_PODF_A1 for API compatibility. + Modify_Impl( NULL, NULL, NULL, &aPos, NULL,formula::FormulaGrammar::GRAM_PODF_A1 ); +} + +sal_Int32 SAL_CALL ScNamedRangeObj::getType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + sal_Int32 nType=0; + ScRangeData* pData = GetRangeData_Impl(); + if (pData) + { + // do not return internal RT_* flags + // see property 'IsSharedFormula' for RT_SHARED + if ( pData->HasType(RT_CRITERIA) ) nType |= sheet::NamedRangeFlag::FILTER_CRITERIA; + if ( pData->HasType(RT_PRINTAREA) ) nType |= sheet::NamedRangeFlag::PRINT_AREA; + if ( pData->HasType(RT_COLHEADER) ) nType |= sheet::NamedRangeFlag::COLUMN_HEADER; + if ( pData->HasType(RT_ROWHEADER) ) nType |= sheet::NamedRangeFlag::ROW_HEADER; + } + return nType; +} + +void SAL_CALL ScNamedRangeObj::setType( sal_Int32 nUnoType ) throw(uno::RuntimeException) +{ + // see property 'IsSharedFormula' for RT_SHARED + ScUnoGuard aGuard; + sal_uInt16 nNewType = RT_NAME; + if ( nUnoType & sheet::NamedRangeFlag::FILTER_CRITERIA ) nNewType |= RT_CRITERIA; + if ( nUnoType & sheet::NamedRangeFlag::PRINT_AREA ) nNewType |= RT_PRINTAREA; + if ( nUnoType & sheet::NamedRangeFlag::COLUMN_HEADER ) nNewType |= RT_COLHEADER; + if ( nUnoType & sheet::NamedRangeFlag::ROW_HEADER ) nNewType |= RT_ROWHEADER; + + // GRAM_PODF_A1 for API compatibility. + Modify_Impl( NULL, NULL, NULL, NULL, &nNewType,formula::FormulaGrammar::GRAM_PODF_A1 ); +} + +// XFormulaTokens + +uno::Sequence<sheet::FormulaToken> SAL_CALL ScNamedRangeObj::getTokens() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Sequence<sheet::FormulaToken> aSequence; + ScRangeData* pData = GetRangeData_Impl(); + if (pData && pDocShell) + { + ScTokenArray* pTokenArray = pData->GetCode(); + if ( pTokenArray ) + (void)ScTokenConversion::ConvertToTokenSequence( *pDocShell->GetDocument(), aSequence, *pTokenArray ); + } + return aSequence; +} + +void SAL_CALL ScNamedRangeObj::setTokens( const uno::Sequence<sheet::FormulaToken>& rTokens ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if( pDocShell ) + { + ScTokenArray aTokenArray; + (void)ScTokenConversion::ConvertToTokenArray( *pDocShell->GetDocument(), aTokenArray, rTokens ); + // GRAM_PODF_A1 for API compatibility. + Modify_Impl( NULL, &aTokenArray, NULL, NULL, NULL, formula::FormulaGrammar::GRAM_PODF_A1 ); + } +} + + +// XCellRangeSource + +uno::Reference<table::XCellRange> SAL_CALL ScNamedRangeObj::getReferredCells() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScRange aRange; + ScRangeData* pData = GetRangeData_Impl(); + if ( pData && pData->IsValidReference( aRange ) ) + { + //! static Funktion um ScCellObj/ScCellRangeObj zu erzeugen am ScCellRangeObj ??? + + if ( aRange.aStart == aRange.aEnd ) + return new ScCellObj( pDocShell, aRange.aStart ); + else + return new ScCellRangeObj( pDocShell, aRange ); + } + return NULL; +} + +// beans::XPropertySet + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScNamedRangeObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference< beans::XPropertySetInfo > aRef(new SfxItemPropertySetInfo( lcl_GetNamedRangeMap() )); + return aRef; +} + +void SAL_CALL ScNamedRangeObj::setPropertyValue( + const rtl::OUString& rPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( rPropertyName.equalsAscii( SC_UNONAME_ISSHAREDFMLA ) ) + { + bool bIsShared = false; + if( aValue >>= bIsShared ) + { + sal_uInt16 nNewType = bIsShared ? RT_SHARED : RT_NAME; + Modify_Impl( NULL, NULL, NULL, NULL, &nNewType,formula::FormulaGrammar::GRAM_PODF_A1 ); + } + } +} + +uno::Any SAL_CALL ScNamedRangeObj::getPropertyValue( const rtl::OUString& rPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Any aRet; + if ( rPropertyName.equalsAscii( SC_UNO_LINKDISPBIT ) ) + { + // no target bitmaps for individual entries (would be all equal) + // ScLinkTargetTypeObj::SetLinkTargetBitmap( aRet, SC_LINKTARGETTYPE_RANGENAME ); + } + else if ( rPropertyName.equalsAscii( SC_UNO_LINKDISPNAME ) ) + aRet <<= rtl::OUString( aName ); + else if ( rPropertyName.equalsAscii( SC_UNONAME_TOKENINDEX ) ) + { + // get index for use in formula tokens (read-only) + ScRangeData* pData = GetRangeData_Impl(); + if (pData) + aRet <<= static_cast<sal_Int32>(pData->GetIndex()); + } + else if ( rPropertyName.equalsAscii( SC_UNONAME_ISSHAREDFMLA ) ) + { + if( ScRangeData* pData = GetRangeData_Impl() ) + aRet <<= static_cast< bool >( pData->HasType( RT_SHARED ) ); + } + return aRet; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScNamedRangeObj ) + +// lang::XServiceInfo + +rtl::OUString SAL_CALL ScNamedRangeObj::getImplementationName() throw(uno::RuntimeException) +{ + return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ScNamedRangeObj" ) ); +} + +sal_Bool SAL_CALL ScNamedRangeObj::supportsService( const rtl::OUString& rServiceName ) + throw(uno::RuntimeException) +{ + return rServiceName.equalsAscii( SCNAMEDRANGEOBJ_SERVICE ) || + rServiceName.equalsAscii( SCLINKTARGET_SERVICE ); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScNamedRangeObj::getSupportedServiceNames() + throw(uno::RuntimeException) +{ + uno::Sequence<rtl::OUString> aRet(2); + aRet[0] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SCNAMEDRANGEOBJ_SERVICE ) ); + aRet[1] = rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( SCLINKTARGET_SERVICE ) ); + return aRet; +} + + +// XUnoTunnel + +sal_Int64 SAL_CALL ScNamedRangeObj::getSomething( + const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); + } + return 0; +} + +// static +const uno::Sequence<sal_Int8>& ScNamedRangeObj::getUnoTunnelId() +{ + static uno::Sequence<sal_Int8> * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +// static +ScNamedRangeObj* ScNamedRangeObj::getImplementation( const uno::Reference<uno::XInterface> xObj ) +{ + ScNamedRangeObj* pRet = NULL; + uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); + if (xUT.is()) + pRet = reinterpret_cast<ScNamedRangeObj*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId()))); + return pRet; +} + +//------------------------------------------------------------------------ + +ScNamedRangesObj::ScNamedRangesObj(ScDocShell* pDocSh) : + pDocShell( pDocSh ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScNamedRangesObj::~ScNamedRangesObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScNamedRangesObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + // Referenz-Update interessiert hier nicht + + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +// sheet::XNamedRanges + +ScNamedRangeObj* ScNamedRangesObj::GetObjectByIndex_Impl(sal_uInt16 nIndex) +{ + if (pDocShell) + { + ScRangeName* pNames = pDocShell->GetDocument()->GetRangeName(); + if (pNames) + { + sal_uInt16 nCount = pNames->GetCount(); + sal_uInt16 nPos = 0; + for (sal_uInt16 i=0; i<nCount; i++) + { + ScRangeData* pData = (*pNames)[i]; + if (lcl_UserVisibleName(pData)) // interne weglassen + { + if ( nPos == nIndex ) + return new ScNamedRangeObj( pDocShell, pData->GetName() ); + ++nPos; + } + } + } + } + return NULL; +} + +ScNamedRangeObj* ScNamedRangesObj::GetObjectByName_Impl(const rtl::OUString& aName) +{ + if ( pDocShell && hasByName(aName) ) + return new ScNamedRangeObj( pDocShell, String(aName) ); + return NULL; +} + +void SAL_CALL ScNamedRangesObj::addNewByName( const rtl::OUString& aName, + const rtl::OUString& aContent, const table::CellAddress& aPosition, + sal_Int32 nUnoType ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aNameStr(aName); + String aContStr(aContent); + ScAddress aPos( (SCCOL)aPosition.Column, (SCROW)aPosition.Row, aPosition.Sheet ); + + sal_uInt16 nNewType = RT_NAME; + if ( nUnoType & sheet::NamedRangeFlag::FILTER_CRITERIA ) nNewType |= RT_CRITERIA; + if ( nUnoType & sheet::NamedRangeFlag::PRINT_AREA ) nNewType |= RT_PRINTAREA; + if ( nUnoType & sheet::NamedRangeFlag::COLUMN_HEADER ) nNewType |= RT_COLHEADER; + if ( nUnoType & sheet::NamedRangeFlag::ROW_HEADER ) nNewType |= RT_ROWHEADER; + + BOOL bDone = FALSE; + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScRangeName* pNames = pDoc->GetRangeName(); + USHORT nIndex = 0; + if (pNames && !pNames->SearchName(aNameStr, nIndex)) + { + ScRangeName* pNewRanges = new ScRangeName( *pNames ); + // GRAM_PODF_A1 for API compatibility. + ScRangeData* pNew = new ScRangeData( pDoc, aNameStr, aContStr, + aPos, nNewType,formula::FormulaGrammar::GRAM_PODF_A1 ); + if ( pNewRanges->Insert(pNew) ) + { + ScDocFunc aFunc(*pDocShell); + aFunc.SetNewRangeNames( pNewRanges, sal_True ); + bDone = TRUE; + } + else + { + delete pNew; + delete pNewRanges; + } + } + } + + if (!bDone) + throw uno::RuntimeException(); // no other exceptions specified +} + +void SAL_CALL ScNamedRangesObj::addNewFromTitles( const table::CellRangeAddress& aSource, + sheet::Border aBorder ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + //! das darf kein enum sein, weil mehrere Bits gesetzt sein koennen !!! + + sal_Bool bTop = ( aBorder == sheet::Border_TOP ); + sal_Bool bLeft = ( aBorder == sheet::Border_LEFT ); + sal_Bool bBottom = ( aBorder == sheet::Border_BOTTOM ); + sal_Bool bRight = ( aBorder == sheet::Border_RIGHT ); + + ScRange aRange; + ScUnoConversion::FillScRange( aRange, aSource ); + + sal_uInt16 nFlags = 0; + if (bTop) nFlags |= NAME_TOP; + if (bLeft) nFlags |= NAME_LEFT; + if (bBottom) nFlags |= NAME_BOTTOM; + if (bRight) nFlags |= NAME_RIGHT; + + if (nFlags) + { + ScDocFunc aFunc(*pDocShell); + aFunc.CreateNames( aRange, nFlags, sal_True ); + } +} + +void SAL_CALL ScNamedRangesObj::removeByName( const rtl::OUString& aName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + BOOL bDone = FALSE; + if (pDocShell) + { + ScRangeName* pNames = pDocShell->GetDocument()->GetRangeName(); + if (pNames) + { + String aString(aName); + sal_uInt16 nPos = 0; + if (pNames->SearchName( aString, nPos )) + if ( lcl_UserVisibleName((*pNames)[nPos]) ) + { + ScRangeName* pNewRanges = new ScRangeName(*pNames); + pNewRanges->AtFree(nPos); + ScDocFunc aFunc(*pDocShell); + aFunc.SetNewRangeNames( pNewRanges, sal_True ); + bDone = TRUE; + } + } + } + + if (!bDone) + throw uno::RuntimeException(); // no other exceptions specified +} + +void SAL_CALL ScNamedRangesObj::outputList( const table::CellAddress& aOutputPosition ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScAddress aPos( (SCCOL)aOutputPosition.Column, (SCROW)aOutputPosition.Row, aOutputPosition.Sheet ); + if (pDocShell) + { + ScDocFunc aFunc(*pDocShell); + aFunc.InsertNameList( aPos, sal_True ); + } +} + +// container::XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScNamedRangesObj::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.NamedRangesEnumeration"))); +} + +// container::XIndexAccess + +sal_Int32 SAL_CALL ScNamedRangesObj::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + long nRet = 0; + if (pDocShell) + { + ScRangeName* pNames = pDocShell->GetDocument()->GetRangeName(); + if (pNames) + { + sal_uInt16 nCount = pNames->GetCount(); + for (sal_uInt16 i=0; i<nCount; i++) + if (lcl_UserVisibleName( (*pNames)[i] )) // interne weglassen + ++nRet; + } + } + return nRet; +} + +uno::Any SAL_CALL ScNamedRangesObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference< sheet::XNamedRange > xRange(GetObjectByIndex_Impl((sal_uInt16)nIndex)); + if ( xRange.is() ) + return uno::makeAny(xRange); + else + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +uno::Type SAL_CALL ScNamedRangesObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ::getCppuType((const uno::Reference< sheet::XNamedRange >*)0); // muss zu getByIndex passen +} + +sal_Bool SAL_CALL ScNamedRangesObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +uno::Any SAL_CALL ScNamedRangesObj::getByName( const rtl::OUString& aName ) + throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference< sheet::XNamedRange > xRange(GetObjectByName_Impl(aName)); + if ( xRange.is() ) + return uno::makeAny(xRange); + else + throw container::NoSuchElementException(); +// return uno::Any(); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScNamedRangesObj::getElementNames() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + ScRangeName* pNames = pDocShell->GetDocument()->GetRangeName(); + if (pNames) + { + long nVisCount = getCount(); // Namen mit lcl_UserVisibleName + uno::Sequence<rtl::OUString> aSeq(nVisCount); + rtl::OUString* pAry = aSeq.getArray(); + + sal_uInt16 nCount = pNames->GetCount(); + sal_uInt16 nVisPos = 0; + for (sal_uInt16 i=0; i<nCount; i++) + { + ScRangeData* pData = (*pNames)[i]; + if ( lcl_UserVisibleName(pData) ) + pAry[nVisPos++] = pData->GetName(); + } +// DBG_ASSERT(nVisPos == nVisCount, "huch, verzaehlt?"); + return aSeq; + } + } + return uno::Sequence<rtl::OUString>(0); +} + +sal_Bool SAL_CALL ScNamedRangesObj::hasByName( const rtl::OUString& aName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + ScRangeName* pNames = pDocShell->GetDocument()->GetRangeName(); + if (pNames) + { + sal_uInt16 nPos = 0; + if (pNames->SearchName( String(aName), nPos )) + if ( lcl_UserVisibleName((*pNames)[nPos]) ) + return sal_True; + } + } + return sal_False; +} + +/** called from the XActionLockable interface methods on initial locking */ +void ScNamedRangesObj::lock() +{ + pDocShell->GetDocument()->CompileNameFormula( TRUE ); // CreateFormulaString +} + +/** called from the XActionLockable interface methods on final unlock */ +void ScNamedRangesObj::unlock() +{ + pDocShell->GetDocument()->CompileNameFormula( FALSE ); // CompileFormulaString +} + +// document::XActionLockable + +sal_Bool ScNamedRangesObj::isActionLocked() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return pDocShell->GetDocument()->GetNamedRangesLockCount() != 0; +} + +void ScNamedRangesObj::addActionLock() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocument* pDoc = pDocShell->GetDocument(); + sal_Int16 nLockCount = pDoc->GetNamedRangesLockCount(); + ++nLockCount; + if ( nLockCount == 1 ) + { + lock(); + } + pDoc->SetNamedRangesLockCount( nLockCount ); +} + +void ScNamedRangesObj::removeActionLock() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocument* pDoc = pDocShell->GetDocument(); + sal_Int16 nLockCount = pDoc->GetNamedRangesLockCount(); + if ( nLockCount > 0 ) + { + --nLockCount; + if ( nLockCount == 0 ) + { + unlock(); + } + pDoc->SetNamedRangesLockCount( nLockCount ); + } +} + +void ScNamedRangesObj::setActionLocks( sal_Int16 nLock ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( nLock >= 0 ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + sal_Int16 nLockCount = pDoc->GetNamedRangesLockCount(); + if ( nLock == 0 && nLockCount > 0 ) + { + unlock(); + } + if ( nLock > 0 && nLockCount == 0 ) + { + lock(); + } + pDoc->SetNamedRangesLockCount( nLock ); + } +} + +sal_Int16 ScNamedRangesObj::resetActionLocks() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScDocument* pDoc = pDocShell->GetDocument(); + sal_Int16 nLockCount = pDoc->GetNamedRangesLockCount(); + if ( nLockCount > 0 ) + { + unlock(); + } + pDoc->SetNamedRangesLockCount( 0 ); + return nLockCount; +} + +//------------------------------------------------------------------------ + +ScLabelRangeObj::ScLabelRangeObj(ScDocShell* pDocSh, sal_Bool bCol, const ScRange& rR) : + pDocShell( pDocSh ), + bColumn( bCol ), + aRange( rR ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScLabelRangeObj::~ScLabelRangeObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScLabelRangeObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + //! Ref-Update !!! + + if ( rHint.ISA( SfxSimpleHint ) && ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + pDocShell = NULL; // ungueltig geworden +} + +// Hilfsfuntionen + +ScRangePair* ScLabelRangeObj::GetData_Impl() +{ + ScRangePair* pRet = NULL; + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScRangePairList* pList = bColumn ? pDoc->GetColNameRanges() : pDoc->GetRowNameRanges(); + if (pList) + pRet = pList->Find( aRange ); + } + return pRet; +} + +void ScLabelRangeObj::Modify_Impl( const ScRange* pLabel, const ScRange* pData ) +{ + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScRangePairList* pOldList = bColumn ? pDoc->GetColNameRanges() : pDoc->GetRowNameRanges(); + if (pOldList) + { + ScRangePairListRef xNewList(pOldList->Clone()); + ScRangePair* pEntry = xNewList->Find( aRange ); + if (pEntry) + { + xNewList->Remove( pEntry ); // nur aus der Liste entfernt, nicht geloescht + + if ( pLabel ) + pEntry->GetRange(0) = *pLabel; + if ( pData ) + pEntry->GetRange(1) = *pData; + + xNewList->Join( *pEntry ); + delete pEntry; + + if (bColumn) + pDoc->GetColNameRangesRef() = xNewList; + else + pDoc->GetRowNameRangesRef() = xNewList; + + pDoc->CompileColRowNameFormula(); + pDocShell->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID ); + pDocShell->SetDocumentModified(); + + //! Undo ?!?! (hier und aus Dialog) + + if ( pLabel ) + aRange = *pLabel; // Objekt anpassen, um Range wiederzufinden + } + } + } +} + +// sheet::XLabelRange + +table::CellRangeAddress SAL_CALL ScLabelRangeObj::getLabelArea() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + table::CellRangeAddress aRet; + ScRangePair* pData = GetData_Impl(); + if (pData) + ScUnoConversion::FillApiRange( aRet, pData->GetRange(0) ); + return aRet; +} + +void SAL_CALL ScLabelRangeObj::setLabelArea( const table::CellRangeAddress& aLabelArea ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScRange aLabelRange; + ScUnoConversion::FillScRange( aLabelRange, aLabelArea ); + Modify_Impl( &aLabelRange, NULL ); +} + +table::CellRangeAddress SAL_CALL ScLabelRangeObj::getDataArea() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + table::CellRangeAddress aRet; + ScRangePair* pData = GetData_Impl(); + if (pData) + ScUnoConversion::FillApiRange( aRet, pData->GetRange(1) ); + return aRet; +} + +void SAL_CALL ScLabelRangeObj::setDataArea( const table::CellRangeAddress& aDataArea ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScRange aDataRange; + ScUnoConversion::FillScRange( aDataRange, aDataArea ); + Modify_Impl( NULL, &aDataRange ); +} + +//------------------------------------------------------------------------ + +ScLabelRangesObj::ScLabelRangesObj(ScDocShell* pDocSh, sal_Bool bCol) : + pDocShell( pDocSh ), + bColumn( bCol ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScLabelRangesObj::~ScLabelRangesObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScLabelRangesObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + // Referenz-Update interessiert hier nicht + + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +// sheet::XLabelRanges + +ScLabelRangeObj* ScLabelRangesObj::GetObjectByIndex_Impl(sal_uInt16 nIndex) +{ + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScRangePairList* pList = bColumn ? pDoc->GetColNameRanges() : pDoc->GetRowNameRanges(); + if ( pList && nIndex < pList->Count() ) + { + ScRangePair* pData = pList->GetObject(nIndex); + if (pData) + return new ScLabelRangeObj( pDocShell, bColumn, pData->GetRange(0) ); + } + } + return NULL; +} + +void SAL_CALL ScLabelRangesObj::addNew( const table::CellRangeAddress& aLabelArea, + const table::CellRangeAddress& aDataArea ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScRangePairList* pOldList = bColumn ? pDoc->GetColNameRanges() : pDoc->GetRowNameRanges(); + if (pOldList) + { + ScRangePairListRef xNewList(pOldList->Clone()); + + ScRange aLabelRange; + ScRange aDataRange; + ScUnoConversion::FillScRange( aLabelRange, aLabelArea ); + ScUnoConversion::FillScRange( aDataRange, aDataArea ); + xNewList->Join( ScRangePair( aLabelRange, aDataRange ) ); + + if (bColumn) + pDoc->GetColNameRangesRef() = xNewList; + else + pDoc->GetRowNameRangesRef() = xNewList; + + pDoc->CompileColRowNameFormula(); + pDocShell->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID ); + pDocShell->SetDocumentModified(); + + //! Undo ?!?! (hier und aus Dialog) + } + } +} + +void SAL_CALL ScLabelRangesObj::removeByIndex( sal_Int32 nIndex ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + BOOL bDone = FALSE; + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScRangePairList* pOldList = bColumn ? pDoc->GetColNameRanges() : pDoc->GetRowNameRanges(); + + if ( pOldList && nIndex >= 0 && nIndex < (sal_Int32)pOldList->Count() ) + { + ScRangePairListRef xNewList(pOldList->Clone()); + + ScRangePair* pEntry = xNewList->GetObject( nIndex ); + if (pEntry) + { + xNewList->Remove( pEntry ); + delete pEntry; + + if (bColumn) + pDoc->GetColNameRangesRef() = xNewList; + else + pDoc->GetRowNameRangesRef() = xNewList; + + pDoc->CompileColRowNameFormula(); + pDocShell->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID ); + pDocShell->SetDocumentModified(); + bDone = TRUE; + + //! Undo ?!?! (hier und aus Dialog) + } + } + } + if (!bDone) + throw uno::RuntimeException(); // no other exceptions specified +} + +// container::XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScLabelRangesObj::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.LabelRangesEnumeration"))); +} + +// container::XIndexAccess + +sal_Int32 SAL_CALL ScLabelRangesObj::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScRangePairList* pList = bColumn ? pDoc->GetColNameRanges() : pDoc->GetRowNameRanges(); + if (pList) + return pList->Count(); + } + return 0; +} + +uno::Any SAL_CALL ScLabelRangesObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference< sheet::XLabelRange > xRange(GetObjectByIndex_Impl((sal_uInt16)nIndex)); + if ( xRange.is() ) + return uno::makeAny(xRange); + else + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +uno::Type SAL_CALL ScLabelRangesObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ::getCppuType((const uno::Reference< sheet::XLabelRange >*)0); // muss zu getByIndex passen + +} + +sal_Bool SAL_CALL ScLabelRangesObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +//------------------------------------------------------------------------ + + + diff --git a/sc/source/ui/unoobj/notesuno.cxx b/sc/source/ui/unoobj/notesuno.cxx new file mode 100644 index 000000000000..c5dd11977478 --- /dev/null +++ b/sc/source/ui/unoobj/notesuno.cxx @@ -0,0 +1,729 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" +#include <svl/smplhint.hxx> + + +#include "rangelst.hxx" +#include <editeng/unotext.hxx> +#include <svx/svdpool.hxx> +#include <svx/svdobj.hxx> +#include "notesuno.hxx" +#include "textuno.hxx" +#include "cellsuno.hxx" // getParent +#include "docsh.hxx" +#include "docfunc.hxx" +#include "hints.hxx" +#include "editsrc.hxx" +#include "miscuno.hxx" + +// setVisible: +#include <svx/svdundo.hxx> +#include "drwlayer.hxx" +#include "detfunc.hxx" +#include "undocell.hxx" +#include "unoguard.hxx" +#include "userdat.hxx" +#include <editeng/outlobj.hxx> +#include <svx/unoshape.hxx> +#include <svx/svdocapt.hxx> +#include <svx/svditer.hxx> +#include <svx/svdpage.hxx> +#include <com/sun/star/drawing/XShapeDescriptor.hpp> + +using namespace com::sun::star; + +//------------------------------------------------------------------------ + +// keine Properties fuer Text in Notizen +const SvxItemPropertySet* lcl_GetAnnotationPropertySet() +{ + static SfxItemPropertyMapEntry aAnnotationPropertyMap_Impl[] = + { + {0,0,0,0,0,0} + }; + static SvxItemPropertySet aAnnotationPropertySet_Impl( aAnnotationPropertyMap_Impl, SdrObject::GetGlobalDrawObjectItemPool() ); + return &aAnnotationPropertySet_Impl; +} + +//------------------------------------------------------------------------ + +SC_SIMPLE_SERVICE_INFO( ScAnnotationObj, "ScAnnotationObj", "com.sun.star.sheet.CellAnnotation" ) +SC_SIMPLE_SERVICE_INFO( ScAnnotationShapeObj, "ScAnnotationShapeObj", "com.sun.star.sheet.CellAnnotationShape" ) + +//------------------------------------------------------------------------ + +ScAnnotationObj::ScAnnotationObj(ScDocShell* pDocSh, const ScAddress& rPos) : + pDocShell( pDocSh ), + aCellPos( rPos ), + pUnoText( NULL ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); + + // pUnoText is allocated on demand (GetUnoText) + // can't be aggregated because getString/setString is handled here +} + +ScAnnotationObj::~ScAnnotationObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); + + if (pUnoText) + pUnoText->release(); +} + +void ScAnnotationObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( ScUpdateRefHint ) ) + { +// const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint; + + //! Ref-Update + } + else if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + + +// XChild + +uno::Reference<uno::XInterface> SAL_CALL ScAnnotationObj::getParent() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + // Parent der Notiz ist die zugehoerige Zelle + //! existierendes Objekt finden und zurueckgeben ??? + + if (pDocShell) + return (cppu::OWeakObject*)new ScCellObj( pDocShell, aCellPos ); + + return NULL; +} + +void SAL_CALL ScAnnotationObj::setParent( const uno::Reference<uno::XInterface>& /* Parent */ ) + throw(lang::NoSupportException, uno::RuntimeException) +{ + // hamma nich + //! Exception oder so ??! +} + +// XSimpleText + +uno::Reference<text::XTextCursor> SAL_CALL ScAnnotationObj::createTextCursor() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + // Notizen brauchen keine Extrawurst + return GetUnoText().createTextCursor(); +} + +uno::Reference<text::XTextCursor> SAL_CALL ScAnnotationObj::createTextCursorByRange( + const uno::Reference<text::XTextRange>& aTextPosition ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + // Notizen brauchen keine Extrawurst + return GetUnoText().createTextCursorByRange(aTextPosition); +} + +rtl::OUString SAL_CALL ScAnnotationObj::getString() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return GetUnoText().getString(); +} + +void SAL_CALL ScAnnotationObj::setString( const rtl::OUString& aText ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + GetUnoText().setString(aText); +} + +void SAL_CALL ScAnnotationObj::insertString( const uno::Reference<text::XTextRange>& xRange, + const rtl::OUString& aString, sal_Bool bAbsorb ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + GetUnoText().insertString( xRange, aString, bAbsorb ); +} + +void SAL_CALL ScAnnotationObj::insertControlCharacter( const uno::Reference<text::XTextRange>& xRange, + sal_Int16 nControlCharacter, sal_Bool bAbsorb ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + GetUnoText().insertControlCharacter( xRange, nControlCharacter, bAbsorb ); +} + +uno::Reference<text::XText> SAL_CALL ScAnnotationObj::getText() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return GetUnoText().getText(); +} + +uno::Reference<text::XTextRange> SAL_CALL ScAnnotationObj::getStart() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return GetUnoText().getStart(); +} + +uno::Reference<text::XTextRange> SAL_CALL ScAnnotationObj::getEnd() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return GetUnoText().getEnd(); +} + +// XSheetAnnotation + +table::CellAddress SAL_CALL ScAnnotationObj::getPosition() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + table::CellAddress aAdr; + aAdr.Sheet = aCellPos.Tab(); + aAdr.Column = aCellPos.Col(); + aAdr.Row = aCellPos.Row(); + return aAdr; +} + +rtl::OUString SAL_CALL ScAnnotationObj::getAuthor() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + const ScPostIt* pNote = ImplGetNote(); + return pNote ? pNote->GetAuthor() : rtl::OUString(); +} + +rtl::OUString SAL_CALL ScAnnotationObj::getDate() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + const ScPostIt* pNote = ImplGetNote(); + return pNote ? pNote->GetDate() : rtl::OUString(); +} + +sal_Bool SAL_CALL ScAnnotationObj::getIsVisible() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + const ScPostIt* pNote = ImplGetNote(); + return pNote && pNote->IsCaptionShown(); +} + +void SAL_CALL ScAnnotationObj::setIsVisible( sal_Bool bIsVisible ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + // show/hide note with undo action + if( pDocShell ) + pDocShell->GetDocFunc().ShowNote( aCellPos, bIsVisible ); +} + +// XSheetAnnotationShapeSupplier +uno::Reference < drawing::XShape > SAL_CALL ScAnnotationObj::getAnnotationShape() + throw(::com::sun::star::uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScAnnotationShapeObj(pDocShell, aCellPos); +} + +SvxUnoText& ScAnnotationObj::GetUnoText() +{ + if (!pUnoText) + { + ScAnnotationEditSource aEditSource( pDocShell, aCellPos ); + pUnoText = new SvxUnoText( &aEditSource, lcl_GetAnnotationPropertySet(), + uno::Reference<text::XText>() ); + pUnoText->acquire(); + } + return *pUnoText; +} + +const ScPostIt* ScAnnotationObj::ImplGetNote() const +{ + return pDocShell ? pDocShell->GetDocument()->GetNote( aCellPos ) : 0; +} +//------------------------------------------------------------------------ + +ScAnnotationShapeObj::ScAnnotationShapeObj(ScDocShell* pDocSh, const ScAddress& rPos) : + pDocShell( pDocSh ), + aCellPos( rPos ), + pUnoText( NULL ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); + + // pUnoText is allocated on demand (GetUnoText) + // can't be aggregated because getString/setString is handled here +} + +SvxUnoText& ScAnnotationShapeObj::GetUnoText() +{ + if (!pUnoText) + { + ScAnnotationEditSource aEditSource( pDocShell, aCellPos ); + pUnoText = new SvxUnoText( &aEditSource, lcl_GetAnnotationPropertySet(), + uno::Reference<text::XText>() ); + pUnoText->acquire(); + } + return *pUnoText; +} + +uno::Reference < drawing::XShape > ScAnnotationShapeObj::GetXShape() +{ + if (!xShape.is()) + if( ScPostIt* pNote = pDocShell->GetDocument()->GetNote( aCellPos ) ) + if( SdrObject* pCaption = pNote->GetOrCreateCaption( aCellPos ) ) + xShape.set( pCaption->getUnoShape(), uno::UNO_QUERY ); + return xShape; +} + +ScAnnotationShapeObj::~ScAnnotationShapeObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); + if (pUnoText) + pUnoText->release(); +} + +void ScAnnotationShapeObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( ScUpdateRefHint ) ) + { +// const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint; + + //! Ref-Update + } + else if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + + +// XChild + +uno::Reference<uno::XInterface> SAL_CALL ScAnnotationShapeObj::getParent() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + // Parent der Notiz ist die zugehoerige Zelle + //! existierendes Objekt finden und zurueckgeben ??? + + if (pDocShell) + return (cppu::OWeakObject*)new ScCellObj( pDocShell, aCellPos ); + + return NULL; +} + +void SAL_CALL ScAnnotationShapeObj::setParent( const uno::Reference<uno::XInterface>& /* Parent */ ) + throw(lang::NoSupportException, uno::RuntimeException) +{ + // hamma nich + //! Exception oder so ??! +} + +// XElementAccess +uno::Type SAL_CALL ScAnnotationShapeObj::getElementType( ) throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + + return GetUnoText().getElementType(); +} + +sal_Bool SAL_CALL ScAnnotationShapeObj::hasElements( ) throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + + return GetUnoText().hasElements(); +} + +// XEnumerationAccess +uno::Reference< container::XEnumeration > SAL_CALL ScAnnotationShapeObj::createEnumeration( ) throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + + return GetUnoText().createEnumeration(); +} + +// XTextRangeMover +void SAL_CALL ScAnnotationShapeObj::moveTextRange( const uno::Reference< text::XTextRange >& xRange, sal_Int16 nParagraphs ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + + GetUnoText().moveTextRange( xRange, nParagraphs ); +} + +// XText +void SAL_CALL ScAnnotationShapeObj::insertTextContent( const uno::Reference< text::XTextRange >& xRange, + const uno::Reference< text::XTextContent >& xContent, sal_Bool bAbsorb ) + throw (lang::IllegalArgumentException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + + GetUnoText().insertTextContent( xRange, xContent, bAbsorb ); +} + +void SAL_CALL ScAnnotationShapeObj::removeTextContent( const uno::Reference< text::XTextContent >& xContent ) + throw (container::NoSuchElementException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + + GetUnoText().removeTextContent( xContent ); +} + +// XSimpleText + +uno::Reference<text::XTextCursor> SAL_CALL ScAnnotationShapeObj::createTextCursor() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + // Notizen brauchen keine Extrawurst + return GetUnoText().createTextCursor(); +} + +uno::Reference<text::XTextCursor> SAL_CALL ScAnnotationShapeObj::createTextCursorByRange( + const uno::Reference<text::XTextRange>& aTextPosition ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + // Notizen brauchen keine Extrawurst + return GetUnoText().createTextCursorByRange(aTextPosition); +} + +rtl::OUString SAL_CALL ScAnnotationShapeObj::getString() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return GetUnoText().getString(); +} + +void SAL_CALL ScAnnotationShapeObj::setString( const rtl::OUString& aText ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + GetUnoText().setString(aText); +} + +void SAL_CALL ScAnnotationShapeObj::insertString( const uno::Reference<text::XTextRange>& xRange, + const rtl::OUString& aString, sal_Bool bAbsorb ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + GetUnoText().insertString( xRange, aString, bAbsorb ); +} + +void SAL_CALL ScAnnotationShapeObj::insertControlCharacter( const uno::Reference<text::XTextRange>& xRange, + sal_Int16 nControlCharacter, sal_Bool bAbsorb ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + GetUnoText().insertControlCharacter( xRange, nControlCharacter, bAbsorb ); +} + +uno::Reference<text::XText> SAL_CALL ScAnnotationShapeObj::getText() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return GetUnoText().getText(); +} + +uno::Reference<text::XTextRange> SAL_CALL ScAnnotationShapeObj::getStart() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return GetUnoText().getStart(); +} + +uno::Reference<text::XTextRange> SAL_CALL ScAnnotationShapeObj::getEnd() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return GetUnoText().getEnd(); +} + +// XShapeDescriptor +::rtl::OUString SAL_CALL ScAnnotationShapeObj::getShapeType( ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference < drawing::XShapeDescriptor > xDesc(GetXShape(), uno::UNO_QUERY); + if (xDesc.is()) + return xDesc->getShapeType(); + return rtl::OUString(); +} + +// XShape +awt::Point SAL_CALL ScAnnotationShapeObj::getPosition( ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + GetXShape(); + return xShape.is() ? xShape->getPosition() : awt::Point(); +} + +void SAL_CALL ScAnnotationShapeObj::setPosition( const awt::Point& aPosition ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + GetXShape(); + if( xShape.is() ) + xShape->setPosition(aPosition); +} + +awt::Size SAL_CALL ScAnnotationShapeObj::getSize( ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + GetXShape(); + return xShape.is() ? xShape->getSize() : awt::Size(); +} + +void SAL_CALL ScAnnotationShapeObj::setSize( const awt::Size& aSize ) + throw (beans::PropertyVetoException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + GetXShape(); + if( xShape.is() ) + xShape->setSize(aSize); +} + +// XPropertyState +beans::PropertyState SAL_CALL ScAnnotationShapeObj::getPropertyState( const rtl::OUString& PropertyName ) + throw (beans::UnknownPropertyException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference < beans::XPropertyState > xState (GetXShape(), uno::UNO_QUERY); + if (xState.is()) + return xState->getPropertyState( PropertyName ); + return beans::PropertyState(); +} + +uno::Sequence< beans::PropertyState > SAL_CALL ScAnnotationShapeObj::getPropertyStates( + const uno::Sequence< rtl::OUString >& aPropertyName ) + throw (beans::UnknownPropertyException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference < beans::XPropertyState > xState (GetXShape(), uno::UNO_QUERY); + if (xState.is()) + return xState->getPropertyStates( aPropertyName ); + return uno::Sequence< beans::PropertyState >(); +} + +void SAL_CALL ScAnnotationShapeObj::setPropertyToDefault( const ::rtl::OUString& PropertyName ) + throw (::com::sun::star::beans::UnknownPropertyException, + ::com::sun::star::uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference < beans::XPropertyState > xState (GetXShape(), uno::UNO_QUERY); + if (xState.is()) + xState->setPropertyToDefault( PropertyName ); +} + +uno::Any SAL_CALL ScAnnotationShapeObj::getPropertyDefault( const rtl::OUString& aPropertyName ) + throw (beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference < beans::XPropertyState > xState (GetXShape(), uno::UNO_QUERY); + if (xState.is()) + return xState->getPropertyDefault( aPropertyName ); + return uno::Any(); +} + +// XPropertySet +uno::Reference< beans::XPropertySetInfo > SAL_CALL ScAnnotationShapeObj::getPropertySetInfo( ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference < beans::XPropertySet > xProp (GetXShape(), uno::UNO_QUERY); + if (xProp.is()) + return xProp->getPropertySetInfo(); + return uno::Reference< beans::XPropertySetInfo >(); +} + +void SAL_CALL ScAnnotationShapeObj::setPropertyValue( const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw (beans::UnknownPropertyException, + beans::PropertyVetoException, + lang::IllegalArgumentException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference < beans::XPropertySet > xProp (GetXShape(), uno::UNO_QUERY); + if (xProp.is()) + xProp->setPropertyValue( aPropertyName, aValue ); +} + +uno::Any SAL_CALL ScAnnotationShapeObj::getPropertyValue( const rtl::OUString& PropertyName ) + throw (beans::UnknownPropertyException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference < beans::XPropertySet > xProp (GetXShape(), uno::UNO_QUERY); + if (xProp.is()) + return xProp->getPropertyValue( PropertyName ); + return uno::Any(); +} + +void SAL_CALL ScAnnotationShapeObj::addPropertyChangeListener( const rtl::OUString& aPropertyName, + const uno::Reference< beans::XPropertyChangeListener >& xListener ) + throw (beans::UnknownPropertyException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference < beans::XPropertySet > xProp (GetXShape(), uno::UNO_QUERY); + if (xProp.is()) + return xProp->addPropertyChangeListener( aPropertyName, xListener ); +} + +void SAL_CALL ScAnnotationShapeObj::removePropertyChangeListener( const rtl::OUString& aPropertyName, + const uno::Reference< beans::XPropertyChangeListener >& aListener ) + throw (beans::UnknownPropertyException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference < beans::XPropertySet > xProp (GetXShape(), uno::UNO_QUERY); + if (xProp.is()) + return xProp->removePropertyChangeListener( aPropertyName, aListener ); +} + +void SAL_CALL ScAnnotationShapeObj::addVetoableChangeListener( const rtl::OUString& PropertyName, + const uno::Reference< beans::XVetoableChangeListener >& aListener ) + throw (beans::UnknownPropertyException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference < beans::XPropertySet > xProp (GetXShape(), uno::UNO_QUERY); + if (xProp.is()) + return xProp->addVetoableChangeListener( PropertyName, aListener ); +} + +void SAL_CALL ScAnnotationShapeObj::removeVetoableChangeListener( const rtl::OUString& PropertyName, + const uno::Reference< beans::XVetoableChangeListener >& aListener ) + throw (beans::UnknownPropertyException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference < beans::XPropertySet > xProp (GetXShape(), uno::UNO_QUERY); + if (xProp.is()) + return xProp->removeVetoableChangeListener( PropertyName, aListener ); +} + + // XMultiPropertySet +void SAL_CALL ScAnnotationShapeObj::setPropertyValues( const uno::Sequence< rtl::OUString >& aPropertyNames, + const uno::Sequence< uno::Any >& aValues ) + throw (beans::PropertyVetoException, + lang::IllegalArgumentException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference < beans::XMultiPropertySet > xProp (GetXShape(), uno::UNO_QUERY); + if (xProp.is()) + xProp->setPropertyValues( aPropertyNames, aValues ); +} + +uno::Sequence< uno::Any > SAL_CALL ScAnnotationShapeObj::getPropertyValues( + const uno::Sequence< rtl::OUString >& aPropertyNames ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference < beans::XMultiPropertySet > xProp (GetXShape(), uno::UNO_QUERY); + if (xProp.is()) + return xProp->getPropertyValues( aPropertyNames ); + return uno::Sequence< uno::Any >(); +} + +void SAL_CALL ScAnnotationShapeObj::addPropertiesChangeListener( const uno::Sequence< rtl::OUString >& aPropertyNames, + const uno::Reference< beans::XPropertiesChangeListener >& xListener ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference < beans::XMultiPropertySet > xProp (GetXShape(), uno::UNO_QUERY); + if (xProp.is()) + xProp->addPropertiesChangeListener( aPropertyNames, xListener ); +} + +void SAL_CALL ScAnnotationShapeObj::removePropertiesChangeListener( const uno::Reference< beans::XPropertiesChangeListener >& xListener ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference < beans::XMultiPropertySet > xProp (GetXShape(), uno::UNO_QUERY); + if (xProp.is()) + xProp->removePropertiesChangeListener( xListener ); +} + +void SAL_CALL ScAnnotationShapeObj::firePropertiesChangeEvent( const uno::Sequence< rtl::OUString >& aPropertyNames, + const uno::Reference< beans::XPropertiesChangeListener >& xListener ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference < beans::XMultiPropertySet > xProp (GetXShape(), uno::UNO_QUERY); + if (xProp.is()) + xProp->firePropertiesChangeEvent( aPropertyNames, xListener ); +} + + // XComponent +void SAL_CALL ScAnnotationShapeObj::dispose( ) throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference < lang::XComponent > xComp (GetXShape(), uno::UNO_QUERY); + if (xComp.is()) + xComp->dispose(); + if (xShape.is()) + xShape.clear(); +} + +void SAL_CALL ScAnnotationShapeObj::addEventListener( const uno::Reference< lang::XEventListener >& xListener ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference < lang::XComponent > xComp (GetXShape(), uno::UNO_QUERY); + if (xComp.is()) + xComp->addEventListener( xListener ); +} + +void SAL_CALL ScAnnotationShapeObj::removeEventListener( const uno::Reference< lang::XEventListener >& aListener ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference < lang::XComponent > xComp (GetXShape(), uno::UNO_QUERY); + if (xComp.is()) + xComp->removeEventListener( aListener ); +} + +//------------------------------------------------------------------------ + + + + diff --git a/sc/source/ui/unoobj/optuno.cxx b/sc/source/ui/unoobj/optuno.cxx new file mode 100644 index 000000000000..0d277fdb19fe --- /dev/null +++ b/sc/source/ui/unoobj/optuno.cxx @@ -0,0 +1,237 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include <svl/itemprop.hxx> + +#include <com/sun/star/util/Date.hpp> + +#include "optuno.hxx" +#include "miscuno.hxx" +#include "unonames.hxx" +#include "docoptio.hxx" +#include "unoguard.hxx" + +using namespace com::sun::star; + +//------------------------------------------------------------------------ +// static +const SfxItemPropertyMapEntry* ScDocOptionsHelper::GetPropertyMap() +{ + static SfxItemPropertyMapEntry aMap[] = + { + {MAP_CHAR_LEN(SC_UNO_CALCASSHOWN), PROP_UNO_CALCASSHOWN , &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_DEFTABSTOP), PROP_UNO_DEFTABSTOP , &getCppuType((sal_Int16*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_IGNORECASE), PROP_UNO_IGNORECASE , &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_ITERENABLED), PROP_UNO_ITERENABLED , &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_ITERCOUNT), PROP_UNO_ITERCOUNT , &getCppuType((sal_Int32*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_ITEREPSILON), PROP_UNO_ITEREPSILON , &getCppuType((double*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_LOOKUPLABELS), PROP_UNO_LOOKUPLABELS, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_MATCHWHOLE), PROP_UNO_MATCHWHOLE , &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_NULLDATE), PROP_UNO_NULLDATE , &getCppuType((util::Date*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SPELLONLINE), PROP_UNO_SPELLONLINE , &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_STANDARDDEC), PROP_UNO_STANDARDDEC , &getCppuType((sal_Int16*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_REGEXENABLED), PROP_UNO_REGEXENABLED, &getBooleanCppuType(), 0, 0}, + {0,0,0,0,0,0} + }; + return aMap; +} + +// static +sal_Bool ScDocOptionsHelper::setPropertyValue( ScDocOptions& rOptions, + const SfxItemPropertyMap& rPropMap, + const rtl::OUString& aPropertyName, const uno::Any& aValue ) +{ + //! use map (with new identifiers) + + const SfxItemPropertySimpleEntry* pEntry = rPropMap.getByName(aPropertyName ); + if( !pEntry || !pEntry->nWID ) + return sal_False; + switch( pEntry->nWID ) + { + case PROP_UNO_CALCASSHOWN : + rOptions.SetCalcAsShown( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + break; + case PROP_UNO_DEFTABSTOP : + { + sal_Int16 nIntVal = 0; + if ( aValue >>= nIntVal ) + rOptions.SetTabDistance( nIntVal ); + } + break; + case PROP_UNO_IGNORECASE : + rOptions.SetIgnoreCase( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + break; + case PROP_UNO_ITERENABLED: + rOptions.SetIter( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + break; + case PROP_UNO_ITERCOUNT : + { + sal_Int32 nIntVal = 0; + if ( aValue >>= nIntVal ) + rOptions.SetIterCount( (USHORT)nIntVal ); + } + break; + case PROP_UNO_ITEREPSILON : + { + double fDoubleVal = 0; + if ( aValue >>= fDoubleVal ) + rOptions.SetIterEps( fDoubleVal ); + } + break; + case PROP_UNO_LOOKUPLABELS : + rOptions.SetLookUpColRowNames( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + break; + case PROP_UNO_MATCHWHOLE : + rOptions.SetMatchWholeCell( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + break; + case PROP_UNO_NULLDATE: + { + util::Date aDate; + if ( aValue >>= aDate ) + rOptions.SetDate( aDate.Day, aDate.Month, aDate.Year ); + } + break; + case PROP_UNO_SPELLONLINE: + rOptions.SetAutoSpell( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + break; + case PROP_UNO_STANDARDDEC: + { + sal_Int16 nIntVal = 0; + if ( aValue >>= nIntVal ) + rOptions.SetStdPrecision( nIntVal ); + } + break; + case PROP_UNO_REGEXENABLED: + rOptions.SetFormulaRegexEnabled( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + break; + default:; + } + return sal_True; +} + +// static +uno::Any ScDocOptionsHelper::getPropertyValue( + const ScDocOptions& rOptions, + const SfxItemPropertyMap& rPropMap, + const rtl::OUString& aPropertyName ) +{ + uno::Any aRet; + const SfxItemPropertySimpleEntry* pEntry = rPropMap.getByName( aPropertyName ); + if( !pEntry || !pEntry->nWID ) + return aRet; + switch( pEntry->nWID ) + { + case PROP_UNO_CALCASSHOWN : + ScUnoHelpFunctions::SetBoolInAny( aRet, rOptions.IsCalcAsShown() ); + break; + case PROP_UNO_DEFTABSTOP : + aRet <<= (sal_Int16)( rOptions.GetTabDistance() ); + break; + case PROP_UNO_IGNORECASE : + ScUnoHelpFunctions::SetBoolInAny( aRet, rOptions.IsIgnoreCase() ); + break; + case PROP_UNO_ITERENABLED: + ScUnoHelpFunctions::SetBoolInAny( aRet, rOptions.IsIter() ); + break; + case PROP_UNO_ITERCOUNT: + aRet <<= (sal_Int32)( rOptions.GetIterCount() ); + break; + case PROP_UNO_ITEREPSILON: + aRet <<= (double)( rOptions.GetIterEps() ); + break; + case PROP_UNO_LOOKUPLABELS: + ScUnoHelpFunctions::SetBoolInAny( aRet, rOptions.IsLookUpColRowNames() ); + break; + case PROP_UNO_MATCHWHOLE: + ScUnoHelpFunctions::SetBoolInAny( aRet, rOptions.IsMatchWholeCell() ); + break; + case PROP_UNO_NULLDATE: + { + USHORT nD, nM, nY; + rOptions.GetDate( nD, nM, nY ); + util::Date aDate( nD, nM, nY ); + aRet <<= aDate; + } + break; + case PROP_UNO_SPELLONLINE: + ScUnoHelpFunctions::SetBoolInAny( aRet, rOptions.IsAutoSpell() ); + break; + case PROP_UNO_STANDARDDEC : + aRet <<= (sal_Int16)( rOptions.GetStdPrecision() ); + break; + case PROP_UNO_REGEXENABLED: + ScUnoHelpFunctions::SetBoolInAny( aRet, rOptions.IsFormulaRegexEnabled() ); + break; + default:; + } + return aRet; +} + +//------------------------------------------------------------------------ + +ScDocOptionsObj::ScDocOptionsObj( const ScDocOptions& rOpt ) : + ScModelObj( NULL ), + aOptions( rOpt ) +{ +} + +ScDocOptionsObj::~ScDocOptionsObj() +{ +} + +void SAL_CALL ScDocOptionsObj::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + + BOOL bDone = ScDocOptionsHelper::setPropertyValue( aOptions, *GetPropertySet().getPropertyMap(), aPropertyName, aValue ); + + if (!bDone) + ScModelObj::setPropertyValue( aPropertyName, aValue ); +} + +uno::Any SAL_CALL ScDocOptionsObj::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + + uno::Any aRet(ScDocOptionsHelper::getPropertyValue( aOptions, *GetPropertySet().getPropertyMap(), aPropertyName )); + if ( !aRet.hasValue() ) + aRet = ScModelObj::getPropertyValue( aPropertyName ); + + return aRet; +} + diff --git a/sc/source/ui/unoobj/pageuno.cxx b/sc/source/ui/unoobj/pageuno.cxx new file mode 100644 index 000000000000..4687683a8ef4 --- /dev/null +++ b/sc/source/ui/unoobj/pageuno.cxx @@ -0,0 +1,78 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include "pageuno.hxx" +#include "shapeuno.hxx" + +using namespace ::com::sun::star; + +//------------------------------------------------------------------------ + +ScPageObj::ScPageObj( SdrPage* pPage ) : + SvxFmDrawPage( pPage ) +{ +} + +ScPageObj::~ScPageObj() throw() +{ +} + +uno::Reference<drawing::XShape > ScPageObj::_CreateShape( SdrObject *pObj ) const throw() +{ + uno::Reference<drawing::XShape> xShape(SvxFmDrawPage::_CreateShape( pObj )); + + new ScShapeObj( xShape ); // aggregates object and modifies xShape + + return xShape; +} + +::rtl::OUString SAL_CALL ScPageObj::getImplementationName() + throw(uno::RuntimeException) +{ + return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("ScPageObj")); +} + +sal_Bool SAL_CALL ScPageObj::supportsService( const rtl::OUString& rServiceName ) + throw(uno::RuntimeException) +{ + String aServiceStr(rServiceName); + return aServiceStr.EqualsAscii( "com.sun.star.sheet.SpreadsheetDrawPage" ); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScPageObj::getSupportedServiceNames() + throw(uno::RuntimeException) +{ + uno::Sequence<rtl::OUString> aRet(1); + rtl::OUString* pArray = aRet.getArray(); + pArray[0] = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.SpreadsheetDrawPage")); + return aRet; +} diff --git a/sc/source/ui/unoobj/scdetect.cxx b/sc/source/ui/unoobj/scdetect.cxx new file mode 100755 index 000000000000..03d6d14a3ac7 --- /dev/null +++ b/sc/source/ui/unoobj/scdetect.cxx @@ -0,0 +1,918 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +#include "scdetect.hxx" + +#include <framework/interaction.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/frame/XFrame.hpp> +#include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/awt/XWindow.hpp> +#include <com/sun/star/lang/XUnoTunnel.hpp> +#ifndef _UNOTOOLS_PROCESSFACTORY_HXX +#include <comphelper/processfactory.hxx> +#endif +#include <com/sun/star/beans/PropertyValue.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <com/sun/star/io/XInputStream.hpp> +#include <com/sun/star/task/XInteractionHandler.hpp> +#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> +#include <com/sun/star/ucb/CommandAbortedException.hpp> +#include <com/sun/star/ucb/InteractiveAppException.hpp> +#include <com/sun/star/ucb/XContent.hpp> +#include <com/sun/star/packages/zip/ZipIOException.hpp> + + +#include <framework/interaction.hxx> + +#ifndef _TOOLKIT_UNOHLP_HXX +#include <toolkit/helper/vclunohelper.hxx> +#endif +#include <ucbhelper/simpleinteractionrequest.hxx> + +#include <svtools/parhtml.hxx> +#include <rtl/ustring.h> +#include <rtl/logfile.hxx> +#include <svl/itemset.hxx> +#include <vcl/window.hxx> +#include <svl/eitem.hxx> +#include <svl/stritem.hxx> +#include <tools/urlobj.hxx> +#include <vos/mutex.hxx> +#include <svtools/sfxecode.hxx> +#include <svtools/ehdl.hxx> +#include <sot/storinfo.hxx> +#include <vcl/svapp.hxx> +#include <sfx2/sfxsids.hrc> +#include <sfx2/request.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/docfilt.hxx> +#include <sfx2/fcontnr.hxx> +#include <sfx2/app.hxx> +#include <sfx2/brokenpackageint.hxx> +#include <sot/storage.hxx> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::io; +using namespace ::com::sun::star::frame; +using namespace ::com::sun::star::task; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::ucb; +using ::rtl::OUString; + +ScFilterDetect::ScFilterDetect( const REFERENCE < ::com::sun::star::lang::XMultiServiceFactory >& /* xFactory */ ) +{ +} + +ScFilterDetect::~ScFilterDetect() +{ +} + +static const sal_Char __FAR_DATA pFilterSc50[] = "StarCalc 5.0"; +static const sal_Char __FAR_DATA pFilterSc50Temp[] = "StarCalc 5.0 Vorlage/Template"; +static const sal_Char __FAR_DATA pFilterSc40[] = "StarCalc 4.0"; +static const sal_Char __FAR_DATA pFilterSc40Temp[] = "StarCalc 4.0 Vorlage/Template"; +static const sal_Char __FAR_DATA pFilterSc30[] = "StarCalc 3.0"; +static const sal_Char __FAR_DATA pFilterSc30Temp[] = "StarCalc 3.0 Vorlage/Template"; +static const sal_Char __FAR_DATA pFilterSc10[] = "StarCalc 1.0"; +static const sal_Char __FAR_DATA pFilterXML[] = "StarOffice XML (Calc)"; +static const sal_Char __FAR_DATA pFilterAscii[] = "Text - txt - csv (StarCalc)"; +static const sal_Char __FAR_DATA pFilterLotus[] = "Lotus"; +static const sal_Char __FAR_DATA pFilterQPro6[] = "Quattro Pro 6.0"; +static const sal_Char __FAR_DATA pFilterExcel4[] = "MS Excel 4.0"; +static const sal_Char __FAR_DATA pFilterEx4Temp[] = "MS Excel 4.0 Vorlage/Template"; +static const sal_Char __FAR_DATA pFilterExcel5[] = "MS Excel 5.0/95"; +static const sal_Char __FAR_DATA pFilterEx5Temp[] = "MS Excel 5.0/95 Vorlage/Template"; +static const sal_Char __FAR_DATA pFilterExcel95[] = "MS Excel 95"; +static const sal_Char __FAR_DATA pFilterEx95Temp[] = "MS Excel 95 Vorlage/Template"; +static const sal_Char __FAR_DATA pFilterExcel97[] = "MS Excel 97"; +static const sal_Char __FAR_DATA pFilterEx97Temp[] = "MS Excel 97 Vorlage/Template"; +static const sal_Char __FAR_DATA pFilterDBase[] = "dBase"; +static const sal_Char __FAR_DATA pFilterDif[] = "DIF"; +static const sal_Char __FAR_DATA pFilterSylk[] = "SYLK"; +static const sal_Char __FAR_DATA pFilterHtml[] = "HTML (StarCalc)"; +static const sal_Char __FAR_DATA pFilterHtmlWeb[] = "calc_HTML_WebQuery"; +static const sal_Char __FAR_DATA pFilterRtf[] = "Rich Text Format (StarCalc)"; + + +static BOOL lcl_MayBeAscii( SvStream& rStream ) +{ + // ASCII/CSV is considered possible if there are no null bytes, or a Byte + // Order Mark is present, or if, for Unicode UCS2/UTF-16, all null bytes + // are on either even or uneven byte positions. + + rStream.Seek(STREAM_SEEK_TO_BEGIN); + + const size_t nBufSize = 2048; + sal_uInt16 aBuffer[ nBufSize ]; + sal_uInt8* pByte = reinterpret_cast<sal_uInt8*>(aBuffer); + ULONG nBytesRead = rStream.Read( pByte, nBufSize*2); + + if ( nBytesRead >= 2 && (aBuffer[0] == 0xfffe || aBuffer[0] == 0xfeff) ) + { + // Unicode BOM file may contain null bytes. + return TRUE; + } + + const sal_uInt16* p = aBuffer; + sal_uInt16 nMask = 0xffff; + nBytesRead /= 2; + while( nBytesRead-- && nMask ) + { + sal_uInt16 nVal = *p++ & nMask; + if (!(nVal & 0x00ff)) + nMask &= 0xff00; + if (!(nVal & 0xff00)) + nMask &= 0x00ff; + } + + return nMask != 0; +} + +static BOOL lcl_MayBeDBase( SvStream& rStream ) +{ + // Look for dbf marker, see connectivity/source/inc/dbase/DTable.hxx + // DBFType for values. + const BYTE nValidMarks[] = { + 0x03, 0x04, 0x05, 0x30, 0x43, 0xB3, 0x83, 0x8b, 0x8e, 0xf5 }; + BYTE nMark; + rStream.Seek(STREAM_SEEK_TO_BEGIN); + rStream >> nMark; + bool bValidMark = false; + for (size_t i=0; i < sizeof(nValidMarks)/sizeof(nValidMarks[0]) && !bValidMark; ++i) + { + if (nValidMarks[i] == nMark) + bValidMark = true; + } + if ( !bValidMark ) + return FALSE; + + const size_t nHeaderBlockSize = 32; + // Empty dbf is >= 32*2+1 bytes in size. + const size_t nEmptyDbf = nHeaderBlockSize * 2 + 1; + + rStream.Seek(STREAM_SEEK_TO_END); + ULONG nSize = rStream.Tell(); + if ( nSize < nEmptyDbf ) + return FALSE; + + // length of header starts at 8 + rStream.Seek(8); + USHORT nHeaderLen; + rStream >> nHeaderLen; + + if ( nHeaderLen < nEmptyDbf || nSize < nHeaderLen ) + return FALSE; + + // Last byte of header must be 0x0d, this is how it's specified. + // #i9581#,#i26407# but some applications don't follow the specification + // and pad the header with one byte 0x00 to reach an + // even boundary. Some (#i88577# ) even pad more or pad using a 0x1a ^Z + // control character (#i8857#). This results in: + // Last byte of header must be 0x0d on 32 bytes boundary. + USHORT nBlocks = (nHeaderLen - 1) / nHeaderBlockSize; + BYTE nEndFlag = 0; + while ( nBlocks > 1 && nEndFlag != 0x0d ) { + rStream.Seek( nBlocks-- * nHeaderBlockSize ); + rStream >> nEndFlag; + } + + return ( 0x0d == nEndFlag ); +} + +#if 0 +static BOOL lcl_IsAnyXMLFilter( const SfxFilter* pFilter ) +{ + if ( !pFilter ) + return FALSE; + + // TRUE for XML file or template + // (template filter has no internal name -> allow configuration key names) + + String aName(pFilter->GetFilterName()); + return aName.EqualsAscii(pFilterXML) || + aName.EqualsAscii("calc_StarOffice_XML_Calc") || + aName.EqualsAscii("calc_StarOffice_XML_Calc_Template"); +} +#endif + +::rtl::OUString SAL_CALL ScFilterDetect::detect( ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& lDescriptor ) throw( ::com::sun::star::uno::RuntimeException ) +{ + REFERENCE< XInputStream > xStream; + REFERENCE< XContent > xContent; + REFERENCE< XInteractionHandler > xInteraction; + String aURL; + ::rtl::OUString sTemp; + String aTypeName; // a name describing the type (from MediaDescriptor, usually from flat detection) + String aPreselectedFilterName; // a name describing the filter to use (from MediaDescriptor, usually from UI action) + + ::rtl::OUString aDocumentTitle; // interesting only if set in this method + + // opening as template is done when a parameter tells to do so and a template filter can be detected + // (otherwise no valid filter would be found) or if the detected filter is a template filter and + // there is no parameter that forbids to open as template + sal_Bool bOpenAsTemplate = sal_False; + sal_Bool bWasReadOnly = sal_False, bReadOnly = sal_False; + + sal_Bool bRepairPackage = sal_False; + sal_Bool bRepairAllowed = sal_False; + + // now some parameters that can already be in the array, but may be overwritten or new inserted here + // remember their indices in the case new values must be added to the array + sal_Int32 nPropertyCount = lDescriptor.getLength(); + sal_Int32 nIndexOfFilterName = -1; + sal_Int32 nIndexOfInputStream = -1; + sal_Int32 nIndexOfContent = -1; + sal_Int32 nIndexOfReadOnlyFlag = -1; + sal_Int32 nIndexOfTemplateFlag = -1; + sal_Int32 nIndexOfDocumentTitle = -1; + bool bFakeXLS = false; + + for( sal_Int32 nProperty=0; nProperty<nPropertyCount; ++nProperty ) + { + // extract properties + if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("URL")) ) + { + lDescriptor[nProperty].Value >>= sTemp; + aURL = sTemp; + } + else if( !aURL.Len() && lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("FileName")) ) + { + lDescriptor[nProperty].Value >>= sTemp; + aURL = sTemp; + } + else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("TypeName")) ) + { + lDescriptor[nProperty].Value >>= sTemp; + aTypeName = sTemp; + } + else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("FilterName")) ) + { + lDescriptor[nProperty].Value >>= sTemp; + aPreselectedFilterName = sTemp; + + // if the preselected filter name is not correct, it must be erased after detection + // remember index of property to get access to it later + nIndexOfFilterName = nProperty; + } + else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("InputStream")) ) + nIndexOfInputStream = nProperty; + else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("ReadOnly")) ) + nIndexOfReadOnlyFlag = nProperty; + else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("UCBContent")) ) + nIndexOfContent = nProperty; + else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("AsTemplate")) ) + { + lDescriptor[nProperty].Value >>= bOpenAsTemplate; + nIndexOfTemplateFlag = nProperty; + } + else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("InteractionHandler")) ) + lDescriptor[nProperty].Value >>= xInteraction; + else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("RepairPackage")) ) + lDescriptor[nProperty].Value >>= bRepairPackage; + else if( lDescriptor[nProperty].Name == OUString(RTL_CONSTASCII_USTRINGPARAM("DocumentTitle")) ) + nIndexOfDocumentTitle = nProperty; + } + + // can't check the type for external filters, so set the "dont" flag accordingly + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + //SfxFilterFlags nMust = SFX_FILTER_IMPORT, nDont = SFX_FILTER_NOTINSTALLED; + + SfxAllItemSet *pSet = new SfxAllItemSet( SFX_APP()->GetPool() ); + TransformParameters( SID_OPENDOC, lDescriptor, *pSet ); + SFX_ITEMSET_ARG( pSet, pItem, SfxBoolItem, SID_DOC_READONLY, FALSE ); + + bWasReadOnly = pItem && pItem->GetValue(); + + const SfxFilter* pFilter = 0; + String aPrefix = String::CreateFromAscii( "private:factory/" ); + if( aURL.Match( aPrefix ) == aPrefix.Len() ) + { + String aPattern( aPrefix ); + aPattern += String::CreateFromAscii("scalc"); + if ( aURL.Match( aPattern ) >= aPattern.Len() ) + pFilter = SfxFilter::GetDefaultFilterFromFactory( aURL ); + } + else + { + // container for Calc filters + SfxFilterMatcher aMatcher( String::CreateFromAscii("scalc") ); + if ( aPreselectedFilterName.Len() ) + pFilter = SfxFilter::GetFilterByName( aPreselectedFilterName ); + else if( aTypeName.Len() ) + pFilter = aMatcher.GetFilter4EA( aTypeName ); + + // ctor of SfxMedium uses owner transition of ItemSet + SfxMedium aMedium( aURL, bWasReadOnly ? STREAM_STD_READ : STREAM_STD_READWRITE, FALSE, NULL, pSet ); + aMedium.UseInteractionHandler( TRUE ); + + BOOL bIsStorage = aMedium.IsStorage(); + if ( aMedium.GetErrorCode() == ERRCODE_NONE ) + { + // remember input stream and content and put them into the descriptor later + // should be done here since later the medium can switch to a version + xStream.set(aMedium.GetInputStream()); + xContent.set(aMedium.GetContent()); + bReadOnly = aMedium.IsReadOnly(); + + // maybe that IsStorage() already created an error! + if ( bIsStorage ) + { + uno::Reference < embed::XStorage > xStorage(aMedium.GetStorage( sal_False )); + if ( aMedium.GetLastStorageCreationState() != ERRCODE_NONE ) + { + // error during storage creation means _here_ that the medium + // is broken, but we can not handle it in medium since unpossibility + // to create a storage does not _always_ means that the medium is broken + aMedium.SetError( aMedium.GetLastStorageCreationState(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); + if ( xInteraction.is() ) + { + OUString empty; + try + { + InteractiveAppException xException( empty, + REFERENCE< XInterface >(), + InteractionClassification_ERROR, + aMedium.GetError() ); + + REFERENCE< XInteractionRequest > xRequest( + new ucbhelper::SimpleInteractionRequest( makeAny( xException ), + ucbhelper::CONTINUATION_APPROVE ) ); + xInteraction->handle( xRequest ); + } + catch ( Exception & ) {}; + } + } + else if ( xStorage.is() ) + { + try + { + String aFilterName; + if ( pFilter ) + aFilterName = pFilter->GetName(); + aTypeName = SfxFilter::GetTypeFromStorage( xStorage, pFilter ? pFilter->IsOwnTemplateFormat() : FALSE, &aFilterName ); + } + catch( lang::WrappedTargetException& aWrap ) + { + packages::zip::ZipIOException aZipException; + + // repairing is done only if this type is requested from outside + if ( ( aWrap.TargetException >>= aZipException ) && aTypeName.Len() ) + { + if ( xInteraction.is() ) + { + // the package is broken one + aDocumentTitle = aMedium.GetURLObject().getName( + INetURLObject::LAST_SEGMENT, + true, + INetURLObject::DECODE_WITH_CHARSET ); + + if ( !bRepairPackage ) + { + // ask the user whether he wants to try to repair + RequestPackageReparation* pRequest = new RequestPackageReparation( aDocumentTitle ); + uno::Reference< task::XInteractionRequest > xRequest ( pRequest ); + + xInteraction->handle( xRequest ); + + bRepairAllowed = pRequest->isApproved(); + } + + if ( !bRepairAllowed ) + { + // repair either not allowed or not successful + NotifyBrokenPackage* pNotifyRequest = new NotifyBrokenPackage( aDocumentTitle ); + uno::Reference< task::XInteractionRequest > xRequest ( pNotifyRequest ); + xInteraction->handle( xRequest ); + } + } + + if ( !bRepairAllowed ) + aTypeName.Erase(); + } + } + catch( uno::RuntimeException& ) + { + throw; + } + catch( uno::Exception& ) + { + aTypeName.Erase(); + } + + if ( aTypeName.Len() ) + pFilter = SfxFilterMatcher( String::CreateFromAscii("scalc") ).GetFilter4EA( aTypeName ); + + } + } + else + { + bool bIsXLS = false; + SvStream* pStream = aMedium.GetInStream(); + const SfxFilter* pPreselectedFilter = pFilter; + if ( pPreselectedFilter && pPreselectedFilter->GetName().SearchAscii("Excel") != STRING_NOTFOUND ) + bIsXLS = true; + pFilter = 0; + if ( pStream ) + { + SotStorageRef aStorage = new SotStorage ( pStream, FALSE ); + if ( !aStorage->GetError() ) + { + // Excel-5: detect through contained streams + // there are some "excel" formats from 3rd party vendors that need to be distinguished + String aStreamName(RTL_CONSTASCII_STRINGPARAM("Workbook")); + BOOL bExcel97Stream = ( aStorage->IsStream( aStreamName ) ); + + aStreamName = String(RTL_CONSTASCII_STRINGPARAM("Book")); + BOOL bExcel5Stream = ( aStorage->IsStream( aStreamName ) ); + if ( bExcel97Stream || bExcel5Stream ) + { + if ( bExcel97Stream ) + { + String aOldName; + BOOL bIsCalcFilter = TRUE; + if ( pPreselectedFilter ) + { + // cross filter; now this should be a type detection only, not a filter detection + // we can simulate it by preserving the preselected filter if the type matches + // example: Excel filters for Writer + aOldName = pPreselectedFilter->GetFilterName(); + bIsCalcFilter = pPreselectedFilter->GetServiceName().EqualsAscii("com.sun.star.sheet.SpreadsheetDocument"); + } + + if ( aOldName.EqualsAscii(pFilterEx97Temp) || !bIsCalcFilter ) + { + // Excel 97 template selected -> keep selection + } + else if ( bExcel5Stream && + ( aOldName.EqualsAscii(pFilterExcel5) || aOldName.EqualsAscii(pFilterEx5Temp) || + aOldName.EqualsAscii(pFilterExcel95) || aOldName.EqualsAscii(pFilterEx95Temp) ) ) + { + // dual format file and Excel 5 selected -> keep selection + } + else + { + // else use Excel 97 filter + pFilter = aMatcher.GetFilter4FilterName( String::CreateFromAscii(pFilterExcel97) ); + } + } + else if ( bExcel5Stream ) + { + String aOldName; + BOOL bIsCalcFilter = TRUE; + if ( pPreselectedFilter ) + { + // cross filter; now this should be a type detection only, not a filter detection + // we can simulate it by preserving the preselected filter if the type matches + // example: Excel filters for Writer + aOldName = pPreselectedFilter->GetFilterName(); + bIsCalcFilter = pPreselectedFilter->GetServiceName().EqualsAscii("com.sun.star.sheet.SpreadsheetDocument"); + } + + if ( aOldName.EqualsAscii(pFilterExcel95) || aOldName.EqualsAscii(pFilterEx95Temp) || + aOldName.EqualsAscii(pFilterEx5Temp) || !bIsCalcFilter ) + { + // Excel 95 oder Vorlage (5 oder 95) eingestellt -> auch gut + } + else if ( aOldName.EqualsAscii(pFilterEx97Temp) ) + { + // #101923# auto detection has found template -> return Excel5 template + pFilter = aMatcher.GetFilter4FilterName( String::CreateFromAscii(pFilterEx5Temp) ); + } + else + { + // sonst wird als Excel 5-Datei erkannt + pFilter = aMatcher.GetFilter4FilterName( String::CreateFromAscii(pFilterExcel5) ); + } + } + } + } + else + { + SvStream &rStr = *pStream; + + // Tabelle mit Suchmustern + // Bedeutung der Sequenzen + // 0x00??: genau Byte 0x?? muss an dieser Stelle stehen + // 0x0100: ein Byte ueberlesen (don't care) + // 0x02nn: ein Byte aus 0xnn Alternativen folgt + // 0x8000: Erkennung abgeschlossen + // + + #define M_DC 0x0100 + #define M_ALT(ANZ) (0x0200+(ANZ)) + #define M_ENDE 0x8000 + + static const UINT16 pLotus[] = // Lotus 1/1A/2 + { 0x0000, 0x0000, 0x0002, 0x0000, + M_ALT(2), 0x0004, 0x0006, + 0x0004, M_ENDE }; + + static const UINT16 pLotusNew[] = // Lotus >= 9.7 + { 0x0000, 0x0000, M_DC, 0x0000, // Rec# + Len (0x1a) + M_ALT(3), 0x0003, 0x0004, 0x0005, // File Revision Code 97->ME + 0x0010, 0x0004, 0x0000, 0x0000, + M_ENDE }; + + static const UINT16 pExcel1[] = // Excel BIFF2, BIFF3, BIFF4 + { 0x09, // lobyte of BOF rec ID (0x0009, 0x0209, 0x0409) + M_ALT(3), 0x00, 0x02, 0x04, // hibyte of BOF rec ID (0x0009, 0x0209, 0x0409) + M_ALT(3), 4, 6, 8, // lobyte of BOF rec size (4, 6, 8, 16) + 0x00, // hibyte of BOF rec size (4, 6, 8, 16) + M_DC, M_DC, // any version + M_ALT(3), 0x10, 0x20, 0x40, // lobyte of data type (0x0010, 0x0020, 0x0040) + 0x00, // hibyte of data type (0x0010, 0x0020, 0x0040) + M_ENDE }; + + static const UINT16 pExcel2[] = // Excel BIFF4 Workspace + { 0x09, // lobyte of BOF rec ID (0x0409) + 0x04, // hibyte of BOF rec ID (0x0409) + M_ALT(3), 4, 6, 8, // lobyte of BOF rec size (4, 6, 8, 16) + 0x00, // hibyte of BOF rec size (4, 6, 8, 16) + M_DC, M_DC, // any version + 0x00, // lobyte of data type (0x0100) + 0x01, // hibyte of data type (0x0100) + M_ENDE }; + + static const UINT16 pExcel3[] = // #i23425# Excel BIFF5, BIFF7, BIFF8 (simple book stream) + { 0x09, // lobyte of BOF rec ID (0x0809) + 0x08, // hibyte of BOF rec ID (0x0809) + M_ALT(4), 4, 6, 8, 16, // lobyte of BOF rec size + 0x00, // hibyte of BOF rec size + M_DC, M_DC, // any version + M_ALT(5), 0x05, 0x06, 0x10, 0x20, 0x40, // lobyte of data type + 0x00, // hibyte of data type + M_ENDE }; + + static const UINT16 pSc10[] = // StarCalc 1.0 Dokumente + { 'B', 'l', 'a', 'i', 's', 'e', '-', 'T', 'a', 'b', 'e', 'l', 'l', + 'e', 0x000A, 0x000D, 0x0000, // Sc10CopyRight[16] + M_DC, M_DC, M_DC, M_DC, M_DC, M_DC, M_DC, M_DC, M_DC, M_DC, M_DC, + M_DC, M_DC, // Sc10CopyRight[29] + M_ALT(2), 0x0065, 0x0066, // Versionsnummer 101 oder 102 + 0x0000, + M_ENDE }; + + static const UINT16 pLotus2[] = // Lotus >3 + { 0x0000, 0x0000, 0x001A, 0x0000, // Rec# + Len (26) + M_ALT(2), 0x0000, 0x0002, // File Revision Code + 0x0010, + 0x0004, 0x0000, // File Revision Subcode + M_ENDE }; + + static const UINT16 pQPro[] = + { 0x0000, 0x0000, 0x0002, 0x0000, + M_ALT(4), 0x0001, 0x0002, // WB1, WB2 + 0x0006, 0x0007, // QPro 6/7 (?) + 0x0010, + M_ENDE }; + + static const UINT16 pDIF1[] = // DIF mit CR-LF + { + 'T', 'A', 'B', 'L', 'E', + M_DC, M_DC, + '0', ',', '1', + M_DC, M_DC, + '\"', + M_ENDE }; + + static const UINT16 pDIF2[] = // DIF mit CR oder LF + { + 'T', 'A', 'B', 'L', 'E', + M_DC, + '0', ',', '1', + M_DC, + '\"', + M_ENDE }; + + static const UINT16 pSylk[] = // Sylk + { + 'I', 'D', ';', + M_ALT(3), 'P', 'N', 'E', // 'P' plus undocumented Excel extensions 'N' and 'E' + M_ENDE }; + + static const UINT16 *ppFilterPatterns[] = // Arrays mit Suchmustern + { + pLotus, + pExcel1, + pExcel2, + pExcel3, + pSc10, + pDIF1, + pDIF2, + pSylk, + pLotusNew, + pLotus2, + pQPro + }; + const UINT16 nFilterCount = sizeof(ppFilterPatterns) / sizeof(ppFilterPatterns[0]); + + static const sal_Char* const pFilterName[] = // zugehoerige Filter + { + pFilterLotus, + pFilterExcel4, + pFilterExcel4, + pFilterExcel4, + pFilterSc10, + pFilterDif, + pFilterDif, + pFilterSylk, + pFilterLotus, + pFilterLotus, + pFilterQPro6 + }; + + // const UINT16 nByteMask = 0xFF; + + // suchen Sie jetzt! + // ... realisiert ueber 'Mustererkennung' + + BYTE nAkt; + BOOL bSync; // Datei und Muster stimmen ueberein + USHORT nFilter; // Zaehler ueber alle Filter + const UINT16 *pSearch; // aktuelles Musterwort + + for ( nFilter = 0 ; nFilter < nFilterCount ; nFilter++ ) + { + rStr.Seek( 0 ); // am Anfang war alles Uebel... + rStr >> nAkt; + pSearch = ppFilterPatterns[ nFilter ]; + bSync = TRUE; + while( !rStr.IsEof() && bSync ) + { + register UINT16 nMuster = *pSearch; + + if( nMuster < 0x0100 ) + { // direkter Byte-Vergleich + if( ( BYTE ) nMuster != nAkt ) + bSync = FALSE; + } + else if( nMuster & M_DC ) + { // don't care + } + else if( nMuster & M_ALT(0) ) + { // alternative Bytes + BYTE nAnzAlt = ( BYTE ) nMuster; + bSync = FALSE; // zunaechst unsynchron + while( nAnzAlt > 0 ) + { + pSearch++; + if( ( BYTE ) *pSearch == nAkt ) + bSync = TRUE; // jetzt erst Synchronisierung + nAnzAlt--; + } + } + else if( nMuster & M_ENDE ) + { // Format detected + if ( pFilterName[nFilter] == pFilterExcel4 && pPreselectedFilter && + ( (pPreselectedFilter)->GetFilterName().EqualsAscii(pFilterEx4Temp) || pPreselectedFilter->GetTypeName().EqualsAscii("calc_MS_Excel_40") ) ) + { + // Excel 4 erkannt, Excel 4 Vorlage eingestellt -> auch gut + // oder Excel 4 Filter anderer Applikation (simulated type detection!) + } + else + { // gefundenen Filter einstellen + pFilter = aMatcher.GetFilter4FilterName( String::CreateFromAscii(pFilterName[ nFilter ]) ); + } + bSync = FALSE; // leave inner loop + nFilter = nFilterCount; // leave outer loop + } + else + { // Tabellenfehler + DBG_ERROR( "-ScApplication::DetectFilter(): Fehler in Mustertabelle"); + } + + pSearch++; + rStr >> nAkt; + } + } + + if ( pPreselectedFilter && !pFilter ) + { + // further checks for filters only if they are preselected: ASCII, HTML, RTF, DBase + // without the preselection other filters (Writer) take precedence + // DBase can't be detected reliably, so it also needs preselection + bool bMaybeText = lcl_MayBeAscii( rStr ); + if ( pPreselectedFilter->GetFilterName().EqualsAscii(pFilterAscii) && bMaybeText ) + { + // Text filter is accepted if preselected + pFilter = pPreselectedFilter; + } + else + { + // get file header + rStr.Seek( 0 ); + const int nTrySize = 80; + ByteString aHeader; + for ( int j = 0; j < nTrySize && !rStr.IsEof(); j++ ) + { + sal_Char c; + rStr >> c; + aHeader += c; + } + aHeader += '\0'; + + if ( HTMLParser::IsHTMLFormat( aHeader.GetBuffer() ) ) + { + // test for HTML + if ( pPreselectedFilter->GetName().EqualsAscii(pFilterHtml) ) + { + pFilter = pPreselectedFilter; + } + else + { + pFilter = aMatcher.GetFilter4FilterName( String::CreateFromAscii(pFilterHtmlWeb) ); + if ( bIsXLS ) + bFakeXLS = true; + } + } + else if ( bIsXLS && bMaybeText ) + { + pFilter = aMatcher.GetFilter4FilterName( String::CreateFromAscii(pFilterAscii) ); + bFakeXLS = true; + } + else if ( aHeader.CompareTo( "{\\rtf", 5 ) == COMPARE_EQUAL ) + { + // test for RTF + pFilter = aMatcher.GetFilter4FilterName( String::CreateFromAscii(pFilterRtf) ); + } + else if ( pPreselectedFilter->GetName().EqualsAscii(pFilterDBase) && lcl_MayBeDBase( rStr ) ) + pFilter = pPreselectedFilter; + } + } + } + } + } + } + } + + if ( nIndexOfInputStream == -1 && xStream.is() ) + { + // if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opend twice + lDescriptor.realloc( nPropertyCount + 1 ); + lDescriptor[nPropertyCount].Name = ::rtl::OUString::createFromAscii("InputStream"); + lDescriptor[nPropertyCount].Value <<= xStream; + nPropertyCount++; + } + + if ( nIndexOfContent == -1 && xContent.is() ) + { + // if input stream wasn't part of the descriptor, now it should be, otherwise the content would be opend twice + lDescriptor.realloc( nPropertyCount + 1 ); + lDescriptor[nPropertyCount].Name = ::rtl::OUString::createFromAscii("UCBContent"); + lDescriptor[nPropertyCount].Value <<= xContent; + nPropertyCount++; + } + + if ( bReadOnly != bWasReadOnly ) + { + if ( nIndexOfReadOnlyFlag == -1 ) + { + lDescriptor.realloc( nPropertyCount + 1 ); + lDescriptor[nPropertyCount].Name = ::rtl::OUString::createFromAscii("ReadOnly"); + lDescriptor[nPropertyCount].Value <<= bReadOnly; + nPropertyCount++; + } + else + lDescriptor[nIndexOfReadOnlyFlag].Value <<= bReadOnly; + } + + if ( !bRepairPackage && bRepairAllowed ) + { + lDescriptor.realloc( nPropertyCount + 1 ); + lDescriptor[nPropertyCount].Name = ::rtl::OUString::createFromAscii("RepairPackage"); + lDescriptor[nPropertyCount].Value <<= bRepairAllowed; + nPropertyCount++; + + bOpenAsTemplate = sal_True; + + // TODO/LATER: set progress bar that should be used + } + + if ( bOpenAsTemplate ) + { + if ( nIndexOfTemplateFlag == -1 ) + { + lDescriptor.realloc( nPropertyCount + 1 ); + lDescriptor[nPropertyCount].Name = ::rtl::OUString::createFromAscii("AsTemplate"); + lDescriptor[nPropertyCount].Value <<= bOpenAsTemplate; + nPropertyCount++; + } + else + lDescriptor[nIndexOfTemplateFlag].Value <<= bOpenAsTemplate; + } + + if ( aDocumentTitle.getLength() ) + { + // the title was set here + if ( nIndexOfDocumentTitle == -1 ) + { + lDescriptor.realloc( nPropertyCount + 1 ); + lDescriptor[nPropertyCount].Name = ::rtl::OUString::createFromAscii("DocumentTitle"); + lDescriptor[nPropertyCount].Value <<= aDocumentTitle; + nPropertyCount++; + } + else + lDescriptor[nIndexOfDocumentTitle].Value <<= aDocumentTitle; + } + + if ( bFakeXLS ) + { + if ( nIndexOfFilterName == -1 ) + { + lDescriptor.realloc( nPropertyCount + 1 ); + lDescriptor[nPropertyCount].Name = ::rtl::OUString::createFromAscii("FilterName"); + lDescriptor[nPropertyCount].Value <<= rtl::OUString(pFilter->GetName()); + nPropertyCount++; + } + else + lDescriptor[nIndexOfFilterName].Value <<= rtl::OUString(pFilter->GetName()); + } + + if ( pFilter ) + aTypeName = pFilter->GetTypeName(); + else + aTypeName.Erase(); + return aTypeName; +} + +SFX_IMPL_SINGLEFACTORY( ScFilterDetect ) + +/* XServiceInfo */ +UNOOUSTRING SAL_CALL ScFilterDetect::getImplementationName() throw( UNORUNTIMEEXCEPTION ) +{ + return impl_getStaticImplementationName(); +} + \ +/* XServiceInfo */ +sal_Bool SAL_CALL ScFilterDetect::supportsService( const UNOOUSTRING& sServiceName ) throw( UNORUNTIMEEXCEPTION ) +{ + UNOSEQUENCE< UNOOUSTRING > seqServiceNames(getSupportedServiceNames()); + const UNOOUSTRING* pArray = seqServiceNames.getConstArray(); + for ( sal_Int32 nCounter=0; nCounter<seqServiceNames.getLength(); nCounter++ ) + { + if ( pArray[nCounter] == sServiceName ) + { + return sal_True ; + } + } + return sal_False ; +} + +/* XServiceInfo */ +UNOSEQUENCE< UNOOUSTRING > SAL_CALL ScFilterDetect::getSupportedServiceNames() throw( UNORUNTIMEEXCEPTION ) +{ + return impl_getStaticSupportedServiceNames(); +} + +/* Helper for XServiceInfo */ +UNOSEQUENCE< UNOOUSTRING > ScFilterDetect::impl_getStaticSupportedServiceNames() +{ + UNOMUTEXGUARD aGuard( UNOMUTEX::getGlobalMutex() ); + UNOSEQUENCE< UNOOUSTRING > seqServiceNames( 1 ); + seqServiceNames.getArray() [0] = UNOOUSTRING::createFromAscii( "com.sun.star.frame.ExtendedTypeDetection" ); + return seqServiceNames ; +} + +/* Helper for XServiceInfo */ +UNOOUSTRING ScFilterDetect::impl_getStaticImplementationName() +{ + return UNOOUSTRING::createFromAscii( "com.sun.star.comp.calc.FormatDetector" ); +} + +/* Helper for registry */ +UNOREFERENCE< UNOXINTERFACE > SAL_CALL ScFilterDetect::impl_createInstance( const UNOREFERENCE< UNOXMULTISERVICEFACTORY >& xServiceManager ) throw( UNOEXCEPTION ) +{ + return UNOREFERENCE< UNOXINTERFACE >( *new ScFilterDetect( xServiceManager ) ); +} + diff --git a/sc/source/ui/unoobj/scdetect.hxx b/sc/source/ui/unoobj/scdetect.hxx new file mode 100644 index 000000000000..a652d11df951 --- /dev/null +++ b/sc/source/ui/unoobj/scdetect.hxx @@ -0,0 +1,95 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +#ifndef _SC_TYPEDETECT_HXX +#define _SC_TYPEDETECT_HXX + +#include <rtl/ustring.hxx> +#include <tools/debug.hxx> +#include <com/sun/star/document/XExtendedFilterDetection.hpp> +#include <com/sun/star/uno/Exception.hpp> +#include <com/sun/star/uno/Reference.h> +#include <cppuhelper/implbase2.hxx> + +#include <com/sun/star/lang/XServiceInfo.hpp> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> +#include <cppuhelper/factory.hxx> +#include <tools/link.hxx> +#include <tools/string.hxx> + +class SfxObjectFactory; +class SfxFilterMatcher; +class LoadEnvironment_Impl; +class SfxMedium; + +namespace com +{ + namespace sun + { + namespace star + { + namespace uno + { + class Any; + } + namespace lang + { + class XMultiServiceFactory; + } + namespace frame + { + class XFrame; + } + namespace beans + { + struct PropertyValue; + } + } + } +} + +#include <sfx2/sfxuno.hxx> + +#define REFERENCE ::com::sun::star::uno::Reference +#define SEQUENCE ::com::sun::star::uno::Sequence +#define RUNTIME_EXCEPTION ::com::sun::star::uno::RuntimeException + +class ScFilterDetect : public ::cppu::WeakImplHelper2< ::com::sun::star::document::XExtendedFilterDetection, ::com::sun::star::lang::XServiceInfo > +{ +public: + ScFilterDetect( const REFERENCE < ::com::sun::star::lang::XMultiServiceFactory >& xFactory ); + virtual ~ScFilterDetect(); + + SFX_DECL_XSERVICEINFO + + //---------------------------------------------------------------------------------- + // XExtendedFilterDetect + //---------------------------------------------------------------------------------- + virtual ::rtl::OUString SAL_CALL detect( SEQUENCE< ::com::sun::star::beans::PropertyValue >& lDescriptor ) throw( RUNTIME_EXCEPTION ); +}; + +#endif diff --git a/sc/source/ui/unoobj/servuno.cxx b/sc/source/ui/unoobj/servuno.cxx new file mode 100644 index 000000000000..a173e6d1e051 --- /dev/null +++ b/sc/source/ui/unoobj/servuno.cxx @@ -0,0 +1,598 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include <tools/debug.hxx> +#include <svtools/unoimap.hxx> +#include <svx/unofill.hxx> +#include <editeng/unonrule.hxx> +#include <com/sun/star/sheet/XSpreadsheetDocument.hpp> + +#include "servuno.hxx" +#include "unoguard.hxx" +#include "unonames.hxx" +#include "cellsuno.hxx" +#include "fielduno.hxx" +#include "styleuno.hxx" +#include "afmtuno.hxx" +#include "defltuno.hxx" +#include "drdefuno.hxx" +#include "docsh.hxx" +#include "drwlayer.hxx" +#include "confuno.hxx" +#include "shapeuno.hxx" +#include "cellvaluebinding.hxx" +#include "celllistsource.hxx" +#include "addruno.hxx" +#include "chart2uno.hxx" +#include "tokenuno.hxx" + +// #100263# Support creation of GraphicObjectResolver and EmbeddedObjectResolver +#include <svx/xmleohlp.hxx> +#include <svx/xmlgrhlp.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/docfilt.hxx> +#include <com/sun/star/script/ScriptEventDescriptor.hpp> +#include <com/sun/star/document/XCodeNameQuery.hpp> +#include <com/sun/star/drawing/XDrawPagesSupplier.hpp> +#include <com/sun/star/form/XFormsSupplier.hpp> +#include <svx/unomod.hxx> +#include <vbahelper/vbaaccesshelper.hxx> + +#include <comphelper/processfactory.hxx> +#include <basic/basmgr.hxx> +#include <sfx2/app.hxx> + +using namespace ::com::sun::star; + +class ScVbaObjectForCodeNameProvider : public ::cppu::WeakImplHelper1< container::XNameAccess > +{ + uno::Any maWorkbook; + uno::Any maCachedObject; + ScDocShell* mpDocShell; +public: + ScVbaObjectForCodeNameProvider( ScDocShell* pDocShell ) : mpDocShell( pDocShell ) + { + ScDocument* pDoc = mpDocShell->GetDocument(); + if ( !pDoc ) + throw uno::RuntimeException( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("")), uno::Reference< uno::XInterface >() ); + + uno::Sequence< uno::Any > aArgs(2); + // access the application object ( parent for workbook ) + aArgs[0] = uno::Any( ooo::vba::createVBAUnoAPIServiceWithArgs( mpDocShell, "ooo.vba.Application", uno::Sequence< uno::Any >() ) ); + aArgs[1] = uno::Any( mpDocShell->GetModel() ); + maWorkbook <<= ooo::vba::createVBAUnoAPIServiceWithArgs( mpDocShell, "ooo.vba.excel.Workbook", aArgs ); + } + + virtual ::sal_Bool SAL_CALL hasByName( const ::rtl::OUString& aName ) throw (::com::sun::star::uno::RuntimeException ) + { + ScUnoGuard aGuard; + maCachedObject = uno::Any(); // clear cached object + String sName = aName; + + ScDocument* pDoc = mpDocShell->GetDocument(); + if ( !pDoc ) + throw uno::RuntimeException(); + if ( sName == pDoc->GetCodeName() ) + maCachedObject = maWorkbook; + else + { + String sCodeName; + SCTAB nCount = pDoc->GetTableCount(); + for( SCTAB i = 0; i < nCount; i++ ) + { + pDoc->GetCodeName( i, sCodeName ); + if( sCodeName == sName ) + { + String sSheetName; + if( pDoc->GetName( i, sSheetName ) ) + { + uno::Reference< frame::XModel > xModel( mpDocShell->GetModel() ); + uno::Reference <sheet::XSpreadsheetDocument> xSpreadDoc( xModel, uno::UNO_QUERY_THROW ); + uno::Reference<sheet::XSpreadsheets > xSheets( xSpreadDoc->getSheets(), uno::UNO_QUERY_THROW ); + uno::Reference< container::XIndexAccess > xIndexAccess( xSheets, uno::UNO_QUERY_THROW ); + uno::Reference< sheet::XSpreadsheet > xSheet( xIndexAccess->getByIndex( i ), uno::UNO_QUERY_THROW ); + uno::Sequence< uno::Any > aArgs(3); + aArgs[0] = maWorkbook; + aArgs[1] = uno::Any( xModel ); + aArgs[2] = uno::Any( rtl::OUString( sSheetName ) ); + // use the convience function + maCachedObject <<= ooo::vba::createVBAUnoAPIServiceWithArgs( mpDocShell, "ooo.vba.excel.Worksheet", aArgs ); + break; + } + } + } + } + return maCachedObject.hasValue(); + + } + ::com::sun::star::uno::Any SAL_CALL getByName( const ::rtl::OUString& aName ) throw (::com::sun::star::container::NoSuchElementException, ::com::sun::star::lang::WrappedTargetException, ::com::sun::star::uno::RuntimeException) + { + ScUnoGuard aGuard; + OSL_TRACE("ScVbaObjectForCodeNameProvider::getByName( %s )", + rtl::OUStringToOString( aName, RTL_TEXTENCODING_UTF8 ).getStr() ); + if ( !hasByName( aName ) ) + throw ::com::sun::star::container::NoSuchElementException(); + return maCachedObject; + } + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getElementNames( ) throw (::com::sun::star::uno::RuntimeException) + { + ScUnoGuard aGuard; + ScDocument* pDoc = mpDocShell->GetDocument(); + if ( !pDoc ) + throw uno::RuntimeException(); + SCTAB nCount = pDoc->GetTableCount(); + uno::Sequence< rtl::OUString > aNames( nCount + 1 ); + SCTAB index = 0; + String sCodeName; + for( ; index < nCount; ++index ) + { + pDoc->GetCodeName( index, sCodeName ); + aNames[ index ] = sCodeName; + } + aNames[ index ] = pDoc->GetCodeName(); + return aNames; + } + // XElemenAccess + virtual ::com::sun::star::uno::Type SAL_CALL getElementType( ) throw (::com::sun::star::uno::RuntimeException){ return uno::Type(); } + virtual ::sal_Bool SAL_CALL hasElements( ) throw (::com::sun::star::uno::RuntimeException ) { return sal_True; } + +}; + +class ScVbaCodeNameProvider : public ::cppu::WeakImplHelper1< document::XCodeNameQuery > +{ +ScDocShell* mpDocShell; +public: + ScVbaCodeNameProvider( ScDocShell* pDocShell ) : mpDocShell( pDocShell ) {} + // XCodeNameQuery + rtl::OUString SAL_CALL getCodeNameForObject( const uno::Reference< uno::XInterface >& xIf ) throw( uno::RuntimeException ) + { + ScUnoGuard aGuard; + rtl::OUString sCodeName; + if ( mpDocShell ) + { + OSL_TRACE( "*** In ScVbaCodeNameProvider::getCodeNameForObject"); + // need to find the page ( and index ) for this control + uno::Reference< drawing::XDrawPagesSupplier > xSupplier( mpDocShell->GetModel(), uno::UNO_QUERY_THROW ); + uno::Reference< container::XIndexAccess > xIndex( xSupplier->getDrawPages(), uno::UNO_QUERY_THROW ); + sal_Int32 nLen = xIndex->getCount(); + bool bMatched = false; + uno::Sequence< script::ScriptEventDescriptor > aFakeEvents; + for ( sal_Int32 index = 0; index < nLen; ++index ) + { + try + { + uno::Reference< form::XFormsSupplier > xFormSupplier( xIndex->getByIndex( index ), uno::UNO_QUERY_THROW ); + uno::Reference< container::XIndexAccess > xFormIndex( xFormSupplier->getForms(), uno::UNO_QUERY_THROW ); + // get the www-standard container + uno::Reference< container::XIndexAccess > xFormControls( xFormIndex->getByIndex(0), uno::UNO_QUERY_THROW ); + sal_Int32 nCntrls = xFormControls->getCount(); + for( sal_Int32 cIndex = 0; cIndex < nCntrls; ++cIndex ) + { + uno::Reference< uno::XInterface > xControl( xFormControls->getByIndex( cIndex ), uno::UNO_QUERY_THROW ); + bMatched = ( xControl == xIf ); + if ( bMatched ) + { + String sName; + mpDocShell->GetDocument()->GetCodeName( static_cast<SCTAB>( index ), sName ); + sCodeName = sName; + } + } + } + catch( uno::Exception& ) {} + if ( bMatched ) + break; + } + } + // Probably should throw here ( if !bMatched ) + return sCodeName; + } + +}; + +//------------------------------------------------------------------------ +// +struct ProvNamesId_Type +{ + const char * pName; + sal_uInt16 nType; +}; + +static const ProvNamesId_Type __FAR_DATA aProvNamesId[] = +{ + { "com.sun.star.sheet.Spreadsheet", SC_SERVICE_SHEET }, + { "com.sun.star.text.TextField.URL", SC_SERVICE_URLFIELD }, + { "com.sun.star.text.TextField.PageNumber", SC_SERVICE_PAGEFIELD }, + { "com.sun.star.text.TextField.PageCount", SC_SERVICE_PAGESFIELD }, + { "com.sun.star.text.TextField.Date", SC_SERVICE_DATEFIELD }, + { "com.sun.star.text.TextField.Time", SC_SERVICE_TIMEFIELD }, + { "com.sun.star.text.TextField.DocumentTitle", SC_SERVICE_TITLEFIELD }, + { "com.sun.star.text.TextField.FileName", SC_SERVICE_FILEFIELD }, + { "com.sun.star.text.TextField.SheetName", SC_SERVICE_SHEETFIELD }, + { "com.sun.star.style.CellStyle", SC_SERVICE_CELLSTYLE }, + { "com.sun.star.style.PageStyle", SC_SERVICE_PAGESTYLE }, + { "com.sun.star.sheet.TableAutoFormat", SC_SERVICE_AUTOFORMAT }, + { "com.sun.star.sheet.SheetCellRanges", SC_SERVICE_CELLRANGES }, + { "com.sun.star.drawing.GradientTable", SC_SERVICE_GRADTAB }, + { "com.sun.star.drawing.HatchTable", SC_SERVICE_HATCHTAB }, + { "com.sun.star.drawing.BitmapTable", SC_SERVICE_BITMAPTAB }, + { "com.sun.star.drawing.TransparencyGradientTable", SC_SERVICE_TRGRADTAB }, + { "com.sun.star.drawing.MarkerTable", SC_SERVICE_MARKERTAB }, + { "com.sun.star.drawing.DashTable", SC_SERVICE_DASHTAB }, + { "com.sun.star.text.NumberingRules", SC_SERVICE_NUMRULES }, + { "com.sun.star.sheet.Defaults", SC_SERVICE_DOCDEFLTS }, + { "com.sun.star.drawing.Defaults", SC_SERVICE_DRAWDEFLTS }, + { "com.sun.star.comp.SpreadsheetSettings", SC_SERVICE_DOCSPRSETT }, + { "com.sun.star.document.Settings", SC_SERVICE_DOCCONF }, + { "com.sun.star.image.ImageMapRectangleObject", SC_SERVICE_IMAP_RECT }, + { "com.sun.star.image.ImageMapCircleObject", SC_SERVICE_IMAP_CIRC }, + { "com.sun.star.image.ImageMapPolygonObject", SC_SERVICE_IMAP_POLY }, + + // #100263# Support creation of GraphicObjectResolver and EmbeddedObjectResolver + { "com.sun.star.document.ExportGraphicObjectResolver", SC_SERVICE_EXPORT_GOR }, + { "com.sun.star.document.ImportGraphicObjectResolver", SC_SERVICE_IMPORT_GOR }, + { "com.sun.star.document.ExportEmbeddedObjectResolver", SC_SERVICE_EXPORT_EOR }, + { "com.sun.star.document.ImportEmbeddedObjectResolver", SC_SERVICE_IMPORT_EOR }, + + { SC_SERVICENAME_VALBIND, SC_SERVICE_VALBIND }, + { SC_SERVICENAME_LISTCELLBIND, SC_SERVICE_LISTCELLBIND }, + { SC_SERVICENAME_LISTSOURCE, SC_SERVICE_LISTSOURCE }, + { SC_SERVICENAME_CELLADDRESS, SC_SERVICE_CELLADDRESS }, + { SC_SERVICENAME_RANGEADDRESS, SC_SERVICE_RANGEADDRESS }, + + { "com.sun.star.sheet.DocumentSettings",SC_SERVICE_SHEETDOCSET }, + + { SC_SERVICENAME_CHDATAPROV, SC_SERVICE_CHDATAPROV }, + { SC_SERVICENAME_FORMULAPARS, SC_SERVICE_FORMULAPARS }, + { SC_SERVICENAME_OPCODEMAPPER, SC_SERVICE_OPCODEMAPPER }, + { "ooo.vba.VBAObjectModuleObjectProvider", SC_SERVICE_VBAOBJECTPROVIDER }, + { "ooo.vba.VBACodeNameProvider", SC_SERVICE_VBACODENAMEPROVIDER }, + { "ooo.vba.VBAGlobals", SC_SERVICE_VBAGLOBALS }, + + // case-correct versions of the service names (#i102468#) + { "com.sun.star.text.textfield.URL", SC_SERVICE_URLFIELD }, + { "com.sun.star.text.textfield.PageNumber", SC_SERVICE_PAGEFIELD }, + { "com.sun.star.text.textfield.PageCount", SC_SERVICE_PAGESFIELD }, + { "com.sun.star.text.textfield.Date", SC_SERVICE_DATEFIELD }, + { "com.sun.star.text.textfield.Time", SC_SERVICE_TIMEFIELD }, + { "com.sun.star.text.textfield.DocumentTitle", SC_SERVICE_TITLEFIELD }, + { "com.sun.star.text.textfield.FileName", SC_SERVICE_FILEFIELD }, + { "com.sun.star.text.textfield.SheetName", SC_SERVICE_SHEETFIELD } +}; + +// +// old service names that were in 567 still work in createInstance, +// in case some macro is still using them +// + +static const sal_Char* __FAR_DATA aOldNames[SC_SERVICE_COUNT] = + { + "", // SC_SERVICE_SHEET + "stardiv.one.text.TextField.URL", // SC_SERVICE_URLFIELD + "stardiv.one.text.TextField.PageNumber", // SC_SERVICE_PAGEFIELD + "stardiv.one.text.TextField.PageCount", // SC_SERVICE_PAGESFIELD + "stardiv.one.text.TextField.Date", // SC_SERVICE_DATEFIELD + "stardiv.one.text.TextField.Time", // SC_SERVICE_TIMEFIELD + "stardiv.one.text.TextField.DocumentTitle", // SC_SERVICE_TITLEFIELD + "stardiv.one.text.TextField.FileName", // SC_SERVICE_FILEFIELD + "stardiv.one.text.TextField.SheetName", // SC_SERVICE_SHEETFIELD + "stardiv.one.style.CellStyle", // SC_SERVICE_CELLSTYLE + "stardiv.one.style.PageStyle", // SC_SERVICE_PAGESTYLE + "", // SC_SERVICE_AUTOFORMAT + "", // SC_SERVICE_CELLRANGES + "", // SC_SERVICE_GRADTAB + "", // SC_SERVICE_HATCHTAB + "", // SC_SERVICE_BITMAPTAB + "", // SC_SERVICE_TRGRADTAB + "", // SC_SERVICE_MARKERTAB + "", // SC_SERVICE_DASHTAB + "", // SC_SERVICE_NUMRULES + "", // SC_SERVICE_DOCDEFLTS + "", // SC_SERVICE_DRAWDEFLTS + "", // SC_SERVICE_DOCSPRSETT + "", // SC_SERVICE_DOCCONF + "", // SC_SERVICE_IMAP_RECT + "", // SC_SERVICE_IMAP_CIRC + "", // SC_SERVICE_IMAP_POLY + + // #100263# Support creation of GraphicObjectResolver and EmbeddedObjectResolver + "", // SC_SERVICE_EXPORT_GOR + "", // SC_SERVICE_IMPORT_GOR + "", // SC_SERVICE_EXPORT_EOR + "", // SC_SERVICE_IMPORT_EOR + + "", // SC_SERVICE_VALBIND + "", // SC_SERVICE_LISTCELLBIND + "", // SC_SERVICE_LISTSOURCE + "", // SC_SERVICE_CELLADDRESS + "", // SC_SERVICE_RANGEADDRESS + "", // SC_SERVICE_SHEETDOCSET + "", // SC_SERVICE_CHDATAPROV + "", // SC_SERVICE_FORMULAPARS + "", // SC_SERVICE_OPCODEMAPPER + "", // SC_SERVICE_VBAOBJECTPROVIDER + "", // SC_SERVICE_VBACODENAMEPROVIDER + "", // SC_SERVICE_VBAGLOBALS + }; + + + + +//------------------------------------------------------------------------ + +// alles static + +//UNUSED2008-05 String ScServiceProvider::GetProviderName(sal_uInt16 nObjectType) +//UNUSED2008-05 { +//UNUSED2008-05 String sRet; +//UNUSED2008-05 if (nObjectType < SC_SERVICE_COUNT) +//UNUSED2008-05 sRet = String::CreateFromAscii( aProvNames[nObjectType] ); +//UNUSED2008-05 return sRet; +//UNUSED2008-05 } + +sal_uInt16 ScServiceProvider::GetProviderType(const String& rServiceName) +{ + if (rServiceName.Len()) + { + const sal_uInt16 nEntries = + sizeof(aProvNamesId) / sizeof(aProvNamesId[0]); + for (sal_uInt16 i = 0; i < nEntries; i++) + { + if (rServiceName.EqualsAscii( aProvNamesId[i].pName )) + { + return aProvNamesId[i].nType; + } + } + + USHORT i; + for (i=0; i<SC_SERVICE_COUNT; i++) + { + DBG_ASSERT( aOldNames[i], "ScServiceProvider::GetProviderType: no oldname => crash"); + if (rServiceName.EqualsAscii( aOldNames[i] )) + { + DBG_ERROR("old service name used"); + return i; + } + } + } + return SC_SERVICE_INVALID; +} + +uno::Reference<uno::XInterface> ScServiceProvider::MakeInstance( + sal_uInt16 nType, ScDocShell* pDocShell ) +{ + uno::Reference<uno::XInterface> xRet; + switch (nType) + { + case SC_SERVICE_SHEET: + // noch nicht eingefuegt - DocShell=Null + xRet.set((sheet::XSpreadsheet*)new ScTableSheetObj(NULL,0)); + break; + case SC_SERVICE_URLFIELD: + xRet.set((text::XTextField*)new ScCellFieldObj( NULL, ScAddress(), ESelection() )); + break; + case SC_SERVICE_PAGEFIELD: + case SC_SERVICE_PAGESFIELD: + case SC_SERVICE_DATEFIELD: + case SC_SERVICE_TIMEFIELD: + case SC_SERVICE_TITLEFIELD: + case SC_SERVICE_FILEFIELD: + case SC_SERVICE_SHEETFIELD: + xRet.set((text::XTextField*)new ScHeaderFieldObj( NULL, 0, nType, ESelection() )); + break; + case SC_SERVICE_CELLSTYLE: + xRet.set((style::XStyle*)new ScStyleObj( NULL, SFX_STYLE_FAMILY_PARA, String() )); + break; + case SC_SERVICE_PAGESTYLE: + xRet.set((style::XStyle*)new ScStyleObj( NULL, SFX_STYLE_FAMILY_PAGE, String() )); + break; + case SC_SERVICE_AUTOFORMAT: + xRet.set((container::XIndexAccess*)new ScAutoFormatObj( SC_AFMTOBJ_INVALID )); + break; + case SC_SERVICE_CELLRANGES: + // wird nicht eingefuegt, sondern gefuellt + // -> DocShell muss gesetzt sein, aber leere Ranges + if (pDocShell) + xRet.set((sheet::XSheetCellRanges*)new ScCellRangesObj( pDocShell, ScRangeList() )); + break; + + case SC_SERVICE_DOCDEFLTS: + if (pDocShell) + xRet.set((beans::XPropertySet*)new ScDocDefaultsObj( pDocShell )); + break; + case SC_SERVICE_DRAWDEFLTS: + if (pDocShell) + xRet.set((beans::XPropertySet*)new ScDrawDefaultsObj( pDocShell )); + break; + + // Drawing layer tables are not in SvxUnoDrawMSFactory, + // because SvxUnoDrawMSFactory doesn't have a SdrModel pointer. + // Drawing layer is always allocated if not there (MakeDrawLayer). + + case SC_SERVICE_GRADTAB: + if (pDocShell) + xRet.set(SvxUnoGradientTable_createInstance( pDocShell->MakeDrawLayer() )); + break; + case SC_SERVICE_HATCHTAB: + if (pDocShell) + xRet.set(SvxUnoHatchTable_createInstance( pDocShell->MakeDrawLayer() )); + break; + case SC_SERVICE_BITMAPTAB: + if (pDocShell) + xRet.set(SvxUnoBitmapTable_createInstance( pDocShell->MakeDrawLayer() )); + break; + case SC_SERVICE_TRGRADTAB: + if (pDocShell) + xRet.set(SvxUnoTransGradientTable_createInstance( pDocShell->MakeDrawLayer() )); + break; + case SC_SERVICE_MARKERTAB: + if (pDocShell) + xRet.set(SvxUnoMarkerTable_createInstance( pDocShell->MakeDrawLayer() )); + break; + case SC_SERVICE_DASHTAB: + if (pDocShell) + xRet.set(SvxUnoDashTable_createInstance( pDocShell->MakeDrawLayer() )); + break; + case SC_SERVICE_NUMRULES: + if (pDocShell) + xRet.set(SvxCreateNumRule( pDocShell->MakeDrawLayer() )); + break; + case SC_SERVICE_DOCSPRSETT: + case SC_SERVICE_SHEETDOCSET: + case SC_SERVICE_DOCCONF: + if (pDocShell) + xRet.set((beans::XPropertySet*)new ScDocumentConfiguration(pDocShell)); + break; + + case SC_SERVICE_IMAP_RECT: + xRet.set(SvUnoImageMapRectangleObject_createInstance( ScShapeObj::GetSupportedMacroItems() )); + break; + case SC_SERVICE_IMAP_CIRC: + xRet.set(SvUnoImageMapCircleObject_createInstance( ScShapeObj::GetSupportedMacroItems() )); + break; + case SC_SERVICE_IMAP_POLY: + xRet.set(SvUnoImageMapPolygonObject_createInstance( ScShapeObj::GetSupportedMacroItems() )); + break; + + // #100263# Support creation of GraphicObjectResolver and EmbeddedObjectResolver + case SC_SERVICE_EXPORT_GOR: + xRet.set((::cppu::OWeakObject * )new SvXMLGraphicHelper( GRAPHICHELPER_MODE_WRITE )); + break; + + case SC_SERVICE_IMPORT_GOR: + xRet.set((::cppu::OWeakObject * )new SvXMLGraphicHelper( GRAPHICHELPER_MODE_READ )); + break; + + case SC_SERVICE_EXPORT_EOR: + if (pDocShell) + xRet.set((::cppu::OWeakObject * )new SvXMLEmbeddedObjectHelper( *pDocShell, EMBEDDEDOBJECTHELPER_MODE_WRITE )); + break; + + case SC_SERVICE_IMPORT_EOR: + if (pDocShell) + xRet.set((::cppu::OWeakObject * )new SvXMLEmbeddedObjectHelper( *pDocShell, EMBEDDEDOBJECTHELPER_MODE_READ )); + break; + + case SC_SERVICE_VALBIND: + case SC_SERVICE_LISTCELLBIND: + if (pDocShell) + { + sal_Bool bListPos = ( nType == SC_SERVICE_LISTCELLBIND ); + uno::Reference<sheet::XSpreadsheetDocument> xDoc( pDocShell->GetBaseModel(), uno::UNO_QUERY ); + xRet.set(*new calc::OCellValueBinding( xDoc, bListPos )); + } + break; + case SC_SERVICE_LISTSOURCE: + if (pDocShell) + { + uno::Reference<sheet::XSpreadsheetDocument> xDoc( pDocShell->GetBaseModel(), uno::UNO_QUERY ); + xRet.set(*new calc::OCellListSource( xDoc )); + } + break; + case SC_SERVICE_CELLADDRESS: + case SC_SERVICE_RANGEADDRESS: + if (pDocShell) + { + sal_Bool bRange = ( nType == SC_SERVICE_RANGEADDRESS ); + xRet.set(*new ScAddressConversionObj( pDocShell, bRange )); + } + break; + + case SC_SERVICE_CHDATAPROV: + if (pDocShell && pDocShell->GetDocument()) + xRet = *new ScChart2DataProvider( pDocShell->GetDocument() ); + break; + + case SC_SERVICE_FORMULAPARS: + if (pDocShell) + xRet.set(static_cast<sheet::XFormulaParser*>(new ScFormulaParserObj( pDocShell ))); + break; + + case SC_SERVICE_OPCODEMAPPER: + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScAddress aAddress; + ScCompiler* pComp = new ScCompiler(pDoc,aAddress); + pComp->SetGrammar( pDoc->GetGrammar() ); + xRet.set(static_cast<sheet::XFormulaOpCodeMapper*>(new ScFormulaOpCodeMapperObj(::std::auto_ptr<formula::FormulaCompiler> (pComp)))); + break; + } + case SC_SERVICE_VBAOBJECTPROVIDER: + if (pDocShell && pDocShell->GetDocument()->IsInVBAMode()) + { + OSL_TRACE("**** creating VBA Object mapper"); + xRet.set(static_cast<container::XNameAccess*>(new ScVbaObjectForCodeNameProvider( pDocShell ))); + } + break; + case SC_SERVICE_VBACODENAMEPROVIDER: + if (pDocShell && pDocShell->GetDocument()->IsInVBAMode()) + { + OSL_TRACE("**** creating VBA Object provider"); + xRet.set(static_cast<document::XCodeNameQuery*>(new ScVbaCodeNameProvider( pDocShell ))); + } + break; + case SC_SERVICE_VBAGLOBALS: + if (pDocShell) + { + uno::Any aGlobs; + if ( !pDocShell->GetBasicManager()->GetGlobalUNOConstant( "VBAGlobals", aGlobs ) ) + { + uno::Sequence< uno::Any > aArgs(1); + aArgs[ 0 ] <<= pDocShell->GetModel(); + xRet = ::comphelper::getProcessServiceFactory()->createInstanceWithArguments( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ooo.vba.excel.Globals" ) ), aArgs ); + pDocShell->GetBasicManager()->SetGlobalUNOConstant( "VBAGlobals", uno::Any( xRet ) ); + BasicManager* pAppMgr = SFX_APP()->GetBasicManager(); + if ( pAppMgr ) + pAppMgr->SetGlobalUNOConstant( "ThisExcelDoc", aArgs[ 0 ] ); + } + } + break; + } + + return xRet; +} + +uno::Sequence<rtl::OUString> ScServiceProvider::GetAllServiceNames() +{ + const sal_uInt16 nEntries = sizeof(aProvNamesId) / sizeof(aProvNamesId[0]); + uno::Sequence<rtl::OUString> aRet(nEntries); + rtl::OUString* pArray = aRet.getArray(); + for (sal_uInt16 i = 0; i < nEntries; i++) + { + pArray[i] = rtl::OUString::createFromAscii( aProvNamesId[i].pName ); + } + return aRet; +} + + + + diff --git a/sc/source/ui/unoobj/shapeuno.cxx b/sc/source/ui/unoobj/shapeuno.cxx new file mode 100644 index 000000000000..1ed384ed2ebd --- /dev/null +++ b/sc/source/ui/unoobj/shapeuno.cxx @@ -0,0 +1,1521 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +#include <tools/debug.hxx> +#include <comphelper/uno3.hxx> +#include <comphelper/stl_types.hxx> +#include <svtools/unoevent.hxx> +#include <svtools/unoimap.hxx> +#include <svx/svdobj.hxx> +#include <svx/unoshape.hxx> +#include <editeng/unofield.hxx> +#include <svx/shapepropertynotifier.hxx> +#include <toolkit/helper/convert.hxx> +#include <cppuhelper/implbase2.hxx> + +#include <com/sun/star/drawing/XShape.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> + +#include "shapeuno.hxx" +#include "miscuno.hxx" +#include "cellsuno.hxx" +#include "textuno.hxx" +#include "fielduno.hxx" +#include "docsh.hxx" +#include "drwlayer.hxx" +#include "userdat.hxx" +#include "unonames.hxx" +#include "unoguard.hxx" + +using namespace ::com::sun::star; + +//------------------------------------------------------------------------ + +DECLARE_STL_USTRINGACCESS_MAP( uno::Sequence< sal_Int8 > *, ScShapeImplementationIdMap ); + +static ScShapeImplementationIdMap aImplementationIdMap; + +const SfxItemPropertyMapEntry* lcl_GetShapeMap() +{ + static SfxItemPropertyMapEntry aShapeMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_ANCHOR), 0, &getCppuType((uno::Reference<uno::XInterface>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_HORIPOS), 0, &getCppuType((sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_IMAGEMAP), 0, &getCppuType((uno::Reference<container::XIndexContainer>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_VERTPOS), 0, &getCppuType((sal_Int32*)0), 0, 0 }, + {0,0,0,0,0,0} + }; + return aShapeMap_Impl; +} + +// static +const SvEventDescription* ScShapeObj::GetSupportedMacroItems() +{ + static const SvEventDescription aMacroDescriptionsImpl[] = + { + { 0, NULL } + }; + return aMacroDescriptionsImpl; +} + +//------------------------------------------------------------------------ + +namespace +{ + void lcl_initializeNotifier( SdrObject& _rSdrObj, ::cppu::OWeakObject& _rShape ) + { + ::svx::PPropertyValueProvider pProvider( new ::svx::PropertyValueProvider( _rShape, "Anchor" ) ); + _rSdrObj.getShapePropertyChangeNotifier().registerProvider( ::svx::eSpreadsheetAnchor, pProvider ); + } +} + +//------------------------------------------------------------------------ + +ScShapeObj::ScShapeObj( uno::Reference<drawing::XShape>& xShape ) : + pShapePropertySet(NULL), + pShapePropertyState(NULL), + pImplementationId(NULL), + bIsTextShape(FALSE), + bInitializedNotifier(false) +{ + comphelper::increment( m_refCount ); + + { + mxShapeAgg = uno::Reference<uno::XAggregation>( xShape, uno::UNO_QUERY ); + // extra block to force deletion of the temporary before setDelegator + } + + if (mxShapeAgg.is()) + { + xShape = NULL; // during setDelegator, mxShapeAgg must be the only ref + + mxShapeAgg->setDelegator( (cppu::OWeakObject*)this ); + + xShape.set(uno::Reference<drawing::XShape>( mxShapeAgg, uno::UNO_QUERY )); + + bIsTextShape = ( SvxUnoTextBase::getImplementation( mxShapeAgg ) != NULL ); + } + + { + SdrObject* pObj = GetSdrObject(); + if ( pObj ) + { + lcl_initializeNotifier( *pObj, *this ); + bInitializedNotifier = true; + } + } + + comphelper::decrement( m_refCount ); +} + +ScShapeObj::~ScShapeObj() +{ +// if (mxShapeAgg.is()) +// mxShapeAgg->setDelegator(uno::Reference<uno::XInterface>()); +} + +// XInterface + +uno::Any SAL_CALL ScShapeObj::queryInterface( const uno::Type& rType ) + throw(uno::RuntimeException) +{ + uno::Any aRet = ScShapeObj_Base::queryInterface( rType ); + + if ( !aRet.hasValue() && bIsTextShape ) + aRet = ScShapeObj_TextBase::queryInterface( rType ); + + if ( !aRet.hasValue() && mxShapeAgg.is() ) + aRet = mxShapeAgg->queryAggregation( rType ); + + return aRet; +} + +void SAL_CALL ScShapeObj::acquire() throw() +{ + OWeakObject::acquire(); +} + +void SAL_CALL ScShapeObj::release() throw() +{ + OWeakObject::release(); +} + +void ScShapeObj::GetShapePropertySet() +{ + // #i61908# Store the result of queryAggregation in a member. + // The reference in mxShapeAgg is kept for this object's lifetime, so the pointer is always valid. + + if (!pShapePropertySet) + { + uno::Reference<beans::XPropertySet> xProp; + if ( mxShapeAgg.is() ) + mxShapeAgg->queryAggregation( getCppuType((uno::Reference<beans::XPropertySet>*) 0) ) >>= xProp; + pShapePropertySet = xProp.get(); + } +} + +void ScShapeObj::GetShapePropertyState() +{ + // #i61908# Store the result of queryAggregation in a member. + // The reference in mxShapeAgg is kept for this object's lifetime, so the pointer is always valid. + + if (!pShapePropertyState) + { + uno::Reference<beans::XPropertyState> xState; + if ( mxShapeAgg.is() ) + mxShapeAgg->queryAggregation( getCppuType((uno::Reference<beans::XPropertyState>*) 0) ) >>= xState; + pShapePropertyState = xState.get(); + } +} + +uno::Reference<lang::XComponent> lcl_GetComponent( const uno::Reference<uno::XAggregation>& xAgg ) +{ + uno::Reference<lang::XComponent> xRet; + if ( xAgg.is() ) + xAgg->queryAggregation( getCppuType((uno::Reference<lang::XComponent>*) 0) ) >>= xRet; + return xRet; +} + +uno::Reference<text::XText> lcl_GetText( const uno::Reference<uno::XAggregation>& xAgg ) +{ + uno::Reference<text::XText> xRet; + if ( xAgg.is() ) + xAgg->queryAggregation( getCppuType((uno::Reference<text::XText>*) 0) ) >>= xRet; + return xRet; +} + +uno::Reference<text::XSimpleText> lcl_GetSimpleText( const uno::Reference<uno::XAggregation>& xAgg ) +{ + uno::Reference<text::XSimpleText> xRet; + if ( xAgg.is() ) + xAgg->queryAggregation( getCppuType((uno::Reference<text::XSimpleText>*) 0) ) >>= xRet; + return xRet; +} + +uno::Reference<text::XTextRange> lcl_GetTextRange( const uno::Reference<uno::XAggregation>& xAgg ) +{ + uno::Reference<text::XTextRange> xRet; + if ( xAgg.is() ) + xAgg->queryAggregation( getCppuType((uno::Reference<text::XTextRange>*) 0) ) >>= xRet; + return xRet; +} + +// XPropertySet + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScShapeObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + // #i61527# cache property set info for this object + if ( !mxPropSetInfo.is() ) + { + // mix own and aggregated properties: + GetShapePropertySet(); + if (pShapePropertySet) + { + uno::Reference<beans::XPropertySetInfo> xAggInfo(pShapePropertySet->getPropertySetInfo()); + const uno::Sequence<beans::Property> aPropSeq(xAggInfo->getProperties()); + mxPropSetInfo.set(new SfxExtItemPropertySetInfo( lcl_GetShapeMap(), aPropSeq )); + } + } + return mxPropSetInfo; +} + +BOOL lcl_GetPageNum( SdrPage* pPage, SdrModel& rModel, SCTAB& rNum ) +{ + USHORT nCount = rModel.GetPageCount(); + for (USHORT i=0; i<nCount; i++) + if ( rModel.GetPage(i) == pPage ) + { + rNum = static_cast<SCTAB>(i); + return TRUE; + } + + return FALSE; +} + +BOOL lcl_GetCaptionPoint( uno::Reference< drawing::XShape >& xShape, awt::Point& rCaptionPoint ) +{ + BOOL bReturn = FALSE; + rtl::OUString sType(xShape->getShapeType()); + sal_Bool bCaptionShape(sType.equalsAscii("com.sun.star.drawing.CaptionShape")); + if (bCaptionShape) + { + uno::Reference < beans::XPropertySet > xShapeProp (xShape, uno::UNO_QUERY); + if (xShapeProp.is()) + { + xShapeProp->getPropertyValue( rtl::OUString(RTL_CONSTASCII_USTRINGPARAM( "CaptionPoint" )) ) >>= rCaptionPoint; + bReturn = TRUE; + } + } + return bReturn; +} + +ScRange lcl_GetAnchorCell( uno::Reference< drawing::XShape >& xShape, ScDocument* pDoc, SCTAB nTab, + awt::Point& rUnoPoint, awt::Size& rUnoSize, awt::Point& rCaptionPoint ) +{ + ScRange aReturn; + rUnoPoint = xShape->getPosition(); + rtl::OUString sType(xShape->getShapeType()); + sal_Bool bCaptionShape(lcl_GetCaptionPoint(xShape, rCaptionPoint)); + if (pDoc->IsNegativePage(nTab)) + { + rUnoSize = xShape->getSize(); + rUnoPoint.X += rUnoSize.Width; // the right top point is base + if (bCaptionShape) + { + if (rCaptionPoint.X > 0 && rCaptionPoint.X > rUnoSize.Width) + rUnoPoint.X += rCaptionPoint.X - rUnoSize.Width; + if (rCaptionPoint.Y < 0) + rUnoPoint.Y += rCaptionPoint.Y; + } + aReturn = pDoc->GetRange( nTab, Rectangle( VCLPoint(rUnoPoint), VCLPoint(rUnoPoint) )); + } + else + { + if (bCaptionShape) + { + if (rCaptionPoint.X < 0) + rUnoPoint.X += rCaptionPoint.X; + if (rCaptionPoint.Y < 0) + rUnoPoint.Y += rCaptionPoint.Y; + } + aReturn = pDoc->GetRange( nTab, Rectangle( VCLPoint(rUnoPoint), VCLPoint(rUnoPoint) )); + } + + return aReturn; +} + +awt::Point lcl_GetRelativePos( uno::Reference< drawing::XShape >& xShape, ScDocument* pDoc, SCTAB nTab, ScRange& rRange, + awt::Size& rUnoSize, awt::Point& rCaptionPoint) +{ + awt::Point aUnoPoint; + rRange = lcl_GetAnchorCell(xShape, pDoc, nTab, aUnoPoint, rUnoSize, rCaptionPoint); + if (pDoc->IsNegativePage(nTab)) + { + Rectangle aRect(pDoc->GetMMRect( rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aStart.Tab() )); + Point aPoint(aRect.TopRight()); + aUnoPoint.X -= aPoint.X(); + aUnoPoint.Y -= aPoint.Y(); + } + else + { + ScRange aRange = pDoc->GetRange( nTab, Rectangle( VCLPoint(aUnoPoint), VCLPoint(aUnoPoint) )); + Rectangle aRect(pDoc->GetMMRect( rRange.aStart.Col(), rRange.aStart.Row(), rRange.aEnd.Col(), rRange.aEnd.Row(), rRange.aStart.Tab() )); + Point aPoint(aRect.TopLeft()); + aUnoPoint.X -= aPoint.X(); + aUnoPoint.Y -= aPoint.Y(); + } + + return aUnoPoint; +} + +void SAL_CALL ScShapeObj::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aNameString(aPropertyName); + + if ( aNameString.EqualsAscii( SC_UNONAME_ANCHOR ) ) + { + uno::Reference<sheet::XCellRangeAddressable> xRangeAdd(aValue, uno::UNO_QUERY); + if (xRangeAdd.is()) + { + SdrObject *pObj = GetSdrObject(); + if (pObj) + { + ScDrawLayer* pModel = (ScDrawLayer*)pObj->GetModel(); + SdrPage* pPage = pObj->GetPage(); + if ( pModel && pPage ) + { + ScDocument* pDoc = pModel->GetDocument(); + if ( pDoc ) + { + SfxObjectShell* pObjSh = pDoc->GetDocumentShell(); + if ( pObjSh && pObjSh->ISA(ScDocShell) ) + { + ScDocShell* pDocSh = (ScDocShell*)pObjSh; + + SCTAB nTab = 0; + if ( lcl_GetPageNum( pPage, *pModel, nTab ) ) + { + table::CellRangeAddress aAddress = xRangeAdd->getRangeAddress(); + if (nTab == aAddress.Sheet) + { + if (aAddress.StartRow != aAddress.EndRow) //should be a Spreadsheet + { + DBG_ASSERT(aAddress.StartRow == 0 && aAddress.EndRow == MAXROW && + aAddress.StartColumn == 0 && aAddress.EndColumn == MAXCOL, "here should be a XSpreadsheet"); + ScDrawLayer::SetAnchor(pObj, SCA_PAGE); + } + else + { + DBG_ASSERT(aAddress.StartRow == aAddress.EndRow && + aAddress.StartColumn == aAddress.EndColumn, "here should be a XCell"); + ScDrawLayer::SetAnchor(pObj, SCA_CELL); + } + Rectangle aRect(pDoc->GetMMRect( static_cast<SCCOL>(aAddress.StartColumn), static_cast<SCROW>(aAddress.StartRow), + static_cast<SCCOL>(aAddress.EndColumn), static_cast<SCROW>(aAddress.EndRow), aAddress.Sheet )); + uno::Reference<drawing::XShape> xShape( mxShapeAgg, uno::UNO_QUERY ); + if (xShape.is()) + { + Point aPoint; + Point aEndPoint; + if (pDoc->IsNegativePage(nTab)) + { + aPoint = aRect.TopRight(); + aEndPoint = aRect.BottomLeft(); + } + else + { + aPoint = aRect.TopLeft(); + aEndPoint = aRect.BottomRight(); + } + awt::Size aUnoSize; + awt::Point aCaptionPoint; + ScRange aRange; + awt::Point aUnoPoint(lcl_GetRelativePos( xShape, pDoc, nTab, aRange, aUnoSize, aCaptionPoint )); + + aUnoPoint.X += aPoint.X(); + aUnoPoint.Y += aPoint.Y(); + + if ( aUnoPoint.Y > aEndPoint.Y() ) + aUnoPoint.Y = aEndPoint.Y() - 2; + if (pDoc->IsNegativePage(nTab)) + { + if ( aUnoPoint.X < aEndPoint.X() ) + aUnoPoint.X = aEndPoint.X() + 2; + aUnoPoint.X -= aUnoSize.Width; + // remove difference to caption point + if (aCaptionPoint.X > 0 && aCaptionPoint.X > aUnoSize.Width) + aUnoPoint.X -= aCaptionPoint.X - aUnoSize.Width; + } + else + { + if ( aUnoPoint.X > aEndPoint.X() ) + aUnoPoint.X = aEndPoint.X() - 2; + if (aCaptionPoint.X < 0) + aUnoPoint.X -= aCaptionPoint.X; + } + if (aCaptionPoint.Y < 0) + aUnoPoint.Y -= aCaptionPoint.Y; + + xShape->setPosition(aUnoPoint); + pDocSh->SetModified(); + } + } + } + } + } + } + } + } + else + throw lang::IllegalArgumentException(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("only XCell or XSpreadsheet objects allowed")), static_cast<cppu::OWeakObject*>(this), 0); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_IMAGEMAP ) ) + { + SdrObject* pObj = GetSdrObject(); + if ( pObj ) + { + ImageMap aImageMap; + uno::Reference< uno::XInterface > xImageMapInt(aValue, uno::UNO_QUERY); + + if( !xImageMapInt.is() || !SvUnoImageMap_fillImageMap( xImageMapInt, aImageMap ) ) + throw lang::IllegalArgumentException(); + + ScIMapInfo* pIMapInfo = ScDrawLayer::GetIMapInfo(pObj); + if( pIMapInfo ) + { + // replace existing image map + pIMapInfo->SetImageMap( aImageMap ); + } + else + { + // insert new user data with image map + pObj->InsertUserData(new ScIMapInfo(aImageMap) ); + } + } + } + else if ( aNameString.EqualsAscii( SC_UNONAME_HORIPOS ) ) + { + sal_Int32 nPos = 0; + if (aValue >>= nPos) + { + SdrObject *pObj = GetSdrObject(); + if (pObj) + { + ScDrawLayer* pModel = (ScDrawLayer*)pObj->GetModel(); + SdrPage* pPage = pObj->GetPage(); + if ( pModel && pPage ) + { + SCTAB nTab = 0; + if ( lcl_GetPageNum( pPage, *pModel, nTab ) ) + { + ScDocument* pDoc = pModel->GetDocument(); + if ( pDoc ) + { + SfxObjectShell* pObjSh = pDoc->GetDocumentShell(); + if ( pObjSh && pObjSh->ISA(ScDocShell) ) + { + ScDocShell* pDocSh = (ScDocShell*)pObjSh; + uno::Reference<drawing::XShape> xShape( mxShapeAgg, uno::UNO_QUERY ); + if (xShape.is()) + { + if (ScDrawLayer::GetAnchor(pObj) == SCA_PAGE) + { + awt::Point aPoint(xShape->getPosition()); + awt::Size aSize(xShape->getSize()); + awt::Point aCaptionPoint; + if (pDoc->IsNegativePage(nTab)) + { + nPos *= -1; + nPos -= aSize.Width; + } + if (lcl_GetCaptionPoint(xShape, aCaptionPoint)) + { + if (pDoc->IsNegativePage(nTab)) + { + if (aCaptionPoint.X > 0 && aCaptionPoint.X > aSize.Width) + nPos -= aCaptionPoint.X - aSize.Width; + } + else + { + if (aCaptionPoint.X < 0) + nPos -= aCaptionPoint.X; + } + } + aPoint.X = nPos; + xShape->setPosition(aPoint); + pDocSh->SetModified(); + } + else if (ScDrawLayer::GetAnchor(pObj) == SCA_CELL) + { + awt::Size aUnoSize; + awt::Point aCaptionPoint; + ScRange aRange; + awt::Point aUnoPoint(lcl_GetRelativePos( xShape, pDoc, nTab, aRange, aUnoSize, aCaptionPoint )); + Rectangle aRect(pDoc->GetMMRect( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab() )); + if (pDoc->IsNegativePage(nTab)) + { + aUnoPoint.X = -nPos; + Point aPoint(aRect.TopRight()); + Point aEndPoint(aRect.BottomLeft()); + aUnoPoint.X += aPoint.X(); + if (aUnoPoint.X < aEndPoint.X()) + aUnoPoint.X = aEndPoint.X() + 2; + aUnoPoint.X -= aUnoSize.Width; + if (aCaptionPoint.X > 0 && aCaptionPoint.X > aUnoSize.Width) + aUnoPoint.X -= aCaptionPoint.X - aUnoSize.Width; + } + else + { + aUnoPoint.X = nPos; + Point aPoint(aRect.TopLeft()); + Point aEndPoint(aRect.BottomRight()); + aUnoPoint.X += aPoint.X(); + if (aUnoPoint.X > aEndPoint.X()) + aUnoPoint.X = aEndPoint.X() - 2; + if (aCaptionPoint.X < 0) + aUnoPoint.X -= aCaptionPoint.X; + } + aUnoPoint.Y = xShape->getPosition().Y; + xShape->setPosition(aUnoPoint); + pDocSh->SetModified(); + } + else + { + DBG_ERROR("unknown anchor type"); + } + } + } + } + } + } + } + } + } + else if ( aNameString.EqualsAscii( SC_UNONAME_VERTPOS ) ) + { + sal_Int32 nPos = 0; + if (aValue >>= nPos) + { + SdrObject *pObj = GetSdrObject(); + if (pObj) + { + ScDrawLayer* pModel = (ScDrawLayer*)pObj->GetModel(); + SdrPage* pPage = pObj->GetPage(); + if ( pModel && pPage ) + { + SCTAB nTab = 0; + if ( lcl_GetPageNum( pPage, *pModel, nTab ) ) + { + ScDocument* pDoc = pModel->GetDocument(); + if ( pDoc ) + { + SfxObjectShell* pObjSh = pDoc->GetDocumentShell(); + if ( pObjSh && pObjSh->ISA(ScDocShell) ) + { + ScDocShell* pDocSh = (ScDocShell*)pObjSh; + uno::Reference<drawing::XShape> xShape( mxShapeAgg, uno::UNO_QUERY ); + if (xShape.is()) + { + if (ScDrawLayer::GetAnchor(pObj) == SCA_PAGE) + { + awt::Point aPoint = xShape->getPosition(); + awt::Point aCaptionPoint; + if (lcl_GetCaptionPoint(xShape, aCaptionPoint)) + { + if (aCaptionPoint.Y < 0) + nPos -= aCaptionPoint.Y; + } + aPoint.Y = nPos; + xShape->setPosition(aPoint); + pDocSh->SetModified(); + } + else if (ScDrawLayer::GetAnchor(pObj) == SCA_CELL) + { + awt::Size aUnoSize; + awt::Point aCaptionPoint; + ScRange aRange; + awt::Point aUnoPoint(lcl_GetRelativePos( xShape, pDoc, nTab, aRange, aUnoSize, aCaptionPoint )); + Rectangle aRect(pDoc->GetMMRect( aRange.aStart.Col(), aRange.aStart.Row(), aRange.aEnd.Col(), aRange.aEnd.Row(), aRange.aStart.Tab() )); + Point aPoint(aRect.TopRight()); + Point aEndPoint(aRect.BottomLeft()); + aUnoPoint.Y = nPos; + aUnoPoint.Y += aPoint.Y(); + if (aUnoPoint.Y > aEndPoint.Y()) + aUnoPoint.Y = aEndPoint.Y() - 2; + if (aCaptionPoint.Y < 0) + aUnoPoint.Y -= aCaptionPoint.Y; + aUnoPoint.X = xShape->getPosition().X; + xShape->setPosition(aUnoPoint); + pDocSh->SetModified(); + } + else + { + DBG_ERROR("unknown anchor type"); + } + } + } + } + } + } + } + } + } + else + { + GetShapePropertySet(); + if (pShapePropertySet) + pShapePropertySet->setPropertyValue( aPropertyName, aValue ); + } +} + +uno::Any SAL_CALL ScShapeObj::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aNameString = aPropertyName; + + uno::Any aAny; + if ( aNameString.EqualsAscii( SC_UNONAME_ANCHOR ) ) + { + SdrObject *pObj = GetSdrObject(); + if (pObj) + { + ScDrawLayer* pModel = (ScDrawLayer*)pObj->GetModel(); + SdrPage* pPage = pObj->GetPage(); + if ( pModel && pPage ) + { + ScDocument* pDoc = pModel->GetDocument(); + if ( pDoc ) + { + SCTAB nTab = 0; + if ( lcl_GetPageNum( pPage, *pModel, nTab ) ) + { + SfxObjectShell* pObjSh = pDoc->GetDocumentShell(); + if ( pObjSh && pObjSh->ISA(ScDocShell) ) + { + ScDocShell* pDocSh = (ScDocShell*)pObjSh; + uno::Reference< uno::XInterface > xAnchor; + if (ScDrawLayer::GetAnchor(pObj) == SCA_CELL) + { + uno::Reference<drawing::XShape> xShape( mxShapeAgg, uno::UNO_QUERY ); + if (xShape.is()) + { + awt::Size aUnoSize; + awt::Point aCaptionPoint; + ScRange aRange; + awt::Point aUnoPoint(lcl_GetRelativePos( xShape, pDoc, nTab, aRange, aUnoSize, aCaptionPoint )); + + xAnchor.set(static_cast<cppu::OWeakObject*>(new ScCellObj( pDocSh, aRange.aStart ))); + } + } + else + { + xAnchor.set(static_cast<cppu::OWeakObject*>(new ScTableSheetObj( pDocSh, nTab ))); + } + aAny <<= xAnchor; + } + } + } + } + } + } + else if ( aNameString.EqualsAscii( SC_UNONAME_IMAGEMAP ) ) + { + uno::Reference< uno::XInterface > xImageMap; + SdrObject* pObj = GetSdrObject(); + if ( pObj ) + { + ScIMapInfo* pIMapInfo = ScDrawLayer::GetIMapInfo(GetSdrObject()); + if( pIMapInfo ) + { + const ImageMap& rIMap = pIMapInfo->GetImageMap(); + xImageMap.set(SvUnoImageMap_createInstance( rIMap, GetSupportedMacroItems() )); + } + else + xImageMap = SvUnoImageMap_createInstance( GetSupportedMacroItems() ); + } + aAny <<= uno::Reference< container::XIndexContainer >::query( xImageMap ); + } + else if ( aNameString.EqualsAscii( SC_UNONAME_HORIPOS ) ) + { + SdrObject *pObj = GetSdrObject(); + if (pObj) + { + ScDrawLayer* pModel = (ScDrawLayer*)pObj->GetModel(); + SdrPage* pPage = pObj->GetPage(); + if ( pModel && pPage ) + { + ScDocument* pDoc = pModel->GetDocument(); + if ( pDoc ) + { + SCTAB nTab = 0; + if ( lcl_GetPageNum( pPage, *pModel, nTab ) ) + { + uno::Reference<drawing::XShape> xShape( mxShapeAgg, uno::UNO_QUERY ); + if (xShape.is()) + { + if (ScDrawLayer::GetAnchor(pObj) == SCA_CELL) + { + awt::Size aUnoSize; + awt::Point aCaptionPoint; + ScRange aRange; + awt::Point aUnoPoint(lcl_GetRelativePos( xShape, pDoc, nTab, aRange, aUnoSize, aCaptionPoint )); + if (pDoc->IsNegativePage(nTab)) + aUnoPoint.X *= -1; + aAny <<= aUnoPoint.X; + } + else + { + awt::Point aCaptionPoint; + awt::Point aUnoPoint(xShape->getPosition()); + awt::Size aUnoSize(xShape->getSize()); + if (pDoc->IsNegativePage(nTab)) + { + aUnoPoint.X *= -1; + aUnoPoint.X -= aUnoSize.Width; + } + if (lcl_GetCaptionPoint(xShape, aCaptionPoint)) + { + if (pDoc->IsNegativePage(nTab)) + { + if (aCaptionPoint.X > 0 && aCaptionPoint.X > aUnoSize.Width) + aUnoPoint.X -= aCaptionPoint.X - aUnoSize.Width; + } + else + { + if (aCaptionPoint.X < 0) + aUnoPoint.X += aCaptionPoint.X; + } + } + aAny <<= aUnoPoint.X; + } + } + } + } + } + } + } + else if ( aNameString.EqualsAscii( SC_UNONAME_VERTPOS ) ) + { + SdrObject *pObj = GetSdrObject(); + if (pObj) + { + ScDrawLayer* pModel = (ScDrawLayer*)pObj->GetModel(); + SdrPage* pPage = pObj->GetPage(); + if ( pModel && pPage ) + { + ScDocument* pDoc = pModel->GetDocument(); + if ( pDoc ) + { + SCTAB nTab = 0; + if ( lcl_GetPageNum( pPage, *pModel, nTab ) ) + { + uno::Reference<drawing::XShape> xShape( mxShapeAgg, uno::UNO_QUERY ); + if (xShape.is()) + { + uno::Reference< uno::XInterface > xAnchor; + if (ScDrawLayer::GetAnchor(pObj) == SCA_CELL) + { + awt::Size aUnoSize; + awt::Point aCaptionPoint; + ScRange aRange; + awt::Point aUnoPoint(lcl_GetRelativePos( xShape, pDoc, nTab, aRange, aUnoSize, aCaptionPoint )); + + aAny <<= aUnoPoint.Y; + } + else + { + awt::Point aUnoPoint(xShape->getPosition()); + awt::Point aCaptionPoint; + if (lcl_GetCaptionPoint(xShape, aCaptionPoint)) + { + if (aCaptionPoint.Y < 0) + aUnoPoint.Y += aCaptionPoint.Y; + } + aAny <<= aUnoPoint.Y; + } + } + } + } + } + } + } + else + { + GetShapePropertySet(); + if (pShapePropertySet) + aAny = pShapePropertySet->getPropertyValue( aPropertyName ); + } + + return aAny; +} + +void SAL_CALL ScShapeObj::addPropertyChangeListener( const rtl::OUString& aPropertyName, + const uno::Reference<beans::XPropertyChangeListener>& aListener) + throw(beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + GetShapePropertySet(); + if (pShapePropertySet) + pShapePropertySet->addPropertyChangeListener( aPropertyName, aListener ); + + if ( !bInitializedNotifier ) + { + // here's the latest chance to initialize the property notification at the SdrObject + // (in the ctor, where we also attempt to do this, we do not necessarily have + // and SdrObject, yet) + SdrObject* pObj = GetSdrObject(); + OSL_ENSURE( pObj, "ScShapeObj::addPropertyChangeListener: no SdrObject -> no property change notification!" ); + if ( pObj ) + lcl_initializeNotifier( *pObj, *this ); + bInitializedNotifier = true; + } +} + +void SAL_CALL ScShapeObj::removePropertyChangeListener( const rtl::OUString& aPropertyName, + const uno::Reference<beans::XPropertyChangeListener>& aListener) + throw(beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + GetShapePropertySet(); + if (pShapePropertySet) + pShapePropertySet->removePropertyChangeListener( aPropertyName, aListener ); +} + +void SAL_CALL ScShapeObj::addVetoableChangeListener( const rtl::OUString& aPropertyName, + const uno::Reference<beans::XVetoableChangeListener>& aListener) + throw(beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + GetShapePropertySet(); + if (pShapePropertySet) + pShapePropertySet->addVetoableChangeListener( aPropertyName, aListener ); +} + +void SAL_CALL ScShapeObj::removeVetoableChangeListener( const rtl::OUString& aPropertyName, + const uno::Reference<beans::XVetoableChangeListener>& aListener) + throw(beans::UnknownPropertyException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + GetShapePropertySet(); + if (pShapePropertySet) + pShapePropertySet->removeVetoableChangeListener( aPropertyName, aListener ); +} + +// XPropertyState + +beans::PropertyState SAL_CALL ScShapeObj::getPropertyState( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aNameString(aPropertyName); + + beans::PropertyState eRet = beans::PropertyState_DIRECT_VALUE; + if ( aNameString.EqualsAscii( SC_UNONAME_IMAGEMAP ) ) + { + // ImageMap is always "direct" + } + else if ( aNameString.EqualsAscii( SC_UNONAME_ANCHOR ) ) + { + // Anchor is always "direct" + } + else if ( aNameString.EqualsAscii( SC_UNONAME_HORIPOS ) ) + { + // HoriPos is always "direct" + } + else if ( aNameString.EqualsAscii( SC_UNONAME_VERTPOS ) ) + { + // VertPos is always "direct" + } + else + { + GetShapePropertyState(); + if (pShapePropertyState) + eRet = pShapePropertyState->getPropertyState( aPropertyName ); + } + + return eRet; +} + +uno::Sequence<beans::PropertyState> SAL_CALL ScShapeObj::getPropertyStates( + const uno::Sequence<rtl::OUString>& aPropertyNames ) + throw(beans::UnknownPropertyException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + // simple loop to get own and aggregated states + + const rtl::OUString* pNames = aPropertyNames.getConstArray(); + uno::Sequence<beans::PropertyState> aRet(aPropertyNames.getLength()); + beans::PropertyState* pStates = aRet.getArray(); + for(sal_Int32 i = 0; i < aPropertyNames.getLength(); i++) + pStates[i] = getPropertyState(pNames[i]); + return aRet; +} + +void SAL_CALL ScShapeObj::setPropertyToDefault( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aNameString(aPropertyName); + + if ( aNameString.EqualsAscii( SC_UNONAME_IMAGEMAP ) ) + { + SdrObject* pObj = GetSdrObject(); + if ( pObj ) + { + ScIMapInfo* pIMapInfo = ScDrawLayer::GetIMapInfo(pObj); + if( pIMapInfo ) + { + ImageMap aEmpty; + pIMapInfo->SetImageMap( aEmpty ); // replace with empty image map + } + else + { + // nothing to do (no need to insert user data for an empty map) + } + } + } + else + { + GetShapePropertyState(); + if (pShapePropertyState) + pShapePropertyState->setPropertyToDefault( aPropertyName ); + } +} + +uno::Any SAL_CALL ScShapeObj::getPropertyDefault( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aNameString = aPropertyName; + + uno::Any aAny; + if ( aNameString.EqualsAscii( SC_UNONAME_IMAGEMAP ) ) + { + // default: empty ImageMap + uno::Reference< uno::XInterface > xImageMap(SvUnoImageMap_createInstance( GetSupportedMacroItems() )); + aAny <<= uno::Reference< container::XIndexContainer >::query( xImageMap ); + } + else + { + GetShapePropertyState(); + if (pShapePropertyState) + aAny = pShapePropertyState->getPropertyDefault( aPropertyName ); + } + + return aAny; +} + +// XTextContent + +void SAL_CALL ScShapeObj::attach( const uno::Reference<text::XTextRange>& /* xTextRange */ ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + throw lang::IllegalArgumentException(); // anchor cannot be changed +} + +uno::Reference<text::XTextRange> SAL_CALL ScShapeObj::getAnchor() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + uno::Reference<text::XTextRange> xRet; + + SdrObject* pObj = GetSdrObject(); + if( pObj ) + { + ScDrawLayer* pModel = (ScDrawLayer*)pObj->GetModel(); + SdrPage* pPage = pObj->GetPage(); + if ( pModel ) + { + ScDocument* pDoc = pModel->GetDocument(); + if ( pDoc ) + { + SfxObjectShell* pObjSh = pDoc->GetDocumentShell(); + if ( pObjSh && pObjSh->ISA(ScDocShell) ) + { + ScDocShell* pDocSh = (ScDocShell*)pObjSh; + + SCTAB nTab = 0; + if ( lcl_GetPageNum( pPage, *pModel, nTab ) ) + { + Point aPos(pObj->GetCurrentBoundRect().TopLeft()); + ScRange aRange(pDoc->GetRange( nTab, Rectangle( aPos, aPos ) )); + + // anchor is always the cell + + xRet.set(new ScCellObj( pDocSh, aRange.aStart )); + } + } + } + } + } + + return xRet; +} + +// XComponent + +void SAL_CALL ScShapeObj::dispose() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + uno::Reference<lang::XComponent> xAggComp(lcl_GetComponent(mxShapeAgg)); + if ( xAggComp.is() ) + xAggComp->dispose(); +} + +void SAL_CALL ScShapeObj::addEventListener( + const uno::Reference<lang::XEventListener>& xListener ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + uno::Reference<lang::XComponent> xAggComp(lcl_GetComponent(mxShapeAgg)); + if ( xAggComp.is() ) + xAggComp->addEventListener(xListener); +} + +void SAL_CALL ScShapeObj::removeEventListener( + const uno::Reference<lang::XEventListener>& xListener ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + uno::Reference<lang::XComponent> xAggComp(lcl_GetComponent(mxShapeAgg)); + if ( xAggComp.is() ) + xAggComp->removeEventListener(xListener); +} + +// XText +// (special handling for ScCellFieldObj) + +void lcl_CopyOneProperty( beans::XPropertySet& rDest, beans::XPropertySet& rSource, const sal_Char* pName ) +{ + rtl::OUString aNameStr(rtl::OUString::createFromAscii(pName)); + try + { + rDest.setPropertyValue( aNameStr, rSource.getPropertyValue( aNameStr ) ); + } + catch (uno::Exception&) + { + DBG_ERROR("Exception in text field"); + } +} + +void SAL_CALL ScShapeObj::insertTextContent( const uno::Reference<text::XTextRange>& xRange, + const uno::Reference<text::XTextContent>& xContent, + sal_Bool bAbsorb ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + uno::Reference<text::XTextContent> xEffContent; + + ScCellFieldObj* pCellField = ScCellFieldObj::getImplementation( xContent ); + if ( pCellField ) + { + // #105585# createInstance("TextField.URL") from the document creates a ScCellFieldObj. + // To insert it into drawing text, a SvxUnoTextField is needed instead. + // The ScCellFieldObj object is left in non-inserted state. + + SvxUnoTextField* pDrawField = new SvxUnoTextField( ID_URLFIELD ); + xEffContent.set(pDrawField); + lcl_CopyOneProperty( *pDrawField, *pCellField, SC_UNONAME_URL ); + lcl_CopyOneProperty( *pDrawField, *pCellField, SC_UNONAME_REPR ); + lcl_CopyOneProperty( *pDrawField, *pCellField, SC_UNONAME_TARGET ); + } + else + xEffContent.set(xContent); + + uno::Reference<text::XText> xAggText(lcl_GetText(mxShapeAgg)); + if ( xAggText.is() ) + xAggText->insertTextContent( xRange, xEffContent, bAbsorb ); +} + +void SAL_CALL ScShapeObj::removeTextContent( const uno::Reference<text::XTextContent>& xContent ) + throw(container::NoSuchElementException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + // ScCellFieldObj can't be used here. + + uno::Reference<text::XText> xAggText(lcl_GetText(mxShapeAgg)); + if ( xAggText.is() ) + xAggText->removeTextContent( xContent ); +} + +// XSimpleText (parent of XText) +// Use own SvxUnoTextCursor subclass - everything is just passed to aggregated object + +uno::Reference<text::XTextCursor> SAL_CALL ScShapeObj::createTextCursor() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if ( mxShapeAgg.is() ) + { + // ScDrawTextCursor must be used to ensure the ScShapeObj is returned by getText + + SvxUnoTextBase* pText = SvxUnoTextBase::getImplementation( mxShapeAgg ); + if (pText) + return new ScDrawTextCursor( this, *pText ); + } + + return uno::Reference<text::XTextCursor>(); +} + +uno::Reference<text::XTextCursor> SAL_CALL ScShapeObj::createTextCursorByRange( + const uno::Reference<text::XTextRange>& aTextPosition ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if ( mxShapeAgg.is() && aTextPosition.is() ) + { + // ScDrawTextCursor must be used to ensure the ScShapeObj is returned by getText + + SvxUnoTextBase* pText = SvxUnoTextBase::getImplementation( mxShapeAgg ); + SvxUnoTextRangeBase* pRange = SvxUnoTextRangeBase::getImplementation( aTextPosition ); + if ( pText && pRange ) + { + SvxUnoTextCursor* pCursor = new ScDrawTextCursor( this, *pText ); + uno::Reference<text::XTextCursor> xCursor( pCursor ); + pCursor->SetSelection( pRange->GetSelection() ); + return xCursor; + } + } + + return uno::Reference<text::XTextCursor>(); +} + +void SAL_CALL ScShapeObj::insertString( const uno::Reference<text::XTextRange>& xRange, + const rtl::OUString& aString, sal_Bool bAbsorb ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + uno::Reference<text::XSimpleText> xAggSimpleText(lcl_GetSimpleText(mxShapeAgg)); + if ( xAggSimpleText.is() ) + xAggSimpleText->insertString( xRange, aString, bAbsorb ); + else + throw uno::RuntimeException(); +} + +void SAL_CALL ScShapeObj::insertControlCharacter( const uno::Reference<text::XTextRange>& xRange, + sal_Int16 nControlCharacter, sal_Bool bAbsorb ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + uno::Reference<text::XSimpleText> xAggSimpleText(lcl_GetSimpleText(mxShapeAgg)); + if ( xAggSimpleText.is() ) + xAggSimpleText->insertControlCharacter( xRange, nControlCharacter, bAbsorb ); + else + throw uno::RuntimeException(); +} + +// XTextRange +// (parent of XSimpleText) + +uno::Reference<text::XText> SAL_CALL ScShapeObj::getText() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return this; +} + +uno::Reference<text::XTextRange> SAL_CALL ScShapeObj::getStart() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + uno::Reference<text::XTextRange> xAggTextRange(lcl_GetTextRange(mxShapeAgg)); + if ( xAggTextRange.is() ) + return xAggTextRange->getStart(); + else + throw uno::RuntimeException(); + +// return uno::Reference<text::XTextRange>(); +} + +uno::Reference<text::XTextRange> SAL_CALL ScShapeObj::getEnd() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + uno::Reference<text::XTextRange> xAggTextRange(lcl_GetTextRange(mxShapeAgg)); + if ( xAggTextRange.is() ) + return xAggTextRange->getEnd(); + else + throw uno::RuntimeException(); + +// return uno::Reference<text::XTextRange>(); +} + +rtl::OUString SAL_CALL ScShapeObj::getString() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + uno::Reference<text::XTextRange> xAggTextRange(lcl_GetTextRange(mxShapeAgg)); + if ( xAggTextRange.is() ) + return xAggTextRange->getString(); + else + throw uno::RuntimeException(); + +// return rtl::OUString(); +} + +void SAL_CALL ScShapeObj::setString( const rtl::OUString& aText ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + uno::Reference<text::XTextRange> xAggTextRange(lcl_GetTextRange(mxShapeAgg)); + if ( xAggTextRange.is() ) + xAggTextRange->setString( aText ); + else + throw uno::RuntimeException(); +} + +// XTypeProvider + +uno::Sequence<uno::Type> SAL_CALL ScShapeObj::getTypes() throw(uno::RuntimeException) +{ + uno::Sequence< uno::Type > aBaseTypes( ScShapeObj_Base::getTypes() ); + + uno::Sequence< uno::Type > aTextTypes; + if ( bIsTextShape ) + aTextTypes = ScShapeObj_TextBase::getTypes(); + + uno::Reference<lang::XTypeProvider> xBaseProvider; + if ( mxShapeAgg.is() ) + mxShapeAgg->queryAggregation( getCppuType((uno::Reference<lang::XTypeProvider>*) 0) ) >>= xBaseProvider; + DBG_ASSERT( xBaseProvider.is(), "ScShapeObj: No XTypeProvider from aggregated shape!" ); + + uno::Sequence< uno::Type > aAggTypes; + if( xBaseProvider.is() ) + aAggTypes = xBaseProvider->getTypes(); + + return ::comphelper::concatSequences( aBaseTypes, aTextTypes, aAggTypes ); +} + +uno::Sequence<sal_Int8> SAL_CALL ScShapeObj::getImplementationId() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + // do we need to compute the implementation id for this instance? + if( !pImplementationId && mxShapeAgg.is()) + { + uno::Reference< drawing::XShape > xAggShape; + mxShapeAgg->queryAggregation( ::getCppuType((uno::Reference< drawing::XShape >*)0) ) >>= xAggShape; + + if( xAggShape.is() ) + { + const rtl::OUString aShapeType( xAggShape->getShapeType() ); + // did we already compute an implementation id for the agregated shape type? + ScShapeImplementationIdMap::iterator aIter( aImplementationIdMap.find(aShapeType ) ); + if( aIter == aImplementationIdMap.end() ) + { + // we need to create a new implementation id for this + // note: this memory is not free'd until application exists + // but since we have a fixed set of shapetypes and the + // memory will be reused this is ok. + pImplementationId = new uno::Sequence< sal_Int8 >( 16 ); + rtl_createUuid( (sal_uInt8 *) pImplementationId->getArray(), 0, sal_True ); + aImplementationIdMap[ aShapeType ] = pImplementationId; + } + else + { + // use the already computed implementation id + pImplementationId = (*aIter).second; + } + } + } + if( NULL == pImplementationId ) + { + DBG_ERROR( "Could not create an implementation id for a ScXShape!" ); + return uno::Sequence< sal_Int8 > (); + } + else + { + return *pImplementationId; + } +} + +SdrObject* ScShapeObj::GetSdrObject() const throw() +{ + if(mxShapeAgg.is()) + { + SvxShape* pShape = SvxShape::getImplementation( mxShapeAgg ); + if(pShape) + return pShape->GetSdrObject(); + } + + return NULL; +} + +#define SC_EVENTACC_ONCLICK ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OnClick" ) ) +#ifdef ISSUE66550_HLINK_FOR_SHAPES +#define SC_EVENTACC_ONACTION ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "OnAction" ) ) +#define SC_EVENTACC_URL ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "URL" ) ) +#define SC_EVENTACC_ACTION ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Action" ) ) +#endif +#define SC_EVENTACC_SCRIPT ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Script" ) ) +#define SC_EVENTACC_EVENTTYPE ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "EventType" ) ) + +typedef ::cppu::WeakImplHelper1< container::XNameReplace > ShapeUnoEventAcess_BASE; +class ShapeUnoEventAccessImpl : public ShapeUnoEventAcess_BASE +{ +private: + ScShapeObj* mpShape; + + ScMacroInfo* getInfo( BOOL bCreate = FALSE ) + { + if( mpShape ) + if( SdrObject* pObj = mpShape->GetSdrObject() ) + return ScDrawLayer::GetMacroInfo( pObj, bCreate ); + return 0; + } + +public: + ShapeUnoEventAccessImpl( ScShapeObj* pShape ): mpShape( pShape ) + { + } + + // XNameReplace + virtual void SAL_CALL replaceByName( const rtl::OUString& aName, const uno::Any& aElement ) throw(lang::IllegalArgumentException, container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException) + { + if ( !hasByName( aName ) ) + throw container::NoSuchElementException(); + uno::Sequence< beans::PropertyValue > aProperties; + aElement >>= aProperties; + const beans::PropertyValue* pProperties = aProperties.getConstArray(); + const sal_Int32 nCount = aProperties.getLength(); + sal_Int32 nIndex; + bool isEventType = false; + for( nIndex = 0; nIndex < nCount; nIndex++, pProperties++ ) + { + if ( pProperties->Name.equals( SC_EVENTACC_EVENTTYPE ) ) + { + isEventType = true; + continue; + } +#ifdef ISSUE66550_HLINK_FOR_SHAPES + if ( isEventType && ((pProperties->Name == SC_EVENTACC_SCRIPT) || (pProperties->Name == SC_EVENTACC_URL)) ) +#else + if ( isEventType && (pProperties->Name == SC_EVENTACC_SCRIPT) ) +#endif + { + rtl::OUString sValue; + if ( pProperties->Value >>= sValue ) + { + ScMacroInfo* pInfo = getInfo( TRUE ); + DBG_ASSERT( pInfo, "shape macro info could not be created!" ); + if ( !pInfo ) + break; + if ( pProperties->Name == SC_EVENTACC_SCRIPT ) + pInfo->SetMacro( sValue ); +#ifdef ISSUE66550_HLINK_FOR_SHAPES + else + pInfo->SetHlink( sValue ); +#endif + } + } + } + } + + // XNameAccess + virtual uno::Any SAL_CALL getByName( const rtl::OUString& aName ) throw(container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException) + { + uno::Sequence< beans::PropertyValue > aProperties; + ScMacroInfo* pInfo = getInfo(); + + if ( aName == SC_EVENTACC_ONCLICK ) + { + if ( pInfo && (pInfo->GetMacro().getLength() > 0) ) + { + aProperties.realloc( 2 ); + aProperties[ 0 ].Name = SC_EVENTACC_EVENTTYPE; + aProperties[ 0 ].Value <<= SC_EVENTACC_SCRIPT; + aProperties[ 1 ].Name = SC_EVENTACC_SCRIPT; + aProperties[ 1 ].Value <<= pInfo->GetMacro(); + } + } +#ifdef ISSUE66550_HLINK_FOR_SHAPES + else if( aName == SC_EVENTACC_ONACTION ) + { + if ( pInfo && (pInfo->GetHlink().getLength() > 0) ) + { + aProperties.realloc( 2 ); + aProperties[ 0 ].Name = SC_EVENTACC_EVENTTYPE; + aProperties[ 0 ].Value <<= SC_EVENTACC_ACTION; + aProperties[ 1 ].Name = SC_EVENTACC_URL; + aProperties[ 1 ].Value <<= pInfo->GetHlink(); + } + } +#endif + else + { + throw container::NoSuchElementException(); + } + + return uno::Any( aProperties ); + } + + virtual uno::Sequence< rtl::OUString > SAL_CALL getElementNames() throw(uno::RuntimeException) + { +#ifdef ISSUE66550_HLINK_FOR_SHAPES + uno::Sequence< rtl::OUString > aSeq( 2 ); +#else + uno::Sequence< rtl::OUString > aSeq( 1 ); +#endif + aSeq[ 0 ] = SC_EVENTACC_ONCLICK; +#ifdef ISSUE66550_HLINK_FOR_SHAPES + aSeq[ 1 ] = SC_EVENTACC_ONACTION; +#endif + return aSeq; + } + + virtual sal_Bool SAL_CALL hasByName( const rtl::OUString& aName ) throw(uno::RuntimeException) + { +#ifdef ISSUE66550_HLINK_FOR_SHAPES + return (aName == SC_EVENTACC_ONCLICK) || (aName == SC_EVENTACC_ONACTION); +#else + return aName == SC_EVENTACC_ONCLICK; +#endif + } + + // XElementAccess + virtual uno::Type SAL_CALL getElementType() throw(uno::RuntimeException) + { + return *SEQTYPE(::getCppuType((const uno::Sequence< beans::PropertyValue >*)0)); + } + + virtual sal_Bool SAL_CALL hasElements() throw(uno::RuntimeException) + { + // elements are always present (but contained property sequences may be empty) + return sal_True; + } +}; + +::uno::Reference< container::XNameReplace > SAL_CALL +ScShapeObj::getEvents( ) throw(uno::RuntimeException) +{ + return new ShapeUnoEventAccessImpl( this ); +} + +::rtl::OUString SAL_CALL ScShapeObj::getImplementationName( ) throw (uno::RuntimeException) +{ + return ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.sc.ScShapeObj" ) ); +} + +::sal_Bool SAL_CALL ScShapeObj::supportsService( const ::rtl::OUString& _ServiceName ) throw (uno::RuntimeException) +{ + uno::Sequence< ::rtl::OUString > aSupported( getSupportedServiceNames() ); + for ( const ::rtl::OUString* pSupported = aSupported.getConstArray(); + pSupported != aSupported.getConstArray() + aSupported.getLength(); + ++pSupported + ) + if ( _ServiceName == *pSupported ) + return sal_True; + return sal_False; +} + +uno::Sequence< ::rtl::OUString > SAL_CALL ScShapeObj::getSupportedServiceNames( ) throw (uno::RuntimeException) +{ + uno::Reference<lang::XServiceInfo> xSI; + if ( mxShapeAgg.is() ) + mxShapeAgg->queryAggregation( lang::XServiceInfo::static_type() ) >>= xSI; + + uno::Sequence< ::rtl::OUString > aSupported; + if ( xSI.is() ) + aSupported = xSI->getSupportedServiceNames(); + + aSupported.realloc( aSupported.getLength() + 1 ); + aSupported[ aSupported.getLength() - 1 ] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.Shape" ) ); + return aSupported; +} diff --git a/sc/source/ui/unoobj/srchuno.cxx b/sc/source/ui/unoobj/srchuno.cxx new file mode 100644 index 000000000000..b005d16ce482 --- /dev/null +++ b/sc/source/ui/unoobj/srchuno.cxx @@ -0,0 +1,276 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include "scitems.hxx" +#include <svl/srchitem.hxx> +#include <osl/mutex.hxx> +#include <rtl/uuid.h> + +#include "srchuno.hxx" +#include "docsh.hxx" +#include "undoblk.hxx" +#include "hints.hxx" +#include "markdata.hxx" +#include "unoguard.hxx" +#include "miscuno.hxx" +#include "unonames.hxx" + +using namespace com::sun::star; + +//------------------------------------------------------------------------ + +//! SearchWords sucht in ganzen Zellen - umbenennen ??? + +// SfxItemPropertyMapEntry nur fuer GetPropertySetInfo + +const SfxItemPropertyMapEntry* lcl_GetSearchPropertyMap() +{ + static SfxItemPropertyMapEntry aSearchPropertyMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNO_SRCHBACK), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SRCHBYROW), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SRCHCASE), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SRCHREGEXP), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SRCHSIM), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SRCHSIMADD), 0, &getCppuType((sal_Int16*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SRCHSIMEX), 0, &getCppuType((sal_Int16*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SRCHSIMREL), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SRCHSIMREM), 0, &getCppuType((sal_Int16*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SRCHSTYLES), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SRCHTYPE), 0, &getCppuType((sal_Int16*)0), 0, 0}, // enum TableSearch ist weg + {MAP_CHAR_LEN(SC_UNO_SRCHWORDS), 0, &getBooleanCppuType(), 0, 0}, + {0,0,0,0,0,0} + }; + return aSearchPropertyMap_Impl; +} + +//------------------------------------------------------------------------ + +#define SCSEARCHDESCRIPTOR_SERVICE "com.sun.star.util.SearchDescriptor" +#define SCREPLACEDESCRIPTOR_SERVICE "com.sun.star.util.ReplaceDescriptor" + +//------------------------------------------------------------------------ + +ScCellSearchObj::ScCellSearchObj() : + aPropSet(lcl_GetSearchPropertyMap()) +{ + pSearchItem = new SvxSearchItem( SCITEM_SEARCHDATA ); + // Defaults: + pSearchItem->SetWordOnly(FALSE); + pSearchItem->SetExact(FALSE); + pSearchItem->SetMatchFullHalfWidthForms(FALSE); + pSearchItem->SetUseAsianOptions(FALSE); // or all asian bits would have to be handled + pSearchItem->SetBackward(FALSE); + pSearchItem->SetSelection(FALSE); + pSearchItem->SetRegExp(FALSE); + pSearchItem->SetPattern(FALSE); + pSearchItem->SetLevenshtein(FALSE); + pSearchItem->SetLEVRelaxed(FALSE); + pSearchItem->SetLEVOther(2); + pSearchItem->SetLEVShorter(2); + pSearchItem->SetLEVLonger(2); + // Calc-Flags + pSearchItem->SetRowDirection(FALSE); + pSearchItem->SetCellType(SVX_SEARCHIN_FORMULA); + + // Selection-Flag wird beim Aufruf gesetzt +} + +ScCellSearchObj::~ScCellSearchObj() +{ + delete pSearchItem; +} + +// XSearchDescriptor + +rtl::OUString SAL_CALL ScCellSearchObj::getSearchString() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return pSearchItem->GetSearchString(); +} + +void SAL_CALL ScCellSearchObj::setSearchString( const rtl::OUString& aString ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + pSearchItem->SetSearchString( aString ); +} + +// XReplaceDescriptor + +rtl::OUString SAL_CALL ScCellSearchObj::getReplaceString() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return pSearchItem->GetReplaceString(); +} + +void SAL_CALL ScCellSearchObj::setReplaceString( const rtl::OUString& aReplaceString ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + pSearchItem->SetReplaceString( aReplaceString ); +} + +// XPropertySet + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScCellSearchObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef( + new SfxItemPropertySetInfo( aPropSet.getPropertyMap() )); + return aRef; +} + +void SAL_CALL ScCellSearchObj::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aString(aPropertyName); + + if (aString.EqualsAscii( SC_UNO_SRCHBACK )) pSearchItem->SetBackward( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if (aString.EqualsAscii( SC_UNO_SRCHBYROW )) pSearchItem->SetRowDirection( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if (aString.EqualsAscii( SC_UNO_SRCHCASE )) pSearchItem->SetExact( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if (aString.EqualsAscii( SC_UNO_SRCHREGEXP )) pSearchItem->SetRegExp( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if (aString.EqualsAscii( SC_UNO_SRCHSIM )) pSearchItem->SetLevenshtein( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if (aString.EqualsAscii( SC_UNO_SRCHSIMREL )) pSearchItem->SetLEVRelaxed( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if (aString.EqualsAscii( SC_UNO_SRCHSTYLES )) pSearchItem->SetPattern( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if (aString.EqualsAscii( SC_UNO_SRCHWORDS )) pSearchItem->SetWordOnly( ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if (aString.EqualsAscii( SC_UNO_SRCHSIMADD )) pSearchItem->SetLEVLonger( ScUnoHelpFunctions::GetInt16FromAny( aValue ) ); + else if (aString.EqualsAscii( SC_UNO_SRCHSIMEX )) pSearchItem->SetLEVOther( ScUnoHelpFunctions::GetInt16FromAny( aValue ) ); + else if (aString.EqualsAscii( SC_UNO_SRCHSIMREM )) pSearchItem->SetLEVShorter( ScUnoHelpFunctions::GetInt16FromAny( aValue ) ); + else if (aString.EqualsAscii( SC_UNO_SRCHTYPE )) pSearchItem->SetCellType( ScUnoHelpFunctions::GetInt16FromAny( aValue ) ); +} + +uno::Any SAL_CALL ScCellSearchObj::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aString(aPropertyName); + uno::Any aRet; + + if (aString.EqualsAscii( SC_UNO_SRCHBACK )) ScUnoHelpFunctions::SetBoolInAny( aRet, pSearchItem->GetBackward() ); + else if (aString.EqualsAscii( SC_UNO_SRCHBYROW )) ScUnoHelpFunctions::SetBoolInAny( aRet, pSearchItem->GetRowDirection() ); + else if (aString.EqualsAscii( SC_UNO_SRCHCASE )) ScUnoHelpFunctions::SetBoolInAny( aRet, pSearchItem->GetExact() ); + else if (aString.EqualsAscii( SC_UNO_SRCHREGEXP )) ScUnoHelpFunctions::SetBoolInAny( aRet, pSearchItem->GetRegExp() ); + else if (aString.EqualsAscii( SC_UNO_SRCHSIM )) ScUnoHelpFunctions::SetBoolInAny( aRet, pSearchItem->IsLevenshtein() ); + else if (aString.EqualsAscii( SC_UNO_SRCHSIMREL )) ScUnoHelpFunctions::SetBoolInAny( aRet, pSearchItem->IsLEVRelaxed() ); + else if (aString.EqualsAscii( SC_UNO_SRCHSTYLES )) ScUnoHelpFunctions::SetBoolInAny( aRet, pSearchItem->GetPattern() ); + else if (aString.EqualsAscii( SC_UNO_SRCHWORDS )) ScUnoHelpFunctions::SetBoolInAny( aRet, pSearchItem->GetWordOnly() ); + else if (aString.EqualsAscii( SC_UNO_SRCHSIMADD )) aRet <<= (sal_Int16) pSearchItem->GetLEVLonger(); + else if (aString.EqualsAscii( SC_UNO_SRCHSIMEX )) aRet <<= (sal_Int16) pSearchItem->GetLEVOther(); + else if (aString.EqualsAscii( SC_UNO_SRCHSIMREM )) aRet <<= (sal_Int16) pSearchItem->GetLEVShorter(); + else if (aString.EqualsAscii( SC_UNO_SRCHTYPE )) aRet <<= (sal_Int16) pSearchItem->GetCellType(); + + return aRet; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScCellSearchObj ) + +// XServiceInfo + +rtl::OUString SAL_CALL ScCellSearchObj::getImplementationName() throw(uno::RuntimeException) +{ + return rtl::OUString::createFromAscii( "ScCellSearchObj" ); +} + +sal_Bool SAL_CALL ScCellSearchObj::supportsService( const rtl::OUString& rServiceName ) + throw(uno::RuntimeException) +{ + String aServiceStr(rServiceName); + return aServiceStr.EqualsAscii( SCSEARCHDESCRIPTOR_SERVICE ) || + aServiceStr.EqualsAscii( SCREPLACEDESCRIPTOR_SERVICE ); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScCellSearchObj::getSupportedServiceNames() + throw(uno::RuntimeException) +{ + uno::Sequence<rtl::OUString> aRet(2); + rtl::OUString* pArray = aRet.getArray(); + pArray[0] = rtl::OUString::createFromAscii( SCSEARCHDESCRIPTOR_SERVICE ); + pArray[1] = rtl::OUString::createFromAscii( SCREPLACEDESCRIPTOR_SERVICE ); + return aRet; +} + +// XUnoTunnel + +sal_Int64 SAL_CALL ScCellSearchObj::getSomething( + const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); + } + return 0; +} + +// static +const uno::Sequence<sal_Int8>& ScCellSearchObj::getUnoTunnelId() +{ + static uno::Sequence<sal_Int8> * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +// static +ScCellSearchObj* ScCellSearchObj::getImplementation( + const uno::Reference<util::XSearchDescriptor> xObj ) +{ + ScCellSearchObj* pRet = NULL; + uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); + if (xUT.is()) + pRet = reinterpret_cast<ScCellSearchObj*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId()))); + return pRet; +} + + +//------------------------------------------------------------------------ + + + + + diff --git a/sc/source/ui/unoobj/styleuno.cxx b/sc/source/ui/unoobj/styleuno.cxx new file mode 100644 index 000000000000..50aecbe7f2e3 --- /dev/null +++ b/sc/source/ui/unoobj/styleuno.cxx @@ -0,0 +1,2140 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include "scitems.hxx" +#include <editeng/memberids.hrc> +#include <svx/algitem.hxx> +#include <editeng/boxitem.hxx> +#include <editeng/langitem.hxx> +#include <editeng/numitem.hxx> +#include <svx/pageitem.hxx> +#include <editeng/pbinitem.hxx> +#include <svx/unomid.hxx> +#include <editeng/unonrule.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/printer.hxx> +#include <vcl/virdev.hxx> +#include <svl/itempool.hxx> +#include <svl/itemset.hxx> +#include <svl/intitem.hxx> +#include <svl/zformat.hxx> +#include <rtl/uuid.h> + +#include <com/sun/star/table/BorderLine.hpp> +#include <com/sun/star/table/CellVertJustify.hpp> +#include <com/sun/star/table/TableBorder.hpp> +#include <com/sun/star/table/ShadowFormat.hpp> +#include <com/sun/star/table/CellHoriJustify.hpp> +#include <com/sun/star/table/CellOrientation.hpp> +#include <com/sun/star/style/PageStyleLayout.hpp> +#include <com/sun/star/style/GraphicLocation.hpp> +#include <com/sun/star/sheet/XHeaderFooterContent.hpp> +#include <com/sun/star/util/CellProtection.hpp> +#include <com/sun/star/awt/FontSlant.hpp> +#include <com/sun/star/awt/Size.hpp> +#include <com/sun/star/lang/Locale.hpp> +#include <com/sun/star/beans/PropertyAttribute.hpp> + +#include "styleuno.hxx" +#include "docsh.hxx" +#include "attrib.hxx" +#include "stlpool.hxx" +#include "docpool.hxx" +#include "unoguard.hxx" +#include "miscuno.hxx" +#include "convuno.hxx" +#include "tablink.hxx" +#include "unonames.hxx" +#include "unowids.hxx" +#include "globstr.hrc" +#include "cellsuno.hxx" + +using namespace ::com::sun::star; + +//------------------------------------------------------------------------ + +const SfxItemPropertySet* lcl_GetCellStyleSet() +{ + static SfxItemPropertyMapEntry aCellStyleMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNONAME_ASIANVERT),ATTR_VERTICAL_ASIAN,&getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_BOTTBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, BOTTOM_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_CELLBACK), ATTR_BACKGROUND, &::getCppuType((const sal_Int32*)0), 0, MID_BACK_COLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CELLPRO), ATTR_PROTECTION, &::getCppuType((const util::CellProtection*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CCOLOR), ATTR_FONT_COLOR, &::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_COUTL), ATTR_FONT_CONTOUR, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CCROSS), ATTR_FONT_CROSSEDOUT,&::getBooleanCppuType(), 0, MID_CROSSED_OUT }, + {MAP_CHAR_LEN(SC_UNONAME_CEMPHAS), ATTR_FONT_EMPHASISMARK,&getCppuType((sal_Int16*)0), 0, MID_EMPHASIS }, + {MAP_CHAR_LEN(SC_UNONAME_CFONT), ATTR_FONT, &::getCppuType((const sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNONAME_CFCHARS), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFCHARS), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFCHARS), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_CHAR_SET }, + {MAP_CHAR_LEN(SC_UNONAME_CFFAMIL), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFFAMIL), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFFAMIL), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_FAMILY }, + {MAP_CHAR_LEN(SC_UNONAME_CFNAME), ATTR_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFNAME), ATTR_CJK_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFNAME), ATTR_CTL_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_FAMILY_NAME }, + {MAP_CHAR_LEN(SC_UNONAME_CFPITCH), ATTR_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFPITCH), ATTR_CJK_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFPITCH), ATTR_CTL_FONT, &getCppuType((sal_Int16*)0), 0, MID_FONT_PITCH }, + {MAP_CHAR_LEN(SC_UNONAME_CFSTYLE), ATTR_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNO_CJK_CFSTYLE), ATTR_CJK_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNO_CTL_CFSTYLE), ATTR_CTL_FONT, &getCppuType((rtl::OUString*)0), 0, MID_FONT_STYLE_NAME }, + {MAP_CHAR_LEN(SC_UNONAME_CHEIGHT), ATTR_FONT_HEIGHT, &::getCppuType((const float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_CJK_CHEIGHT), ATTR_CJK_FONT_HEIGHT,&::getCppuType((const float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_CTL_CHEIGHT), ATTR_CTL_FONT_HEIGHT,&::getCppuType((const float*)0), 0, MID_FONTHEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_CLOCAL), ATTR_FONT_LANGUAGE, &::getCppuType((const lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNO_CJK_CLOCAL), ATTR_CJK_FONT_LANGUAGE,&::getCppuType((const lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNO_CTL_CLOCAL), ATTR_CTL_FONT_LANGUAGE,&::getCppuType((const lang::Locale*)0), 0, MID_LANG_LOCALE }, + {MAP_CHAR_LEN(SC_UNONAME_COVER), ATTR_FONT_OVERLINE, &::getCppuType((const sal_Int16*)0), 0, MID_TL_STYLE }, + {MAP_CHAR_LEN(SC_UNONAME_COVRLCOL), ATTR_FONT_OVERLINE, &getCppuType((sal_Int32*)0), 0, MID_TL_COLOR }, + {MAP_CHAR_LEN(SC_UNONAME_COVRLHAS), ATTR_FONT_OVERLINE, &getBooleanCppuType(), 0, MID_TL_HASCOLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CPOST), ATTR_FONT_POSTURE, &::getCppuType((const awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNO_CJK_CPOST), ATTR_CJK_FONT_POSTURE,&::getCppuType((const awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNO_CTL_CPOST), ATTR_CTL_FONT_POSTURE,&::getCppuType((const awt::FontSlant*)0), 0, MID_POSTURE }, + {MAP_CHAR_LEN(SC_UNONAME_CRELIEF), ATTR_FONT_RELIEF, &getCppuType((sal_Int16*)0), 0, MID_RELIEF }, + {MAP_CHAR_LEN(SC_UNONAME_CSHADD), ATTR_FONT_SHADOWED, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CSTRIKE), ATTR_FONT_CROSSEDOUT,&getCppuType((sal_Int16*)0), 0, MID_CROSS_OUT }, + {MAP_CHAR_LEN(SC_UNONAME_CUNDER), ATTR_FONT_UNDERLINE,&::getCppuType((const sal_Int16*)0), 0, MID_TL_STYLE }, + {MAP_CHAR_LEN(SC_UNONAME_CUNDLCOL), ATTR_FONT_UNDERLINE,&getCppuType((sal_Int32*)0), 0, MID_TL_COLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CUNDLHAS), ATTR_FONT_UNDERLINE,&getBooleanCppuType(), 0, MID_TL_HASCOLOR }, + {MAP_CHAR_LEN(SC_UNONAME_CWEIGHT), ATTR_FONT_WEIGHT, &::getCppuType((const float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNO_CJK_CWEIGHT), ATTR_CJK_FONT_WEIGHT,&::getCppuType((const float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNO_CTL_CWEIGHT), ATTR_CTL_FONT_WEIGHT,&::getCppuType((const float*)0), 0, MID_WEIGHT }, + {MAP_CHAR_LEN(SC_UNONAME_CWORDMOD), ATTR_FONT_WORDLINE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_DIAGONAL_BLTR), ATTR_BORDER_BLTR, &::getCppuType((const table::BorderLine*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_DIAGONAL_TLBR), ATTR_BORDER_TLBR, &::getCppuType((const table::BorderLine*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_DISPNAME), SC_WID_UNO_DISPNAME,&::getCppuType((rtl::OUString*)0), beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLHJUS), ATTR_HOR_JUSTIFY, &::getCppuType((const table::CellHoriJustify*)0), 0, MID_HORJUST_HORJUST }, + {MAP_CHAR_LEN(SC_UNONAME_CELLTRAN), ATTR_BACKGROUND, &::getBooleanCppuType(), 0, MID_GRAPHIC_TRANSPARENT }, + {MAP_CHAR_LEN(SC_UNONAME_WRAP), ATTR_LINEBREAK, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_LEFTBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, LEFT_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_NUMFMT), ATTR_VALUE_FORMAT, &::getCppuType((const sal_Int32*)0), 0, 0 }, +// {MAP_CHAR_LEN(SC_UNONAME_NUMRULES), SC_WID_UNO_NUMRULES,&getCppuType((const uno::Reference<container::XIndexReplace>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLORI), ATTR_STACKED, &::getCppuType((const table::CellOrientation*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PADJUST), ATTR_HOR_JUSTIFY, &::getCppuType((const sal_Int16*)0), 0, MID_HORJUST_ADJUST }, + {MAP_CHAR_LEN(SC_UNONAME_PBMARGIN), ATTR_MARGIN, &::getCppuType((const sal_Int32*)0), 0, MID_MARGIN_LO_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PINDENT), ATTR_INDENT, &::getCppuType((const sal_Int16*)0), 0, 0 }, //! CONVERT_TWIPS + {MAP_CHAR_LEN(SC_UNONAME_PISCHDIST),ATTR_SCRIPTSPACE, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PISFORBID),ATTR_FORBIDDEN_RULES,&::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PISHANG), ATTR_HANGPUNCTUATION,&::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PISHYPHEN),ATTR_HYPHENATE, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_PLASTADJ), ATTR_HOR_JUSTIFY, &::getCppuType((const sal_Int16*)0), 0, MID_HORJUST_ADJUST }, + {MAP_CHAR_LEN(SC_UNONAME_PLMARGIN), ATTR_MARGIN, &::getCppuType((const sal_Int32*)0), 0, MID_MARGIN_L_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PRMARGIN), ATTR_MARGIN, &::getCppuType((const sal_Int32*)0), 0, MID_MARGIN_R_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_PTMARGIN), ATTR_MARGIN, &::getCppuType((const sal_Int32*)0), 0, MID_MARGIN_UP_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_RIGHTBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, RIGHT_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_ROTANG), ATTR_ROTATE_VALUE, &::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_ROTREF), ATTR_ROTATE_MODE, &::getCppuType((const table::CellVertJustify*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_SHADOW), ATTR_SHADOW, &::getCppuType((const table::ShadowFormat*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_SHRINK_TO_FIT), ATTR_SHRINKTOFIT, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_TBLBORD), SC_WID_UNO_TBLBORD, &::getCppuType((const table::TableBorder*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_TOPBORDER),ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, TOP_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_USERDEF), ATTR_USERDEF, &getCppuType((uno::Reference<container::XNameContainer>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_CELLVJUS), ATTR_VER_JUSTIFY, &::getCppuType((const table::CellVertJustify*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_WRITING), ATTR_WRITINGDIR, &getCppuType((sal_Int16*)0), 0, 0 }, + {0,0,0,0,0,0} + }; + static SfxItemPropertySet aCellStyleSet_Impl( aCellStyleMap_Impl ); + return &aCellStyleSet_Impl; +} + +// Map mit allen Seitenattributen, incl. Kopf-/Fusszeilenattribute + +const SfxItemPropertySet * lcl_GetPageStyleSet() +{ + static SfxItemPropertyMapEntry aPageStyleMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNO_PAGE_BACKCOLOR), ATTR_BACKGROUND, &::getCppuType((const sal_Int32*)0), 0, MID_BACK_COLOR }, + {MAP_CHAR_LEN(SC_UNO_PAGE_GRAPHICFILT), ATTR_BACKGROUND, &::getCppuType((const ::rtl::OUString*)0), 0, MID_GRAPHIC_FILTER }, + {MAP_CHAR_LEN(SC_UNO_PAGE_GRAPHICLOC), ATTR_BACKGROUND, &::getCppuType((const style::GraphicLocation*)0), 0, MID_GRAPHIC_POSITION }, + {MAP_CHAR_LEN(SC_UNO_PAGE_GRAPHICURL), ATTR_BACKGROUND, &::getCppuType((const ::rtl::OUString*)0), 0, MID_GRAPHIC_URL }, + {MAP_CHAR_LEN(SC_UNO_PAGE_BACKTRANS), ATTR_BACKGROUND, &::getBooleanCppuType(), 0, MID_GRAPHIC_TRANSPARENT }, + {MAP_CHAR_LEN(OLD_UNO_PAGE_BACKCOLOR), ATTR_BACKGROUND, &::getCppuType((const sal_Int32*)0), 0, MID_BACK_COLOR }, + {MAP_CHAR_LEN(SC_UNO_PAGE_BORDERDIST), ATTR_BORDER, &::getCppuType((const sal_Int32*)0), 0, BORDER_DISTANCE | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_BOTTBORDER), ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, BOTTOM_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_BOTTBRDDIST), ATTR_BORDER, &::getCppuType((const sal_Int32*)0), 0, BOTTOM_BORDER_DISTANCE | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_BOTTMARGIN), ATTR_ULSPACE, &::getCppuType((const sal_Int32*)0), 0, MID_LO_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_CENTERHOR), ATTR_PAGE_HORCENTER,&::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_CENTERVER), ATTR_PAGE_VERCENTER,&::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_DISPNAME), SC_WID_UNO_DISPNAME,&::getCppuType((rtl::OUString*)0), beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FIRSTPAGE), ATTR_PAGE_FIRSTPAGENO,&::getCppuType((const sal_Int16*)0), 0, 0 }, +// + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRBACKCOL), SC_WID_UNO_FOOTERSET,&::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRGRFFILT), SC_WID_UNO_FOOTERSET,&::getCppuType((const ::rtl::OUString*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRGRFLOC), SC_WID_UNO_FOOTERSET,&::getCppuType((const style::GraphicLocation*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRGRFURL), SC_WID_UNO_FOOTERSET,&::getCppuType((const ::rtl::OUString*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRBACKTRAN), SC_WID_UNO_FOOTERSET,&::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(OLD_UNO_PAGE_FTRBACKCOL), SC_WID_UNO_FOOTERSET,&::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRBODYDIST), SC_WID_UNO_FOOTERSET,&::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRBRDDIST), SC_WID_UNO_FOOTERSET,&::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRBOTTBOR), SC_WID_UNO_FOOTERSET,&::getCppuType((const table::BorderLine*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRBOTTBDIS), SC_WID_UNO_FOOTERSET,&::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(OLD_UNO_PAGE_FTRDYNAMIC), SC_WID_UNO_FOOTERSET,&::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRHEIGHT), SC_WID_UNO_FOOTERSET,&::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRDYNAMIC), SC_WID_UNO_FOOTERSET,&::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRON), SC_WID_UNO_FOOTERSET,&::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRSHARED), SC_WID_UNO_FOOTERSET,&::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRLEFTBOR), SC_WID_UNO_FOOTERSET,&::getCppuType((const table::BorderLine*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRLEFTBDIS), SC_WID_UNO_FOOTERSET,&::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRLEFTMAR), SC_WID_UNO_FOOTERSET,&::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(OLD_UNO_PAGE_FTRON), SC_WID_UNO_FOOTERSET,&::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRRIGHTBOR), SC_WID_UNO_FOOTERSET,&::getCppuType((const table::BorderLine*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRRIGHTBDIS),SC_WID_UNO_FOOTERSET,&::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRRIGHTMAR), SC_WID_UNO_FOOTERSET,&::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRSHADOW), SC_WID_UNO_FOOTERSET,&::getCppuType((const table::ShadowFormat*)0), 0, 0 }, + {MAP_CHAR_LEN(OLD_UNO_PAGE_FTRSHARED), SC_WID_UNO_FOOTERSET,&::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRTOPBOR), SC_WID_UNO_FOOTERSET,&::getCppuType((const table::BorderLine*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRTOPBDIS), SC_WID_UNO_FOOTERSET,&::getCppuType((const sal_Int32*)0), 0, 0 }, +// + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRBACKCOL), SC_WID_UNO_HEADERSET,&::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRGRFFILT), SC_WID_UNO_HEADERSET,&::getCppuType((const ::rtl::OUString*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRGRFLOC), SC_WID_UNO_HEADERSET,&::getCppuType((const style::GraphicLocation*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRGRFURL), SC_WID_UNO_HEADERSET,&::getCppuType((const ::rtl::OUString*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRBACKTRAN), SC_WID_UNO_HEADERSET,&::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(OLD_UNO_PAGE_HDRBACKCOL), SC_WID_UNO_HEADERSET,&::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRBODYDIST), SC_WID_UNO_HEADERSET,&::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRBRDDIST), SC_WID_UNO_HEADERSET,&::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRBOTTBOR), SC_WID_UNO_HEADERSET,&::getCppuType((const table::BorderLine*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRBOTTBDIS), SC_WID_UNO_HEADERSET,&::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(OLD_UNO_PAGE_HDRDYNAMIC), SC_WID_UNO_HEADERSET,&::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRHEIGHT), SC_WID_UNO_HEADERSET,&::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRDYNAMIC), SC_WID_UNO_HEADERSET,&::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRON), SC_WID_UNO_HEADERSET,&::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRSHARED), SC_WID_UNO_HEADERSET,&::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRLEFTBOR), SC_WID_UNO_HEADERSET,&::getCppuType((const table::BorderLine*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRLEFTBDIS), SC_WID_UNO_HEADERSET,&::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRLEFTMAR), SC_WID_UNO_HEADERSET,&::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(OLD_UNO_PAGE_HDRON), SC_WID_UNO_HEADERSET,&::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRRIGHTBOR), SC_WID_UNO_HEADERSET,&::getCppuType((const table::BorderLine*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRRIGHTBDIS),SC_WID_UNO_HEADERSET,&::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRRIGHTMAR), SC_WID_UNO_HEADERSET,&::getCppuType((const sal_Int32*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRSHADOW), SC_WID_UNO_HEADERSET,&::getCppuType((const table::ShadowFormat*)0), 0, 0 }, + {MAP_CHAR_LEN(OLD_UNO_PAGE_HDRSHARED), SC_WID_UNO_HEADERSET,&::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRTOPBOR), SC_WID_UNO_HEADERSET,&::getCppuType((const table::BorderLine*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRTOPBDIS), SC_WID_UNO_HEADERSET,&::getCppuType((const sal_Int32*)0), 0, 0 }, +// + {MAP_CHAR_LEN(SC_UNO_PAGE_HEIGHT), ATTR_PAGE_SIZE, &::getCppuType((const sal_Int32*)0), 0, MID_SIZE_HEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(OLD_UNO_PAGE_BACKTRANS), ATTR_BACKGROUND, &::getBooleanCppuType(), 0, MID_GRAPHIC_TRANSPARENT }, + {MAP_CHAR_LEN(SC_UNO_PAGE_LANDSCAPE), ATTR_PAGE, &::getBooleanCppuType(), 0, MID_PAGE_ORIENTATION }, + {MAP_CHAR_LEN(SC_UNO_PAGE_LEFTBORDER), ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, LEFT_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_LEFTBRDDIST), ATTR_BORDER, &::getCppuType((const sal_Int32*)0), 0, LEFT_BORDER_DISTANCE | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_LEFTMARGIN), ATTR_LRSPACE, &::getCppuType((const sal_Int32*)0), 0, MID_L_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_LEFTFTRCONT), ATTR_PAGE_FOOTERLEFT,&::getCppuType((const uno::Reference< sheet::XHeaderFooterContent >*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_LEFTHDRCONT), ATTR_PAGE_HEADERLEFT,&::getCppuType((const uno::Reference< sheet::XHeaderFooterContent >*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_NUMBERTYPE), ATTR_PAGE, &::getCppuType((const sal_Int16*)0), 0, MID_PAGE_NUMTYPE }, + {MAP_CHAR_LEN(SC_UNO_PAGE_SCALEVAL), ATTR_PAGE_SCALE, &::getCppuType((const sal_Int16*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_SYTLELAYOUT), ATTR_PAGE, &::getCppuType((const style::PageStyleLayout*)0), 0, MID_PAGE_LAYOUT }, + {MAP_CHAR_LEN(SC_UNO_PAGE_PRINTANNOT), ATTR_PAGE_NOTES, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_PRINTCHARTS), ATTR_PAGE_CHARTS, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_PRINTDOWN), ATTR_PAGE_TOPDOWN, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_PRINTDRAW), ATTR_PAGE_DRAWINGS, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_PRINTFORMUL), ATTR_PAGE_FORMULAS, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_PRINTGRID), ATTR_PAGE_GRID, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_PRINTHEADER), ATTR_PAGE_HEADERS, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_PRINTOBJS), ATTR_PAGE_OBJECTS, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_PRINTZERO), ATTR_PAGE_NULLVALS, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_PAPERTRAY), ATTR_PAGE_PAPERBIN, &::getCppuType((const ::rtl::OUString*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_RIGHTBORDER), ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, RIGHT_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_RIGHTBRDDIST),ATTR_BORDER, &::getCppuType((const sal_Int32*)0), 0, RIGHT_BORDER_DISTANCE | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_RIGHTMARGIN), ATTR_LRSPACE, &::getCppuType((const sal_Int32*)0), 0, MID_R_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_RIGHTFTRCON), ATTR_PAGE_FOOTERRIGHT,&::getCppuType((const uno::Reference< sheet::XHeaderFooterContent >*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_RIGHTHDRCON), ATTR_PAGE_HEADERRIGHT,&::getCppuType((const uno::Reference< sheet::XHeaderFooterContent >*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_SCALETOPAG), ATTR_PAGE_SCALETOPAGES,&::getCppuType((const sal_Int16*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_SCALETOX), ATTR_PAGE_SCALETO, &::getCppuType((const sal_Int16*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_SCALETOY), ATTR_PAGE_SCALETO, &::getCppuType((const sal_Int16*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_SHADOWFORM), ATTR_SHADOW, &::getCppuType((const table::ShadowFormat*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_SIZE), ATTR_PAGE_SIZE, &::getCppuType((const awt::Size*)0), 0, MID_SIZE_SIZE | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_TOPBORDER), ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, TOP_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_TOPBRDDIST), ATTR_BORDER, &::getCppuType((const sal_Int32*)0), 0, TOP_BORDER_DISTANCE | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_TOPMARGIN), ATTR_ULSPACE, &::getCppuType((const sal_Int32*)0), 0, MID_UP_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(OLD_UNO_PAGE_FTRBACKTRAN),SC_WID_UNO_FOOTERSET,&::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(OLD_UNO_PAGE_HDRBACKTRAN),SC_WID_UNO_HEADERSET,&::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNONAME_USERDEF), ATTR_USERDEF, &getCppuType((uno::Reference<container::XNameContainer>*)0), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_WIDTH), ATTR_PAGE_SIZE, &::getCppuType((const sal_Int32*)0), 0, MID_SIZE_WIDTH | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNONAME_WRITING), ATTR_WRITINGDIR, &getCppuType((sal_Int16*)0), 0, 0 }, + {0,0,0,0,0,0} + }; + static SfxItemPropertySet aPageStyleSet_Impl( aPageStyleMap_Impl ); + return &aPageStyleSet_Impl; +} + +// Map mit Inhalten des Header-Item-Sets + +const SfxItemPropertyMap* lcl_GetHeaderStyleMap() +{ + static SfxItemPropertyMapEntry aHeaderStyleMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRBACKCOL), ATTR_BACKGROUND, &::getCppuType((const sal_Int32*)0), 0, MID_BACK_COLOR }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRGRFFILT), ATTR_BACKGROUND, &::getCppuType((const ::rtl::OUString*)0), 0, MID_GRAPHIC_FILTER }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRGRFLOC), ATTR_BACKGROUND, &::getCppuType((const style::GraphicLocation*)0), 0, MID_GRAPHIC_POSITION }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRGRFURL), ATTR_BACKGROUND, &::getCppuType((const ::rtl::OUString*)0), 0, MID_GRAPHIC_URL }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRBACKTRAN), ATTR_BACKGROUND, &::getBooleanCppuType(), 0, MID_GRAPHIC_TRANSPARENT }, + {MAP_CHAR_LEN(OLD_UNO_PAGE_HDRBACKCOL), ATTR_BACKGROUND, &::getCppuType((const sal_Int32*)0), 0, MID_BACK_COLOR }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRBODYDIST), ATTR_ULSPACE, &::getCppuType((const sal_Int32*)0), 0, MID_LO_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRBRDDIST), ATTR_BORDER, &::getCppuType((const sal_Int32*)0), 0, BORDER_DISTANCE | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRBOTTBOR), ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, BOTTOM_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRBOTTBDIS), ATTR_BORDER, &::getCppuType((const sal_Int32*)0), 0, BOTTOM_BORDER_DISTANCE | CONVERT_TWIPS }, + {MAP_CHAR_LEN(OLD_UNO_PAGE_HDRDYNAMIC), ATTR_PAGE_DYNAMIC, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRHEIGHT), ATTR_PAGE_SIZE, &::getCppuType((const sal_Int32*)0), 0, MID_SIZE_HEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRDYNAMIC), ATTR_PAGE_DYNAMIC, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRON), ATTR_PAGE_ON, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRSHARED), ATTR_PAGE_SHARED, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRLEFTBOR), ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, LEFT_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRLEFTBDIS), ATTR_BORDER, &::getCppuType((const sal_Int32*)0), 0, LEFT_BORDER_DISTANCE | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRLEFTMAR), ATTR_LRSPACE, &::getCppuType((const sal_Int32*)0), 0, MID_L_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(OLD_UNO_PAGE_HDRON), ATTR_PAGE_ON, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRRIGHTBOR), ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, RIGHT_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRRIGHTBDIS),ATTR_BORDER, &::getCppuType((const sal_Int32*)0), 0, RIGHT_BORDER_DISTANCE | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRRIGHTMAR), ATTR_LRSPACE, &::getCppuType((const sal_Int32*)0), 0, MID_R_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRSHADOW), ATTR_SHADOW, &::getCppuType((const table::ShadowFormat*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(OLD_UNO_PAGE_HDRSHARED), ATTR_PAGE_SHARED, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRTOPBOR), ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, TOP_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_HDRTOPBDIS), ATTR_BORDER, &::getCppuType((const sal_Int32*)0), 0, TOP_BORDER_DISTANCE | CONVERT_TWIPS }, + {MAP_CHAR_LEN(OLD_UNO_PAGE_HDRBACKTRAN),ATTR_BACKGROUND, &::getBooleanCppuType(), 0, MID_GRAPHIC_TRANSPARENT }, + {0,0,0,0,0,0} + }; + static SfxItemPropertyMap aHeaderStyleMap( aHeaderStyleMap_Impl ); + return &aHeaderStyleMap; +} + +// Map mit Inhalten des Footer-Item-Sets + +const SfxItemPropertyMap* lcl_GetFooterStyleMap() +{ + static SfxItemPropertyMapEntry aFooterStyleMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRBACKCOL), ATTR_BACKGROUND, &::getCppuType((const sal_Int32*)0), 0, MID_BACK_COLOR }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRGRFFILT), ATTR_BACKGROUND, &::getCppuType((const ::rtl::OUString*)0), 0, MID_GRAPHIC_FILTER }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRGRFLOC), ATTR_BACKGROUND, &::getCppuType((const style::GraphicLocation*)0), 0, MID_GRAPHIC_POSITION }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRGRFURL), ATTR_BACKGROUND, &::getCppuType((const ::rtl::OUString*)0), 0, MID_GRAPHIC_URL }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRBACKTRAN), ATTR_BACKGROUND, &::getBooleanCppuType(), 0, MID_GRAPHIC_TRANSPARENT }, + {MAP_CHAR_LEN(OLD_UNO_PAGE_FTRBACKCOL), ATTR_BACKGROUND, &::getCppuType((const sal_Int32*)0), 0, MID_BACK_COLOR }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRBODYDIST), ATTR_ULSPACE, &::getCppuType((const sal_Int32*)0), 0, MID_UP_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRBRDDIST), ATTR_BORDER, &::getCppuType((const sal_Int32*)0), 0, BORDER_DISTANCE | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRBOTTBOR), ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, BOTTOM_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRBOTTBDIS), ATTR_BORDER, &::getCppuType((const sal_Int32*)0), 0, BOTTOM_BORDER_DISTANCE | CONVERT_TWIPS }, + {MAP_CHAR_LEN(OLD_UNO_PAGE_FTRDYNAMIC), ATTR_PAGE_DYNAMIC, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRHEIGHT), ATTR_PAGE_SIZE, &::getCppuType((const sal_Int32*)0), 0, MID_SIZE_HEIGHT | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRDYNAMIC), ATTR_PAGE_DYNAMIC, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRON), ATTR_PAGE_ON, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRSHARED), ATTR_PAGE_SHARED, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRLEFTBOR), ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, LEFT_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRLEFTBDIS), ATTR_BORDER, &::getCppuType((const sal_Int32*)0), 0, LEFT_BORDER_DISTANCE | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRLEFTMAR), ATTR_LRSPACE, &::getCppuType((const sal_Int32*)0), 0, MID_L_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(OLD_UNO_PAGE_FTRON), ATTR_PAGE_ON, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRRIGHTBOR), ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, RIGHT_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRRIGHTBDIS),ATTR_BORDER, &::getCppuType((const sal_Int32*)0), 0, RIGHT_BORDER_DISTANCE | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRRIGHTMAR), ATTR_LRSPACE, &::getCppuType((const sal_Int32*)0), 0, MID_R_MARGIN | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRSHADOW), ATTR_SHADOW, &::getCppuType((const table::ShadowFormat*)0), 0, 0 | CONVERT_TWIPS }, + {MAP_CHAR_LEN(OLD_UNO_PAGE_FTRSHARED), ATTR_PAGE_SHARED, &::getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRTOPBOR), ATTR_BORDER, &::getCppuType((const table::BorderLine*)0), 0, TOP_BORDER | CONVERT_TWIPS }, + {MAP_CHAR_LEN(SC_UNO_PAGE_FTRTOPBDIS), ATTR_BORDER, &::getCppuType((const sal_Int32*)0), 0, TOP_BORDER_DISTANCE | CONVERT_TWIPS }, + {MAP_CHAR_LEN(OLD_UNO_PAGE_FTRBACKTRAN),ATTR_BACKGROUND, &::getBooleanCppuType(), 0, MID_GRAPHIC_TRANSPARENT }, + {0,0,0,0,0,0} + }; + static SfxItemPropertyMap aFooterStyleMap( aFooterStyleMap_Impl ); + return &aFooterStyleMap; +} + + +//------------------------------------------------------------------------ + +// Index-Access auf die Style-Typen: 0 = Cell, 1 = Page + +#define SC_STYLE_FAMILY_COUNT 2 + +#define SC_FAMILYNAME_CELL "CellStyles" +#define SC_FAMILYNAME_PAGE "PageStyles" + +static UINT16 aStyleFamilyTypes[SC_STYLE_FAMILY_COUNT] = { SFX_STYLE_FAMILY_PARA, SFX_STYLE_FAMILY_PAGE }; + +//------------------------------------------------------------------------ + +//! diese Funktionen in einen allgemeinen Header verschieben +inline long TwipsToHMM(long nTwips) { return (nTwips * 127 + 36) / 72; } +inline long HMMToTwips(long nHMM) { return (nHMM * 72 + 63) / 127; } + +//------------------------------------------------------------------------ + +#define SCSTYLE_SERVICE "com.sun.star.style.Style" +#define SCCELLSTYLE_SERVICE "com.sun.star.style.CellStyle" +#define SCPAGESTYLE_SERVICE "com.sun.star.style.PageStyle" + +SC_SIMPLE_SERVICE_INFO( ScStyleFamiliesObj, "ScStyleFamiliesObj", "com.sun.star.style.StyleFamilies" ) +SC_SIMPLE_SERVICE_INFO( ScStyleFamilyObj, "ScStyleFamilyObj", "com.sun.star.style.StyleFamily" ) + +//------------------------------------------------------------------------ + +#define SC_PAPERBIN_DEFAULTNAME "[From printer settings]" + +//------------------------------------------------------------------------ + +// conversion programmatic <-> display (visible) name +// currently, the core always has the visible names +// the api is required to use programmatic names for default styles +// these programmatic names must never change! + +#define SC_STYLE_PROG_STANDARD "Default" +#define SC_STYLE_PROG_RESULT "Result" +#define SC_STYLE_PROG_RESULT1 "Result2" +#define SC_STYLE_PROG_HEADLINE "Heading" +#define SC_STYLE_PROG_HEADLINE1 "Heading1" +#define SC_STYLE_PROG_REPORT "Report" + +struct ScDisplayNameMap +{ + String aDispName; + String aProgName; +}; + +const ScDisplayNameMap* lcl_GetStyleNameMap( UINT16 nType ) +{ + if ( nType == SFX_STYLE_FAMILY_PARA ) + { + static BOOL bCellMapFilled = FALSE; + static ScDisplayNameMap aCellMap[6]; + if ( !bCellMapFilled ) + { + aCellMap[0].aDispName = ScGlobal::GetRscString( STR_STYLENAME_STANDARD ); + aCellMap[0].aProgName = String::CreateFromAscii( SC_STYLE_PROG_STANDARD ); + + aCellMap[1].aDispName = ScGlobal::GetRscString( STR_STYLENAME_RESULT ); + aCellMap[1].aProgName = String::CreateFromAscii( SC_STYLE_PROG_RESULT ); + + aCellMap[2].aDispName = ScGlobal::GetRscString( STR_STYLENAME_RESULT1 ); + aCellMap[2].aProgName = String::CreateFromAscii( SC_STYLE_PROG_RESULT1 ); + + aCellMap[3].aDispName = ScGlobal::GetRscString( STR_STYLENAME_HEADLINE ); + aCellMap[3].aProgName = String::CreateFromAscii( SC_STYLE_PROG_HEADLINE ); + + aCellMap[4].aDispName = ScGlobal::GetRscString( STR_STYLENAME_HEADLINE1 ); + aCellMap[4].aProgName = String::CreateFromAscii( SC_STYLE_PROG_HEADLINE1 ); + + // last entry remains empty + + bCellMapFilled = TRUE; + } + return aCellMap; + } + else if ( nType == SFX_STYLE_FAMILY_PAGE ) + { + static BOOL bPageMapFilled = FALSE; + static ScDisplayNameMap aPageMap[3]; + if ( !bPageMapFilled ) + { + aPageMap[0].aDispName = ScGlobal::GetRscString( STR_STYLENAME_STANDARD ); + aPageMap[0].aProgName = String::CreateFromAscii( SC_STYLE_PROG_STANDARD ); + + aPageMap[1].aDispName = ScGlobal::GetRscString( STR_STYLENAME_REPORT ); + aPageMap[1].aProgName = String::CreateFromAscii( SC_STYLE_PROG_REPORT ); + + // last entry remains empty + + bPageMapFilled = TRUE; + } + return aPageMap; + } + DBG_ERROR("invalid family"); + return NULL; +} + +// programmatic name suffix for display names that match other programmatic names +// is " (user)" including a space + +#define SC_SUFFIX_USER " (user)" +#define SC_SUFFIX_USER_LEN 7 + +BOOL lcl_EndsWithUser( const String& rString ) +{ + const sal_Unicode *pChar = rString.GetBuffer(); + xub_StrLen nLen = rString.Len(); + return nLen >= SC_SUFFIX_USER_LEN && + pChar[nLen-7] == ' ' && + pChar[nLen-6] == '(' && + pChar[nLen-5] == 'u' && + pChar[nLen-4] == 's' && + pChar[nLen-3] == 'e' && + pChar[nLen-2] == 'r' && + pChar[nLen-1] == ')'; +} + +// static +String ScStyleNameConversion::DisplayToProgrammaticName( const String& rDispName, UINT16 nType ) +{ + BOOL bDisplayIsProgrammatic = FALSE; + + const ScDisplayNameMap* pNames = lcl_GetStyleNameMap( nType ); + if (pNames) + { + do + { + if (pNames->aDispName == rDispName) + return pNames->aProgName; + else if (pNames->aProgName == rDispName) + bDisplayIsProgrammatic = TRUE; // display name matches any programmatic name + } + while( (++pNames)->aDispName.Len() ); + } + + if ( bDisplayIsProgrammatic || lcl_EndsWithUser( rDispName ) ) + { + // add the (user) suffix if the display name matches any style's programmatic name + // or if it already contains the suffix + + String aRet(rDispName); + aRet.AppendAscii( RTL_CONSTASCII_STRINGPARAM( SC_SUFFIX_USER ) ); + return aRet; + } + + return rDispName; +} + +// static +String ScStyleNameConversion::ProgrammaticToDisplayName( const String& rProgName, UINT16 nType ) +{ + if ( lcl_EndsWithUser( rProgName ) ) + { + // remove the (user) suffix, don't compare to map entries + return rProgName.Copy( 0, rProgName.Len() - SC_SUFFIX_USER_LEN ); + } + + const ScDisplayNameMap* pNames = lcl_GetStyleNameMap( nType ); + if (pNames) + { + do + { + if (pNames->aProgName == rProgName) + return pNames->aDispName; + } + while( (++pNames)->aDispName.Len() ); + } + return rProgName; +} + +//------------------------------------------------------------------------ + +sal_Bool lcl_AnyTabProtected( ScDocument& rDoc ) +{ + SCTAB nTabCount = rDoc.GetTableCount(); + for (SCTAB i=0; i<nTabCount; i++) + if (rDoc.IsTabProtected(i)) + return sal_True; + return sal_False; +} + +//------------------------------------------------------------------------ + +ScStyleFamiliesObj::ScStyleFamiliesObj(ScDocShell* pDocSh) : + pDocShell( pDocSh ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScStyleFamiliesObj::~ScStyleFamiliesObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScStyleFamiliesObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + // Referenz-Update interessiert hier nicht + + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +// XStyleFamilies + +ScStyleFamilyObj*ScStyleFamiliesObj::GetObjectByType_Impl(UINT16 nType) const +{ + if ( pDocShell ) + { + if ( nType == SFX_STYLE_FAMILY_PARA ) + return new ScStyleFamilyObj( pDocShell, SFX_STYLE_FAMILY_PARA ); + else if ( nType == SFX_STYLE_FAMILY_PAGE ) + return new ScStyleFamilyObj( pDocShell, SFX_STYLE_FAMILY_PAGE ); + } + DBG_ERROR("getStyleFamilyByType: keine DocShell oder falscher Typ"); + return NULL; +} + +ScStyleFamilyObj* ScStyleFamiliesObj::GetObjectByIndex_Impl(UINT32 nIndex) const +{ + if ( nIndex < SC_STYLE_FAMILY_COUNT ) + return GetObjectByType_Impl(aStyleFamilyTypes[nIndex]); + + return NULL; // ungueltiger Index +} + +ScStyleFamilyObj* ScStyleFamiliesObj::GetObjectByName_Impl(const rtl::OUString& aName) const +{ + if ( pDocShell ) + { + String aNameStr( aName ); + if ( aNameStr.EqualsAscii( SC_FAMILYNAME_CELL ) ) + return new ScStyleFamilyObj( pDocShell, SFX_STYLE_FAMILY_PARA ); + else if ( aNameStr.EqualsAscii( SC_FAMILYNAME_PAGE ) ) + return new ScStyleFamilyObj( pDocShell, SFX_STYLE_FAMILY_PAGE ); + } + // no assertion - called directly from getByName + return NULL; +} + +// container::XIndexAccess + +sal_Int32 SAL_CALL ScStyleFamiliesObj::getCount() throw(uno::RuntimeException) +{ + return SC_STYLE_FAMILY_COUNT; +} + +uno::Any SAL_CALL ScStyleFamiliesObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference< container::XNameContainer > xFamily(GetObjectByIndex_Impl(nIndex)); + if (xFamily.is()) + return uno::makeAny(xFamily); + else + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +uno::Type SAL_CALL ScStyleFamiliesObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ::getCppuType((const uno::Reference< container::XNameContainer >*)0); // muss zu getByIndex passen +} + +sal_Bool SAL_CALL ScStyleFamiliesObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +// container::XNameAccess + +uno::Any SAL_CALL ScStyleFamiliesObj::getByName( const rtl::OUString& aName ) + throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference< container::XNameContainer > xFamily(GetObjectByName_Impl(aName)); + if (xFamily.is()) + return uno::makeAny(xFamily); + else + throw container::NoSuchElementException(); +// return uno::Any(); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScStyleFamiliesObj::getElementNames() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Sequence<rtl::OUString> aNames(SC_STYLE_FAMILY_COUNT); + rtl::OUString* pNames = aNames.getArray(); + pNames[0] = rtl::OUString::createFromAscii( SC_FAMILYNAME_CELL ); + pNames[1] = rtl::OUString::createFromAscii( SC_FAMILYNAME_PAGE ); + return aNames; +} + +sal_Bool SAL_CALL ScStyleFamiliesObj::hasByName( const rtl::OUString& aName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aNameStr( aName ); + return ( aNameStr.EqualsAscii( SC_FAMILYNAME_CELL ) || aNameStr.EqualsAscii( SC_FAMILYNAME_PAGE ) ); +} + +// style::XStyleLoader + +void SAL_CALL ScStyleFamiliesObj::loadStylesFromURL( const rtl::OUString& aURL, + const uno::Sequence<beans::PropertyValue>& aOptions ) + throw(io::IOException, uno::RuntimeException) +{ + //! use aOptions (like Writer) + //! set flag to disable filter option dialogs when importing + + String aFilter; // empty - detect + String aFiltOpt; + ScDocumentLoader aLoader( aURL, aFilter, aFiltOpt ); + + ScDocShell* pSource = aLoader.GetDocShell(); + if ( pSource && pDocShell ) + { + // collect options + + BOOL bLoadReplace = TRUE; // defaults + BOOL bLoadCellStyles = TRUE; + BOOL bLoadPageStyles = TRUE; + + const beans::PropertyValue* pPropArray = aOptions.getConstArray(); + long nPropCount = aOptions.getLength(); + for (long i = 0; i < nPropCount; i++) + { + const beans::PropertyValue& rProp = pPropArray[i]; + String aPropName(rProp.Name); + + if (aPropName.EqualsAscii( SC_UNONAME_OVERWSTL )) + bLoadReplace = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value ); + else if (aPropName.EqualsAscii( SC_UNONAME_LOADCELL )) + bLoadCellStyles = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value ); + else if (aPropName.EqualsAscii( SC_UNONAME_LOADPAGE )) + bLoadPageStyles = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value ); + } + + pDocShell->LoadStylesArgs( *pSource, bLoadReplace, bLoadCellStyles, bLoadPageStyles ); + pDocShell->SetDocumentModified(); // paint is inside LoadStyles + } +} + +uno::Sequence<beans::PropertyValue> SAL_CALL ScStyleFamiliesObj::getStyleLoaderOptions() + throw(uno::RuntimeException) +{ + // return defaults for options (?) + + uno::Sequence<beans::PropertyValue> aSequence(3); + beans::PropertyValue* pArray = aSequence.getArray(); + + pArray[0].Name = rtl::OUString::createFromAscii( SC_UNONAME_OVERWSTL ); + ScUnoHelpFunctions::SetBoolInAny( pArray[0].Value, TRUE ); + + pArray[1].Name = rtl::OUString::createFromAscii( SC_UNONAME_LOADCELL ); + ScUnoHelpFunctions::SetBoolInAny( pArray[1].Value, TRUE ); + + pArray[2].Name = rtl::OUString::createFromAscii( SC_UNONAME_LOADPAGE ); + ScUnoHelpFunctions::SetBoolInAny( pArray[2].Value, TRUE ); + + return aSequence; +} + +//------------------------------------------------------------------------ + +ScStyleFamilyObj::ScStyleFamilyObj(ScDocShell* pDocSh, SfxStyleFamily eFam) : + pDocShell( pDocSh ), + eFamily( eFam ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScStyleFamilyObj::~ScStyleFamilyObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScStyleFamilyObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + // Referenz-Update interessiert hier nicht + + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +// XStyleFamily + +ScStyleObj* ScStyleFamilyObj::GetObjectByIndex_Impl(UINT32 nIndex) +{ + if ( pDocShell ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool(); + + SfxStyleSheetIterator aIter( pStylePool, eFamily ); + if ( nIndex < aIter.Count() ) + { + SfxStyleSheetBase* pStyle = aIter[(USHORT)nIndex]; + if ( pStyle ) + { + return new ScStyleObj( pDocShell, eFamily, String (pStyle->GetName()) ); + } + } + } + return NULL; +} + +ScStyleObj* ScStyleFamilyObj::GetObjectByName_Impl(const rtl::OUString& aName) +{ + if ( pDocShell ) + { + String aString(aName); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool(); + if ( pStylePool->Find( aString, eFamily ) ) + return new ScStyleObj( pDocShell, eFamily, aString ); + } + return NULL; +} + +void SAL_CALL ScStyleFamilyObj::insertByName( const rtl::OUString& aName, const uno::Any& aElement ) + throw(lang::IllegalArgumentException, container::ElementExistException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + sal_Bool bDone = sal_False; + // Reflection muss nicht uno::XInterface sein, kann auch irgendein Interface sein... + uno::Reference< uno::XInterface > xInterface(aElement, uno::UNO_QUERY); + if ( xInterface.is() ) + { + ScStyleObj* pStyleObj = ScStyleObj::getImplementation( xInterface ); + if ( pStyleObj && pStyleObj->GetFamily() == eFamily && + !pStyleObj->IsInserted() ) // noch nicht eingefuegt? + { + String aNameStr(ScStyleNameConversion::ProgrammaticToDisplayName( aName, sal::static_int_cast<UINT16>(eFamily) )); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool(); + + //! DocFunc-Funktion?? + //! Undo ????????????? + + if ( !pStylePool->Find( aNameStr, eFamily ) ) // noch nicht vorhanden + { + (void)pStylePool->Make( aNameStr, eFamily, SFXSTYLEBIT_USERDEF ); + + if ( eFamily == SFX_STYLE_FAMILY_PARA && !pDoc->IsImportingXML() ) + pDoc->GetPool()->CellStyleCreated( aNameStr ); + + pStyleObj->InitDoc( pDocShell, aNameStr ); // Objekt kann benutzt werden + + pDocShell->SetDocumentModified(); // verwendet wird der neue Style noch nicht + bDone = sal_True; + } + else + throw container::ElementExistException(); + } + } + + if (!bDone) + { + // other errors are handled above + throw lang::IllegalArgumentException(); + } +} + +void SAL_CALL ScStyleFamilyObj::replaceByName( const rtl::OUString& aName, const uno::Any& aElement ) + throw(lang::IllegalArgumentException, container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + //! zusammenfassen? + removeByName( aName ); + insertByName( aName, aElement ); +} + +void SAL_CALL ScStyleFamilyObj::removeByName( const rtl::OUString& aName ) + throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + BOOL bFound = FALSE; + if ( pDocShell ) + { + String aString(ScStyleNameConversion::ProgrammaticToDisplayName( aName, sal::static_int_cast<UINT16>(eFamily) )); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool(); + + //! DocFunc-Funktion?? + //! Undo ????????????? + + SfxStyleSheetBase* pStyle = pStylePool->Find( aString, eFamily ); + if (pStyle) + { + bFound = TRUE; + if ( eFamily == SFX_STYLE_FAMILY_PARA ) + { + // wie ScViewFunc::RemoveStyleSheetInUse + VirtualDevice aVDev; + Point aLogic = aVDev.LogicToPixel( Point(1000,1000), MAP_TWIP ); + double nPPTX = aLogic.X() / 1000.0; + double nPPTY = aLogic.Y() / 1000.0; + Fraction aZoom(1,1); + pDoc->StyleSheetChanged( pStyle, sal_False, &aVDev, nPPTX, nPPTY, aZoom, aZoom ); + pDocShell->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID|PAINT_LEFT ); + pDocShell->SetDocumentModified(); + + pStylePool->Remove( pStyle ); + + //! InvalidateAttribs(); // Bindings-Invalidate + } + else + { + if ( pDoc->RemovePageStyleInUse( aString ) ) + pDocShell->PageStyleModified( ScGlobal::GetRscString(STR_STYLENAME_STANDARD), sal_True ); + + pStylePool->Remove( pStyle ); + + SfxBindings* pBindings = pDocShell->GetViewBindings(); + if (pBindings) + pBindings->Invalidate( SID_STYLE_FAMILY4 ); + pDocShell->SetDocumentModified(); + } + } + } + + if (!bFound) + throw container::NoSuchElementException(); +} + +// container::XIndexAccess + +sal_Int32 SAL_CALL ScStyleFamilyObj::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( pDocShell ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool(); + + SfxStyleSheetIterator aIter( pStylePool, eFamily ); + return aIter.Count(); + } + return 0; +} + +uno::Any SAL_CALL ScStyleFamilyObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference< style::XStyle > xObj(GetObjectByIndex_Impl(nIndex)); + if (xObj.is()) + return uno::makeAny(xObj); + else + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +uno::Type SAL_CALL ScStyleFamilyObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ::getCppuType((const uno::Reference< style::XStyle >*)0); // muss zu getByIndex passen +} + +sal_Bool SAL_CALL ScStyleFamilyObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +// container::XNameAccess + +uno::Any SAL_CALL ScStyleFamilyObj::getByName( const rtl::OUString& aName ) + throw(container::NoSuchElementException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference< style::XStyle > xObj( + GetObjectByName_Impl( ScStyleNameConversion::ProgrammaticToDisplayName( aName, sal::static_int_cast<UINT16>(eFamily) ) )); + if (xObj.is()) + return uno::makeAny(xObj); + else + throw container::NoSuchElementException(); +// return uno::Any(); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScStyleFamilyObj::getElementNames() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( pDocShell ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool(); + + SfxStyleSheetIterator aIter( pStylePool, eFamily ); + UINT16 nCount = aIter.Count(); + + String aName; + uno::Sequence<rtl::OUString> aSeq(nCount); + rtl::OUString* pAry = aSeq.getArray(); + SfxStyleSheetBase* pStyle = aIter.First(); + UINT16 nPos = 0; + while (pStyle) + { + DBG_ASSERT( nPos<nCount, "Anzahl durcheinandergekommen" ); + if (nPos<nCount) + pAry[nPos++] = ScStyleNameConversion::DisplayToProgrammaticName( + pStyle->GetName(), sal::static_int_cast<UINT16>(eFamily) ); + pStyle = aIter.Next(); + } + return aSeq; + } + return uno::Sequence<rtl::OUString>(); +} + +sal_Bool SAL_CALL ScStyleFamilyObj::hasByName( const rtl::OUString& aName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( pDocShell ) + { + String aString(ScStyleNameConversion::ProgrammaticToDisplayName( aName, sal::static_int_cast<UINT16>(eFamily) )); + + ScDocument* pDoc = pDocShell->GetDocument(); + ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool(); + if ( pStylePool->Find( aString, eFamily ) ) + return sal_True; + } + return sal_False; +} + +// XPropertySet + +uno::Reference< beans::XPropertySetInfo > SAL_CALL ScStyleFamilyObj::getPropertySetInfo( ) throw (uno::RuntimeException) +{ + OSL_ENSURE( 0, "###unexpected!" ); + return uno::Reference< beans::XPropertySetInfo >(); +} + +void SAL_CALL ScStyleFamilyObj::setPropertyValue( const ::rtl::OUString&, const uno::Any& ) throw (beans::UnknownPropertyException, beans::PropertyVetoException, lang::IllegalArgumentException, lang::WrappedTargetException, uno::RuntimeException) +{ + OSL_ENSURE( 0, "###unexpected!" ); +} + +uno::Any SAL_CALL ScStyleFamilyObj::getPropertyValue( const ::rtl::OUString& sPropertyName ) throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + uno::Any aRet; + + if ( sPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("DisplayName") ) ) + { + ScUnoGuard aGuard; + sal_uInt32 nResId = 0; + switch ( eFamily ) + { + case SFX_STYLE_FAMILY_PARA: + nResId = STR_STYLE_FAMILY_CELL; break; + case SFX_STYLE_FAMILY_PAGE: + nResId = STR_STYLE_FAMILY_PAGE; break; + default: + OSL_ENSURE( 0, "ScStyleFamilyObj::getPropertyValue(): invalid family" ); + } + if ( nResId > 0 ) + { + ::rtl::OUString sDisplayName( ScGlobal::GetRscString( static_cast< USHORT >( nResId ) ) ); + aRet = uno::makeAny( sDisplayName ); + } + } + else + { + throw beans::UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("unknown property: ") ) + sPropertyName, static_cast<OWeakObject *>(this) ); + } + + return aRet; +} + +void SAL_CALL ScStyleFamilyObj::addPropertyChangeListener( const ::rtl::OUString&, const uno::Reference< beans::XPropertyChangeListener >& ) throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + OSL_ENSURE( 0, "###unexpected!" ); +} + +void SAL_CALL ScStyleFamilyObj::removePropertyChangeListener( const ::rtl::OUString&, const uno::Reference< beans::XPropertyChangeListener >& ) throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + OSL_ENSURE( 0, "###unexpected!" ); +} + +void SAL_CALL ScStyleFamilyObj::addVetoableChangeListener( const ::rtl::OUString&, const uno::Reference< beans::XVetoableChangeListener >& ) throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + OSL_ENSURE( 0, "###unexpected!" ); +} + +void SAL_CALL ScStyleFamilyObj::removeVetoableChangeListener( const ::rtl::OUString&, const uno::Reference< beans::XVetoableChangeListener >& ) throw (beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException) +{ + OSL_ENSURE( 0, "###unexpected!" ); +} + +//------------------------------------------------------------------------ + +// Default-ctor wird fuer die Reflection gebraucht + +//UNUSED2008-05 ScStyleObj::ScStyleObj() : +//UNUSED2008-05 aPropSet( lcl_GetCellStyleMap() ), +//UNUSED2008-05 pDocShell( NULL ), +//UNUSED2008-05 eFamily( SFX_STYLE_FAMILY_PARA ) +//UNUSED2008-05 { +//UNUSED2008-05 } + +ScStyleObj::ScStyleObj(ScDocShell* pDocSh, SfxStyleFamily eFam, const String& rName) : + pPropSet( (eFam == SFX_STYLE_FAMILY_PARA) ? lcl_GetCellStyleSet() : lcl_GetPageStyleSet() ), + pDocShell( pDocSh ), + eFamily( eFam ), + aStyleName( rName ) +{ + // pDocShell ist Null, wenn per ServiceProvider erzeugt + + if (pDocShell) + pDocShell->GetDocument()->AddUnoObject(*this); +} + +void ScStyleObj::InitDoc( ScDocShell* pNewDocSh, const String& rNewName ) +{ + if ( pNewDocSh && !pDocShell ) + { + aStyleName = rNewName; + pDocShell = pNewDocSh; + pDocShell->GetDocument()->AddUnoObject(*this); + } +} + +ScStyleObj::~ScStyleObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +// XUnoTunnel + +sal_Int64 SAL_CALL ScStyleObj::getSomething( + const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); + } + return 0; +} + +// static +const uno::Sequence<sal_Int8>& ScStyleObj::getUnoTunnelId() +{ + static uno::Sequence<sal_Int8> * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +// static +ScStyleObj* ScStyleObj::getImplementation( + const uno::Reference<uno::XInterface> xObj ) +{ + ScStyleObj* pRet = NULL; + uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); + if (xUT.is()) + pRet = reinterpret_cast<ScStyleObj*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId()))); + return pRet; +} + +void ScStyleObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + // Referenz-Update interessiert hier nicht + + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + { + pDocShell = NULL; // ungueltig geworden + } +} + +SfxStyleSheetBase* ScStyleObj::GetStyle_Impl() +{ + if ( pDocShell ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool(); + return pStylePool->Find( aStyleName, eFamily ); + } + return NULL; +} + +// style::XStyle + +sal_Bool SAL_CALL ScStyleObj::isUserDefined() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + SfxStyleSheetBase* pStyle = GetStyle_Impl(); + if (pStyle) + return pStyle->IsUserDefined(); + return sal_False; +} + +sal_Bool SAL_CALL ScStyleObj::isInUse() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + SfxStyleSheetBase* pStyle = GetStyle_Impl(); + if (pStyle) + return pStyle->IsUsed(); + return sal_False; +} + +rtl::OUString SAL_CALL ScStyleObj::getParentStyle() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + SfxStyleSheetBase* pStyle = GetStyle_Impl(); + if (pStyle) + return ScStyleNameConversion::DisplayToProgrammaticName( pStyle->GetParent(), sal::static_int_cast<UINT16>(eFamily) ); + return rtl::OUString(); +} + +void SAL_CALL ScStyleObj::setParentStyle( const rtl::OUString& rParentStyle ) + throw(container::NoSuchElementException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + SfxStyleSheetBase* pStyle = GetStyle_Impl(); + if (pStyle) + { + // #70909# cell styles cannot be modified if any sheet is protected + if ( eFamily == SFX_STYLE_FAMILY_PARA && lcl_AnyTabProtected( *pDocShell->GetDocument() ) ) + return; //! exception? + + //! DocFunc-Funktion?? + //! Undo ????????????? + + String aString(ScStyleNameConversion::ProgrammaticToDisplayName( rParentStyle, sal::static_int_cast<UINT16>(eFamily) )); + sal_Bool bOk = pStyle->SetParent( aString ); + if (bOk) + { + // wie bei setPropertyValue + + ScDocument* pDoc = pDocShell->GetDocument(); + if ( eFamily == SFX_STYLE_FAMILY_PARA ) + { + // Zeilenhoehen anpassen... + + VirtualDevice aVDev; + Point aLogic = aVDev.LogicToPixel( Point(1000,1000), MAP_TWIP ); + double nPPTX = aLogic.X() / 1000.0; + double nPPTY = aLogic.Y() / 1000.0; + Fraction aZoom(1,1); + pDoc->StyleSheetChanged( pStyle, sal_False, &aVDev, nPPTX, nPPTY, aZoom, aZoom ); + + pDocShell->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID|PAINT_LEFT ); + pDocShell->SetDocumentModified(); + } + else + { + //! ModifyStyleSheet am Dokument (alte Werte merken) + + pDocShell->PageStyleModified( aStyleName, sal_True ); + } + } + } +} + +// container::XNamed + +rtl::OUString SAL_CALL ScStyleObj::getName() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + SfxStyleSheetBase* pStyle = GetStyle_Impl(); + if (pStyle) + return ScStyleNameConversion::DisplayToProgrammaticName( pStyle->GetName(), sal::static_int_cast<UINT16>(eFamily) ); + return rtl::OUString(); +} + +void SAL_CALL ScStyleObj::setName( const rtl::OUString& aNewName ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + SfxStyleSheetBase* pStyle = GetStyle_Impl(); + if (pStyle) + { + // #71225# cell styles cannot be renamed if any sheet is protected + if ( eFamily == SFX_STYLE_FAMILY_PARA && lcl_AnyTabProtected( *pDocShell->GetDocument() ) ) + return; //! exception? + + //! DocFunc-Funktion?? + //! Undo ????????????? + + String aString(aNewName); + sal_Bool bOk = pStyle->SetName( aString ); + if (bOk) + { + aStyleName = aString; //! notify other objects for this style? + + ScDocument* pDoc = pDocShell->GetDocument(); + if ( eFamily == SFX_STYLE_FAMILY_PARA && !pDoc->IsImportingXML() ) + pDoc->GetPool()->CellStyleCreated( aString ); + + // Zellvorlagen = 2, Seitenvorlagen = 4 + UINT16 nId = ( eFamily == SFX_STYLE_FAMILY_PARA ) ? + SID_STYLE_FAMILY2 : SID_STYLE_FAMILY4; + SfxBindings* pBindings = pDocShell->GetViewBindings(); + if (pBindings) + { + pBindings->Invalidate( nId ); + pBindings->Invalidate( SID_STYLE_APPLY ); + } + } + } +} + +// static +uno::Reference<container::XIndexReplace> ScStyleObj::CreateEmptyNumberingRules() +{ + SvxNumRule aRule( 0, 0, TRUE ); // nothing supported + return SvxCreateNumRule( &aRule ); +} + +// beans::XPropertyState + +const SfxItemSet* ScStyleObj::GetStyleItemSet_Impl( const ::rtl::OUString& rPropName, + const SfxItemPropertySimpleEntry*& rpResultEntry ) +{ + //! OUString as argument? + + SfxStyleSheetBase* pStyle = GetStyle_Impl(); + if (pStyle) + { + const SfxItemPropertySimpleEntry* pEntry = NULL; + if ( eFamily == SFX_STYLE_FAMILY_PAGE ) + { + pEntry = lcl_GetHeaderStyleMap()->getByName( rPropName ); + if ( pEntry ) // only item-wids in header/footer map + { + rpResultEntry = pEntry; + return &((const SvxSetItem&)pStyle->GetItemSet().Get(ATTR_PAGE_HEADERSET)).GetItemSet(); + } + pEntry = lcl_GetFooterStyleMap()->getByName( rPropName ); + if ( pEntry ) // only item-wids in header/footer map + { + rpResultEntry = pEntry; + return &((const SvxSetItem&)pStyle->GetItemSet().Get(ATTR_PAGE_FOOTERSET)).GetItemSet(); + } + } + pEntry = pPropSet->getPropertyMap()->getByName( rPropName ); + if ( pEntry ) + { + rpResultEntry = pEntry; + return &pStyle->GetItemSet(); + } + } + + rpResultEntry = NULL; + return NULL; +} + +beans::PropertyState SAL_CALL ScStyleObj::getPropertyState( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + beans::PropertyState eRet = beans::PropertyState_DIRECT_VALUE; + + const SfxItemPropertySimpleEntry* pResultEntry = NULL; + const SfxItemSet* pItemSet = GetStyleItemSet_Impl( aPropertyName, pResultEntry ); + + if ( pItemSet && pResultEntry ) + { + USHORT nWhich = pResultEntry->nWID; + if ( nWhich == SC_WID_UNO_TBLBORD ) + { + nWhich = ATTR_BORDER; + } + if ( IsScItemWid( nWhich ) ) + { + SfxItemState eState = pItemSet->GetItemState( nWhich, sal_False ); + +// // if no rotate value is set, look at orientation +// //! also for a fixed value of 0 (in case orientation is ambiguous)? +// if ( nWhich == ATTR_ROTATE_VALUE && eState == SFX_ITEM_DEFAULT ) +// eState = pItemSet->GetItemState( ATTR_ORIENTATION, sal_False ); + + if ( eState == SFX_ITEM_SET ) + eRet = beans::PropertyState_DIRECT_VALUE; + else if ( eState == SFX_ITEM_DEFAULT ) + eRet = beans::PropertyState_DEFAULT_VALUE; + else if ( eState == SFX_ITEM_DONTCARE ) + eRet = beans::PropertyState_AMBIGUOUS_VALUE; // kann eigentlich nicht sein... + else + { + DBG_ERROR("unbekannter ItemState"); + } + } + } + return eRet; +} + +uno::Sequence<beans::PropertyState> SAL_CALL ScStyleObj::getPropertyStates( + const uno::Sequence<rtl::OUString>& aPropertyNames ) + throw(beans::UnknownPropertyException, uno::RuntimeException) +{ + // duemmliche Default-Implementierung: alles einzeln per getPropertyState holen + //! sollte optimiert werden! + + ScUnoGuard aGuard; + const rtl::OUString* pNames = aPropertyNames.getConstArray(); + uno::Sequence<beans::PropertyState> aRet(aPropertyNames.getLength()); + beans::PropertyState* pStates = aRet.getArray(); + for(sal_Int32 i = 0; i < aPropertyNames.getLength(); i++) + pStates[i] = getPropertyState(pNames[i]); + return aRet; +} + +void SAL_CALL ScStyleObj::setPropertyToDefault( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + const SfxItemPropertyMap* pMap = pPropSet->getPropertyMap(); + const SfxItemPropertySimpleEntry* pEntry = pMap->getByName( aPropertyName ); + if ( !pEntry ) + throw beans::UnknownPropertyException(); + + SetOnePropertyValue( aPropertyName, pEntry, NULL ); +} + +uno::Any SAL_CALL ScStyleObj::getPropertyDefault( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Any aAny; + + const SfxItemPropertySimpleEntry* pResultEntry = NULL; + const SfxItemSet* pStyleSet = GetStyleItemSet_Impl( aPropertyName, pResultEntry ); + + if ( pStyleSet && pResultEntry ) + { + USHORT nWhich = pResultEntry->nWID; + + if ( IsScItemWid( nWhich ) ) + { + // Default ist Default vom ItemPool, nicht vom Standard-Style, + // damit es zu setPropertyToDefault passt + SfxItemSet aEmptySet( *pStyleSet->GetPool(), pStyleSet->GetRanges() ); + // #65253# Default-Items mit falscher Slot-ID funktionieren im SfxItemPropertySet3 nicht + //! Slot-IDs aendern... + if ( aEmptySet.GetPool()->GetSlotId(nWhich) == nWhich && + aEmptySet.GetItemState(nWhich, sal_False) == SFX_ITEM_DEFAULT ) + { + aEmptySet.Put( aEmptySet.Get( nWhich ) ); + } + const SfxItemSet* pItemSet = &aEmptySet; + + switch ( nWhich ) // fuer Item-Spezial-Behandlungen + { + case ATTR_VALUE_FORMAT: + // default has no language set + aAny <<= sal_Int32( ((const SfxUInt32Item&)pItemSet->Get(nWhich)).GetValue() ); + break; + case ATTR_INDENT: + aAny <<= sal_Int16( TwipsToHMM(((const SfxUInt16Item&) + pItemSet->Get(nWhich)).GetValue()) ); + break; + case ATTR_PAGE_SCALE: + case ATTR_PAGE_SCALETOPAGES: + case ATTR_PAGE_FIRSTPAGENO: + aAny <<= sal_Int16( ((const SfxUInt16Item&)pItemSet->Get(nWhich)).GetValue() ); + break; + case ATTR_PAGE_CHARTS: + case ATTR_PAGE_OBJECTS: + case ATTR_PAGE_DRAWINGS: + //! sal_Bool-MID fuer ScViewObjectModeItem definieren? + aAny <<= sal_Bool( ((const ScViewObjectModeItem&)pItemSet->Get(nWhich)). + GetValue() == VOBJ_MODE_SHOW ); + break; + case ATTR_PAGE_SCALETO: + { + const ScPageScaleToItem aItem((const ScPageScaleToItem&)pItemSet->Get(nWhich)); + if (aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SC_UNO_PAGE_SCALETOX ))) + aAny = uno::makeAny(static_cast<sal_Int16>(aItem.GetWidth())); + else + aAny = uno::makeAny(static_cast<sal_Int16>(aItem.GetHeight())); + } + break; + default: + pPropSet->getPropertyValue( *pResultEntry, *pItemSet, aAny ); + } + } + else if ( IsScUnoWid( nWhich ) ) + { + SfxItemSet aEmptySet( *pStyleSet->GetPool(), pStyleSet->GetRanges() ); + const SfxItemSet* pItemSet = &aEmptySet; + switch ( nWhich ) + { + case SC_WID_UNO_TBLBORD: + { + const SfxPoolItem* pItem = &pItemSet->Get( ATTR_BORDER ); + if ( pItem ) + { + SvxBoxItem aOuter( *( static_cast<const SvxBoxItem*>( pItem ) ) ); + SvxBoxInfoItem aInner( ATTR_BORDER_INNER ); + table::TableBorder aBorder; + ScHelperFunctions::FillTableBorder( aBorder, aOuter, aInner ); + aBorder.IsHorizontalLineValid = sal_False; + aBorder.IsVerticalLineValid = sal_False; + aBorder.IsDistanceValid = sal_False; + aAny <<= aBorder; + } + } + break; + } + } + } + return aAny; +} + +// XMultiPropertySet + +void SAL_CALL ScStyleObj::setPropertyValues( const uno::Sequence< rtl::OUString >& aPropertyNames, + const uno::Sequence< uno::Any >& aValues ) + throw (beans::PropertyVetoException, lang::IllegalArgumentException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + sal_Int32 nCount = aPropertyNames.getLength(); + if ( aValues.getLength() != nCount ) + throw lang::IllegalArgumentException(); + + if ( nCount ) + { + const rtl::OUString* pNames = aPropertyNames.getConstArray(); + const uno::Any* pValues = aValues.getConstArray(); + + const SfxItemPropertyMap* pPropertyMap = pPropSet->getPropertyMap(); + for (sal_Int32 i = 0; i < nCount; i++) + { + const SfxItemPropertySimpleEntry* pEntry = pPropertyMap->getByName( pNames[i] ); + SetOnePropertyValue( pNames[i], pEntry, &pValues[i] ); + } + } +} + +uno::Sequence<uno::Any> SAL_CALL ScStyleObj::getPropertyValues( + const uno::Sequence< rtl::OUString >& aPropertyNames ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + + //! optimize + + sal_Int32 nCount = aPropertyNames.getLength(); + uno::Sequence<uno::Any> aSequence( nCount ); + if ( nCount ) + { + uno::Any* pValues = aSequence.getArray(); + for (sal_Int32 i=0; i<nCount; i++) + pValues[i] = getPropertyValue( aPropertyNames[i] ); + } + return aSequence; +} + +void SAL_CALL ScStyleObj::addPropertiesChangeListener( const uno::Sequence<rtl::OUString>& /* aPropertyNames */, + const uno::Reference<beans::XPropertiesChangeListener>& /* xListener */ ) + throw (uno::RuntimeException) +{ + // no bound properties +} + +void SAL_CALL ScStyleObj::removePropertiesChangeListener( + const uno::Reference<beans::XPropertiesChangeListener>& /* xListener */ ) + throw (uno::RuntimeException) +{ + // no bound properties +} + +void SAL_CALL ScStyleObj::firePropertiesChangeEvent( const uno::Sequence<rtl::OUString>& /* aPropertyNames */, + const uno::Reference<beans::XPropertiesChangeListener>& /* xListener */ ) + throw (uno::RuntimeException) +{ + // no bound properties +} + +// XMultiPropertyStates +// getPropertyStates already defined for XPropertyState + +void SAL_CALL ScStyleObj::setAllPropertiesToDefault() throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + + SfxStyleSheetBase* pStyle = GetStyle_Impl(); + if ( pStyle ) + { + // #70909# cell styles cannot be modified if any sheet is protected + if ( eFamily == SFX_STYLE_FAMILY_PARA && lcl_AnyTabProtected( *pDocShell->GetDocument() ) ) + throw uno::RuntimeException(); + + SfxItemSet& rSet = pStyle->GetItemSet(); + rSet.ClearItem(); // set all items to default + + //! merge with SetOneProperty + + ScDocument* pDoc = pDocShell->GetDocument(); + if ( eFamily == SFX_STYLE_FAMILY_PARA ) + { + // row heights + + VirtualDevice aVDev; + Point aLogic = aVDev.LogicToPixel( Point(1000,1000), MAP_TWIP ); + double nPPTX = aLogic.X() / 1000.0; + double nPPTY = aLogic.Y() / 1000.0; + Fraction aZoom(1,1); + pDoc->StyleSheetChanged( pStyle, sal_False, &aVDev, nPPTX, nPPTY, aZoom, aZoom ); + + pDocShell->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID|PAINT_LEFT ); + pDocShell->SetDocumentModified(); + } + else + { + // #i22448# apply the default BoxInfoItem for page styles again + // (same content as in ScStyleSheet::GetItemSet, to control the dialog) + SvxBoxInfoItem aBoxInfoItem( ATTR_BORDER_INNER ); + aBoxInfoItem.SetTable( FALSE ); + aBoxInfoItem.SetDist( TRUE ); + aBoxInfoItem.SetValid( VALID_DISTANCE, TRUE ); + rSet.Put( aBoxInfoItem ); + + pDocShell->PageStyleModified( aStyleName, sal_True ); + } + } +} + +void SAL_CALL ScStyleObj::setPropertiesToDefault( const uno::Sequence<rtl::OUString>& aPropertyNames ) + throw (beans::UnknownPropertyException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + sal_Int32 nCount = aPropertyNames.getLength(); + if ( nCount ) + { + const rtl::OUString* pNames = aPropertyNames.getConstArray(); + + const SfxItemPropertyMap* pPropertyMap = pPropSet->getPropertyMap(); + for (sal_Int32 i = 0; i < nCount; i++) + { + const SfxItemPropertySimpleEntry* pEntry = pPropertyMap->getByName( pNames[i] ); + SetOnePropertyValue( pNames[i], pEntry, NULL ); + } + } +} + +uno::Sequence<uno::Any> SAL_CALL ScStyleObj::getPropertyDefaults( + const uno::Sequence<rtl::OUString>& aPropertyNames ) + throw (beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + + //! optimize + + sal_Int32 nCount = aPropertyNames.getLength(); + uno::Sequence<uno::Any> aSequence( nCount ); + if ( nCount ) + { + uno::Any* pValues = aSequence.getArray(); + for (sal_Int32 i=0; i<nCount; i++) + pValues[i] = getPropertyDefault( aPropertyNames[i] ); + } + return aSequence; +} + +// beans::XPropertySet + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScStyleObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return pPropSet->getPropertySetInfo(); +} + +void SAL_CALL ScStyleObj::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + + const SfxItemPropertySimpleEntry* pEntry = pPropSet->getPropertyMap()->getByName( aPropertyName ); + if ( !pEntry ) + throw beans::UnknownPropertyException(); + + SetOnePropertyValue( aPropertyName, pEntry, &aValue ); +} + +void ScStyleObj::SetOnePropertyValue( const ::rtl::OUString& rPropertyName, const SfxItemPropertySimpleEntry* pEntry, const uno::Any* pValue ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + SfxStyleSheetBase* pStyle = GetStyle_Impl(); + if ( pStyle && pEntry ) + { + // #70909# cell styles cannot be modified if any sheet is protected + if ( eFamily == SFX_STYLE_FAMILY_PARA && lcl_AnyTabProtected( *pDocShell->GetDocument() ) ) + throw uno::RuntimeException(); + + SfxItemSet& rSet = pStyle->GetItemSet(); // direkt im lebenden Style aendern... + sal_Bool bDone = sal_False; + if ( eFamily == SFX_STYLE_FAMILY_PAGE ) + { + if(pEntry->nWID == SC_WID_UNO_HEADERSET) + { + const SfxItemPropertySimpleEntry* pHeaderEntry = lcl_GetHeaderStyleMap()->getByName( rPropertyName ); + if ( pHeaderEntry ) // only item-wids in header/footer map + { + SvxSetItem aNewHeader( (const SvxSetItem&)rSet.Get(ATTR_PAGE_HEADERSET) ); + if (pValue) + pPropSet->setPropertyValue( *pHeaderEntry, *pValue, aNewHeader.GetItemSet() ); + else + aNewHeader.GetItemSet().ClearItem( pHeaderEntry->nWID ); + rSet.Put( aNewHeader ); + bDone = sal_True; + } + } + else if(pEntry->nWID == SC_WID_UNO_FOOTERSET) + { + const SfxItemPropertySimpleEntry* pFooterEntry = lcl_GetFooterStyleMap()->getByName( rPropertyName ); + if ( pFooterEntry ) // only item-wids in header/footer map + { + SvxSetItem aNewFooter( (const SvxSetItem&)rSet.Get(ATTR_PAGE_FOOTERSET) ); + if (pValue) + pPropSet->setPropertyValue( *pFooterEntry, *pValue, aNewFooter.GetItemSet() ); + else + aNewFooter.GetItemSet().ClearItem( pFooterEntry->nWID ); + rSet.Put( aNewFooter ); + bDone = sal_True; + } + } + } + if (!bDone) + { + if ( pEntry ) + { + if ( IsScItemWid( pEntry->nWID ) ) + { + if (pValue) + { + switch ( pEntry->nWID ) // fuer Item-Spezial-Behandlungen + { + case ATTR_VALUE_FORMAT: + { + // #67847# language for number formats + SvNumberFormatter* pFormatter = + pDocShell->GetDocument()->GetFormatTable(); + UINT32 nOldFormat = ((const SfxUInt32Item&) + rSet.Get( ATTR_VALUE_FORMAT )).GetValue(); + LanguageType eOldLang = ((const SvxLanguageItem&) + rSet.Get( ATTR_LANGUAGE_FORMAT )).GetLanguage(); + nOldFormat = pFormatter-> + GetFormatForLanguageIfBuiltIn( nOldFormat, eOldLang ); + + UINT32 nNewFormat = 0; + *pValue >>= nNewFormat; + rSet.Put( SfxUInt32Item( ATTR_VALUE_FORMAT, nNewFormat ) ); + + const SvNumberformat* pNewEntry = pFormatter->GetEntry( nNewFormat ); + LanguageType eNewLang = + pNewEntry ? pNewEntry->GetLanguage() : LANGUAGE_DONTKNOW; + if ( eNewLang != eOldLang && eNewLang != LANGUAGE_DONTKNOW ) + rSet.Put( SvxLanguageItem( eNewLang, ATTR_LANGUAGE_FORMAT ) ); + + //! keep default state of number format if only language changed? + } + break; + case ATTR_INDENT: + { + sal_Int16 nVal = 0; + *pValue >>= nVal; + rSet.Put( SfxUInt16Item( pEntry->nWID, (USHORT)HMMToTwips(nVal) ) ); + } + break; + case ATTR_ROTATE_VALUE: + { + sal_Int32 nRotVal = 0; + if ( *pValue >>= nRotVal ) + { + // stored value is always between 0 and 360 deg. + nRotVal %= 36000; + if ( nRotVal < 0 ) + nRotVal += 36000; + rSet.Put( SfxInt32Item( ATTR_ROTATE_VALUE, nRotVal ) ); + } + } + break; + case ATTR_STACKED: + { + table::CellOrientation eOrient; + if( *pValue >>= eOrient ) + { + switch( eOrient ) + { + case table::CellOrientation_STANDARD: + rSet.Put( SfxBoolItem( ATTR_STACKED, FALSE ) ); + break; + case table::CellOrientation_TOPBOTTOM: + rSet.Put( SfxBoolItem( ATTR_STACKED, FALSE ) ); + rSet.Put( SfxInt32Item( ATTR_ROTATE_VALUE, 27000 ) ); + break; + case table::CellOrientation_BOTTOMTOP: + rSet.Put( SfxBoolItem( ATTR_STACKED, FALSE ) ); + rSet.Put( SfxInt32Item( ATTR_ROTATE_VALUE, 9000 ) ); + break; + case table::CellOrientation_STACKED: + rSet.Put( SfxBoolItem( ATTR_STACKED, TRUE ) ); + break; + default: + { + // added to avoid warnings + } + } + } + } + break; + case ATTR_PAGE_SCALE: + case ATTR_PAGE_SCALETOPAGES: + { + rSet.ClearItem(ATTR_PAGE_SCALETOPAGES); + rSet.ClearItem(ATTR_PAGE_SCALE); + rSet.ClearItem(ATTR_PAGE_SCALETO); + sal_Int16 nVal = 0; + *pValue >>= nVal; + rSet.Put( SfxUInt16Item( pEntry->nWID, nVal ) ); + } + break; + case ATTR_PAGE_FIRSTPAGENO: + { + sal_Int16 nVal = 0; + *pValue >>= nVal; + rSet.Put( SfxUInt16Item( ATTR_PAGE_FIRSTPAGENO, nVal ) ); + } + break; + case ATTR_PAGE_CHARTS: + case ATTR_PAGE_OBJECTS: + case ATTR_PAGE_DRAWINGS: + { + sal_Bool bBool = sal_False; + *pValue >>= bBool; + //! sal_Bool-MID fuer ScViewObjectModeItem definieren? + rSet.Put( ScViewObjectModeItem( pEntry->nWID, + bBool ? VOBJ_MODE_SHOW : VOBJ_MODE_HIDE ) ); + } + break; + case ATTR_PAGE_PAPERBIN: + { + BYTE nTray = PAPERBIN_PRINTER_SETTINGS; + BOOL bFound = FALSE; + + rtl::OUString aName; + if ( *pValue >>= aName ) + { + if ( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( SC_PAPERBIN_DEFAULTNAME ) ) ) + bFound = TRUE; + else + { + Printer* pPrinter = pDocShell->GetPrinter(); + if (pPrinter) + { + String aNameStr = aName; + USHORT nCount = pPrinter->GetPaperBinCount(); + for (USHORT i=0; i<nCount; i++) + if ( aNameStr == pPrinter->GetPaperBinName(i) ) + { + nTray = (BYTE) i; + bFound = TRUE; + break; + } + } + } + } + if ( bFound ) + rSet.Put( SvxPaperBinItem( ATTR_PAGE_PAPERBIN, nTray ) ); + else + throw lang::IllegalArgumentException(); + } + break; + case ATTR_PAGE_SCALETO: + { + sal_Int16 nPages = 0; + if (*pValue >>= nPages) + { + ScPageScaleToItem aItem = ((const ScPageScaleToItem&)rSet.Get(ATTR_PAGE_SCALETO)); + if ( rPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SC_UNO_PAGE_SCALETOX))) + aItem.SetWidth(static_cast<sal_uInt16>(nPages)); + else + aItem.SetHeight(static_cast<sal_uInt16>(nPages)); + rSet.Put( aItem ); + rSet.ClearItem(ATTR_PAGE_SCALETOPAGES); + rSet.ClearItem(ATTR_PAGE_SCALE); + } + } + break; + default: + // #65253# Default-Items mit falscher Slot-ID + // funktionieren im SfxItemPropertySet3 nicht + //! Slot-IDs aendern... + if ( rSet.GetPool()->GetSlotId(pEntry->nWID) == pEntry->nWID && + rSet.GetItemState(pEntry->nWID, sal_False) == SFX_ITEM_DEFAULT ) + { + rSet.Put( rSet.Get(pEntry->nWID) ); + } + pPropSet->setPropertyValue( *pEntry, *pValue, rSet ); + } + } + else + { + rSet.ClearItem( pEntry->nWID ); + // #67847# language for number formats + if ( pEntry->nWID == ATTR_VALUE_FORMAT ) + rSet.ClearItem( ATTR_LANGUAGE_FORMAT ); + + //! for ATTR_ROTATE_VALUE, also reset ATTR_ORIENTATION? + } + } + else if ( IsScUnoWid( pEntry->nWID ) ) + { + switch ( pEntry->nWID ) + { + case SC_WID_UNO_TBLBORD: + { + if (pValue) + { + table::TableBorder aBorder; + if ( *pValue >>= aBorder ) + { + SvxBoxItem aOuter( ATTR_BORDER ); + SvxBoxInfoItem aInner( ATTR_BORDER_INNER ); + ScHelperFunctions::FillBoxItems( aOuter, aInner, aBorder ); + rSet.Put( aOuter ); + } + } + else + { + rSet.ClearItem( ATTR_BORDER ); + } + } + break; + } + } + } + } + + //! DocFunc-Funktion?? + //! Undo ????????????? + + ScDocument* pDoc = pDocShell->GetDocument(); + if ( eFamily == SFX_STYLE_FAMILY_PARA ) + { + // Zeilenhoehen anpassen... + + VirtualDevice aVDev; + Point aLogic = aVDev.LogicToPixel( Point(1000,1000), MAP_TWIP ); + double nPPTX = aLogic.X() / 1000.0; + double nPPTY = aLogic.Y() / 1000.0; + Fraction aZoom(1,1); + pDoc->StyleSheetChanged( pStyle, sal_False, &aVDev, nPPTX, nPPTY, aZoom, aZoom ); + + pDocShell->PostPaint( 0,0,0, MAXCOL,MAXROW,MAXTAB, PAINT_GRID|PAINT_LEFT ); + pDocShell->SetDocumentModified(); + } + else + { + //! ModifyStyleSheet am Dokument (alte Werte merken) + + pDocShell->PageStyleModified( aStyleName, sal_True ); + } + } +} + +uno::Any SAL_CALL ScStyleObj::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Any aAny; + + if ( aPropertyName.equalsAscii( SC_UNONAME_DISPNAME ) ) // read-only + { + // core always has the display name + SfxStyleSheetBase* pStyle = GetStyle_Impl(); + if (pStyle) + aAny <<= rtl::OUString( pStyle->GetName() ); + } + else + { + const SfxItemPropertySimpleEntry* pResultEntry = NULL; + const SfxItemSet* pItemSet = GetStyleItemSet_Impl( aPropertyName, pResultEntry ); + + if ( pItemSet && pResultEntry ) + { + USHORT nWhich = pResultEntry->nWID; + + if ( IsScItemWid( nWhich ) ) + { + switch ( nWhich ) // fuer Item-Spezial-Behandlungen + { + case ATTR_VALUE_FORMAT: + if ( pDocShell ) + { + UINT32 nOldFormat = ((const SfxUInt32Item&) + pItemSet->Get( ATTR_VALUE_FORMAT )).GetValue(); + LanguageType eOldLang = ((const SvxLanguageItem&) + pItemSet->Get( ATTR_LANGUAGE_FORMAT )).GetLanguage(); + nOldFormat = pDocShell->GetDocument()->GetFormatTable()-> + GetFormatForLanguageIfBuiltIn( nOldFormat, eOldLang ); + aAny <<= nOldFormat; + } + break; + case ATTR_INDENT: + aAny <<= sal_Int16( TwipsToHMM(((const SfxUInt16Item&) + pItemSet->Get(nWhich)).GetValue()) ); + break; + case ATTR_STACKED: + { + sal_Int32 nRot = ((const SfxInt32Item&)pItemSet->Get(ATTR_ROTATE_VALUE)).GetValue(); + BOOL bStacked = ((const SfxBoolItem&)pItemSet->Get(nWhich)).GetValue(); + SvxOrientationItem( nRot, bStacked, 0 ).QueryValue( aAny ); + } + break; + case ATTR_PAGE_SCALE: + case ATTR_PAGE_SCALETOPAGES: + case ATTR_PAGE_FIRSTPAGENO: + aAny <<= sal_Int16( ((const SfxUInt16Item&)pItemSet->Get(nWhich)).GetValue() ); + break; + case ATTR_PAGE_CHARTS: + case ATTR_PAGE_OBJECTS: + case ATTR_PAGE_DRAWINGS: + //! sal_Bool-MID fuer ScViewObjectModeItem definieren? + aAny <<= sal_Bool( ((const ScViewObjectModeItem&)pItemSet-> + Get(nWhich)).GetValue() == VOBJ_MODE_SHOW ); + break; + case ATTR_PAGE_PAPERBIN: + { + // property PrinterPaperTray is the name of the tray + + BYTE nValue = ((const SvxPaperBinItem&)pItemSet->Get(nWhich)).GetValue(); + rtl::OUString aName; + if ( nValue == PAPERBIN_PRINTER_SETTINGS ) + aName = rtl::OUString::createFromAscii( SC_PAPERBIN_DEFAULTNAME ); + else + { + Printer* pPrinter = pDocShell->GetPrinter(); + if (pPrinter) + aName = pPrinter->GetPaperBinName( nValue ); + } + aAny <<= aName; + } + break; + case ATTR_PAGE_SCALETO: + { + ScPageScaleToItem aItem((const ScPageScaleToItem&)pItemSet->Get(ATTR_PAGE_SCALETO)); + if (aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SC_UNO_PAGE_SCALETOX))) + aAny = uno::makeAny(static_cast<sal_Int16>(aItem.GetWidth())); + else + aAny = uno::makeAny(static_cast<sal_Int16>(aItem.GetHeight())); + } + break; + default: + // #65253# Default-Items mit falscher Slot-ID + // funktionieren im SfxItemPropertySet3 nicht + //! Slot-IDs aendern... + if ( pItemSet->GetPool()->GetSlotId(nWhich) == nWhich && + pItemSet->GetItemState(nWhich, sal_False) == SFX_ITEM_DEFAULT ) + { + SfxItemSet aNoEmptySet( *pItemSet ); + aNoEmptySet.Put( aNoEmptySet.Get( nWhich ) ); + pPropSet->getPropertyValue( *pResultEntry, aNoEmptySet, aAny ); + } + else + pPropSet->getPropertyValue( *pResultEntry, *pItemSet, aAny ); + } + } + else if ( IsScUnoWid( nWhich ) ) + { + switch ( nWhich ) + { + case SC_WID_UNO_TBLBORD: + { + const SfxPoolItem* pItem = &pItemSet->Get( ATTR_BORDER ); + if ( pItem ) + { + SvxBoxItem aOuter( *( static_cast<const SvxBoxItem*>( pItem ) ) ); + SvxBoxInfoItem aInner( ATTR_BORDER_INNER ); + table::TableBorder aBorder; + ScHelperFunctions::FillTableBorder( aBorder, aOuter, aInner ); + aBorder.IsHorizontalLineValid = sal_False; + aBorder.IsVerticalLineValid = sal_False; + aBorder.IsDistanceValid = sal_False; + aAny <<= aBorder; + } + } + break; + } + } + } + } + + return aAny; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScStyleObj ) + +// lang::XServiceInfo + +rtl::OUString SAL_CALL ScStyleObj::getImplementationName() throw(uno::RuntimeException) +{ + return rtl::OUString::createFromAscii( "ScStyleObj" ); +} + +sal_Bool SAL_CALL ScStyleObj::supportsService( const rtl::OUString& rServiceName ) + throw(uno::RuntimeException) +{ + BOOL bPage = ( eFamily == SFX_STYLE_FAMILY_PAGE ); + return rServiceName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( SCSTYLE_SERVICE ) )|| + rServiceName.equalsAsciiL( + RTL_CONSTASCII_STRINGPARAM ( bPage ? SCPAGESTYLE_SERVICE : SCCELLSTYLE_SERVICE )); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScStyleObj::getSupportedServiceNames() + throw(uno::RuntimeException) +{ + BOOL bPage = ( eFamily == SFX_STYLE_FAMILY_PAGE ); + uno::Sequence<rtl::OUString> aRet(2); + rtl::OUString* pArray = aRet.getArray(); + pArray[0] = rtl::OUString::createFromAscii( SCSTYLE_SERVICE ); + pArray[1] = rtl::OUString::createFromAscii( bPage ? SCPAGESTYLE_SERVICE + : SCCELLSTYLE_SERVICE ); + return aRet; +} + +//------------------------------------------------------------------------ + + diff --git a/sc/source/ui/unoobj/targuno.cxx b/sc/source/ui/unoobj/targuno.cxx new file mode 100644 index 000000000000..aa4cdf58882d --- /dev/null +++ b/sc/source/ui/unoobj/targuno.cxx @@ -0,0 +1,318 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include <vcl/image.hxx> +#include <vcl/virdev.hxx> +//#include <toolkit/unoiface.hxx> +#include <toolkit/unohlp.hxx> +#include <svl/itemprop.hxx> +#include <svl/smplhint.hxx> +#include <vcl/svapp.hxx> +#include <vcl/settings.hxx> +#include <com/sun/star/awt/XBitmap.hpp> + +#include "targuno.hxx" +#include "miscuno.hxx" +#include "docuno.hxx" +#include "datauno.hxx" +#include "nameuno.hxx" +#include "docsh.hxx" +#include "content.hxx" +#include "unoguard.hxx" +#include "scresid.hxx" +#include "sc.hrc" +#include "unonames.hxx" + +using namespace ::com::sun::star; + +//------------------------------------------------------------------------ + +sal_uInt16 nTypeResIds[SC_LINKTARGETTYPE_COUNT] = +{ + SCSTR_CONTENT_TABLE, // SC_LINKTARGETTYPE_SHEET + SCSTR_CONTENT_RANGENAME, // SC_LINKTARGETTYPE_RANGENAME + SCSTR_CONTENT_DBAREA // SC_LINKTARGETTYPE_DBAREA +}; + +const SfxItemPropertyMapEntry* lcl_GetLinkTargetMap() +{ + static SfxItemPropertyMapEntry aLinkTargetMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNO_LINKDISPBIT), 0, &getCppuType((const uno::Reference<awt::XBitmap>*)0), beans::PropertyAttribute::READONLY, 0 }, + {MAP_CHAR_LEN(SC_UNO_LINKDISPNAME), 0, &getCppuType((const ::rtl::OUString*)0), beans::PropertyAttribute::READONLY, 0 }, + {0,0,0,0,0,0} + }; + return aLinkTargetMap_Impl; +} + +//------------------------------------------------------------------------ + +// service for ScLinkTargetTypeObj is not defined +// must not support document::LinkTarget because the target type cannot be used as a target + +SC_SIMPLE_SERVICE_INFO( ScLinkTargetTypesObj, "ScLinkTargetTypesObj", "com.sun.star.document.LinkTargets" ) +SC_SIMPLE_SERVICE_INFO( ScLinkTargetTypeObj, "ScLinkTargetTypeObj", "com.sun.star.document.LinkTargetSupplier" ) +SC_SIMPLE_SERVICE_INFO( ScLinkTargetsObj, "ScLinkTargetsObj", "com.sun.star.document.LinkTargets" ) + +//------------------------------------------------------------------------ + +ScLinkTargetTypesObj::ScLinkTargetTypesObj(ScDocShell* pDocSh) : + pDocShell( pDocSh ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); + + for (sal_uInt16 i=0; i<SC_LINKTARGETTYPE_COUNT; i++) + aNames[i] = String( ScResId( nTypeResIds[i] ) ); +} + +ScLinkTargetTypesObj::~ScLinkTargetTypesObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScLinkTargetTypesObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( SfxSimpleHint ) && ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + pDocShell = NULL; // document gone +} + +// container::XNameAccess + +uno::Any SAL_CALL ScLinkTargetTypesObj::getByName(const rtl::OUString& aName) + throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException ) +{ + if (pDocShell) + { + String aNameStr(aName); + for (sal_uInt16 i=0; i<SC_LINKTARGETTYPE_COUNT; i++) + if ( aNames[i] == aNameStr ) + return uno::makeAny(uno::Reference< beans::XPropertySet >(new ScLinkTargetTypeObj( pDocShell, i ))); + } + + throw container::NoSuchElementException(); +// return uno::Any(); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScLinkTargetTypesObj::getElementNames(void) throw( uno::RuntimeException ) +{ + uno::Sequence<rtl::OUString> aRet(SC_LINKTARGETTYPE_COUNT); + rtl::OUString* pArray = aRet.getArray(); + for (sal_uInt16 i=0; i<SC_LINKTARGETTYPE_COUNT; i++) + pArray[i] = aNames[i]; + return aRet; +} + +sal_Bool SAL_CALL ScLinkTargetTypesObj::hasByName(const rtl::OUString& aName) throw( uno::RuntimeException ) +{ + String aNameStr = aName; + for (sal_uInt16 i=0; i<SC_LINKTARGETTYPE_COUNT; i++) + if ( aNames[i] == aNameStr ) + return sal_True; + return sal_False; +} + +// container::XElementAccess + +uno::Type SAL_CALL ScLinkTargetTypesObj::getElementType(void) throw( uno::RuntimeException ) +{ + return ::getCppuType((const uno::Reference< beans::XPropertySet >*)0); +} + +sal_Bool SAL_CALL ScLinkTargetTypesObj::hasElements(void) throw( uno::RuntimeException ) +{ + return sal_True; +} + +//------------------------------------------------------------------------ + +ScLinkTargetTypeObj::ScLinkTargetTypeObj(ScDocShell* pDocSh, sal_uInt16 nT) : + pDocShell( pDocSh ), + nType( nT ) +{ + pDocShell->GetDocument()->AddUnoObject(*this); + aName = String( ScResId( nTypeResIds[nType] ) ); //! on demand? +} + +ScLinkTargetTypeObj::~ScLinkTargetTypeObj() +{ + if (pDocShell) + pDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScLinkTargetTypeObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( SfxSimpleHint ) && ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + pDocShell = NULL; // document gone +} + +// document::XLinkTargetSupplier + +uno::Reference< container::XNameAccess > SAL_CALL ScLinkTargetTypeObj::getLinks(void) throw( uno::RuntimeException ) +{ + uno::Reference< container::XNameAccess > xCollection; + + if ( pDocShell ) + { + switch ( nType ) + { + case SC_LINKTARGETTYPE_SHEET: + xCollection.set(new ScTableSheetsObj(pDocShell)); + break; + case SC_LINKTARGETTYPE_RANGENAME: + xCollection.set(new ScNamedRangesObj(pDocShell)); + break; + case SC_LINKTARGETTYPE_DBAREA: + xCollection.set(new ScDatabaseRangesObj(pDocShell)); + break; + default: + DBG_ERROR("invalid type"); + } + } + + // wrap collection in ScLinkTargetsObj because service document::LinkTargets requires + // beans::XPropertySet as ElementType in container::XNameAccess. + if ( xCollection.is() ) + return new ScLinkTargetsObj( xCollection ); + return NULL; +} + +// beans::XPropertySet + +uno::Reference< beans::XPropertySetInfo > SAL_CALL ScLinkTargetTypeObj::getPropertySetInfo(void) throw( uno::RuntimeException ) +{ + ScUnoGuard aGuard; + static uno::Reference< beans::XPropertySetInfo > aRef(new SfxItemPropertySetInfo( lcl_GetLinkTargetMap() )); + return aRef; +} + +void SAL_CALL ScLinkTargetTypeObj::setPropertyValue(const rtl::OUString& /* aPropertyName */, + const uno::Any& /* aValue */) + throw( beans::UnknownPropertyException, + beans::PropertyVetoException, + lang::IllegalArgumentException, + lang::WrappedTargetException, + uno::RuntimeException ) +{ + // everything is read-only + //! exception? +} + +// static +void ScLinkTargetTypeObj::SetLinkTargetBitmap( uno::Any& rRet, sal_uInt16 nType ) +{ + sal_uInt16 nImgId = 0; + switch ( nType ) + { + case SC_LINKTARGETTYPE_SHEET: + nImgId = SC_CONTENT_TABLE; + break; + case SC_LINKTARGETTYPE_RANGENAME: + nImgId = SC_CONTENT_RANGENAME; + break; + case SC_LINKTARGETTYPE_DBAREA: + nImgId = SC_CONTENT_DBAREA; + break; + } + if (nImgId) + { + BOOL bHighContrast = Application::GetSettings().GetStyleSettings().GetHighContrastMode(); + ImageList aEntryImages( ScResId( bHighContrast ? RID_IMAGELIST_H_NAVCONT : RID_IMAGELIST_NAVCONT ) ); + const Image& rImage = aEntryImages.GetImage( nImgId ); + rRet <<= uno::Reference< awt::XBitmap > (VCLUnoHelper::CreateBitmap( rImage.GetBitmapEx() )); + } +} + +uno::Any SAL_CALL ScLinkTargetTypeObj::getPropertyValue(const rtl::OUString& PropertyName) + throw( beans::UnknownPropertyException, lang::WrappedTargetException, uno::RuntimeException ) +{ + uno::Any aRet; + String aNameStr(PropertyName); + if ( aNameStr.EqualsAscii( SC_UNO_LINKDISPBIT ) ) + SetLinkTargetBitmap( aRet, nType ); + else if ( aNameStr.EqualsAscii( SC_UNO_LINKDISPNAME ) ) + aRet <<= rtl::OUString( aName ); + + return aRet; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScLinkTargetTypeObj ) + +//------------------------------------------------------------------------ + +ScLinkTargetsObj::ScLinkTargetsObj( const uno::Reference< container::XNameAccess > & rColl ) : + xCollection( rColl ) +{ + DBG_ASSERT( xCollection.is(), "ScLinkTargetsObj: NULL" ); +} + +ScLinkTargetsObj::~ScLinkTargetsObj() +{ +} + +// container::XNameAccess + +uno::Any SAL_CALL ScLinkTargetsObj::getByName(const rtl::OUString& aName) + throw( container::NoSuchElementException, lang::WrappedTargetException, uno::RuntimeException ) +{ + uno::Reference< beans::XPropertySet > xProp( ScUnoHelpFunctions::AnyToInterface( xCollection->getByName(aName) ), uno::UNO_QUERY ); + if (xProp.is()) + return uno::makeAny(xProp); + + throw container::NoSuchElementException(); +// return uno::Any(); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScLinkTargetsObj::getElementNames(void) throw( uno::RuntimeException ) +{ + return xCollection->getElementNames(); +} + +sal_Bool SAL_CALL ScLinkTargetsObj::hasByName(const rtl::OUString& aName) throw( uno::RuntimeException ) +{ + return xCollection->hasByName(aName); +} + +// container::XElementAccess + +uno::Type SAL_CALL ScLinkTargetsObj::getElementType(void) throw( uno::RuntimeException ) +{ + return ::getCppuType((const uno::Reference< beans::XPropertySet >*)0); +} + +sal_Bool SAL_CALL ScLinkTargetsObj::hasElements(void) throw( uno::RuntimeException ) +{ + return xCollection->hasElements(); +} + + + diff --git a/sc/source/ui/unoobj/textuno.cxx b/sc/source/ui/unoobj/textuno.cxx new file mode 100644 index 000000000000..5c45195621d8 --- /dev/null +++ b/sc/source/ui/unoobj/textuno.cxx @@ -0,0 +1,1152 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include "scitems.hxx" +#include <editeng/eeitem.hxx> +#include <svx/svdpool.hxx> +#include <svx/svdobj.hxx> +#include <editeng/editeng.hxx> +#include <editeng/editobj.hxx> +#include <editeng/flditem.hxx> +#include <svx/unomid.hxx> +#include <editeng/unoprnms.hxx> +#include <editeng/unofored.hxx> +#include <rtl/uuid.h> +#include <vcl/virdev.hxx> +#include <com/sun/star/awt/FontSlant.hpp> + +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <editeng/unoipset.hxx> +#include "textuno.hxx" +#include "fielduno.hxx" +#include "servuno.hxx" +#include "editsrc.hxx" +#include "docsh.hxx" +#include "editutil.hxx" +#include "unoguard.hxx" +#include "miscuno.hxx" +#include "cellsuno.hxx" +#include "hints.hxx" +#include "patattr.hxx" +#include "cell.hxx" +#include "docfunc.hxx" +#include "scmod.hxx" + +using namespace com::sun::star; + +//------------------------------------------------------------------------ + +const SvxItemPropertySet * lcl_GetHdFtPropertySet() +{ + static SfxItemPropertyMapEntry aHdFtPropertyMap_Impl[] = + { + SVX_UNOEDIT_CHAR_PROPERTIES, + SVX_UNOEDIT_FONT_PROPERTIES, + SVX_UNOEDIT_PARA_PROPERTIES, + SVX_UNOEDIT_NUMBERING_PROPERTIE, // for completeness of service ParagraphProperties + {0,0,0,0,0,0} + }; + static BOOL bTwipsSet = FALSE; + + if (!bTwipsSet) + { + // modify PropertyMap to include CONVERT_TWIPS flag for font height + // (headers/footers are in twips) + + SfxItemPropertyMapEntry* pEntry = aHdFtPropertyMap_Impl; + while (pEntry->pName) + { + if ( ( pEntry->nWID == EE_CHAR_FONTHEIGHT || + pEntry->nWID == EE_CHAR_FONTHEIGHT_CJK || + pEntry->nWID == EE_CHAR_FONTHEIGHT_CTL ) && + pEntry->nMemberId == MID_FONTHEIGHT ) + { + pEntry->nMemberId |= CONVERT_TWIPS; + } + + ++pEntry; + } + bTwipsSet = TRUE; + } + static SvxItemPropertySet aHdFtPropertySet_Impl( aHdFtPropertyMap_Impl, SdrObject::GetGlobalDrawObjectItemPool() ); + return &aHdFtPropertySet_Impl; +} + +//------------------------------------------------------------------------ + +SC_SIMPLE_SERVICE_INFO( ScHeaderFooterContentObj, "ScHeaderFooterContentObj", "com.sun.star.sheet.HeaderFooterContent" ) +SC_SIMPLE_SERVICE_INFO( ScHeaderFooterTextObj, "ScHeaderFooterTextObj", "stardiv.one.Text.Text" ) + +//------------------------------------------------------------------------ + +ScHeaderFooterContentObj::ScHeaderFooterContentObj( const EditTextObject* pLeft, + const EditTextObject* pCenter, + const EditTextObject* pRight ) : + pLeftText ( NULL ), + pCenterText ( NULL ), + pRightText ( NULL ) +{ + if ( pLeft ) + pLeftText = pLeft->Clone(); + if ( pCenter ) + pCenterText = pCenter->Clone(); + if ( pRight ) + pRightText = pRight->Clone(); +} + +ScHeaderFooterContentObj::~ScHeaderFooterContentObj() +{ + delete pLeftText; + delete pCenterText; + delete pRightText; +} + +void ScHeaderFooterContentObj::AddListener( SfxListener& rListener ) +{ + rListener.StartListening( aBC ); +} + +void ScHeaderFooterContentObj::RemoveListener( SfxListener& rListener ) +{ + rListener.EndListening( aBC ); +} + +void ScHeaderFooterContentObj::UpdateText( USHORT nPart, EditEngine& rSource ) +{ + EditTextObject* pNew = rSource.CreateTextObject(); + switch (nPart) + { + case SC_HDFT_LEFT: + delete pLeftText; + pLeftText = pNew; + break; + case SC_HDFT_CENTER: + delete pCenterText; + pCenterText = pNew; + break; + default: // SC_HDFT_RIGHT + delete pRightText; + pRightText = pNew; + break; + } + + aBC.Broadcast( ScHeaderFooterChangedHint( nPart ) ); +} + +// XHeaderFooterContent + +uno::Reference<text::XText> SAL_CALL ScHeaderFooterContentObj::getLeftText() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScHeaderFooterTextObj( *this, SC_HDFT_LEFT ); +} + +uno::Reference<text::XText> SAL_CALL ScHeaderFooterContentObj::getCenterText() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScHeaderFooterTextObj( *this, SC_HDFT_CENTER ); +} + +uno::Reference<text::XText> SAL_CALL ScHeaderFooterContentObj::getRightText() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScHeaderFooterTextObj( *this, SC_HDFT_RIGHT ); +} + +// XUnoTunnel + +sal_Int64 SAL_CALL ScHeaderFooterContentObj::getSomething( + const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); + } + return 0; +} + +// static +const uno::Sequence<sal_Int8>& ScHeaderFooterContentObj::getUnoTunnelId() +{ + static uno::Sequence<sal_Int8> * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +// static +ScHeaderFooterContentObj* ScHeaderFooterContentObj::getImplementation( + const uno::Reference<sheet::XHeaderFooterContent> xObj ) +{ + ScHeaderFooterContentObj* pRet = NULL; + uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); + if (xUT.is()) + pRet = reinterpret_cast<ScHeaderFooterContentObj*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId()))); + return pRet; +} + + +//------------------------------------------------------------------------ + +ScHeaderFooterTextData::ScHeaderFooterTextData( ScHeaderFooterContentObj& rContent, + USHORT nP ) : + rContentObj( rContent ), + nPart( nP ), + pEditEngine( NULL ), + pForwarder( NULL ), + bDataValid( FALSE ), + bInUpdate( FALSE ) +{ + rContentObj.acquire(); // must not go away + rContentObj.AddListener( *this ); +} + +ScHeaderFooterTextData::~ScHeaderFooterTextData() +{ + ScUnoGuard aGuard; // needed for EditEngine dtor + + rContentObj.RemoveListener( *this ); + + delete pForwarder; + delete pEditEngine; + + rContentObj.release(); +} + +void ScHeaderFooterTextData::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( ScHeaderFooterChangedHint ) ) + { + if ( ((const ScHeaderFooterChangedHint&)rHint).GetPart() == nPart ) + { + if (!bInUpdate) // not for own updates + bDataValid = FALSE; // text has to be fetched again + } + } +} + +SvxTextForwarder* ScHeaderFooterTextData::GetTextForwarder() +{ + if (!pEditEngine) + { + SfxItemPool* pEnginePool = EditEngine::CreatePool(); + pEnginePool->FreezeIdRanges(); + ScHeaderEditEngine* pHdrEngine = new ScHeaderEditEngine( pEnginePool, TRUE ); + + pHdrEngine->EnableUndo( FALSE ); + pHdrEngine->SetRefMapMode( MAP_TWIP ); + + // default font must be set, independently of document + // -> use global pool from module + + SfxItemSet aDefaults( pHdrEngine->GetEmptyItemSet() ); + const ScPatternAttr& rPattern = (const ScPatternAttr&)SC_MOD()->GetPool().GetDefaultItem(ATTR_PATTERN); + rPattern.FillEditItemSet( &aDefaults ); + // FillEditItemSet adjusts font height to 1/100th mm, + // but for header/footer twips is needed, as in the PatternAttr: + aDefaults.Put( rPattern.GetItem(ATTR_FONT_HEIGHT), EE_CHAR_FONTHEIGHT ); + aDefaults.Put( rPattern.GetItem(ATTR_CJK_FONT_HEIGHT), EE_CHAR_FONTHEIGHT_CJK ); + aDefaults.Put( rPattern.GetItem(ATTR_CTL_FONT_HEIGHT), EE_CHAR_FONTHEIGHT_CTL ); + pHdrEngine->SetDefaults( aDefaults ); + + ScHeaderFieldData aData; + ScHeaderFooterTextObj::FillDummyFieldData( aData ); + pHdrEngine->SetData( aData ); + + pEditEngine = pHdrEngine; + pForwarder = new SvxEditEngineForwarder(*pEditEngine); + } + + if (bDataValid) + return pForwarder; + + const EditTextObject* pData; + if (nPart == SC_HDFT_LEFT) + pData = rContentObj.GetLeftEditObject(); + else if (nPart == SC_HDFT_CENTER) + pData = rContentObj.GetCenterEditObject(); + else + pData = rContentObj.GetRightEditObject(); + + if (pData) + pEditEngine->SetText(*pData); + + bDataValid = TRUE; + return pForwarder; +} + +void ScHeaderFooterTextData::UpdateData() +{ + if ( pEditEngine ) + { + bInUpdate = TRUE; // don't reset bDataValid during UpdateText + + rContentObj.UpdateText( nPart, *pEditEngine ); + + bInUpdate = FALSE; + } +} + +//------------------------------------------------------------------------ + +ScHeaderFooterTextObj::ScHeaderFooterTextObj( ScHeaderFooterContentObj& rContent, + USHORT nP ) : + aTextData( rContent, nP ), + pUnoText( NULL ) +{ + // ScHeaderFooterTextData acquires rContent + // pUnoText is created on demand (getString/setString work without it) +} + +void ScHeaderFooterTextObj::CreateUnoText_Impl() +{ + if ( !pUnoText ) + { + // can't be aggregated because getString/setString is handled here + ScSharedHeaderFooterEditSource aEditSource( &aTextData ); + pUnoText = new SvxUnoText( &aEditSource, lcl_GetHdFtPropertySet(), uno::Reference<text::XText>() ); + pUnoText->acquire(); + } +} + +ScHeaderFooterTextObj::~ScHeaderFooterTextObj() +{ + if (pUnoText) + pUnoText->release(); +} + +const SvxUnoText& ScHeaderFooterTextObj::GetUnoText() +{ + if (!pUnoText) + CreateUnoText_Impl(); + return *pUnoText; +} + +// XText + +uno::Reference<text::XTextCursor> SAL_CALL ScHeaderFooterTextObj::createTextCursor() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScHeaderFooterTextCursor( *this ); +} + +uno::Reference<text::XTextCursor> SAL_CALL ScHeaderFooterTextObj::createTextCursorByRange( + const uno::Reference<text::XTextRange>& aTextPosition ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (!pUnoText) + CreateUnoText_Impl(); + return pUnoText->createTextCursorByRange(aTextPosition); + //! wie ScCellObj::createTextCursorByRange, wenn SvxUnoTextRange_getReflection verfuegbar +} + +void ScHeaderFooterTextObj::FillDummyFieldData( ScHeaderFieldData& rData ) // static +{ + String aDummy(String::CreateFromAscii(RTL_CONSTASCII_STRINGPARAM( "???" ))); + rData.aTitle = aDummy; + rData.aLongDocName = aDummy; + rData.aShortDocName = aDummy; + rData.aTabName = aDummy; + rData.nPageNo = 1; + rData.nTotalPages = 99; +} + +rtl::OUString SAL_CALL ScHeaderFooterTextObj::getString() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + rtl::OUString aRet; + const EditTextObject* pData; + + USHORT nPart = aTextData.GetPart(); + ScHeaderFooterContentObj& rContentObj = aTextData.GetContentObj(); + + if (nPart == SC_HDFT_LEFT) + pData = rContentObj.GetLeftEditObject(); + else if (nPart == SC_HDFT_CENTER) + pData = rContentObj.GetCenterEditObject(); + else + pData = rContentObj.GetRightEditObject(); + if (pData) + { + // for pure text, no font info is needed in pool defaults + ScHeaderEditEngine aEditEngine( EditEngine::CreatePool(), TRUE ); + + ScHeaderFieldData aData; + FillDummyFieldData( aData ); + aEditEngine.SetData( aData ); + + aEditEngine.SetText(*pData); + aRet = ScEditUtil::GetSpaceDelimitedString( aEditEngine ); + } + return aRet; +} + +void SAL_CALL ScHeaderFooterTextObj::setString( const rtl::OUString& aText ) throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aString(aText); + + // for pure text, no font info is needed in pool defaults + ScHeaderEditEngine aEditEngine( EditEngine::CreatePool(), TRUE ); + aEditEngine.SetText( aString ); + + aTextData.GetContentObj().UpdateText( aTextData.GetPart(), aEditEngine ); +} + +void SAL_CALL ScHeaderFooterTextObj::insertString( const uno::Reference<text::XTextRange>& xRange, + const rtl::OUString& aString, sal_Bool bAbsorb ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (!pUnoText) + CreateUnoText_Impl(); + pUnoText->insertString( xRange, aString, bAbsorb ); +} + +void SAL_CALL ScHeaderFooterTextObj::insertControlCharacter( + const uno::Reference<text::XTextRange>& xRange, + sal_Int16 nControlCharacter, sal_Bool bAbsorb ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (!pUnoText) + CreateUnoText_Impl(); + pUnoText->insertControlCharacter( xRange, nControlCharacter, bAbsorb ); +} + +void SAL_CALL ScHeaderFooterTextObj::insertTextContent( + const uno::Reference<text::XTextRange >& xRange, + const uno::Reference<text::XTextContent >& xContent, + sal_Bool bAbsorb ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( xContent.is() && xRange.is() ) + { + ScHeaderFieldObj* pHeaderField = ScHeaderFieldObj::getImplementation( xContent ); + + SvxUnoTextRangeBase* pTextRange = + ScHeaderFooterTextCursor::getImplementation( xRange ); + +#if 0 + if (!pTextRange) + pTextRange = (SvxUnoTextRange*)xRange->getImplementation( + SvxUnoTextRange_getReflection() ); + //! bei SvxUnoTextRange testen, ob in passendem Objekt !!! +#endif + + if ( pHeaderField && !pHeaderField->IsInserted() && pTextRange ) + { + SvxEditSource* pEditSource = pTextRange->GetEditSource(); + ESelection aSelection(pTextRange->GetSelection()); + + if (!bAbsorb) + { + // don't replace -> append at end + aSelection.Adjust(); + aSelection.nStartPara = aSelection.nEndPara; + aSelection.nStartPos = aSelection.nEndPos; + } + + SvxFieldItem aItem(pHeaderField->CreateFieldItem()); + + SvxTextForwarder* pForwarder = pEditSource->GetTextForwarder(); + pForwarder->QuickInsertField( aItem, aSelection ); + pEditSource->UpdateData(); + + // neue Selektion: ein Zeichen + aSelection.Adjust(); + aSelection.nEndPara = aSelection.nStartPara; + aSelection.nEndPos = aSelection.nStartPos + 1; + pHeaderField->InitDoc( &aTextData.GetContentObj(), aTextData.GetPart(), aSelection ); + + // #91431# for bAbsorb=FALSE, the new selection must be behind the inserted content + // (the xml filter relies on this) + if (!bAbsorb) + aSelection.nStartPos = aSelection.nEndPos; + + pTextRange->SetSelection( aSelection ); + + return; + } + } + + if (!pUnoText) + CreateUnoText_Impl(); + pUnoText->insertTextContent( xRange, xContent, bAbsorb ); +} + +void SAL_CALL ScHeaderFooterTextObj::removeTextContent( + const uno::Reference<text::XTextContent>& xContent ) + throw(container::NoSuchElementException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + if ( xContent.is() ) + { + ScHeaderFieldObj* pHeaderField = ScHeaderFieldObj::getImplementation( xContent ); + if ( pHeaderField && pHeaderField->IsInserted() ) + { + //! Testen, ob das Feld in dieser Zelle ist + pHeaderField->DeleteField(); + return; + } + } + if (!pUnoText) + CreateUnoText_Impl(); + pUnoText->removeTextContent( xContent ); +} + +uno::Reference<text::XText> SAL_CALL ScHeaderFooterTextObj::getText() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (!pUnoText) + CreateUnoText_Impl(); + return pUnoText->getText(); +} + +uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextObj::getStart() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (!pUnoText) + CreateUnoText_Impl(); + return pUnoText->getStart(); +} + +uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextObj::getEnd() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (!pUnoText) + CreateUnoText_Impl(); + return pUnoText->getEnd(); +} + +// XTextFieldsSupplier + +uno::Reference<container::XEnumerationAccess> SAL_CALL ScHeaderFooterTextObj::getTextFields() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + // all fields + return new ScHeaderFieldsObj( &aTextData.GetContentObj(), aTextData.GetPart(), SC_SERVICE_INVALID ); +} + +uno::Reference<container::XNameAccess> SAL_CALL ScHeaderFooterTextObj::getTextFieldMasters() + throw(uno::RuntimeException) +{ + // sowas gibts nicht im Calc (?) + return NULL; +} + +// XTextRangeMover + +void SAL_CALL ScHeaderFooterTextObj::moveTextRange( + const uno::Reference<text::XTextRange>& xRange, + sal_Int16 nParagraphs ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (!pUnoText) + CreateUnoText_Impl(); + pUnoText->moveTextRange( xRange, nParagraphs ); +} + +// XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScHeaderFooterTextObj::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (!pUnoText) + CreateUnoText_Impl(); + return pUnoText->createEnumeration(); +} + +// XElementAccess + +uno::Type SAL_CALL ScHeaderFooterTextObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (!pUnoText) + CreateUnoText_Impl(); + return pUnoText->getElementType(); +} + +sal_Bool SAL_CALL ScHeaderFooterTextObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (!pUnoText) + CreateUnoText_Impl(); + return pUnoText->hasElements(); +} + +//------------------------------------------------------------------------ + +ScCellTextCursor::ScCellTextCursor(const ScCellTextCursor& rOther) : + SvxUnoTextCursor( rOther ), + rTextObj( rOther.rTextObj ) +{ + rTextObj.acquire(); +} + +ScCellTextCursor::ScCellTextCursor(ScCellObj& rText) : + SvxUnoTextCursor( rText.GetUnoText() ), + rTextObj( rText ) +{ + rTextObj.acquire(); +} + +ScCellTextCursor::~ScCellTextCursor() throw() +{ + rTextObj.release(); +} + +// SvxUnoTextCursor methods reimplemented here to return the right objects: + +uno::Reference<text::XText> SAL_CALL ScCellTextCursor::getText() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return &rTextObj; +} + +uno::Reference<text::XTextRange> SAL_CALL ScCellTextCursor::getStart() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + //! use other object for range than cursor? + + ScCellTextCursor* pNew = new ScCellTextCursor( *this ); + uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) ); + + ESelection aNewSel(GetSelection()); + aNewSel.nEndPara = aNewSel.nStartPara; + aNewSel.nEndPos = aNewSel.nStartPos; + pNew->SetSelection( aNewSel ); + + return xRange; +} + +uno::Reference<text::XTextRange> SAL_CALL ScCellTextCursor::getEnd() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + //! use other object for range than cursor? + + ScCellTextCursor* pNew = new ScCellTextCursor( *this ); + uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) ); + + ESelection aNewSel(GetSelection()); + aNewSel.nStartPara = aNewSel.nEndPara; + aNewSel.nStartPos = aNewSel.nEndPos; + pNew->SetSelection( aNewSel ); + + return xRange; +} + +// XUnoTunnel + +sal_Int64 SAL_CALL ScCellTextCursor::getSomething( + const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); + } + return SvxUnoTextCursor::getSomething( rId ); +} + +// static +const uno::Sequence<sal_Int8>& ScCellTextCursor::getUnoTunnelId() +{ + static uno::Sequence<sal_Int8> * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +// static +ScCellTextCursor* ScCellTextCursor::getImplementation( const uno::Reference<uno::XInterface> xObj ) +{ + ScCellTextCursor* pRet = NULL; + uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); + if (xUT.is()) + pRet = reinterpret_cast<ScCellTextCursor*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId()))); + return pRet; +} + +//------------------------------------------------------------------------ + +ScHeaderFooterTextCursor::ScHeaderFooterTextCursor(const ScHeaderFooterTextCursor& rOther) : + SvxUnoTextCursor( rOther ), + rTextObj( rOther.rTextObj ) +{ + rTextObj.acquire(); +} + +ScHeaderFooterTextCursor::ScHeaderFooterTextCursor(ScHeaderFooterTextObj& rText) : + SvxUnoTextCursor( rText.GetUnoText() ), + rTextObj( rText ) +{ + rTextObj.acquire(); +} + +ScHeaderFooterTextCursor::~ScHeaderFooterTextCursor() throw() +{ + rTextObj.release(); +} + +// SvxUnoTextCursor methods reimplemented here to return the right objects: + +uno::Reference<text::XText> SAL_CALL ScHeaderFooterTextCursor::getText() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return &rTextObj; +} + +uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextCursor::getStart() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + //! use other object for range than cursor? + + ScHeaderFooterTextCursor* pNew = new ScHeaderFooterTextCursor( *this ); + uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) ); + + ESelection aNewSel(GetSelection()); + aNewSel.nEndPara = aNewSel.nStartPara; + aNewSel.nEndPos = aNewSel.nStartPos; + pNew->SetSelection( aNewSel ); + + return xRange; +} + +uno::Reference<text::XTextRange> SAL_CALL ScHeaderFooterTextCursor::getEnd() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + //! use other object for range than cursor? + + ScHeaderFooterTextCursor* pNew = new ScHeaderFooterTextCursor( *this ); + uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) ); + + ESelection aNewSel(GetSelection()); + aNewSel.nStartPara = aNewSel.nEndPara; + aNewSel.nStartPos = aNewSel.nEndPos; + pNew->SetSelection( aNewSel ); + + return xRange; +} + +// XUnoTunnel + +sal_Int64 SAL_CALL ScHeaderFooterTextCursor::getSomething( + const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); + } + return SvxUnoTextCursor::getSomething( rId ); +} + +// static +const uno::Sequence<sal_Int8>& ScHeaderFooterTextCursor::getUnoTunnelId() +{ + static uno::Sequence<sal_Int8> * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +// static +ScHeaderFooterTextCursor* ScHeaderFooterTextCursor::getImplementation( + const uno::Reference<uno::XInterface> xObj ) +{ + ScHeaderFooterTextCursor* pRet = NULL; + uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); + if (xUT.is()) + pRet = reinterpret_cast<ScHeaderFooterTextCursor*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId()))); + return pRet; +} + +//------------------------------------------------------------------------ + +ScDrawTextCursor::ScDrawTextCursor(const ScDrawTextCursor& rOther) : + SvxUnoTextCursor( rOther ), + xParentText( rOther.xParentText ) +{ +} + +ScDrawTextCursor::ScDrawTextCursor( const uno::Reference<text::XText>& xParent, + const SvxUnoTextBase& rText ) : + SvxUnoTextCursor( rText ), + xParentText( xParent ) + +{ +} + +ScDrawTextCursor::~ScDrawTextCursor() throw() +{ +} + +// SvxUnoTextCursor methods reimplemented here to return the right objects: + +uno::Reference<text::XText> SAL_CALL ScDrawTextCursor::getText() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return xParentText; +} + +uno::Reference<text::XTextRange> SAL_CALL ScDrawTextCursor::getStart() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + //! use other object for range than cursor? + + ScDrawTextCursor* pNew = new ScDrawTextCursor( *this ); + uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) ); + + ESelection aNewSel(GetSelection()); + aNewSel.nEndPara = aNewSel.nStartPara; + aNewSel.nEndPos = aNewSel.nStartPos; + pNew->SetSelection( aNewSel ); + + return xRange; +} + +uno::Reference<text::XTextRange> SAL_CALL ScDrawTextCursor::getEnd() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + //! use other object for range than cursor? + + ScDrawTextCursor* pNew = new ScDrawTextCursor( *this ); + uno::Reference<text::XTextRange> xRange( static_cast<SvxUnoTextRangeBase*>(pNew) ); + + ESelection aNewSel(GetSelection()); + aNewSel.nStartPara = aNewSel.nEndPara; + aNewSel.nStartPos = aNewSel.nEndPos; + pNew->SetSelection( aNewSel ); + + return xRange; +} + +// XUnoTunnel + +sal_Int64 SAL_CALL ScDrawTextCursor::getSomething( + const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); + } + return SvxUnoTextCursor::getSomething( rId ); +} + +// static +const uno::Sequence<sal_Int8>& ScDrawTextCursor::getUnoTunnelId() +{ + static uno::Sequence<sal_Int8> * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +// static +ScDrawTextCursor* ScDrawTextCursor::getImplementation( const uno::Reference<uno::XInterface> xObj ) +{ + ScDrawTextCursor* pRet = NULL; + uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); + if (xUT.is()) + pRet = reinterpret_cast<ScDrawTextCursor*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId()))); + return pRet; +} + +//------------------------------------------------------------------------ + +ScSimpleEditSourceHelper::ScSimpleEditSourceHelper() +{ + SfxItemPool* pEnginePool = EditEngine::CreatePool(); + pEnginePool->SetDefaultMetric( SFX_MAPUNIT_100TH_MM ); + pEnginePool->FreezeIdRanges(); + + pEditEngine = new ScFieldEditEngine( pEnginePool, NULL, TRUE ); // TRUE: become owner of pool + pForwarder = new SvxEditEngineForwarder( *pEditEngine ); + pOriginalSource = new ScSimpleEditSource( pForwarder ); +} + +ScSimpleEditSourceHelper::~ScSimpleEditSourceHelper() +{ + ScUnoGuard aGuard; // needed for EditEngine dtor + + delete pOriginalSource; + delete pForwarder; + delete pEditEngine; +} + +ScEditEngineTextObj::ScEditEngineTextObj() : + SvxUnoText( GetOriginalSource(), ScCellObj::GetEditPropertySet(), uno::Reference<text::XText>() ) +{ +} + +ScEditEngineTextObj::~ScEditEngineTextObj() throw() +{ +} + +void ScEditEngineTextObj::SetText( const EditTextObject& rTextObject ) +{ + GetEditEngine()->SetText( rTextObject ); + + ESelection aSel; + ::GetSelection( aSel, GetEditSource()->GetTextForwarder() ); + SetSelection( aSel ); +} + +EditTextObject* ScEditEngineTextObj::CreateTextObject() +{ + return GetEditEngine()->CreateTextObject(); +} + +//------------------------------------------------------------------------ + +ScCellTextData::ScCellTextData(ScDocShell* pDocSh, const ScAddress& rP) : + pDocShell( pDocSh ), + aCellPos( rP ), + pEditEngine( NULL ), + pForwarder( NULL ), + pOriginalSource( NULL ), + bDataValid( FALSE ), + bInUpdate( FALSE ), + bDirty( FALSE ), + bDoUpdate( TRUE ) +{ + if (pDocShell) + pDocShell->GetDocument()->AddUnoObject(*this); +} + +ScCellTextData::~ScCellTextData() +{ + ScUnoGuard aGuard; // needed for EditEngine dtor + + if (pDocShell) + { + pDocShell->GetDocument()->RemoveUnoObject(*this); + pDocShell->GetDocument()->DisposeFieldEditEngine(pEditEngine); + } + else + delete pEditEngine; + + delete pForwarder; + + delete pOriginalSource; +} + +ScSharedCellEditSource* ScCellTextData::GetOriginalSource() +{ + if (!pOriginalSource) + pOriginalSource = new ScSharedCellEditSource( this ); + return pOriginalSource; +} + +void ScCellTextData::GetCellText(const ScAddress& rCellPos, String& rText) +{ + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + pDoc->GetInputString( rCellPos.Col(), rCellPos.Row(), rCellPos.Tab(), rText ); + } +} + +SvxTextForwarder* ScCellTextData::GetTextForwarder() +{ + if (!pEditEngine) + { + if ( pDocShell ) + { + ScDocument* pDoc = pDocShell->GetDocument(); + pEditEngine = pDoc->CreateFieldEditEngine(); + } + else + { + SfxItemPool* pEnginePool = EditEngine::CreatePool(); + pEnginePool->FreezeIdRanges(); + pEditEngine = new ScFieldEditEngine( pEnginePool, NULL, TRUE ); + } + // currently, GetPortions doesn't work if UpdateMode is FALSE, + // this will be fixed (in EditEngine) by src600 +// pEditEngine->SetUpdateMode( FALSE ); + pEditEngine->EnableUndo( FALSE ); + if (pDocShell) + pEditEngine->SetRefDevice(pDocShell->GetRefDevice()); + else + pEditEngine->SetRefMapMode( MAP_100TH_MM ); + pForwarder = new SvxEditEngineForwarder(*pEditEngine); + } + + if (bDataValid) + return pForwarder; + + String aText; + + if (pDocShell) + { + ScDocument* pDoc = pDocShell->GetDocument(); + + SfxItemSet aDefaults( pEditEngine->GetEmptyItemSet() ); + if( const ScPatternAttr* pPattern = + pDoc->GetPattern( aCellPos.Col(), aCellPos.Row(), aCellPos.Tab() ) ) + { + pPattern->FillEditItemSet( &aDefaults ); + pPattern->FillEditParaItems( &aDefaults ); // including alignment etc. (for reading) + } + + const ScBaseCell* pCell = pDoc->GetCell( aCellPos ); + if ( pCell && pCell->GetCellType() == CELLTYPE_EDIT ) + pEditEngine->SetTextNewDefaults( *((const ScEditCell*)pCell)->GetData(), aDefaults ); + else + { + GetCellText( aCellPos, aText ); + if (aText.Len()) + pEditEngine->SetTextNewDefaults( aText, aDefaults ); + else + pEditEngine->SetDefaults(aDefaults); + } + } + + bDataValid = TRUE; + return pForwarder; +} + +void ScCellTextData::UpdateData() +{ + if ( bDoUpdate ) + { + DBG_ASSERT(pEditEngine != NULL, "no EditEngine for UpdateData()"); + if ( pDocShell && pEditEngine ) + { + // during the own UpdateData call, bDataValid must not be reset, + // or things like attributes after the text would be lost + // (are not stored in the cell) + + bInUpdate = TRUE; // prevents bDataValid from being reset + + ScDocFunc aFunc(*pDocShell); + aFunc.PutData( aCellPos, *pEditEngine, FALSE, TRUE ); // always as text + + bInUpdate = FALSE; + bDirty = FALSE; + } + } + else + bDirty = TRUE; +} + +void ScCellTextData::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( ScUpdateRefHint ) ) + { +// const ScUpdateRefHint& rRef = (const ScUpdateRefHint&)rHint; + + //! Ref-Update + } + else if ( rHint.ISA( SfxSimpleHint ) ) + { + ULONG nId = ((const SfxSimpleHint&)rHint).GetId(); + if ( nId == SFX_HINT_DYING ) + { + pDocShell = NULL; // invalid now + + DELETEZ( pForwarder ); + DELETEZ( pEditEngine ); // EditEngine uses document's pool + } + else if ( nId == SFX_HINT_DATACHANGED ) + { + if (!bInUpdate) // not for own UpdateData calls + bDataValid = FALSE; // text has to be read from the cell again + } + } +} + +ScCellTextObj::ScCellTextObj(ScDocShell* pDocSh, const ScAddress& rP) : + ScCellTextData( pDocSh, rP ), + SvxUnoText( GetOriginalSource(), ScCellObj::GetEditPropertySet(), uno::Reference<text::XText>() ) +{ +} + +ScCellTextObj::~ScCellTextObj() throw() +{ +} + diff --git a/sc/source/ui/unoobj/tokenuno.cxx b/sc/source/ui/unoobj/tokenuno.cxx new file mode 100644 index 000000000000..5e3b3102e14a --- /dev/null +++ b/sc/source/ui/unoobj/tokenuno.cxx @@ -0,0 +1,467 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +#include "tokenuno.hxx" + +#include <com/sun/star/sheet/ComplexReference.hpp> +#include <com/sun/star/sheet/ExternalReference.hpp> +#include <com/sun/star/sheet/ReferenceFlags.hpp> +#include <com/sun/star/sheet/AddressConvention.hpp> +#include <com/sun/star/table/CellAddress.hpp> + +#include <svl/itemprop.hxx> + +#include "miscuno.hxx" +#include "convuno.hxx" +#include "unonames.hxx" +#include "unoguard.hxx" +#include "token.hxx" +#include "compiler.hxx" +#include "tokenarray.hxx" +#include "docsh.hxx" +#include "rangeseq.hxx" +#include "externalrefmgr.hxx" + +using namespace ::formula; +using namespace ::com::sun::star; + +// ============================================================================ + +const SfxItemPropertyMapEntry* lcl_GetFormulaParserMap() +{ + static SfxItemPropertyMapEntry aFormulaParserMap_Impl[] = + { + {MAP_CHAR_LEN(SC_UNO_COMPILEFAP), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_COMPILEENGLISH), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_IGNORELEADING), 0, &getBooleanCppuType(), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_FORMULACONVENTION), 0, &getCppuType(&sheet::AddressConvention::UNSPECIFIED), 0, 0 }, + {MAP_CHAR_LEN(SC_UNO_OPCODEMAP), 0, &getCppuType((uno::Sequence< sheet::FormulaOpCodeMapEntry >*)0), 0, 0 }, + {0,0,0,0,0,0} + }; + return aFormulaParserMap_Impl; +} + +SC_SIMPLE_SERVICE_INFO( ScFormulaParserObj, "ScFormulaParserObj", SC_SERVICENAME_FORMULAPARS ) + +// ============================================================================ + +ScFormulaParserObj::ScFormulaParserObj(ScDocShell* pDocSh) : + mpDocShell( pDocSh ), + mnConv( sheet::AddressConvention::UNSPECIFIED ), + mbEnglish( false ), + mbIgnoreSpaces( true ), + mbCompileFAP( false ) +{ + mpDocShell->GetDocument()->AddUnoObject(*this); +} + +ScFormulaParserObj::~ScFormulaParserObj() +{ + if (mpDocShell) + mpDocShell->GetDocument()->RemoveUnoObject(*this); +} + +void ScFormulaParserObj::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( SfxSimpleHint ) && ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + mpDocShell = NULL; +} + +// XFormulaParser + +void ScFormulaParserObj::SetCompilerFlags( ScCompiler& rCompiler ) const +{ + static const formula::FormulaGrammar::AddressConvention aConvMap[] = { + formula::FormulaGrammar::CONV_OOO, // <- AddressConvention::OOO + formula::FormulaGrammar::CONV_XL_A1, // <- AddressConvention::XL_A1 + formula::FormulaGrammar::CONV_XL_R1C1, // <- AddressConvention::XL_R1C1 + formula::FormulaGrammar::CONV_XL_OOX, // <- AddressConvention::XL_OOX + formula::FormulaGrammar::CONV_LOTUS_A1 // <- AddressConvention::LOTUS_A1 + }; + static const sal_Int16 nConvMapCount = sizeof(aConvMap)/sizeof(aConvMap[0]); + + // If mxOpCodeMap is not empty it overrides mbEnglish, and vice versa. We + // don't need to initialize things twice. + if (mxOpCodeMap.get()) + rCompiler.SetFormulaLanguage( mxOpCodeMap ); + else + { + sal_Int32 nFormulaLanguage = mbEnglish ? + sheet::FormulaLanguage::ENGLISH : + sheet::FormulaLanguage::NATIVE; + ScCompiler::OpCodeMapPtr xMap = rCompiler.GetOpCodeMap( nFormulaLanguage); + rCompiler.SetFormulaLanguage( xMap); + } + + formula::FormulaGrammar::AddressConvention eConv = formula::FormulaGrammar::CONV_UNSPECIFIED; + if (mnConv >= 0 && mnConv < nConvMapCount) + eConv = aConvMap[mnConv]; + + rCompiler.SetRefConvention( eConv ); + + rCompiler.SetCompileForFAP(mbCompileFAP); + + rCompiler.SetExternalLinks( maExternalLinks); +} + +uno::Sequence<sheet::FormulaToken> SAL_CALL ScFormulaParserObj::parseFormula( + const rtl::OUString& aFormula, const table::CellAddress& rReferencePos ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Sequence<sheet::FormulaToken> aRet; + + if (mpDocShell) + { + ScDocument* pDoc = mpDocShell->GetDocument(); + ScExternalRefManager::ApiGuard aExtRefGuard(pDoc); + + ScAddress aRefPos( ScAddress::UNINITIALIZED ); + ScUnoConversion::FillScAddress( aRefPos, rReferencePos ); + ScCompiler aCompiler( pDoc, aRefPos); + aCompiler.SetGrammar(pDoc->GetGrammar()); + SetCompilerFlags( aCompiler ); + + ScTokenArray* pCode = aCompiler.CompileString( aFormula ); + (void)ScTokenConversion::ConvertToTokenSequence( *pDoc, aRet, *pCode ); + delete pCode; + } + + return aRet; +} + +rtl::OUString SAL_CALL ScFormulaParserObj::printFormula( + const uno::Sequence<sheet::FormulaToken>& aTokens, const table::CellAddress& rReferencePos ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + rtl::OUString aRet; + + if (mpDocShell) + { + ScDocument* pDoc = mpDocShell->GetDocument(); + ScTokenArray aCode; + (void)ScTokenConversion::ConvertToTokenArray( *pDoc, aCode, aTokens ); + ScAddress aRefPos( ScAddress::UNINITIALIZED ); + ScUnoConversion::FillScAddress( aRefPos, rReferencePos ); + ScCompiler aCompiler( pDoc, aRefPos, aCode); + aCompiler.SetGrammar(pDoc->GetGrammar()); + SetCompilerFlags( aCompiler ); + + rtl::OUStringBuffer aBuffer; + aCompiler.CreateStringFromTokenArray( aBuffer ); + aRet = aBuffer.makeStringAndClear(); + } + + return aRet; +} + +// XPropertySet + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScFormulaParserObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference< beans::XPropertySetInfo > aRef(new SfxItemPropertySetInfo( lcl_GetFormulaParserMap() )); + return aRef; +} + +void SAL_CALL ScFormulaParserObj::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aString(aPropertyName); + if ( aString.EqualsAscii( SC_UNO_COMPILEFAP ) ) + { + aValue >>= mbCompileFAP; + } + else if ( aString.EqualsAscii( SC_UNO_COMPILEENGLISH ) ) + { + bool bOldEnglish = mbEnglish; + if (aValue >>= mbEnglish) + { + // Need to recreate the symbol map to change English property + // because the map is const. So for performance reasons set + // CompileEnglish _before_ OpCodeMap! + if (mxOpCodeMap.get() && mbEnglish != bOldEnglish) + { + ScDocument* pDoc = mpDocShell->GetDocument(); + ScCompiler aCompiler( pDoc, ScAddress()); + aCompiler.SetGrammar(pDoc->GetGrammar()); + mxOpCodeMap = aCompiler.CreateOpCodeMap( maOpCodeMapping, mbEnglish); + } + } + else + throw lang::IllegalArgumentException(); + } + else if ( aString.EqualsAscii( SC_UNO_FORMULACONVENTION ) ) + { + aValue >>= mnConv; + } + else if ( aString.EqualsAscii( SC_UNO_IGNORELEADING ) ) + { + aValue >>= mbIgnoreSpaces; + } + else if ( aString.EqualsAscii( SC_UNO_OPCODEMAP ) ) + { + if (aValue >>= maOpCodeMapping) + { + ScDocument* pDoc = mpDocShell->GetDocument(); + ScCompiler aCompiler( pDoc, ScAddress()); + aCompiler.SetGrammar(pDoc->GetGrammar()); + mxOpCodeMap = aCompiler.CreateOpCodeMap( maOpCodeMapping, mbEnglish); + } + else + throw lang::IllegalArgumentException(); + } + else if ( aString.EqualsAscii( SC_UNO_EXTERNALLINKS ) ) + { + if (!(aValue >>= maExternalLinks)) + throw lang::IllegalArgumentException(); + } + else + throw beans::UnknownPropertyException(); +} + +uno::Any SAL_CALL ScFormulaParserObj::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Any aRet; + String aString(aPropertyName); + if ( aString.EqualsAscii( SC_UNO_COMPILEFAP ) ) + { + aRet <<= mbCompileFAP; + } + else if ( aString.EqualsAscii( SC_UNO_COMPILEENGLISH ) ) + { + aRet <<= mbEnglish; + } + else if ( aString.EqualsAscii( SC_UNO_FORMULACONVENTION ) ) + { + aRet <<= mnConv; + } + else if ( aString.EqualsAscii( SC_UNO_IGNORELEADING ) ) + { + aRet <<= mbIgnoreSpaces; + } + else if ( aString.EqualsAscii( SC_UNO_OPCODEMAP ) ) + { + aRet <<= maOpCodeMapping; + } + else if ( aString.EqualsAscii( SC_UNO_EXTERNALLINKS ) ) + { + aRet <<= maExternalLinks; + } + else + throw beans::UnknownPropertyException(); + return aRet; +} + +SC_IMPL_DUMMY_PROPERTY_LISTENER( ScFormulaParserObj ) + +// ============================================================================ + +void lcl_ExternalRefToApi( sheet::SingleReference& rAPI, const ScSingleRefData& rRef ) +{ + rAPI.Column = rRef.nCol; + rAPI.Row = rRef.nRow; + rAPI.Sheet = 0; + rAPI.RelativeColumn = rRef.nRelCol; + rAPI.RelativeRow = rRef.nRelRow; + rAPI.RelativeSheet = 0; + + sal_Int32 nFlags = 0; + if ( rRef.IsColRel() ) nFlags |= sheet::ReferenceFlags::COLUMN_RELATIVE; + if ( rRef.IsRowRel() ) nFlags |= sheet::ReferenceFlags::ROW_RELATIVE; + if ( rRef.IsColDeleted() ) nFlags |= sheet::ReferenceFlags::COLUMN_DELETED; + if ( rRef.IsRowDeleted() ) nFlags |= sheet::ReferenceFlags::ROW_DELETED; + if ( rRef.IsFlag3D() ) nFlags |= sheet::ReferenceFlags::SHEET_3D; + if ( rRef.IsRelName() ) nFlags |= sheet::ReferenceFlags::RELATIVE_NAME; + rAPI.Flags = nFlags; +} + +void lcl_SingleRefToApi( sheet::SingleReference& rAPI, const ScSingleRefData& rRef ) +{ + rAPI.Column = rRef.nCol; + rAPI.Row = rRef.nRow; + rAPI.Sheet = rRef.nTab; + rAPI.RelativeColumn = rRef.nRelCol; + rAPI.RelativeRow = rRef.nRelRow; + rAPI.RelativeSheet = rRef.nRelTab; + + sal_Int32 nFlags = 0; + if ( rRef.IsColRel() ) nFlags |= sheet::ReferenceFlags::COLUMN_RELATIVE; + if ( rRef.IsRowRel() ) nFlags |= sheet::ReferenceFlags::ROW_RELATIVE; + if ( rRef.IsTabRel() ) nFlags |= sheet::ReferenceFlags::SHEET_RELATIVE; + if ( rRef.IsColDeleted() ) nFlags |= sheet::ReferenceFlags::COLUMN_DELETED; + if ( rRef.IsRowDeleted() ) nFlags |= sheet::ReferenceFlags::ROW_DELETED; + if ( rRef.IsTabDeleted() ) nFlags |= sheet::ReferenceFlags::SHEET_DELETED; + if ( rRef.IsFlag3D() ) nFlags |= sheet::ReferenceFlags::SHEET_3D; + if ( rRef.IsRelName() ) nFlags |= sheet::ReferenceFlags::RELATIVE_NAME; + rAPI.Flags = nFlags; +} + +// static +bool ScTokenConversion::ConvertToTokenArray( ScDocument& rDoc, + ScTokenArray& rTokenArray, const uno::Sequence<sheet::FormulaToken>& rSequence ) +{ + return !rTokenArray.Fill(rSequence,rDoc.GetExternalRefManager()); +} + +// static +bool ScTokenConversion::ConvertToTokenSequence( ScDocument& rDoc, + uno::Sequence<sheet::FormulaToken>& rSequence, const ScTokenArray& rTokenArray ) +{ + bool bError = false; + + sal_Int32 nLen = static_cast<sal_Int32>(rTokenArray.GetLen()); + formula::FormulaToken** pTokens = rTokenArray.GetArray(); + if ( pTokens ) + { + rSequence.realloc(nLen); + for (sal_Int32 nPos=0; nPos<nLen; nPos++) + { + const formula::FormulaToken& rToken = *pTokens[nPos]; + sheet::FormulaToken& rAPI = rSequence[nPos]; + + OpCode eOpCode = rToken.GetOpCode(); + // eOpCode may be changed in the following switch/case + switch ( rToken.GetType() ) + { + case svByte: + // Only the count of spaces is stored as "long". Parameter count is ignored. + if ( eOpCode == ocSpaces ) + rAPI.Data <<= (sal_Int32) rToken.GetByte(); + else + rAPI.Data.clear(); // no data + break; + case formula::svDouble: + rAPI.Data <<= rToken.GetDouble(); + break; + case formula::svString: + rAPI.Data <<= rtl::OUString( rToken.GetString() ); + break; + case svExternal: + // Function name is stored as string. + // Byte (parameter count) is ignored. + rAPI.Data <<= rtl::OUString( rToken.GetExternal() ); + break; + case svSingleRef: + { + sheet::SingleReference aSingleRef; + lcl_SingleRefToApi( aSingleRef, static_cast<const ScToken&>(rToken).GetSingleRef() ); + rAPI.Data <<= aSingleRef; + } + break; + case formula::svDoubleRef: + { + sheet::ComplexReference aCompRef; + lcl_SingleRefToApi( aCompRef.Reference1, static_cast<const ScToken&>(rToken).GetSingleRef() ); + lcl_SingleRefToApi( aCompRef.Reference2, static_cast<const ScToken&>(rToken).GetSingleRef2() ); + rAPI.Data <<= aCompRef; + } + break; + case svIndex: + rAPI.Data <<= static_cast<sal_Int32>( rToken.GetIndex() ); + break; + case svMatrix: + if (!ScRangeToSequence::FillMixedArray( rAPI.Data, static_cast<const ScToken&>(rToken).GetMatrix(), true)) + rAPI.Data.clear(); + break; + case svExternalSingleRef: + { + sheet::SingleReference aSingleRef; + lcl_ExternalRefToApi( aSingleRef, static_cast<const ScToken&>(rToken).GetSingleRef() ); + size_t nCacheId; + rDoc.GetExternalRefManager()->getCacheTable( rToken.GetIndex(), rToken.GetString(), false, &nCacheId ); + aSingleRef.Sheet = static_cast< sal_Int32 >( nCacheId ); + sheet::ExternalReference aExtRef; + aExtRef.Index = rToken.GetIndex(); + aExtRef.Reference <<= aSingleRef; + rAPI.Data <<= aExtRef; + eOpCode = ocPush; + } + break; + case svExternalDoubleRef: + { + sheet::ComplexReference aComplRef; + lcl_ExternalRefToApi( aComplRef.Reference1, static_cast<const ScToken&>(rToken).GetSingleRef() ); + lcl_ExternalRefToApi( aComplRef.Reference2, static_cast<const ScToken&>(rToken).GetSingleRef2() ); + size_t nCacheId; + rDoc.GetExternalRefManager()->getCacheTable( rToken.GetIndex(), rToken.GetString(), false, &nCacheId ); + aComplRef.Reference1.Sheet = static_cast< sal_Int32 >( nCacheId ); + // NOTE: This assumes that cached sheets are in consecutive order! + aComplRef.Reference2.Sheet = aComplRef.Reference1.Sheet + (static_cast<const ScToken&>(rToken).GetSingleRef2().nTab - static_cast<const ScToken&>(rToken).GetSingleRef().nTab); + sheet::ExternalReference aExtRef; + aExtRef.Index = rToken.GetIndex(); + aExtRef.Reference <<= aComplRef; + rAPI.Data <<= aExtRef; + eOpCode = ocPush; + } + break; + case svExternalName: + { + sheet::ExternalReference aExtRef; + aExtRef.Index = rToken.GetIndex(); + aExtRef.Reference <<= ::rtl::OUString( rToken.GetString() ); + rAPI.Data <<= aExtRef; + eOpCode = ocPush; + } + break; + default: + DBG_ERROR1( "ScTokenConversion::ConvertToTokenSequence: unhandled token type SvStackVar %d", rToken.GetType()); + case svSep: // occurs with ocSep, ocOpen, ocClose, ocArray* + case svJump: // occurs with ocIf, ocChose + case svMissing: // occurs with ocMissing + rAPI.Data.clear(); // no data + } + rAPI.OpCode = static_cast<sal_Int32>(eOpCode); //! assuming equal values for the moment + } + } + else + rSequence.realloc(0); + + return !bError; +} + +// ============================================================================ + +ScFormulaOpCodeMapperObj::ScFormulaOpCodeMapperObj(::std::auto_ptr<formula::FormulaCompiler> _pCompiler) +: formula::FormulaOpCodeMapperObj(_pCompiler) +{ +} + +// ============================================================================ + diff --git a/sc/source/ui/unoobj/unodoc.cxx b/sc/source/ui/unoobj/unodoc.cxx new file mode 100644 index 000000000000..d3d755e8b495 --- /dev/null +++ b/sc/source/ui/unoobj/unodoc.cxx @@ -0,0 +1,67 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +// System - Includes ----------------------------------------------------- + +#include <tools/string.hxx> +#include <sfx2/docfac.hxx> +#include <sfx2/sfxmodelfactory.hxx> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> + +#include "scmod.hxx" +#include <vos/mutex.hxx> +#include <vcl/svapp.hxx> + +#include "docsh.hxx" + +using namespace ::com::sun::star; + +::rtl::OUString SAL_CALL ScDocument_getImplementationName() throw() +{ + return rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.Calc.SpreadsheetDocument" ) ); +} + +uno::Sequence< rtl::OUString > SAL_CALL ScDocument_getSupportedServiceNames() throw() +{ + uno::Sequence< rtl::OUString > aSeq( 1 ); + aSeq[0] = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.SpreadsheetDocument" )); + return aSeq; +} + +uno::Reference< uno::XInterface > SAL_CALL ScDocument_createInstance( + const uno::Reference< lang::XMultiServiceFactory > & /* rSMgr */, const sal_uInt64 _nCreationFlags ) throw( uno::Exception ) +{ + ::vos::OGuard aGuard( Application::GetSolarMutex() ); + ScDLL::Init(); + SfxObjectShell* pShell = new ScDocShell( _nCreationFlags ); + return uno::Reference< uno::XInterface >( pShell->GetModel() ); +} + + diff --git a/sc/source/ui/unoobj/unoguard.cxx b/sc/source/ui/unoobj/unoguard.cxx new file mode 100644 index 000000000000..ff1c94338b72 --- /dev/null +++ b/sc/source/ui/unoobj/unoguard.cxx @@ -0,0 +1,47 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + + +#include <vcl/svapp.hxx> +#include <tools/debug.hxx> + +#include "unoguard.hxx" + +//------------------------------------------------------------------------ + +ScUnoGuard::ScUnoGuard() : + OGuard( Application::GetSolarMutex() ) +{ +} + + + + diff --git a/sc/source/ui/unoobj/unoreflist.cxx b/sc/source/ui/unoobj/unoreflist.cxx new file mode 100644 index 000000000000..65f43273f6e7 --- /dev/null +++ b/sc/source/ui/unoobj/unoreflist.cxx @@ -0,0 +1,73 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + + +#include "unoreflist.hxx" +#include "document.hxx" + +//------------------------------------------------------------------------ + +ScUnoRefList::ScUnoRefList() +{ +} + +ScUnoRefList::~ScUnoRefList() +{ +} + +void ScUnoRefList::Add( sal_Int64 nId, const ScRangeList& rOldRanges ) +{ + aEntries.push_back( ScUnoRefEntry( nId, rOldRanges ) ); +} + +void ScUnoRefList::Undo( ScDocument* pDoc ) +{ + std::list<ScUnoRefEntry>::const_iterator aEnd( aEntries.end() ); + for ( std::list<ScUnoRefEntry>::const_iterator aIter( aEntries.begin() ); + aIter != aEnd; ++aIter ) + { + ScUnoRefUndoHint aHint( *aIter ); + pDoc->BroadcastUno( aHint ); + } +} + +//------------------------------------------------------------------------ + +TYPEINIT1(ScUnoRefUndoHint, SfxHint); + +ScUnoRefUndoHint::ScUnoRefUndoHint( const ScUnoRefEntry& rRefEntry ) : + aEntry( rRefEntry ) +{ +} + +ScUnoRefUndoHint::~ScUnoRefUndoHint() +{ +} + diff --git a/sc/source/ui/unoobj/viewuno.cxx b/sc/source/ui/unoobj/viewuno.cxx new file mode 100644 index 000000000000..fd1e655b8ffb --- /dev/null +++ b/sc/source/ui/unoobj/viewuno.cxx @@ -0,0 +1,2358 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +#include <com/sun/star/awt/MouseButton.hpp> +#include <com/sun/star/script/vba/VBAEventId.hpp> +#include <com/sun/star/script/vba/XVBAEventProcessor.hpp> +#include <com/sun/star/view/DocumentZoomType.hpp> + +#include <editeng/outliner.hxx> +#include <svx/fmdpage.hxx> +#include <svx/svditer.hxx> +#include <svx/svdmark.hxx> +#include <svx/svdouno.hxx> +#include <svx/svdpage.hxx> +#include <svx/svdpagv.hxx> +#include <svx/svdview.hxx> +#include <svx/unoshape.hxx> +#include <svx/unoshcol.hxx> +#include <svx/fmshell.hxx> +#include <sfx2/bindings.hxx> +#include <sfx2/dispatch.hxx> +#include <sfx2/printer.hxx> +#include <sfx2/request.hxx> +#include <sfx2/viewfrm.hxx> +#include <rtl/uuid.h> +#include <toolkit/helper/convert.hxx> + +#include "drawsh.hxx" +#include "drtxtob.hxx" +#include "transobj.hxx" +#include "editsh.hxx" +#include "viewuno.hxx" +#include "cellsuno.hxx" +#include "miscuno.hxx" +#include "tabvwsh.hxx" +#include "docsh.hxx" +#include "drwlayer.hxx" +#include "drawview.hxx" +#include "fupoor.hxx" +#include "sc.hrc" +#include "unoguard.hxx" +#include "unonames.hxx" +#include "scmod.hxx" +#include "appoptio.hxx" +#include "gridwin.hxx" +#include "sheetevents.hxx" +#include "AccessibilityHints.hxx" +#include <svx/sdrhittesthelper.hxx> + +using namespace com::sun::star; + +//------------------------------------------------------------------------ + +//! Clipping-Markierungen + +// alles ohne Which-ID, Map nur fuer PropertySetInfo + +const SfxItemPropertyMapEntry* lcl_GetViewOptPropertyMap() +{ + static SfxItemPropertyMapEntry aViewOptPropertyMap_Impl[] = + { + {MAP_CHAR_LEN(OLD_UNO_COLROWHDR), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_GRIDCOLOR), 0, &getCppuType((sal_Int32*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_COLROWHDR), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_HORSCROLL), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SHEETTABS), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_VERTSCROLL), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_HIDESPELL), 0, &getBooleanCppuType(), 0, 0}, /* deprecated #i91949 */ + {MAP_CHAR_LEN(OLD_UNO_HORSCROLL), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_OUTLSYMB), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_VALUEHIGH), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(OLD_UNO_OUTLSYMB), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(OLD_UNO_SHEETTABS), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SHOWANCHOR), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SHOWCHARTS), 0, &getCppuType((sal_Int16*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SHOWDRAW), 0, &getCppuType((sal_Int16*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SHOWFORM), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SHOWGRID), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SHOWHELP), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SHOWNOTES), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SHOWOBJ), 0, &getCppuType((sal_Int16*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SHOWPAGEBR), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SHOWZERO), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_SHOWSOLID), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(OLD_UNO_VALUEHIGH), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(OLD_UNO_VERTSCROLL), 0, &getBooleanCppuType(), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_VISAREA), 0, &getCppuType((awt::Rectangle*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_ZOOMTYPE), 0, &getCppuType((sal_Int16*)0), 0, 0}, + {MAP_CHAR_LEN(SC_UNO_ZOOMVALUE), 0, &getCppuType((sal_Int16*)0), 0, 0}, + {0,0,0,0,0,0} + }; + return aViewOptPropertyMap_Impl; +} + +//------------------------------------------------------------------------ + +SV_IMPL_PTRARR( XRangeSelectionListenerArr_Impl, XRangeSelectionListenerPtr ); +SV_IMPL_PTRARR( XRangeSelectionChangeListenerArr_Impl, XRangeSelectionChangeListenerPtr ); +SV_IMPL_PTRARR( XSelectionChangeListenerArr_Impl, XSelectionChangeListenerPtr ); +SV_IMPL_PTRARR( XViewPropertyChangeListenerArr_Impl, XViewPropertyChangeListenerPtr ); +SV_IMPL_PTRARR( XMouseClickHandlerArr_Impl, XMouseClickHandlerPtr ); +SV_IMPL_PTRARR( XActivationEventListenerArr_Impl, XActivationEventListenerPtr ); + +#define SCTABVIEWOBJ_SERVICE "com.sun.star.sheet.SpreadsheetView" +#define SCVIEWSETTINGS_SERVICE "com.sun.star.sheet.SpreadsheetViewSettings" + +SC_SIMPLE_SERVICE_INFO( ScViewPaneBase, "ScViewPaneObj", "com.sun.star.sheet.SpreadsheetViewPane" ) + +//------------------------------------------------------------------------ + +ScViewPaneBase::ScViewPaneBase(ScTabViewShell* pViewSh, USHORT nP) : + pViewShell( pViewSh ), + nPane( nP ) +{ + if (pViewShell) + StartListening(*pViewShell); +} + +ScViewPaneBase::~ScViewPaneBase() +{ + if (pViewShell) + EndListening(*pViewShell); +} + +void ScViewPaneBase::Notify( SfxBroadcaster&, const SfxHint& rHint ) +{ + if ( rHint.ISA( SfxSimpleHint ) && + ((const SfxSimpleHint&)rHint).GetId() == SFX_HINT_DYING ) + pViewShell = NULL; +} + +uno::Any SAL_CALL ScViewPaneBase::queryInterface( const uno::Type& rType ) + throw(uno::RuntimeException) +{ + SC_QUERYINTERFACE( sheet::XViewPane ) + SC_QUERYINTERFACE( sheet::XCellRangeReferrer ) + SC_QUERYINTERFACE( view::XFormLayerAccess ) + SC_QUERYINTERFACE( view::XControlAccess ) + SC_QUERYINTERFACE( lang::XServiceInfo ) + SC_QUERYINTERFACE( lang::XTypeProvider ) + + return uno::Any(); // OWeakObject is in derived objects +} + +uno::Sequence<uno::Type> SAL_CALL ScViewPaneBase::getTypes() throw(uno::RuntimeException) +{ + static uno::Sequence<uno::Type> aTypes; + if ( aTypes.getLength() == 0 ) + { + aTypes.realloc(5); + uno::Type* pPtr = aTypes.getArray(); + pPtr[0] = getCppuType((const uno::Reference<sheet::XViewPane>*)0); + pPtr[1] = getCppuType((const uno::Reference<sheet::XCellRangeReferrer>*)0); + pPtr[2] = getCppuType((const uno::Reference<view::XFormLayerAccess>*)0); + pPtr[3] = getCppuType((const uno::Reference<lang::XServiceInfo>*)0); + pPtr[4] = getCppuType((const uno::Reference<lang::XTypeProvider>*)0); + } + return aTypes; +} + +uno::Sequence<sal_Int8> SAL_CALL ScViewPaneBase::getImplementationId() + throw(uno::RuntimeException) +{ + static uno::Sequence< sal_Int8 > aId; + if( aId.getLength() == 0 ) + { + aId.realloc( 16 ); + rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True ); + } + return aId; +} + +// XViewPane + +sal_Int32 SAL_CALL ScViewPaneBase::getFirstVisibleColumn() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pViewShell) + { + ScViewData* pViewData = pViewShell->GetViewData(); + ScSplitPos eWhich = ( nPane == SC_VIEWPANE_ACTIVE ) ? + pViewData->GetActivePart() : + (ScSplitPos) nPane; + ScHSplitPos eWhichH = WhichH( eWhich ); + + return pViewData->GetPosX( eWhichH ); + } + DBG_ERROR("keine View ?!?"); //! Exception? + return 0; +} + +void SAL_CALL ScViewPaneBase::setFirstVisibleColumn( sal_Int32 nFirstVisibleColumn ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pViewShell) + { + ScViewData* pViewData = pViewShell->GetViewData(); + ScSplitPos eWhich = ( nPane == SC_VIEWPANE_ACTIVE ) ? + pViewData->GetActivePart() : + (ScSplitPos) nPane; + ScHSplitPos eWhichH = WhichH( eWhich ); + + long nDeltaX = ((long)nFirstVisibleColumn) - pViewData->GetPosX( eWhichH ); + pViewShell->ScrollX( nDeltaX, eWhichH ); + } +} + +sal_Int32 SAL_CALL ScViewPaneBase::getFirstVisibleRow() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pViewShell) + { + ScViewData* pViewData = pViewShell->GetViewData(); + ScSplitPos eWhich = ( nPane == SC_VIEWPANE_ACTIVE ) ? + pViewData->GetActivePart() : + (ScSplitPos) nPane; + ScVSplitPos eWhichV = WhichV( eWhich ); + + return pViewData->GetPosY( eWhichV ); + } + DBG_ERROR("keine View ?!?"); //! Exception? + return 0; +} + +void SAL_CALL ScViewPaneBase::setFirstVisibleRow( sal_Int32 nFirstVisibleRow ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pViewShell) + { + ScViewData* pViewData = pViewShell->GetViewData(); + ScSplitPos eWhich = ( nPane == SC_VIEWPANE_ACTIVE ) ? + pViewData->GetActivePart() : + (ScSplitPos) nPane; + ScVSplitPos eWhichV = WhichV( eWhich ); + + long nDeltaY = ((long)nFirstVisibleRow) - pViewData->GetPosY( eWhichV ); + pViewShell->ScrollY( nDeltaY, eWhichV ); + } +} + +table::CellRangeAddress SAL_CALL ScViewPaneBase::getVisibleRange() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + table::CellRangeAddress aAdr; + if (pViewShell) + { + ScViewData* pViewData = pViewShell->GetViewData(); + ScSplitPos eWhich = ( nPane == SC_VIEWPANE_ACTIVE ) ? + pViewData->GetActivePart() : + (ScSplitPos) nPane; + ScHSplitPos eWhichH = WhichH( eWhich ); + ScVSplitPos eWhichV = WhichV( eWhich ); + + // VisibleCellsX gibt nur komplett sichtbare Zellen, + // VisibleRange in Excel auch teilweise sichtbare. + //! anpassen ??? + + SCCOL nVisX = pViewData->VisibleCellsX( eWhichH ); + SCROW nVisY = pViewData->VisibleCellsY( eWhichV ); + if (!nVisX) nVisX = 1; // irgendwas muss ja im Range sein + if (!nVisY) nVisY = 1; + aAdr.Sheet = pViewData->GetTabNo(); + aAdr.StartColumn = pViewData->GetPosX( eWhichH ); + aAdr.StartRow = pViewData->GetPosY( eWhichV ); + aAdr.EndColumn = aAdr.StartColumn + nVisX - 1; + aAdr.EndRow = aAdr.StartRow + nVisY - 1; + } + return aAdr; +} + +// XCellRangeSource + +uno::Reference<table::XCellRange> SAL_CALL ScViewPaneBase::getReferredCells() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + if (pViewShell) + { + ScDocShell* pDocSh = pViewShell->GetViewData()->GetDocShell(); + + table::CellRangeAddress aAdr(getVisibleRange()); //! Hilfsfunktion mit ScRange? + ScRange aRange( (SCCOL)aAdr.StartColumn, (SCROW)aAdr.StartRow, aAdr.Sheet, + (SCCOL)aAdr.EndColumn, (SCROW)aAdr.EndRow, aAdr.Sheet ); + if ( aRange.aStart == aRange.aEnd ) + return new ScCellObj( pDocSh, aRange.aStart ); + else + return new ScCellRangeObj( pDocSh, aRange ); + } + + return NULL; +} + +namespace +{ + bool lcl_prepareFormShellCall( ScTabViewShell* _pViewShell, USHORT _nPane, FmFormShell*& _rpFormShell, Window*& _rpWindow, SdrView*& _rpSdrView ) + { + if ( !_pViewShell ) + return false; + + ScViewData* pViewData = _pViewShell->GetViewData(); + ScSplitPos eWhich = ( _nPane == SC_VIEWPANE_ACTIVE ) ? + pViewData->GetActivePart() : + (ScSplitPos) _nPane; + _rpWindow = _pViewShell->GetWindowByPos( eWhich ); + _rpSdrView = _pViewShell->GetSdrView(); + _rpFormShell = _pViewShell->GetFormShell(); + return ( _rpFormShell != NULL ) && ( _rpSdrView != NULL )&& ( _rpWindow != NULL ); + } +} + +// XFormLayerAccess +uno::Reference< form::runtime::XFormController > SAL_CALL ScViewPaneBase::getFormController( const uno::Reference< form::XForm >& _Form ) throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + + uno::Reference< form::runtime::XFormController > xController; + + Window* pWindow( NULL ); + SdrView* pSdrView( NULL ); + FmFormShell* pFormShell( NULL ); + if ( lcl_prepareFormShellCall( pViewShell, nPane, pFormShell, pWindow, pSdrView ) ) + xController = pFormShell->GetFormController( _Form, *pSdrView, *pWindow ); + + return xController; +} + +::sal_Bool SAL_CALL ScViewPaneBase::isFormDesignMode( ) throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + + sal_Bool bIsFormDesignMode( sal_True ); + + FmFormShell* pFormShell( pViewShell ? pViewShell->GetFormShell() : NULL ); + if ( pFormShell ) + bIsFormDesignMode = pFormShell->IsDesignMode(); + + return bIsFormDesignMode; +} + +void SAL_CALL ScViewPaneBase::setFormDesignMode( ::sal_Bool _DesignMode ) throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + + Window* pWindow( NULL ); + SdrView* pSdrView( NULL ); + FmFormShell* pFormShell( NULL ); + if ( lcl_prepareFormShellCall( pViewShell, nPane, pFormShell, pWindow, pSdrView ) ) + pFormShell->SetDesignMode( _DesignMode ); +} + +// XControlAccess + +uno::Reference<awt::XControl> SAL_CALL ScViewPaneBase::getControl( + const uno::Reference<awt::XControlModel>& xModel ) + throw(container::NoSuchElementException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + + uno::Reference<awt::XControl> xRet; + + Window* pWindow( NULL ); + SdrView* pSdrView( NULL ); + FmFormShell* pFormShell( NULL ); + if ( lcl_prepareFormShellCall( pViewShell, nPane, pFormShell, pWindow, pSdrView ) ) + pFormShell->GetFormControl( xModel, *pSdrView, *pWindow, xRet ); + + if ( !xRet.is() ) + throw container::NoSuchElementException(); // no control found + + return xRet; +} + +awt::Rectangle ScViewPaneBase::GetVisArea() const +{ + awt::Rectangle aVisArea; + if (pViewShell) + { + ScSplitPos eWhich = ( nPane == SC_VIEWPANE_ACTIVE ) ? + pViewShell->GetViewData()->GetActivePart() : + (ScSplitPos) nPane; + ScGridWindow* pWindow = (ScGridWindow*)pViewShell->GetWindowByPos(eWhich); + ScDocument* pDoc = pViewShell->GetViewData()->GetDocument(); + if (pWindow && pDoc) + { + ScHSplitPos eWhichH = ((eWhich == SC_SPLIT_TOPLEFT) || (eWhich == SC_SPLIT_BOTTOMLEFT)) ? + SC_SPLIT_LEFT : SC_SPLIT_RIGHT; + ScVSplitPos eWhichV = ((eWhich == SC_SPLIT_TOPLEFT) || (eWhich == SC_SPLIT_TOPRIGHT)) ? + SC_SPLIT_TOP : SC_SPLIT_BOTTOM; + ScAddress aCell(pViewShell->GetViewData()->GetPosX(eWhichH), + pViewShell->GetViewData()->GetPosY(eWhichV), + pViewShell->GetViewData()->GetTabNo()); + Rectangle aVisRect(pDoc->GetMMRect(aCell.Col(), aCell.Row(), aCell.Col(), aCell.Row(), aCell.Tab())); + + aVisRect.SetSize(pWindow->PixelToLogic(pWindow->GetSizePixel(), pWindow->GetDrawMapMode(sal_True))); + + aVisArea = AWTRectangle(aVisRect); + } + } + return aVisArea; +} + +//------------------------------------------------------------------------ + +ScViewPaneObj::ScViewPaneObj(ScTabViewShell* pViewSh, USHORT nP) : + ScViewPaneBase( pViewSh, nP ) +{ +} + +ScViewPaneObj::~ScViewPaneObj() +{ +} + +uno::Any SAL_CALL ScViewPaneObj::queryInterface( const uno::Type& rType ) + throw(uno::RuntimeException) +{ + // ScViewPaneBase has everything except OWeakObject + + uno::Any aRet(ScViewPaneBase::queryInterface( rType )); + if (!aRet.hasValue()) + aRet = OWeakObject::queryInterface( rType ); + return aRet; +} + +void SAL_CALL ScViewPaneObj::acquire() throw() +{ + OWeakObject::acquire(); +} + +void SAL_CALL ScViewPaneObj::release() throw() +{ + OWeakObject::release(); +} + +//------------------------------------------------------------------------ + +// Default-ctor wird fuer SMART_REFLECTION_IMPLEMENTATION gebraucht + +//UNUSED2008-05 ScTabViewObj::ScTabViewObj() : +//UNUSED2008-05 ScViewPaneBase( NULL, SC_VIEWPANE_ACTIVE ), +//UNUSED2008-05 SfxBaseController( NULL ), +//UNUSED2008-05 aPropSet( lcl_GetViewOptPropertyMap() ), +//UNUSED2008-05 aMouseClickHandlers( 0 ), +//UNUSED2008-05 aActivationListeners( 0 ), +//UNUSED2008-05 bDrawSelModeSet(sal_False), +//UNUSED2008-05 bFilteredRangeSelection(sal_True) +//UNUSED2008-05 { +//UNUSED2008-05 } + +ScTabViewObj::ScTabViewObj( ScTabViewShell* pViewSh ) : + ScViewPaneBase( pViewSh, SC_VIEWPANE_ACTIVE ), + SfxBaseController( pViewSh ), + aPropSet( lcl_GetViewOptPropertyMap() ), + aMouseClickHandlers( 0 ), + aActivationListeners( 0 ), + nPreviousTab( 0 ), + bDrawSelModeSet(sal_False) +{ + if (pViewSh) + nPreviousTab = pViewSh->GetViewData()->GetTabNo(); +} + +ScTabViewObj::~ScTabViewObj() +{ + //! Listening oder so + if (aMouseClickHandlers.Count()) + { + acquire(); + EndMouseListening(); + } + if (aActivationListeners.Count()) + { + acquire(); + EndActivationListening(); + } +} + +uno::Any SAL_CALL ScTabViewObj::queryInterface( const uno::Type& rType ) + throw(uno::RuntimeException) +{ + SC_QUERYINTERFACE( sheet::XSpreadsheetView ) + SC_QUERYINTERFACE( sheet::XEnhancedMouseClickBroadcaster ) + SC_QUERYINTERFACE( sheet::XActivationBroadcaster ) + SC_QUERYINTERFACE( container::XEnumerationAccess ) + SC_QUERYINTERFACE( container::XIndexAccess ) + SC_QUERY_MULTIPLE( container::XElementAccess, container::XIndexAccess ) + SC_QUERYINTERFACE( view::XSelectionSupplier ) + SC_QUERYINTERFACE( beans::XPropertySet ) + SC_QUERYINTERFACE( sheet::XViewSplitable ) + SC_QUERYINTERFACE( sheet::XViewFreezable ) + SC_QUERYINTERFACE( sheet::XRangeSelection ) + SC_QUERYINTERFACE( lang::XUnoTunnel ) + SC_QUERYINTERFACE( datatransfer::XTransferableSupplier ) + + uno::Any aRet(ScViewPaneBase::queryInterface( rType )); + if (!aRet.hasValue()) + aRet = SfxBaseController::queryInterface( rType ); + return aRet; +} + +void SAL_CALL ScTabViewObj::acquire() throw() +{ + SfxBaseController::acquire(); +} + +void SAL_CALL ScTabViewObj::release() throw() +{ + SfxBaseController::release(); +} + +void lcl_CallActivate( ScDocShell* pDocSh, SCTAB nTab, sal_Int32 nEvent ) +{ + ScDocument* pDoc = pDocSh->GetDocument(); + // when deleting a sheet, nPreviousTab can be invalid + // (could be handled with reference updates) + if (!pDoc->HasTable(nTab)) + return; + + const ScSheetEvents* pEvents = pDoc->GetSheetEvents(nTab); + if (pEvents) + { + const rtl::OUString* pScript = pEvents->GetScript(nEvent); + if (pScript) + { + uno::Any aRet; + uno::Sequence<uno::Any> aParams; + uno::Sequence<sal_Int16> aOutArgsIndex; + uno::Sequence<uno::Any> aOutArgs; + /*ErrCode eRet =*/ pDocSh->CallXScript( *pScript, aParams, aRet, aOutArgsIndex, aOutArgs ); + } + } + + // execute VBA event handlers + try + { + uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( pDoc->GetVbaEventProcessor(), uno::UNO_SET_THROW ); + // the parameter is the clicked object, as in the mousePressed call above + uno::Sequence< uno::Any > aArgs( 1 ); + aArgs[ 0 ] <<= nTab; + xVbaEvents->processVbaEvent( ScSheetEvents::GetVbaSheetEventId( nEvent ), aArgs ); + } + catch( uno::Exception& ) + { + } +} + +void ScTabViewObj::SheetChanged() +{ + if ( !GetViewShell() ) + return; + + ScViewData* pViewData = GetViewShell()->GetViewData(); + ScDocShell* pDocSh = pViewData->GetDocShell(); + if (aActivationListeners.Count() > 0) + { + sheet::ActivationEvent aEvent; + uno::Reference< sheet::XSpreadsheetView > xView(this); + uno::Reference< uno::XInterface > xSource(xView, uno::UNO_QUERY); + aEvent.Source = xSource; + aEvent.ActiveSheet = new ScTableSheetObj(pDocSh, pViewData->GetTabNo()); + for ( USHORT n=0; n<aActivationListeners.Count(); n++ ) + { + try + { + (*aActivationListeners[n])->activeSpreadsheetChanged( aEvent ); + } + catch( uno::Exception& ) + { + aActivationListeners.DeleteAndDestroy( n ); + --n; // because it will be increased again in the loop + } + } + } + + // handle sheet events + SCTAB nNewTab = pViewData->GetTabNo(); + if ( nNewTab != nPreviousTab ) + { + lcl_CallActivate( pDocSh, nPreviousTab, SC_SHEETEVENT_UNFOCUS ); + lcl_CallActivate( pDocSh, nNewTab, SC_SHEETEVENT_FOCUS ); + } + nPreviousTab = nNewTab; +} + +uno::Sequence<uno::Type> SAL_CALL ScTabViewObj::getTypes() throw(uno::RuntimeException) +{ + static uno::Sequence<uno::Type> aTypes; + if ( aTypes.getLength() == 0 ) + { + uno::Sequence<uno::Type> aViewPaneTypes(ScViewPaneBase::getTypes()); + long nViewPaneLen = aViewPaneTypes.getLength(); + const uno::Type* pViewPanePtr = aViewPaneTypes.getConstArray(); + + uno::Sequence<uno::Type> aControllerTypes(SfxBaseController::getTypes()); + long nControllerLen = aControllerTypes.getLength(); + const uno::Type* pControllerPtr = aControllerTypes.getConstArray(); + + long nParentLen = nViewPaneLen + nControllerLen; + + aTypes.realloc( nParentLen + 12 ); + uno::Type* pPtr = aTypes.getArray(); + pPtr[nParentLen + 0] = getCppuType((const uno::Reference<sheet::XSpreadsheetView>*)0); + pPtr[nParentLen + 1] = getCppuType((const uno::Reference<container::XEnumerationAccess>*)0); + pPtr[nParentLen + 2] = getCppuType((const uno::Reference<container::XIndexAccess>*)0); + pPtr[nParentLen + 3] = getCppuType((const uno::Reference<view::XSelectionSupplier>*)0); + pPtr[nParentLen + 4] = getCppuType((const uno::Reference<beans::XPropertySet>*)0); + pPtr[nParentLen + 5] = getCppuType((const uno::Reference<sheet::XViewSplitable>*)0); + pPtr[nParentLen + 6] = getCppuType((const uno::Reference<sheet::XViewFreezable>*)0); + pPtr[nParentLen + 7] = getCppuType((const uno::Reference<sheet::XRangeSelection>*)0); + pPtr[nParentLen + 8] = getCppuType((const uno::Reference<lang::XUnoTunnel>*)0); + pPtr[nParentLen + 9] = getCppuType((const uno::Reference<sheet::XEnhancedMouseClickBroadcaster>*)0); + pPtr[nParentLen + 10] = getCppuType((const uno::Reference<sheet::XActivationBroadcaster>*)0); + pPtr[nParentLen + 11] = getCppuType((const uno::Reference<datatransfer::XTransferableSupplier>*)0); + + long i; + for (i=0; i<nViewPaneLen; i++) + pPtr[i] = pViewPanePtr[i]; // parent types first + for (i=0; i<nControllerLen; i++) + pPtr[nViewPaneLen+i] = pControllerPtr[i]; + } + return aTypes; +} + +uno::Sequence<sal_Int8> SAL_CALL ScTabViewObj::getImplementationId() + throw(uno::RuntimeException) +{ + static uno::Sequence< sal_Int8 > aId; + if( aId.getLength() == 0 ) + { + aId.realloc( 16 ); + rtl_createUuid( (sal_uInt8 *)aId.getArray(), 0, sal_True ); + } + return aId; +} + +// XDocumentView + +BOOL lcl_TabInRanges( SCTAB nTab, const ScRangeList& rRanges ) +{ + ULONG nCount = rRanges.Count(); + for (ULONG i=0; i<nCount; i++) + { + const ScRange* pRange = rRanges.GetObject(i); + if ( nTab >= pRange->aStart.Tab() && nTab <= pRange->aEnd.Tab() ) + return TRUE; + } + return FALSE; +} + +void lcl_ShowObject( ScTabViewShell& rViewSh, ScDrawView& rDrawView, SdrObject* pSelObj ) +{ + BOOL bFound = FALSE; + SCTAB nObjectTab = 0; + + SdrModel* pModel = rDrawView.GetModel(); + USHORT nPageCount = pModel->GetPageCount(); + for (USHORT i=0; i<nPageCount && !bFound; i++) + { + SdrPage* pPage = pModel->GetPage(i); + if (pPage) + { + SdrObjListIter aIter( *pPage, IM_DEEPWITHGROUPS ); + SdrObject* pObject = aIter.Next(); + while (pObject && !bFound) + { + if ( pObject == pSelObj ) + { + bFound = TRUE; + nObjectTab = static_cast<SCTAB>(i); + } + pObject = aIter.Next(); + } + } + } + + if (bFound) + { + rViewSh.SetTabNo( nObjectTab ); + rViewSh.ScrollToObject( pSelObj ); + } +} + +sal_Bool SAL_CALL ScTabViewObj::select( const uno::Any& aSelection ) + throw(lang::IllegalArgumentException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScTabViewShell* pViewSh = GetViewShell(); + + if ( !pViewSh ) + return FALSE; + + //! Type of aSelection can be some specific interface instead of XInterface + + BOOL bRet = FALSE; + uno::Reference<uno::XInterface> xInterface(aSelection, uno::UNO_QUERY); + if ( !xInterface.is() ) //clear all selections + { + ScDrawView* pDrawView = pViewSh->GetScDrawView(); + if (pDrawView) + { + pDrawView->ScEndTextEdit(); + pDrawView->UnmarkAll(); + } + else //#102232#; if there is no DrawView remove range selection + pViewSh->Unmark(); + bRet = TRUE; + } + + if (bDrawSelModeSet) // remove DrawSelMode if set by API; if necessary it will be set again later + { + pViewSh->SetDrawSelMode(sal_False); + pViewSh->UpdateLayerLocks(); + bDrawSelModeSet = sal_False; + } + + if (bRet) + return bRet; + + + ScCellRangesBase* pRangesImp = ScCellRangesBase::getImplementation( xInterface ); + uno::Reference<drawing::XShapes> xShapeColl( xInterface, uno::UNO_QUERY ); + uno::Reference<drawing::XShape> xShapeSel( xInterface, uno::UNO_QUERY ); + SvxShape* pShapeImp = SvxShape::getImplementation( xShapeSel ); + + if (pRangesImp) // Zell-Ranges + { + ScViewData* pViewData = pViewSh->GetViewData(); + if ( pViewData->GetDocShell() == pRangesImp->GetDocShell() ) + { + // Zuerst evtl. Drawing-Selektion aufheben + // (MarkListHasChanged hebt Tabellen-Selektion auf) + + ScDrawView* pDrawView = pViewSh->GetScDrawView(); + if (pDrawView) + { + pDrawView->ScEndTextEdit(); + pDrawView->UnmarkAll(); + } + FuPoor* pFunc = pViewSh->GetDrawFuncPtr(); + if ( pFunc && pFunc->GetSlotID() != SID_OBJECT_SELECT ) + { + // Slot der Zeichenfunktion nochmal ausfuehren -> abschalten + SfxDispatcher* pDisp = pViewSh->GetDispatcher(); + if (pDisp) + pDisp->Execute( pFunc->GetSlotID(), SFX_CALLMODE_SYNCHRON ); + } + pViewSh->SetDrawShell(FALSE); + pViewSh->SetDrawSelMode(FALSE); // nach dem Dispatcher-Execute + + // Ranges selektieren + + const ScRangeList& rRanges = pRangesImp->GetRangeList(); + ULONG nRangeCount = rRanges.Count(); + // for empty range list, remove selection (cursor remains where it was) + if ( nRangeCount == 0 ) + pViewSh->Unmark(); + else if ( nRangeCount == 1 ) + pViewSh->MarkRange( *rRanges.GetObject(0) ); + else + { + // Mehrfachselektion + + const ScRange* pFirst = rRanges.GetObject(0); + if ( pFirst && !lcl_TabInRanges( pViewData->GetTabNo(), rRanges ) ) + pViewSh->SetTabNo( pFirst->aStart.Tab() ); + pViewSh->DoneBlockMode(); + pViewSh->InitOwnBlockMode(); + pViewData->GetMarkData().MarkFromRangeList( rRanges, TRUE ); + pViewSh->MarkDataChanged(); + pViewData->GetDocShell()->PostPaintGridAll(); // Markierung (alt&neu) + if ( pFirst ) + { + pViewSh->AlignToCursor( pFirst->aStart.Col(), pFirst->aStart.Row(), + SC_FOLLOW_JUMP ); + pViewSh->SetCursor( pFirst->aStart.Col(), pFirst->aStart.Row() ); + } + + //! Methode an der View, um RangeList zu selektieren + } + bRet = TRUE; + } + } + else if ( pShapeImp || xShapeColl.is() ) // Drawing-Layer + { + ScDrawView* pDrawView = pViewSh->GetScDrawView(); + if (pDrawView) + { + pDrawView->ScEndTextEdit(); + pDrawView->UnmarkAll(); + + if (pShapeImp) // einzelnes Shape + { + SdrObject *pObj = pShapeImp->GetSdrObject(); + if (pObj) + { + lcl_ShowObject( *pViewSh, *pDrawView, pObj ); + SdrPageView* pPV = pDrawView->GetSdrPageView(); + if ( pPV && pObj->GetPage() == pPV->GetPage() ) + { + pDrawView->MarkObj( pObj, pPV ); + bRet = TRUE; + } + } + } + else // Shape-Collection (xShapeColl ist nicht 0) + { + // Es wird auf die Tabelle des ersten Objekts umgeschaltet, + // und alle Objekte selektiert, die auf dieser Tabelle liegen + //! Exception, wenn Objekte auf verschiedenen Tabellen? + + SdrPageView* pPV = NULL; + long nCount = xShapeColl->getCount(); + if (nCount) + { + sal_Bool bAllMarked(sal_True); + for ( long i = 0; i < nCount; i++ ) + { + uno::Reference<drawing::XShape> xShapeInt(xShapeColl->getByIndex(i), uno::UNO_QUERY); + if (xShapeInt.is()) + { + SvxShape* pShape = SvxShape::getImplementation( xShapeInt ); + if (pShape) + { + SdrObject *pObj = pShape->GetSdrObject(); + if (pObj) + { + if (!bDrawSelModeSet && (pObj->GetLayer() == SC_LAYER_BACK)) + { + pViewSh->SetDrawSelMode(sal_True); + pViewSh->UpdateLayerLocks(); + bDrawSelModeSet = sal_True; + } + if (!pPV) // erstes Objekt + { + lcl_ShowObject( *pViewSh, *pDrawView, pObj ); + pPV = pDrawView->GetSdrPageView(); + } + if ( pPV && pObj->GetPage() == pPV->GetPage() ) + { + if (pDrawView->IsObjMarkable( pObj, pPV )) + pDrawView->MarkObj( pObj, pPV ); + else + bAllMarked = sal_False; + } + } + } + } + } + if (bAllMarked) + bRet = TRUE; + } + else + bRet = TRUE; // empty XShapes (all shapes are deselected) + } + + if (bRet) + pViewSh->SetDrawShell(TRUE); + } + } + + if (!bRet) + throw lang::IllegalArgumentException(); + + return bRet; +} + +uno::Any SAL_CALL ScTabViewObj::getSelection() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScTabViewShell* pViewSh = GetViewShell(); + ScCellRangesBase* pObj = NULL; + if (pViewSh) + { + // Ist auf dem Drawing-Layer etwas selektiert? + + SdrView* pDrawView = pViewSh->GetSdrView(); + if (pDrawView) + { + const SdrMarkList& rMarkList = pDrawView->GetMarkedObjectList(); + ULONG nMarkCount = rMarkList.GetMarkCount(); + if (nMarkCount) + { + // ShapeCollection erzeugen (wie in SdXImpressView::getSelection im Draw) + // Zurueckgegeben wird XInterfaceRef, das muss das UsrObject-XInterface sein + + SvxShapeCollection* pShapes = new SvxShapeCollection(); + uno::Reference<uno::XInterface> xRet(static_cast<cppu::OWeakObject*>(pShapes)); + + for (ULONG i=0; i<nMarkCount; i++) + { + SdrObject* pDrawObj = rMarkList.GetMark(i)->GetMarkedSdrObj(); + if (pDrawObj) + { + uno::Reference<drawing::XShape> xShape( pDrawObj->getUnoShape(), uno::UNO_QUERY ); + if (xShape.is()) + pShapes->add(xShape); + } + } + return uno::makeAny(xRet); + } + } + + // sonst Tabellen-(Zellen-)Selektion + + ScViewData* pViewData = pViewSh->GetViewData(); + ScDocShell* pDocSh = pViewData->GetDocShell(); + + const ScMarkData& rMark = pViewData->GetMarkData(); + SCTAB nTabs = rMark.GetSelectCount(); + + ScRange aRange; + ScMarkType eMarkType = pViewData->GetSimpleArea(aRange); + if ( nTabs == 1 && (eMarkType == SC_MARK_SIMPLE) ) + { + if (aRange.aStart == aRange.aEnd) + pObj = new ScCellObj( pDocSh, aRange.aStart ); + else + pObj = new ScCellRangeObj( pDocSh, aRange ); + } + else if ( nTabs == 1 && (eMarkType == SC_MARK_SIMPLE_FILTERED) ) + { + ScMarkData aFilteredMark( rMark ); + ScViewUtil::UnmarkFiltered( aFilteredMark, pDocSh->GetDocument()); + ScRangeList aRangeList; + aFilteredMark.FillRangeListWithMarks( &aRangeList, FALSE); + // Theoretically a selection may start and end on a filtered row. + switch (aRangeList.Count()) + { + case 0: + // No unfiltered row, we have to return some object, so + // here is one with no ranges. + pObj = new ScCellRangesObj( pDocSh, aRangeList ); + break; + case 1: + { + const ScRange& rRange = *(aRangeList.GetObject(0)); + if (rRange.aStart == rRange.aEnd) + pObj = new ScCellObj( pDocSh, rRange.aStart ); + else + pObj = new ScCellRangeObj( pDocSh, rRange ); + } + break; + default: + pObj = new ScCellRangesObj( pDocSh, aRangeList ); + } + } + else // Mehrfachselektion + { + ScRangeListRef xRanges; + pViewData->GetMultiArea( xRanges ); + + // bei mehreren Tabellen Ranges kopieren + //! sollte eigentlich schon in ScMarkData::FillRangeListWithMarks passieren? + if ( nTabs > 1 ) + rMark.ExtendRangeListTables( xRanges ); + + pObj = new ScCellRangesObj( pDocSh, *xRanges ); + } + + if ( !rMark.IsMarked() && !rMark.IsMultiMarked() ) + { + // remember if the selection was from the cursor position without anything selected + // (used when rendering the selection) + + pObj->SetCursorOnly( TRUE ); + } + } + + return uno::makeAny(uno::Reference<uno::XInterface>(static_cast<cppu::OWeakObject*>(pObj))); +} + + +#if 0 +// XPrintable + +rtl::OUString ScTabViewObj::getPrinterName(void) const +{ + ScUnoGuard aGuard; + ScTabViewShell* pViewSh = GetViewShell(); + if (pViewSh) + { + SfxPrinter* pPrinter = pViewSh->GetPrinter(TRUE); + if (pPrinter) + return pPrinter->GetName(); + } + + DBG_ERROR("getPrinterName: keine View oder kein Printer"); + return rtl::OUString(); +} + +void ScTabViewObj::setPrinterName(const rtl::OUString& PrinterName) +{ + ScUnoGuard aGuard; + // Drucker setzen - wie in SfxViewShell::ExecPrint_Impl + + ScTabViewShell* pViewSh = GetViewShell(); + if (pViewSh) + { + SfxPrinter* pPrinter = pViewSh->GetPrinter(TRUE); + if (pPrinter) + { + String aString(PrinterName); + SfxPrinter* pNewPrinter = new SfxPrinter( pPrinter->GetOptions().Clone(), aString ); + if (pNewPrinter->IsKnown()) + pViewSh->SetPrinter( pNewPrinter, SFX_PRINTER_PRINTER ); + else + delete pNewPrinter; + } + } +} + +XPropertySetRef ScTabViewObj::createPrintOptions(void) +{ + ScUnoGuard aGuard; + return new ScPrintSettingsObj; //! ScPrintSettingsObj implementieren! +} + +void ScTabViewObj::print(const XPropertySetRef& xOptions) +{ + ScUnoGuard aGuard; + ScTabViewShell* pViewSh = GetViewShell(); + if (pViewSh) + { + //! xOptions auswerten (wie denn?) + + SfxRequest aReq( SID_PRINTDOCDIRECT, SFX_CALLMODE_SYNCHRON, pViewSh->GetPool() ); + pViewSh->ExecuteSlot( aReq ); + } +} +#endif + +// XEnumerationAccess + +uno::Reference<container::XEnumeration> SAL_CALL ScTabViewObj::createEnumeration() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return new ScIndexEnumeration(this, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.sheet.SpreadsheetViewPanesEnumeration"))); +} + +// XIndexAccess + +sal_Int32 SAL_CALL ScTabViewObj::getCount() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScTabViewShell* pViewSh = GetViewShell(); + USHORT nPanes = 0; + if (pViewSh) + { + nPanes = 1; + ScViewData* pViewData = pViewSh->GetViewData(); + if ( pViewData->GetHSplitMode() != SC_SPLIT_NONE ) + nPanes *= 2; + if ( pViewData->GetVSplitMode() != SC_SPLIT_NONE ) + nPanes *= 2; + } + return nPanes; +} + +uno::Any SAL_CALL ScTabViewObj::getByIndex( sal_Int32 nIndex ) + throw(lang::IndexOutOfBoundsException, + lang::WrappedTargetException, uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<sheet::XViewPane> xPane(GetObjectByIndex_Impl((USHORT)nIndex)); + if (xPane.is()) + return uno::makeAny(xPane); + else + throw lang::IndexOutOfBoundsException(); +// return uno::Any(); +} + +uno::Type SAL_CALL ScTabViewObj::getElementType() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return getCppuType((uno::Reference<sheet::XViewPane>*)0); +} + +sal_Bool SAL_CALL ScTabViewObj::hasElements() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + return ( getCount() != 0 ); +} + +// XSpreadsheetView + +ScViewPaneObj* ScTabViewObj::GetObjectByIndex_Impl(USHORT nIndex) const +{ + static ScSplitPos ePosHV[4] = + { SC_SPLIT_TOPLEFT, SC_SPLIT_BOTTOMLEFT, SC_SPLIT_TOPRIGHT, SC_SPLIT_BOTTOMRIGHT }; + + ScTabViewShell* pViewSh = GetViewShell(); + if (pViewSh) + { + ScSplitPos eWhich = SC_SPLIT_BOTTOMLEFT; // default Position + BOOL bError = FALSE; + ScViewData* pViewData = pViewSh->GetViewData(); + BOOL bHor = ( pViewData->GetHSplitMode() != SC_SPLIT_NONE ); + BOOL bVer = ( pViewData->GetVSplitMode() != SC_SPLIT_NONE ); + if ( bHor && bVer ) + { + // links oben, links unten, rechts oben, rechts unten - wie in Excel + if ( nIndex < 4 ) + eWhich = ePosHV[nIndex]; + else + bError = TRUE; + } + else if ( bHor ) + { + if ( nIndex > 1 ) + bError = TRUE; + else if ( nIndex == 1 ) + eWhich = SC_SPLIT_BOTTOMRIGHT; + // sonst SC_SPLIT_BOTTOMLEFT + } + else if ( bVer ) + { + if ( nIndex > 1 ) + bError = TRUE; + else if ( nIndex == 0 ) + eWhich = SC_SPLIT_TOPLEFT; + // sonst SC_SPLIT_BOTTOMLEFT + } + else if ( nIndex > 0 ) + bError = TRUE; // nicht geteilt: nur 0 gueltig + + if (!bError) + return new ScViewPaneObj( pViewSh, sal::static_int_cast<USHORT>(eWhich) ); + } + + return NULL; +} + +uno::Reference<sheet::XSpreadsheet> SAL_CALL ScTabViewObj::getActiveSheet() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScTabViewShell* pViewSh = GetViewShell(); + if (pViewSh) + { + ScViewData* pData = pViewSh->GetViewData(); + SCTAB nTab = pData->GetTabNo(); + return new ScTableSheetObj( pData->GetDocShell(), nTab ); + } + return NULL; +} + +void SAL_CALL ScTabViewObj::setActiveSheet( const uno::Reference<sheet::XSpreadsheet>& xActiveSheet ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + + ScTabViewShell* pViewSh = GetViewShell(); + if ( pViewSh && xActiveSheet.is() ) + { + // XSpreadsheet und ScCellRangesBase -> muss ein Sheet sein + + ScCellRangesBase* pRangesImp = ScCellRangesBase::getImplementation( xActiveSheet ); + if ( pRangesImp && pViewSh->GetViewData()->GetDocShell() == pRangesImp->GetDocShell() ) + { + const ScRangeList& rRanges = pRangesImp->GetRangeList(); + if ( rRanges.Count() == 1 ) + { + SCTAB nNewTab = rRanges.GetObject(0)->aStart.Tab(); + if ( pViewSh->GetViewData()->GetDocument()->HasTable(nNewTab) ) + pViewSh->SetTabNo( nNewTab ); + } + } + } +} + +uno::Reference< uno::XInterface > ScTabViewObj::GetClickedObject(const Point& rPoint) const +{ + uno::Reference< uno::XInterface > xTarget; + if (GetViewShell()) + { + SCsCOL nX; + SCsROW nY; + ScViewData* pData = GetViewShell()->GetViewData(); + ScSplitPos eSplitMode = pData->GetActivePart(); + SCTAB nTab(pData->GetTabNo()); + pData->GetPosFromPixel( rPoint.X(), rPoint.Y(), eSplitMode, nX, nY); + + ScAddress aCellPos (nX, nY, nTab); + ScCellObj* pCellObj = new ScCellObj(pData->GetDocShell(), aCellPos); + + xTarget.set(uno::Reference<table::XCell>(pCellObj), uno::UNO_QUERY); + + ScDocument* pDoc = pData->GetDocument(); + if (pDoc && pDoc->GetDrawLayer()) + { + SdrPage* pDrawPage = NULL; + ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); + if (pDrawLayer->HasObjects() && (pDrawLayer->GetPageCount() > nTab)) + pDrawPage = pDrawLayer->GetPage(static_cast<sal_uInt16>(nTab)); + + SdrView* pDrawView = GetViewShell()->GetSdrView(); + + if (pDrawPage && pDrawView && pDrawView->GetSdrPageView()) + { + Window* pActiveWin = pData->GetActiveWin(); + Point aPos = pActiveWin->PixelToLogic(rPoint); + + USHORT nHitLog = (USHORT) pActiveWin->PixelToLogic( + Size(pDrawView->GetHitTolerancePixel(),0)).Width(); + + sal_uInt32 nCount(pDrawPage->GetObjCount()); + sal_Bool bFound(sal_False); + sal_uInt32 i(0); + while (i < nCount && !bFound) + { + SdrObject* pObj = pDrawPage->GetObj(i); + if (pObj && SdrObjectPrimitiveHit(*pObj, aPos, nHitLog, *pDrawView->GetSdrPageView(), 0, false)) + { + xTarget.set(pObj->getUnoShape(), uno::UNO_QUERY); + bFound = sal_True; + } + ++i; + } + } + } + } + return xTarget; +} + +bool ScTabViewObj::IsMouseListening() const +{ + if ( aMouseClickHandlers.Count() > 0 ) + return true; + + // also include sheet events, because MousePressed must be called for them + ScViewData* pViewData = GetViewShell()->GetViewData(); + ScDocument* pDoc = pViewData->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + return + pDoc->HasSheetEventScript( nTab, SC_SHEETEVENT_RIGHTCLICK, true ) || + pDoc->HasSheetEventScript( nTab, SC_SHEETEVENT_DOUBLECLICK, true ); +} + +sal_Bool ScTabViewObj::MousePressed( const awt::MouseEvent& e ) + throw (::uno::RuntimeException) +{ + sal_Bool bReturn(sal_False); + + uno::Reference< uno::XInterface > xTarget = GetClickedObject(Point(e.X, e.Y)); + if (aMouseClickHandlers.Count() && xTarget.is()) + { + awt::EnhancedMouseEvent aMouseEvent; + + aMouseEvent.Buttons = e.Buttons; + aMouseEvent.X = e.X; + aMouseEvent.Y = e.Y; + aMouseEvent.ClickCount = e.ClickCount; + aMouseEvent.PopupTrigger = e.PopupTrigger; + aMouseEvent.Target = xTarget; + + for ( USHORT n=0; n<aMouseClickHandlers.Count(); n++ ) + { + try + { + if (!(*aMouseClickHandlers[n])->mousePressed( aMouseEvent )) + bReturn = sal_True; + } + catch ( uno::Exception& ) + { + aMouseClickHandlers.DeleteAndDestroy(n); + --n; // because it will be increased again in the loop + } + } + } + + // handle sheet events + bool bDoubleClick = ( e.Buttons == awt::MouseButton::LEFT && e.ClickCount == 2 ); + bool bRightClick = ( e.Buttons == awt::MouseButton::RIGHT && e.ClickCount == 1 ); + if ( ( bDoubleClick || bRightClick ) && !bReturn && xTarget.is()) + { + sal_Int32 nEvent = bDoubleClick ? SC_SHEETEVENT_DOUBLECLICK : SC_SHEETEVENT_RIGHTCLICK; + + ScTabViewShell* pViewSh = GetViewShell(); + ScViewData* pViewData = pViewSh->GetViewData(); + ScDocShell* pDocSh = pViewData->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + const ScSheetEvents* pEvents = pDoc->GetSheetEvents(nTab); + if (pEvents) + { + const rtl::OUString* pScript = pEvents->GetScript(nEvent); + if (pScript) + { + // the macro parameter is the clicked object, as in the mousePressed call above + uno::Sequence<uno::Any> aParams(1); + aParams[0] <<= xTarget; + + uno::Any aRet; + uno::Sequence<sal_Int16> aOutArgsIndex; + uno::Sequence<uno::Any> aOutArgs; + + /*ErrCode eRet =*/ pDocSh->CallXScript( *pScript, aParams, aRet, aOutArgsIndex, aOutArgs ); + + // look for a boolean return value of true + sal_Bool bRetValue = sal_False; + if (aRet >>= bRetValue) + { + if (bRetValue) + bReturn = sal_True; + } + } + } + + // execute VBA event handler + if (!bReturn && xTarget.is()) try + { + uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( pDoc->GetVbaEventProcessor(), uno::UNO_SET_THROW ); + // the parameter is the clicked object, as in the mousePressed call above + uno::Sequence< uno::Any > aArgs( 1 ); + aArgs[ 0 ] <<= xTarget; + xVbaEvents->processVbaEvent( ScSheetEvents::GetVbaSheetEventId( nEvent ), aArgs ); + } + catch( util::VetoException& ) + { + bReturn = sal_True; + } + catch( uno::Exception& ) + { + } + } + + return bReturn; +} + +sal_Bool ScTabViewObj::MouseReleased( const awt::MouseEvent& e ) + throw (uno::RuntimeException) +{ + sal_Bool bReturn(sal_False); + + if (aMouseClickHandlers.Count()) + { + uno::Reference< uno::XInterface > xTarget = GetClickedObject(Point(e.X, e.Y)); + + if (xTarget.is()) + { + awt::EnhancedMouseEvent aMouseEvent; + + aMouseEvent.Buttons = e.Buttons; + aMouseEvent.X = e.X; + aMouseEvent.Y = e.Y; + aMouseEvent.ClickCount = e.ClickCount; + aMouseEvent.PopupTrigger = e.PopupTrigger; + aMouseEvent.Target = xTarget; + + for ( USHORT n=0; n<aMouseClickHandlers.Count(); n++ ) + { + try + { + if (!(*aMouseClickHandlers[n])->mouseReleased( aMouseEvent )) + bReturn = sal_True; + } + catch ( uno::Exception& ) + { + aMouseClickHandlers.DeleteAndDestroy(n); + --n; // because it will be increased again in the loop + } + } + } + } + return bReturn; +} + +// XEnhancedMouseClickBroadcaster + +void ScTabViewObj::StartMouseListening() +{ +} + +void ScTabViewObj::EndMouseListening() +{ + USHORT nCount(aMouseClickHandlers.Count()); + lang::EventObject aEvent; + aEvent.Source = (cppu::OWeakObject*)this; + for ( USHORT n=0; n<nCount; n++ ) + { + try + { + (*aMouseClickHandlers[n])->disposing(aEvent); + } + catch ( uno::Exception& ) + { + } + } + aMouseClickHandlers.DeleteAndDestroy(0, nCount); +} + +void ScTabViewObj::StartActivationListening() +{ +} + +void ScTabViewObj::EndActivationListening() +{ + USHORT nCount = aActivationListeners.Count(); + lang::EventObject aEvent; + aEvent.Source = (cppu::OWeakObject*)this; + for ( USHORT n=0; n<nCount; n++ ) + { + try + { + (*aActivationListeners[n])->disposing(aEvent); + } + catch ( uno::Exception& ) + { + } + } + aActivationListeners.DeleteAndDestroy(0, nCount); +} + +void SAL_CALL ScTabViewObj::addEnhancedMouseClickHandler( const uno::Reference< awt::XEnhancedMouseClickHandler >& aListener ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if (aListener.is()) + { + USHORT nCount = aMouseClickHandlers.Count(); + uno::Reference<awt::XEnhancedMouseClickHandler> *pObj = + new uno::Reference<awt::XEnhancedMouseClickHandler>( aListener ); + aMouseClickHandlers.Insert( pObj, nCount ); + + if (aMouseClickHandlers.Count() == 1 && nCount == 0) // only if a listener added + StartMouseListening(); + } +} + +void SAL_CALL ScTabViewObj::removeEnhancedMouseClickHandler( const uno::Reference< awt::XEnhancedMouseClickHandler >& aListener ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + USHORT nCount = aMouseClickHandlers.Count(); + for ( USHORT n=nCount; n--; ) + { + uno::Reference<awt::XEnhancedMouseClickHandler> *pObj = aMouseClickHandlers[n]; + if ( *pObj == aListener ) + aMouseClickHandlers.DeleteAndDestroy( n ); + } + if ((aMouseClickHandlers.Count() == 0) && (nCount > 0)) // only if last listener removed + EndMouseListening(); +} + +// XActivationBroadcaster + +void SAL_CALL ScTabViewObj::addActivationEventListener( const uno::Reference< sheet::XActivationEventListener >& aListener ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + + if (aListener.is()) + { + USHORT nCount = aActivationListeners.Count(); + uno::Reference<sheet::XActivationEventListener> *pObj = + new uno::Reference<sheet::XActivationEventListener>( aListener ); + aActivationListeners.Insert( pObj, nCount ); + + if (aActivationListeners.Count() == 1 && nCount == 0) // only if a listener added + StartActivationListening(); + } +} + +void SAL_CALL ScTabViewObj::removeActivationEventListener( const uno::Reference< sheet::XActivationEventListener >& aListener ) + throw (uno::RuntimeException) +{ + ScUnoGuard aGuard; + USHORT nCount = aActivationListeners.Count(); + for ( USHORT n=nCount; n--; ) + { + uno::Reference<sheet::XActivationEventListener> *pObj = aActivationListeners[n]; + if ( *pObj == aListener ) + aActivationListeners.DeleteAndDestroy( n ); + } + if ((aActivationListeners.Count() == 0) && (nCount > 0)) // only if last listener removed + EndActivationListening(); +} + +// PageBreakMode / Zoom sind Properties + +#if 0 + +BOOL ScTabViewObj::getPagebreakMode(void) const +{ + ScUnoGuard aGuard; + ScTabViewShell* pViewSh = GetViewShell(); + if (pViewSh) + return pViewSh->GetViewData()->IsPagebreakMode(); + return FALSE; +} + +void ScTabViewObj::setPagebreakMode(BOOL PagebreakMode) +{ + ScUnoGuard aGuard; + ScTabViewShell* pViewSh = GetViewShell(); + if (pViewSh) + pViewSh->SetPagebreakMode(PagebreakMode); +} + +#endif + +INT16 ScTabViewObj::GetZoom(void) const +{ + ScTabViewShell* pViewSh = GetViewShell(); + if (pViewSh) + { + const Fraction& rZoomY = pViewSh->GetViewData()->GetZoomY(); // Y wird angezeigt + return (INT16)(( rZoomY.GetNumerator() * 100 ) / rZoomY.GetDenominator()); + } + return 0; +} + +void ScTabViewObj::SetZoom(INT16 nZoom) +{ + ScTabViewShell* pViewSh = GetViewShell(); + if (pViewSh) + { + if ( nZoom != GetZoom() && nZoom != 0 ) + { + if (!pViewSh->GetViewData()->IsPagebreakMode()) + { + ScModule* pScMod = SC_MOD(); + ScAppOptions aNewOpt(pScMod->GetAppOptions()); + aNewOpt.SetZoom( nZoom ); + aNewOpt.SetZoomType( pViewSh->GetViewData()->GetView()->GetZoomType() ); + pScMod->SetAppOptions( aNewOpt ); + } + } + Fraction aFract( nZoom, 100 ); + pViewSh->SetZoom( aFract, aFract, TRUE ); + pViewSh->PaintGrid(); + pViewSh->PaintTop(); + pViewSh->PaintLeft(); + pViewSh->GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOM ); + pViewSh->GetViewFrame()->GetBindings().Invalidate( SID_ATTR_ZOOMSLIDER ); + } +} + +INT16 ScTabViewObj::GetZoomType(void) const +{ + INT16 aZoomType = view::DocumentZoomType::OPTIMAL; + ScTabViewShell* pViewSh = GetViewShell(); + if (pViewSh) + { + SvxZoomType eZoomType = pViewSh->GetViewData()->GetView()->GetZoomType(); + switch (eZoomType) + { + case SVX_ZOOM_PERCENT: + aZoomType = view::DocumentZoomType::BY_VALUE; + break; + case SVX_ZOOM_OPTIMAL: + aZoomType = view::DocumentZoomType::OPTIMAL; + break; + case SVX_ZOOM_WHOLEPAGE: + aZoomType = view::DocumentZoomType::ENTIRE_PAGE; + break; + case SVX_ZOOM_PAGEWIDTH: + aZoomType = view::DocumentZoomType::PAGE_WIDTH; + break; + case SVX_ZOOM_PAGEWIDTH_NOBORDER: + aZoomType = view::DocumentZoomType::PAGE_WIDTH_EXACT; + break; + } + } + return aZoomType; +} + +void ScTabViewObj::SetZoomType(INT16 aZoomType) +{ + ScTabViewShell* pViewSh = GetViewShell(); + if (pViewSh) + { + ScDBFunc* pView = pViewSh->GetViewData()->GetView(); + if (pView) + { + SvxZoomType eZoomType; + switch (aZoomType) + { + case view::DocumentZoomType::BY_VALUE: + eZoomType = SVX_ZOOM_PERCENT; + break; + case view::DocumentZoomType::OPTIMAL: + eZoomType = SVX_ZOOM_OPTIMAL; + break; + case view::DocumentZoomType::ENTIRE_PAGE: + eZoomType = SVX_ZOOM_WHOLEPAGE; + break; + case view::DocumentZoomType::PAGE_WIDTH: + eZoomType = SVX_ZOOM_PAGEWIDTH; + break; + case view::DocumentZoomType::PAGE_WIDTH_EXACT: + eZoomType = SVX_ZOOM_PAGEWIDTH_NOBORDER; + break; + default: + eZoomType = SVX_ZOOM_OPTIMAL; + } + sal_Int16 nZoom(GetZoom()); + sal_Int16 nOldZoom(nZoom); + if ( eZoomType == SVX_ZOOM_PERCENT ) + { + if ( nZoom < MINZOOM ) nZoom = MINZOOM; + if ( nZoom > MAXZOOM ) nZoom = MAXZOOM; + } + else + nZoom = pView->CalcZoom( eZoomType, nOldZoom ); + + switch ( eZoomType ) + { + case SVX_ZOOM_WHOLEPAGE: + case SVX_ZOOM_PAGEWIDTH: + pView->SetZoomType( eZoomType, TRUE ); + break; + + default: + pView->SetZoomType( SVX_ZOOM_PERCENT, TRUE ); + } + SetZoom( nZoom ); + } + } +} + +sal_Bool SAL_CALL ScTabViewObj::getIsWindowSplit() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + // wie Menue-Slot SID_WINDOW_SPLIT + + ScTabViewShell* pViewSh = GetViewShell(); + if (pViewSh) + { + ScViewData* pViewData = pViewSh->GetViewData(); + return ( pViewData->GetHSplitMode() == SC_SPLIT_NORMAL || + pViewData->GetVSplitMode() == SC_SPLIT_NORMAL ); + } + + return FALSE; +} + +sal_Bool SAL_CALL ScTabViewObj::hasFrozenPanes() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + // wie Menue-Slot SID_WINDOW_FIX + + ScTabViewShell* pViewSh = GetViewShell(); + if (pViewSh) + { + ScViewData* pViewData = pViewSh->GetViewData(); + return ( pViewData->GetHSplitMode() == SC_SPLIT_FIX || + pViewData->GetVSplitMode() == SC_SPLIT_FIX ); + } + + return FALSE; +} + +sal_Int32 SAL_CALL ScTabViewObj::getSplitHorizontal() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScTabViewShell* pViewSh = GetViewShell(); + if (pViewSh) + { + ScViewData* pViewData = pViewSh->GetViewData(); + if ( pViewData->GetHSplitMode() != SC_SPLIT_NONE ) + return pViewData->GetHSplitPos(); + } + return 0; +} + +sal_Int32 SAL_CALL ScTabViewObj::getSplitVertical() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScTabViewShell* pViewSh = GetViewShell(); + if (pViewSh) + { + ScViewData* pViewData = pViewSh->GetViewData(); + if ( pViewData->GetVSplitMode() != SC_SPLIT_NONE ) + return pViewData->GetVSplitPos(); + } + return 0; +} + +sal_Int32 SAL_CALL ScTabViewObj::getSplitColumn() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScTabViewShell* pViewSh = GetViewShell(); + if (pViewSh) + { + ScViewData* pViewData = pViewSh->GetViewData(); + if ( pViewData->GetHSplitMode() != SC_SPLIT_NONE ) + { + long nSplit = pViewData->GetHSplitPos(); + + ScSplitPos ePos = SC_SPLIT_BOTTOMLEFT; + if ( pViewData->GetVSplitMode() != SC_SPLIT_NONE ) + ePos = SC_SPLIT_TOPLEFT; + + SCsCOL nCol; + SCsROW nRow; + pViewData->GetPosFromPixel( nSplit, 0, ePos, nCol, nRow, FALSE ); + if ( nCol > 0 ) + return nCol; + } + } + return 0; +} + +sal_Int32 SAL_CALL ScTabViewObj::getSplitRow() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScTabViewShell* pViewSh = GetViewShell(); + if (pViewSh) + { + ScViewData* pViewData = pViewSh->GetViewData(); + if ( pViewData->GetVSplitMode() != SC_SPLIT_NONE ) + { + long nSplit = pViewData->GetVSplitPos(); + + ScSplitPos ePos = SC_SPLIT_TOPLEFT; // es ist vertikal geteilt + SCsCOL nCol; + SCsROW nRow; + pViewData->GetPosFromPixel( 0, nSplit, ePos, nCol, nRow, FALSE ); + if ( nRow > 0 ) + return nRow; + } + } + return 0; +} + +void SAL_CALL ScTabViewObj::splitAtPosition( sal_Int32 nPixelX, sal_Int32 nPixelY ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScTabViewShell* pViewSh = GetViewShell(); + if (pViewSh) + { + pViewSh->SplitAtPixel( Point( nPixelX, nPixelY ), TRUE, TRUE ); + pViewSh->FreezeSplitters( FALSE ); + pViewSh->InvalidateSplit(); + } +} + +void SAL_CALL ScTabViewObj::freezeAtPosition( sal_Int32 nColumns, sal_Int32 nRows ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScTabViewShell* pViewSh = GetViewShell(); + if (pViewSh) + { + // erst alles aufheben -> kein Stress mit Scrolling zwischendurch o.ae. + + pViewSh->RemoveSplit(); + + Point aWinStart; + Window* pWin = pViewSh->GetWindowByPos( SC_SPLIT_BOTTOMLEFT ); + if (pWin) + aWinStart = pWin->GetPosPixel(); + + ScViewData* pViewData = pViewSh->GetViewData(); + Point aSplit(pViewData->GetScrPos( (SCCOL)nColumns, (SCROW)nRows, SC_SPLIT_BOTTOMLEFT, TRUE )); + aSplit += aWinStart; + + pViewSh->SplitAtPixel( aSplit, TRUE, TRUE ); + pViewSh->FreezeSplitters( TRUE ); + pViewSh->InvalidateSplit(); + } +} + +void SAL_CALL ScTabViewObj::addSelectionChangeListener( + const uno::Reference<view::XSelectionChangeListener>& xListener ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<view::XSelectionChangeListener>* pObj = + new uno::Reference<view::XSelectionChangeListener>( xListener ); + aSelectionListeners.Insert( pObj, aSelectionListeners.Count() ); +} + +void SAL_CALL ScTabViewObj::removeSelectionChangeListener( + const uno::Reference< view::XSelectionChangeListener >& xListener ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + USHORT nCount = aSelectionListeners.Count(); + for ( USHORT n=nCount; n--; ) + { + uno::Reference<view::XSelectionChangeListener> *pObj = aSelectionListeners[n]; + if ( *pObj == xListener ) //! wozu der Mumpitz mit queryInterface? + { + aSelectionListeners.DeleteAndDestroy( n ); + break; + } + } +} + +void ScTabViewObj::SelectionChanged() +{ + lang::EventObject aEvent; + aEvent.Source.set(static_cast<cppu::OWeakObject*>(this)); + for ( USHORT n=0; n<aSelectionListeners.Count(); n++ ) + (*aSelectionListeners[n])->selectionChanged( aEvent ); + + // handle sheet events + ScTabViewShell* pViewSh = GetViewShell(); + ScViewData* pViewData = pViewSh->GetViewData(); + ScDocShell* pDocSh = pViewData->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + SCTAB nTab = pViewData->GetTabNo(); + const ScSheetEvents* pEvents = pDoc->GetSheetEvents(nTab); + if (pEvents) + { + const rtl::OUString* pScript = pEvents->GetScript(SC_SHEETEVENT_SELECT); + if (pScript) + { + // the macro parameter is the selection as returned by getSelection + uno::Sequence<uno::Any> aParams(1); + aParams[0] = getSelection(); + uno::Any aRet; + uno::Sequence<sal_Int16> aOutArgsIndex; + uno::Sequence<uno::Any> aOutArgs; + /*ErrCode eRet =*/ pDocSh->CallXScript( *pScript, aParams, aRet, aOutArgsIndex, aOutArgs ); + } + } + + // execute VBA event handler + try + { + uno::Reference< script::vba::XVBAEventProcessor > xVbaEvents( pDoc->GetVbaEventProcessor(), uno::UNO_SET_THROW ); + // the parameter is the clicked object, as in the mousePressed call above + uno::Sequence< uno::Any > aArgs( 1 ); + aArgs[ 0 ] <<= getSelection(); + xVbaEvents->processVbaEvent( ScSheetEvents::GetVbaSheetEventId( SC_SHEETEVENT_SELECT ), aArgs ); + } + catch( uno::Exception& ) + { + } +} + + +// XPropertySet (View-Optionen) +//! auch an der Applikation anbieten? + +uno::Reference<beans::XPropertySetInfo> SAL_CALL ScTabViewObj::getPropertySetInfo() + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + static uno::Reference<beans::XPropertySetInfo> aRef( + new SfxItemPropertySetInfo( aPropSet.getPropertyMap() )); + return aRef; +} + +void SAL_CALL ScTabViewObj::setPropertyValue( + const rtl::OUString& aPropertyName, const uno::Any& aValue ) + throw(beans::UnknownPropertyException, beans::PropertyVetoException, + lang::IllegalArgumentException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aString(aPropertyName); + + ScTabViewShell* pViewSh = GetViewShell(); + if (pViewSh) + { + ScViewData* pViewData = pViewSh->GetViewData(); + const ScViewOptions& rOldOpt = pViewSh->GetViewData()->GetOptions(); + ScViewOptions aNewOpt(rOldOpt); + + if ( aString.EqualsAscii( SC_UNO_COLROWHDR ) || aString.EqualsAscii( OLD_UNO_COLROWHDR ) ) + aNewOpt.SetOption( VOPT_HEADER, ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aString.EqualsAscii( SC_UNO_HORSCROLL ) || aString.EqualsAscii( OLD_UNO_HORSCROLL ) ) + aNewOpt.SetOption( VOPT_HSCROLL, ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aString.EqualsAscii( SC_UNO_OUTLSYMB ) || aString.EqualsAscii( OLD_UNO_OUTLSYMB ) ) + aNewOpt.SetOption( VOPT_OUTLINER, ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aString.EqualsAscii( SC_UNO_SHEETTABS ) || aString.EqualsAscii( OLD_UNO_SHEETTABS ) ) + aNewOpt.SetOption( VOPT_TABCONTROLS, ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aString.EqualsAscii( SC_UNO_SHOWANCHOR ) ) + aNewOpt.SetOption( VOPT_ANCHOR, ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aString.EqualsAscii( SC_UNO_SHOWFORM ) ) + aNewOpt.SetOption( VOPT_FORMULAS, ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aString.EqualsAscii( SC_UNO_SHOWGRID ) ) + aNewOpt.SetOption( VOPT_GRID, ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aString.EqualsAscii( SC_UNO_SHOWHELP ) ) + aNewOpt.SetOption( VOPT_HELPLINES, ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aString.EqualsAscii( SC_UNO_SHOWNOTES ) ) + aNewOpt.SetOption( VOPT_NOTES, ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aString.EqualsAscii( SC_UNO_SHOWPAGEBR ) ) + aNewOpt.SetOption( VOPT_PAGEBREAKS, ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aString.EqualsAscii( SC_UNO_SHOWZERO ) ) + aNewOpt.SetOption( VOPT_NULLVALS, ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aString.EqualsAscii( SC_UNO_SHOWSOLID ) ) + aNewOpt.SetOption( VOPT_SOLIDHANDLES, ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aString.EqualsAscii( SC_UNO_VALUEHIGH ) || aString.EqualsAscii( OLD_UNO_VALUEHIGH ) ) + aNewOpt.SetOption( VOPT_SYNTAX, ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aString.EqualsAscii( SC_UNO_VERTSCROLL ) || aString.EqualsAscii( OLD_UNO_VERTSCROLL ) ) + aNewOpt.SetOption( VOPT_VSCROLL, ScUnoHelpFunctions::GetBoolFromAny( aValue ) ); + else if ( aString.EqualsAscii( SC_UNO_SHOWOBJ ) ) + { + sal_Int16 nIntVal = 0; + if ( aValue >>= nIntVal ) + { + //#i80528# adapt to new range eventually + if((sal_Int16)VOBJ_MODE_HIDE < nIntVal) nIntVal = (sal_Int16)VOBJ_MODE_SHOW; + + aNewOpt.SetObjMode( VOBJ_TYPE_OLE, (ScVObjMode)nIntVal); + } + } + else if ( aString.EqualsAscii( SC_UNO_SHOWCHARTS ) ) + { + sal_Int16 nIntVal = 0; + if ( aValue >>= nIntVal ) + { + //#i80528# adapt to new range eventually + if((sal_Int16)VOBJ_MODE_HIDE < nIntVal) nIntVal = (sal_Int16)VOBJ_MODE_SHOW; + + aNewOpt.SetObjMode( VOBJ_TYPE_CHART, (ScVObjMode)nIntVal); + } + } + else if ( aString.EqualsAscii( SC_UNO_SHOWDRAW ) ) + { + sal_Int16 nIntVal = 0; + if ( aValue >>= nIntVal ) + { + //#i80528# adapt to new range eventually + if((sal_Int16)VOBJ_MODE_HIDE < nIntVal) nIntVal = (sal_Int16)VOBJ_MODE_SHOW; + + aNewOpt.SetObjMode( VOBJ_TYPE_DRAW, (ScVObjMode)nIntVal); + } + } + else if ( aString.EqualsAscii( SC_UNO_GRIDCOLOR ) ) + { + sal_Int32 nIntVal = 0; + if ( aValue >>= nIntVal ) + aNewOpt.SetGridColor( nIntVal, String() ); + } + else if ( aString.EqualsAscii( SC_UNO_ZOOMTYPE ) ) + { + sal_Int16 nIntVal = 0; + if ( aValue >>= nIntVal ) + SetZoomType(nIntVal); + } + else if ( aString.EqualsAscii( SC_UNO_ZOOMVALUE ) ) + { + sal_Int16 nIntVal = 0; + if ( aValue >>= nIntVal ) + SetZoom(nIntVal); + } + + // Optionen werden an der View und am Dokument (fuer neue Views) gesetzt, + // damit sie beim Speichern erhalten bleiben. + //! An der App (Module) braeuchte man noch eine Extra-Moeglichkeit, + //! das einzustellen (fuer neue Dokumente) + + if ( aNewOpt != rOldOpt ) + { + pViewData->SetOptions( aNewOpt ); + pViewData->GetDocument()->SetViewOptions( aNewOpt ); + pViewData->GetDocShell()->SetDocumentModified(); //! wirklich? + + pViewSh->UpdateFixPos(); + pViewSh->PaintGrid(); + pViewSh->PaintTop(); + pViewSh->PaintLeft(); + pViewSh->PaintExtras(); + pViewSh->InvalidateBorder(); + + SfxBindings& rBindings = pViewSh->GetViewFrame()->GetBindings(); + rBindings.Invalidate( FID_TOGGLEHEADERS ); // -> Checks im Menue + rBindings.Invalidate( FID_TOGGLESYNTAX ); + } + } +} + +uno::Any SAL_CALL ScTabViewObj::getPropertyValue( const rtl::OUString& aPropertyName ) + throw(beans::UnknownPropertyException, lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + String aString(aPropertyName); + uno::Any aRet; + + ScTabViewShell* pViewSh = GetViewShell(); + if (pViewSh) + { + const ScViewOptions& rOpt = pViewSh->GetViewData()->GetOptions(); + + if ( aString.EqualsAscii( SC_UNO_COLROWHDR ) || aString.EqualsAscii( OLD_UNO_COLROWHDR ) ) + ScUnoHelpFunctions::SetBoolInAny( aRet, rOpt.GetOption( VOPT_HEADER ) ); + else if ( aString.EqualsAscii( SC_UNO_HORSCROLL ) || aString.EqualsAscii( OLD_UNO_HORSCROLL ) ) + ScUnoHelpFunctions::SetBoolInAny( aRet, rOpt.GetOption( VOPT_HSCROLL ) ); + else if ( aString.EqualsAscii( SC_UNO_OUTLSYMB ) || aString.EqualsAscii( OLD_UNO_OUTLSYMB ) ) + ScUnoHelpFunctions::SetBoolInAny( aRet, rOpt.GetOption( VOPT_OUTLINER ) ); + else if ( aString.EqualsAscii( SC_UNO_SHEETTABS ) || aString.EqualsAscii( OLD_UNO_SHEETTABS ) ) + ScUnoHelpFunctions::SetBoolInAny( aRet, rOpt.GetOption( VOPT_TABCONTROLS ) ); + else if ( aString.EqualsAscii( SC_UNO_SHOWANCHOR ) ) ScUnoHelpFunctions::SetBoolInAny( aRet, rOpt.GetOption( VOPT_ANCHOR ) ); + else if ( aString.EqualsAscii( SC_UNO_SHOWFORM ) ) ScUnoHelpFunctions::SetBoolInAny( aRet, rOpt.GetOption( VOPT_FORMULAS ) ); + else if ( aString.EqualsAscii( SC_UNO_SHOWGRID ) ) ScUnoHelpFunctions::SetBoolInAny( aRet, rOpt.GetOption( VOPT_GRID ) ); + else if ( aString.EqualsAscii( SC_UNO_SHOWHELP ) ) ScUnoHelpFunctions::SetBoolInAny( aRet, rOpt.GetOption( VOPT_HELPLINES ) ); + else if ( aString.EqualsAscii( SC_UNO_SHOWNOTES ) ) ScUnoHelpFunctions::SetBoolInAny( aRet, rOpt.GetOption( VOPT_NOTES ) ); + else if ( aString.EqualsAscii( SC_UNO_SHOWPAGEBR ) ) ScUnoHelpFunctions::SetBoolInAny( aRet, rOpt.GetOption( VOPT_PAGEBREAKS ) ); + else if ( aString.EqualsAscii( SC_UNO_SHOWZERO ) ) ScUnoHelpFunctions::SetBoolInAny( aRet, rOpt.GetOption( VOPT_NULLVALS ) ); + else if ( aString.EqualsAscii( SC_UNO_SHOWSOLID ) ) ScUnoHelpFunctions::SetBoolInAny( aRet, rOpt.GetOption( VOPT_SOLIDHANDLES ) ); + else if ( aString.EqualsAscii( SC_UNO_VALUEHIGH ) || aString.EqualsAscii( OLD_UNO_VALUEHIGH ) ) + ScUnoHelpFunctions::SetBoolInAny( aRet, rOpt.GetOption( VOPT_SYNTAX ) ); + else if ( aString.EqualsAscii( SC_UNO_VERTSCROLL ) || aString.EqualsAscii( OLD_UNO_VERTSCROLL ) ) + ScUnoHelpFunctions::SetBoolInAny( aRet, rOpt.GetOption( VOPT_VSCROLL ) ); + else if ( aString.EqualsAscii( SC_UNO_SHOWOBJ ) ) aRet <<= (sal_Int16)( rOpt.GetObjMode( VOBJ_TYPE_OLE ) ); + else if ( aString.EqualsAscii( SC_UNO_SHOWCHARTS ) ) aRet <<= (sal_Int16)( rOpt.GetObjMode( VOBJ_TYPE_CHART ) ); + else if ( aString.EqualsAscii( SC_UNO_SHOWDRAW ) ) aRet <<= (sal_Int16)( rOpt.GetObjMode( VOBJ_TYPE_DRAW ) ); + else if ( aString.EqualsAscii( SC_UNO_GRIDCOLOR ) ) aRet <<= (sal_Int32)( rOpt.GetGridColor().GetColor() ); + else if ( aString.EqualsAscii( SC_UNO_VISAREA ) ) aRet <<= GetVisArea(); + else if ( aString.EqualsAscii( SC_UNO_ZOOMTYPE ) ) aRet <<= GetZoomType(); + else if ( aString.EqualsAscii( SC_UNO_ZOOMVALUE ) ) aRet <<= GetZoom(); + } + + return aRet; +} + +void SAL_CALL ScTabViewObj::addPropertyChangeListener( const ::rtl::OUString& /* aPropertyName */, + const uno::Reference<beans::XPropertyChangeListener >& xListener ) + throw(beans::UnknownPropertyException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<beans::XPropertyChangeListener>* pObj = + new uno::Reference<beans::XPropertyChangeListener>( xListener ); + aPropertyChgListeners.Insert( pObj, aPropertyChgListeners.Count() ); +} + +void SAL_CALL ScTabViewObj::removePropertyChangeListener( const ::rtl::OUString& /* aPropertyName */, + const uno::Reference<beans::XPropertyChangeListener >& xListener ) + throw(beans::UnknownPropertyException, + lang::WrappedTargetException, + uno::RuntimeException) +{ + ScUnoGuard aGuard; + USHORT nCount = aPropertyChgListeners.Count(); + for ( USHORT n=nCount; n--; ) + { + uno::Reference<beans::XPropertyChangeListener> *pObj = aPropertyChgListeners[n]; + if ( *pObj == xListener ) //! wozu der Mumpitz mit queryInterface? + { + aPropertyChgListeners.DeleteAndDestroy( n ); + break; + } + } +} + +void SAL_CALL ScTabViewObj::addVetoableChangeListener( const ::rtl::OUString& /* PropertyName */, + const uno::Reference<beans::XVetoableChangeListener >& /* aListener */ ) + throw(beans::UnknownPropertyException, + lang::WrappedTargetException, + uno::RuntimeException) +{ +} + +void SAL_CALL ScTabViewObj::removeVetoableChangeListener( const ::rtl::OUString& /* PropertyName */, + const uno::Reference<beans::XVetoableChangeListener >& /* aListener */ ) + throw(beans::UnknownPropertyException, + lang::WrappedTargetException, + uno::RuntimeException) +{ +} + +void ScTabViewObj::VisAreaChanged() +{ + beans::PropertyChangeEvent aEvent; + aEvent.Source.set(static_cast<cppu::OWeakObject*>(this)); + for ( USHORT n=0; n<aPropertyChgListeners.Count(); n++ ) + (*aPropertyChgListeners[n])->propertyChange( aEvent ); +} + +// XRangeSelection + +void SAL_CALL ScTabViewObj::startRangeSelection( + const uno::Sequence<beans::PropertyValue>& aArguments ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScTabViewShell* pViewSh = GetViewShell(); + if (pViewSh) + { + String aInitVal, aTitle; + BOOL bCloseOnButtonUp = FALSE; + BOOL bSingleCell = FALSE; + BOOL bMultiSelection = FALSE; + + rtl::OUString aStrVal; + const beans::PropertyValue* pPropArray = aArguments.getConstArray(); + long nPropCount = aArguments.getLength(); + for (long i = 0; i < nPropCount; i++) + { + const beans::PropertyValue& rProp = pPropArray[i]; + String aPropName(rProp.Name); + + if (aPropName.EqualsAscii( SC_UNONAME_CLOSEONUP )) + bCloseOnButtonUp = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value ); + else if (aPropName.EqualsAscii( SC_UNONAME_TITLE )) + { + if ( rProp.Value >>= aStrVal ) + aTitle = String( aStrVal ); + } + else if (aPropName.EqualsAscii( SC_UNONAME_INITVAL )) + { + if ( rProp.Value >>= aStrVal ) + aInitVal = String( aStrVal ); + } + else if (aPropName.EqualsAscii( SC_UNONAME_SINGLECELL )) + bSingleCell = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value ); + else if (aPropName.EqualsAscii( SC_UNONAME_MULTISEL )) + bMultiSelection = ScUnoHelpFunctions::GetBoolFromAny( rProp.Value ); + } + + pViewSh->StartSimpleRefDialog( aTitle, aInitVal, bCloseOnButtonUp, bSingleCell, bMultiSelection ); + } +} + +void SAL_CALL ScTabViewObj::abortRangeSelection() throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScTabViewShell* pViewSh = GetViewShell(); + if (pViewSh) + pViewSh->StopSimpleRefDialog(); +} + +void SAL_CALL ScTabViewObj::addRangeSelectionListener( + const uno::Reference<sheet::XRangeSelectionListener>& xListener ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<sheet::XRangeSelectionListener>* pObj = + new uno::Reference<sheet::XRangeSelectionListener>( xListener ); + aRangeSelListeners.Insert( pObj, aRangeSelListeners.Count() ); +} + +void SAL_CALL ScTabViewObj::removeRangeSelectionListener( + const uno::Reference<sheet::XRangeSelectionListener>& xListener ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + USHORT nCount = aRangeSelListeners.Count(); + for ( USHORT n=nCount; n--; ) + { + uno::Reference<sheet::XRangeSelectionListener> *pObj = aRangeSelListeners[n]; + if ( *pObj == xListener ) + { + aRangeSelListeners.DeleteAndDestroy( n ); + break; + } + } +} + +void SAL_CALL ScTabViewObj::addRangeSelectionChangeListener( + const uno::Reference<sheet::XRangeSelectionChangeListener>& xListener ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + uno::Reference<sheet::XRangeSelectionChangeListener>* pObj = + new uno::Reference<sheet::XRangeSelectionChangeListener>( xListener ); + aRangeChgListeners.Insert( pObj, aRangeChgListeners.Count() ); +} + +void SAL_CALL ScTabViewObj::removeRangeSelectionChangeListener( + const uno::Reference<sheet::XRangeSelectionChangeListener>& xListener ) + throw(uno::RuntimeException) +{ + ScUnoGuard aGuard; + USHORT nCount = aRangeChgListeners.Count(); + for ( USHORT n=nCount; n--; ) + { + uno::Reference<sheet::XRangeSelectionChangeListener> *pObj = aRangeChgListeners[n]; + if ( *pObj == xListener ) + { + aRangeChgListeners.DeleteAndDestroy( n ); + break; + } + } +} + +void ScTabViewObj::RangeSelDone( const String& rText ) +{ + sheet::RangeSelectionEvent aEvent; + aEvent.Source.set(static_cast<cppu::OWeakObject*>(this)); + aEvent.RangeDescriptor = rtl::OUString( rText ); + + for ( USHORT n=0; n<aRangeSelListeners.Count(); n++ ) + (*aRangeSelListeners[n])->done( aEvent ); +} + +void ScTabViewObj::RangeSelAborted( const String& rText ) +{ + sheet::RangeSelectionEvent aEvent; + aEvent.Source.set(static_cast<cppu::OWeakObject*>(this)); + aEvent.RangeDescriptor = rtl::OUString( rText ); + + for ( USHORT n=0; n<aRangeSelListeners.Count(); n++ ) + (*aRangeSelListeners[n])->aborted( aEvent ); +} + +void ScTabViewObj::RangeSelChanged( const String& rText ) +{ + sheet::RangeSelectionEvent aEvent; + aEvent.Source.set(static_cast<cppu::OWeakObject*>(this)); + aEvent.RangeDescriptor = rtl::OUString( rText ); + + for ( USHORT n=0; n<aRangeChgListeners.Count(); n++ ) + (*aRangeChgListeners[n])->descriptorChanged( aEvent ); +} + +// XServiceInfo + +rtl::OUString SAL_CALL ScTabViewObj::getImplementationName() throw(uno::RuntimeException) +{ + return rtl::OUString::createFromAscii( "ScTabViewObj" ); +} + +sal_Bool SAL_CALL ScTabViewObj::supportsService( const rtl::OUString& rServiceName ) + throw(uno::RuntimeException) +{ + String aServiceStr( rServiceName ); + return aServiceStr.EqualsAscii( SCTABVIEWOBJ_SERVICE ) || + aServiceStr.EqualsAscii( SCVIEWSETTINGS_SERVICE ); +} + +uno::Sequence<rtl::OUString> SAL_CALL ScTabViewObj::getSupportedServiceNames() + throw(uno::RuntimeException) +{ + uno::Sequence<rtl::OUString> aRet(2); + rtl::OUString* pArray = aRet.getArray(); + pArray[0] = rtl::OUString::createFromAscii( SCTABVIEWOBJ_SERVICE ); + pArray[1] = rtl::OUString::createFromAscii( SCVIEWSETTINGS_SERVICE ); + return aRet; +} + +// XUnoTunnel + +sal_Int64 SAL_CALL ScTabViewObj::getSomething( + const uno::Sequence<sal_Int8 >& rId ) throw(uno::RuntimeException) +{ + if ( rId.getLength() == 16 && + 0 == rtl_compareMemory( getUnoTunnelId().getConstArray(), + rId.getConstArray(), 16 ) ) + { + return sal::static_int_cast<sal_Int64>(reinterpret_cast<sal_IntPtr>(this)); + } + return 0; +} + +// static +const uno::Sequence<sal_Int8>& ScTabViewObj::getUnoTunnelId() +{ + static uno::Sequence<sal_Int8> * pSeq = 0; + if( !pSeq ) + { + osl::Guard< osl::Mutex > aGuard( osl::Mutex::getGlobalMutex() ); + if( !pSeq ) + { + static uno::Sequence< sal_Int8 > aSeq( 16 ); + rtl_createUuid( (sal_uInt8*)aSeq.getArray(), 0, sal_True ); + pSeq = &aSeq; + } + } + return *pSeq; +} + +// static +ScTabViewObj* ScTabViewObj::getImplementation( const uno::Reference<uno::XInterface> xObj ) +{ + ScTabViewObj* pRet = NULL; + uno::Reference<lang::XUnoTunnel> xUT( xObj, uno::UNO_QUERY ); + if (xUT.is()) + pRet = reinterpret_cast<ScTabViewObj*>(sal::static_int_cast<sal_IntPtr>(xUT->getSomething(getUnoTunnelId()))); + return pRet; +} + +::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable > SAL_CALL ScTabViewObj::getTransferable( ) throw (::com::sun::star::uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScEditShell* pShell = PTR_CAST( ScEditShell, GetViewShell()->GetViewFrame()->GetDispatcher()->GetShell(0) ); + if (pShell) + return pShell->GetEditView()->GetTransferable(); + + ScDrawTextObjectBar* pTextShell = PTR_CAST( ScDrawTextObjectBar, GetViewShell()->GetViewFrame()->GetDispatcher()->GetShell(0) ); + if (pTextShell) + { + ScViewData* pViewData = GetViewShell()->GetViewData(); + ScDrawView* pView = pViewData->GetScDrawView(); + OutlinerView* pOutView = pView->GetTextEditOutlinerView(); + if (pOutView) + return pOutView->GetEditView().GetTransferable(); + } + + ScDrawShell* pDrawShell = PTR_CAST( ScDrawShell, GetViewShell()->GetViewFrame()->GetDispatcher()->GetShell(0) ); + if (pDrawShell) + return pDrawShell->GetDrawView()->CopyToTransferable(); + + ScTransferObj* pObj = GetViewShell()->CopyToTransferable(); + uno::Reference<datatransfer::XTransferable> xTransferable( pObj ); + return xTransferable; +} + +void SAL_CALL ScTabViewObj::insertTransferable( const ::com::sun::star::uno::Reference< ::com::sun::star::datatransfer::XTransferable >& xTrans ) throw (::com::sun::star::datatransfer::UnsupportedFlavorException, ::com::sun::star::uno::RuntimeException) +{ + ScUnoGuard aGuard; + ScEditShell* pShell = PTR_CAST( ScEditShell, GetViewShell()->GetViewFrame()->GetDispatcher()->GetShell(0) ); + if (pShell) + pShell->GetEditView()->InsertText( xTrans, ::rtl::OUString(), FALSE ); + else + { + ScDrawTextObjectBar* pTextShell = PTR_CAST( ScDrawTextObjectBar, GetViewShell()->GetViewFrame()->GetDispatcher()->GetShell(0) ); + if (pTextShell) + { + ScViewData* pViewData = GetViewShell()->GetViewData(); + ScDrawView* pView = pViewData->GetScDrawView(); + OutlinerView* pOutView = pView->GetTextEditOutlinerView(); + if ( pOutView ) + { + pOutView->GetEditView().InsertText( xTrans, ::rtl::OUString(), FALSE ); + return; + } + } + + GetViewShell()->PasteFromTransferable( xTrans ); + } +} + +//------------------------------------------------------------------------ + + + + diff --git a/sc/source/ui/unoobj/warnpassword.cxx b/sc/source/ui/unoobj/warnpassword.cxx new file mode 100644 index 000000000000..ce81fd2645c4 --- /dev/null +++ b/sc/source/ui/unoobj/warnpassword.cxx @@ -0,0 +1,95 @@ +/************************************************************************* + * + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * Copyright 2000, 2010 Oracle and/or its affiliates. + * + * OpenOffice.org - a multi-platform office productivity suite + * + * This file is part of OpenOffice.org. + * + * OpenOffice.org is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License version 3 + * only, as published by the Free Software Foundation. + * + * OpenOffice.org is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License version 3 for more details + * (a copy is included in the LICENSE file that accompanied this code). + * + * You should have received a copy of the GNU Lesser General Public License + * version 3 along with OpenOffice.org. If not, see + * <http://www.openoffice.org/license.html> + * for a copy of the LGPLv3 License. + * + ************************************************************************/ + +// MARKER(update_precomp.py): autogen include statement, do not remove +#include "precompiled_sc.hxx" + +// ============================================================================ +#include "warnpassword.hxx" +#include <com/sun/star/task/XInteractionHandler.hpp> +#include <com/sun/star/task/XInteractionRequest.hpp> +#include <svl/itemset.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/sfxsids.hrc> +#include <ucbhelper/simpleinteractionrequest.hxx> +#include <com/sun/star/task/InteractionClassification.hpp> +#include <com/sun/star/ucb/InteractiveAppException.hpp> +#include <com/sun/star/ucb/XContent.hpp> +#include <svx/svxerr.hxx> + + +using ::rtl::OUString; +using ::com::sun::star::uno::makeAny; +using ::com::sun::star::uno::Any; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Exception; +using ::com::sun::star::uno::XInterface; +using ::com::sun::star::task::InteractionClassification_QUERY; +using ::com::sun::star::task::XInteractionHandler; +using ::com::sun::star::task::XInteractionRequest; +using ::com::sun::star::ucb::InteractiveAppException; + +bool ScWarnPassword::WarningOnPassword( SfxMedium& rMedium ) +{ + bool bReturn = true; + Reference< XInteractionHandler > xHandler( rMedium.GetInteractionHandler()); + if( xHandler.is() ) + { + + OUString empty; + Any xException( makeAny(InteractiveAppException(empty, + Reference <XInterface> (), + InteractionClassification_QUERY, + ERRCODE_SVX_EXPORT_FILTER_CRYPT))); + + Reference< ucbhelper::SimpleInteractionRequest > xRequest + = new ucbhelper::SimpleInteractionRequest( + xException, + ucbhelper::CONTINUATION_APPROVE + | ucbhelper::CONTINUATION_DISAPPROVE ); + + xHandler->handle( xRequest.get() ); + + const sal_Int32 nResp = xRequest->getResponse(); + + switch ( nResp ) + { + case ucbhelper::CONTINUATION_UNKNOWN: + break; + + case ucbhelper::CONTINUATION_APPROVE: + // Continue + break; + + case ucbhelper::CONTINUATION_DISAPPROVE: + bReturn = false; + break; + } + } + return bReturn; +} + |