diff options
author | Jens-Heiner Rechtien <hr@openoffice.org> | 2009-12-01 17:41:04 +0000 |
---|---|---|
committer | Jens-Heiner Rechtien <hr@openoffice.org> | 2009-12-01 17:41:04 +0000 |
commit | c2b4af25ca2f1266be37f074ef22b903b31fbc5f (patch) | |
tree | 382e5b5b79e3003cde0288e24c179af85207fb32 | |
parent | 23d63d58c951ea4c172c5c759e764c8a783951d9 (diff) | |
parent | bebc983ea6df34dbc310d1dfbb3ca74ea62db830 (diff) |
chartshapes: merge with DEV300 m55
293 files changed, 22743 insertions, 3612 deletions
diff --git a/chart2/prj/build.lst b/chart2/prj/build.lst index d824fc575bca..0d4978606d11 100644 --- a/chart2/prj/build.lst +++ b/chart2/prj/build.lst @@ -1,4 +1,4 @@ -ch chart2 : comphelper cppu cppuhelper sal svtools svx tools vcl toolkit unotools sfx2 goodies NULL +ch chart2 : l10n comphelper cppu cppuhelper sal svtools svx tools vcl toolkit unotools sfx2 goodies NULL ch chart2 usr1 - all ch_mkout NULL ch chart2\inc nmake - all ch_inc NULL ch chart2\source\inc get - all ch_source_inc NULL diff --git a/chart2/source/controller/chartapiwrapper/Chart2ModelContact.cxx b/chart2/source/controller/chartapiwrapper/Chart2ModelContact.cxx index 4b44b2e0593d..3d930f72f0af 100644 --- a/chart2/source/controller/chartapiwrapper/Chart2ModelContact.cxx +++ b/chart2/source/controller/chartapiwrapper/Chart2ModelContact.cxx @@ -177,6 +177,17 @@ sal_Int32 Chart2ModelContact::getExplicitNumberFormatKeyForAxis( , Reference< util::XNumberFormatsSupplier >( m_xChartModel.get(), uno::UNO_QUERY ) ); } +sal_Int32 Chart2ModelContact::getExplicitNumberFormatKeyForSeries( + const Reference< chart2::XDataSeries >& xSeries ) +{ + return ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel( + uno::Reference< beans::XPropertySet >( xSeries, uno::UNO_QUERY ), + xSeries, + -1 /*-1 for whole series*/, + ChartModelHelper::findDiagram( m_xChartModel ) + ); +} + //----------------------------------------------------------------------------- awt::Size Chart2ModelContact::GetPageSize() const diff --git a/chart2/source/controller/chartapiwrapper/Chart2ModelContact.hxx b/chart2/source/controller/chartapiwrapper/Chart2ModelContact.hxx index b8ce668dff28..0cc8a16bafff 100644 --- a/chart2/source/controller/chartapiwrapper/Chart2ModelContact.hxx +++ b/chart2/source/controller/chartapiwrapper/Chart2ModelContact.hxx @@ -34,6 +34,7 @@ #include <com/sun/star/chart2/ExplicitIncrementData.hpp> #include <com/sun/star/chart2/XAxis.hpp> #include <com/sun/star/chart2/XChartDocument.hpp> +#include <com/sun/star/chart2/XDataSeries.hpp> #include <com/sun/star/chart2/XDiagram.hpp> #include <com/sun/star/chart2/XTitle.hpp> #include <cppuhelper/weakref.hxx> @@ -87,6 +88,9 @@ public: sal_Int32 getExplicitNumberFormatKeyForAxis( const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XAxis >& xAxis ); + sal_Int32 getExplicitNumberFormatKeyForSeries( + const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XDataSeries >& xSeries ); + /** Returns the size of the page in logic coordinates. This value is used for setting an appropriate "ReferencePageSize" for FontHeights. */ diff --git a/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx b/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx index 3e3b7254f578..fcc17fefeebc 100644 --- a/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx +++ b/chart2/source/controller/chartapiwrapper/ChartDocumentWrapper.cxx @@ -98,6 +98,7 @@ enum eServiceType SERVICE_NAME_PIE_DIAGRAM, SERVICE_NAME_STOCK_DIAGRAM, SERVICE_NAME_XY_DIAGRAM, + SERVICE_NAME_BUBBLE_DIAGRAM, SERVICE_NAME_DASH_TABLE, SERVICE_NAME_GARDIENT_TABLE, @@ -126,6 +127,7 @@ tServiceNameMap & lcl_getStaticServiceNameMap() ( C2U( "com.sun.star.chart.PieDiagram" ), SERVICE_NAME_PIE_DIAGRAM ) ( C2U( "com.sun.star.chart.StockDiagram" ), SERVICE_NAME_STOCK_DIAGRAM ) ( C2U( "com.sun.star.chart.XYDiagram" ), SERVICE_NAME_XY_DIAGRAM ) + ( C2U( "com.sun.star.chart.BubbleDiagram" ), SERVICE_NAME_BUBBLE_DIAGRAM ) ( C2U( "com.sun.star.drawing.DashTable" ), SERVICE_NAME_DASH_TABLE ) ( C2U( "com.sun.star.drawing.GradientTable" ), SERVICE_NAME_GARDIENT_TABLE ) @@ -1367,6 +1369,16 @@ uno::Reference< uno::XInterface > SAL_CALL ChartDocumentWrapper::createInstance( } break; + case SERVICE_NAME_BUBBLE_DIAGRAM: + if( xManagerFact.is()) + { + xTemplate.set( + xManagerFact->createInstance( + C2U( "com.sun.star.chart2.template.Bubble" )), uno::UNO_QUERY ); + bCreateDiagram = true; + } + break; + case SERVICE_NAME_DASH_TABLE: case SERVICE_NAME_GARDIENT_TABLE: case SERVICE_NAME_HATCH_TABLE: diff --git a/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx b/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx index a6c18f9475dc..ce417155dc4f 100644 --- a/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx +++ b/chart2/source/controller/chartapiwrapper/DataSeriesPointWrapper.cxx @@ -50,6 +50,7 @@ #include "WrappedDataCaptionProperties.hxx" #include "WrappedSeriesAreaOrLineProperty.hxx" #include "WrappedScaleTextProperties.hxx" +#include "WrappedNumberFormatProperty.hxx" #include "WrappedTextRotationProperty.hxx" #include <rtl/ustrbuf.hxx> #include <rtl/math.hxx> @@ -88,6 +89,7 @@ enum PROP_SERIES_DATAPOINT_PERCENT_DIAGONAL, PROP_SERIES_DATAPOINT_LABEL_SEPARATOR, PROP_SERIES_NUMBERFORMAT, + PROP_SERIES_LINK_NUMBERFORMAT_TO_SOURCE, PROP_SERIES_PERCENTAGE_NUMBERFORMAT, PROP_SERIES_DATAPOINT_LABEL_PLACEMENT, //other series properties @@ -165,6 +167,13 @@ void lcl_AddPropertiesToVector_SeriesOnly( ::getCppuType( reinterpret_cast< sal_Int32 * >(0)), beans::PropertyAttribute::BOUND | beans::PropertyAttribute::MAYBEDEFAULT )); + + rOutProperties.push_back( + Property( C2U( "LinkNumberFormatToSource" ), + PROP_SERIES_LINK_NUMBERFORMAT_TO_SOURCE, + ::getBooleanCppuType(), + beans::PropertyAttribute::BOUND + | beans::PropertyAttribute::MAYBEDEFAULT )); } const uno::Sequence< Property > & lcl_GetPropertySequence( DataSeriesPointWrapper::eType _eType ) @@ -713,6 +722,10 @@ const std::vector< WrappedProperty* > DataSeriesPointWrapper::createWrappedPrope { WrappedStatisticProperties::addWrappedPropertiesForSeries( aWrappedProperties, m_spChart2ModelContact ); aWrappedProperties.push_back( new WrappedAttachedAxisProperty( m_spChart2ModelContact ) ); + + WrappedNumberFormatProperty* pWrappedNumberFormatProperty = new WrappedNumberFormatProperty( m_spChart2ModelContact ); + aWrappedProperties.push_back( pWrappedNumberFormatProperty ); + aWrappedProperties.push_back( new WrappedLinkNumberFormatProperty(pWrappedNumberFormatProperty) ); } WrappedSymbolProperties::addWrappedPropertiesForSeries( aWrappedProperties, m_spChart2ModelContact ); diff --git a/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx b/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx index 5bd12775fbcd..fe1359aab7f3 100644 --- a/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx +++ b/chart2/source/controller/chartapiwrapper/DiagramWrapper.cxx @@ -549,6 +549,9 @@ OUString lcl_getDiagramType( const OUString & rTemplateServiceName ) if( aName.indexOf( C2U("Stock") ) != -1 ) return C2U( "com.sun.star.chart.StockDiagram" ); + if( aName.indexOf( C2U("Bubble") ) != -1 ) + return C2U( "com.sun.star.chart.BubbleDiagram" ); + // Note: this must be checked after Bar, Net and Scatter // "Symbol" "StackedSymbol" "PercentStackedSymbol" "Line" "StackedLine" @@ -594,6 +597,9 @@ const tMakeStringStringMap& lcl_getChartTypeNameMap() ( ::rtl::OUString::createFromAscii( "com.sun.star.chart2.CandleStickChartType" ) , ::rtl::OUString::createFromAscii( "com.sun.star.chart.StockDiagram" ) ) + ( ::rtl::OUString::createFromAscii( "com.sun.star.chart2.BubbleChartType" ) + , ::rtl::OUString::createFromAscii( "com.sun.star.chart.BubbleDiagram" ) ) + ; return g_aChartTypeNameMap; } diff --git a/chart2/source/controller/chartapiwrapper/WrappedNumberFormatProperty.cxx b/chart2/source/controller/chartapiwrapper/WrappedNumberFormatProperty.cxx index 4110a6ef3b54..00101ef10f34 100644 --- a/chart2/source/controller/chartapiwrapper/WrappedNumberFormatProperty.cxx +++ b/chart2/source/controller/chartapiwrapper/WrappedNumberFormatProperty.cxx @@ -98,8 +98,15 @@ Any WrappedNumberFormatProperty::getPropertyValue( const Reference< beans::XProp Any aRet( xInnerPropertySet->getPropertyValue( m_aInnerName )); if( !aRet.hasValue() ) { - Reference< chart2::XAxis > xAxis( xInnerPropertySet, uno::UNO_QUERY ); - sal_Int32 nKey = m_spChart2ModelContact->getExplicitNumberFormatKeyForAxis( xAxis ); + sal_Int32 nKey = 0; + Reference< chart2::XDataSeries > xSeries( xInnerPropertySet, uno::UNO_QUERY ); + if( xSeries.is() ) + nKey = m_spChart2ModelContact->getExplicitNumberFormatKeyForSeries( xSeries ); + else + { + Reference< chart2::XAxis > xAxis( xInnerPropertySet, uno::UNO_QUERY ); + nKey = m_spChart2ModelContact->getExplicitNumberFormatKeyForAxis( xAxis ); + } aRet <<= nKey; } return aRet; diff --git a/chart2/source/controller/dialogs/Bitmaps.hrc b/chart2/source/controller/dialogs/Bitmaps.hrc index 58b1d540cc1a..07ed2eeec0d5 100644 --- a/chart2/source/controller/dialogs/Bitmaps.hrc +++ b/chart2/source/controller/dialogs/Bitmaps.hrc @@ -34,23 +34,28 @@ #include <svtools/solar.hrc> #endif -// next free: 100 - #ifndef STD_MASKCOLOR #define STD_MASKCOLOR Color { Red = 0xFF00; Green = 0x0000; Blue = 0xFF00; } #endif //----------------------------------------------------------------------------- // chart types +// Images: #define IMG_TYPE_COLUMN (RID_APP_START + 1) #define IMG_TYPE_BAR (RID_APP_START + 2) #define IMG_TYPE_PIE (RID_APP_START + 3) -#define IMG_TYPE_LINE (RID_APP_START + 4) -#define IMG_TYPE_AREA (RID_APP_START + 5) -#define IMG_TYPE_NET (RID_APP_START + 6) -#define IMG_TYPE_STOCK (RID_APP_START + 7) -#define IMG_TYPE_COLUMN_LINE (RID_APP_START + 8) +#define IMG_TYPE_AREA (RID_APP_START + 4) +#define IMG_TYPE_LINE (RID_APP_START + 5) +#define IMG_TYPE_XY (RID_APP_START + 6) +#define IMG_TYPE_BUBBLE (RID_APP_START + 7) +#define IMG_TYPE_NET (RID_APP_START + 8) +#define IMG_TYPE_STOCK (RID_APP_START + 9) +#define IMG_TYPE_COLUMN_LINE (RID_APP_START + 10) + +//----------------------------------------------------------------------------- +//Chart Subtypes +// Bitmaps: //---------------------- // Column Chart Subtypes @@ -185,7 +190,13 @@ #define BMP_COLUMN_LINE (RID_APP_START + 86) #define BMP_COLUMN_LINE_STACKED (RID_APP_START + 87) +//---------------------- +// Bubble Chart Subtypes +#define BMP_BUBBLE_1 (RID_APP_START + 88) + //----------------------------------------------------------------------------- +//further Images: + //SchStatisticTabPage and SchDataStatisticsDlg part 1 #define BMP_INDICATE_BOTH_VERTI (RID_APP_START + 89) #define BMP_INDICATE_UP (RID_APP_START + 90) @@ -201,9 +212,8 @@ #define BMP_REGRESSION_EXP (RID_APP_START + 95) #define BMP_REGRESSION_POWER (RID_APP_START + 96) -//----------------------------------------------------------------------------- // hide-button for range-choosing -#define IMG_SELECTRANGE (RID_APP_START + 9) +#define IMG_SELECTRANGE (RID_APP_START + 100) // CHART_BITMAPS_HRC #endif diff --git a/chart2/source/controller/dialogs/Bitmaps.src b/chart2/source/controller/dialogs/Bitmaps.src index 2af607b6963c..35a897848fb1 100644 --- a/chart2/source/controller/dialogs/Bitmaps.src +++ b/chart2/source/controller/dialogs/Bitmaps.src @@ -49,6 +49,11 @@ Image IMG_TYPE_LINE ImageBitmap = Bitmap { File = "typepointline_16.png" ; }; MaskColor = STD_MASKCOLOR; }; +Image IMG_TYPE_XY +{ + ImageBitmap = Bitmap { File = "typexy_16.png" ; }; + MaskColor = STD_MASKCOLOR; +}; Image IMG_TYPE_AREA { ImageBitmap = Bitmap { File = "typearea_16.png" ; }; @@ -69,6 +74,15 @@ Image IMG_TYPE_COLUMN_LINE ImageBitmap = Bitmap { File = "typecolumnline_16.png" ; }; MaskColor = STD_MASKCOLOR; }; +Image IMG_TYPE_BUBBLE +{ + ImageBitmap = Bitmap { File = "typebubble_16.png" ; }; + MaskColor = STD_MASKCOLOR; +}; +Bitmap BMP_BUBBLE_1 +{ + File = "bubble_52x60.png" ; +}; Bitmap BMP_AREAS_2D { File = "areas_52x60.png" ; diff --git a/chart2/source/controller/dialogs/Bitmaps_HC.hrc b/chart2/source/controller/dialogs/Bitmaps_HC.hrc index 0b65579973c5..84a23ba426bc 100644 --- a/chart2/source/controller/dialogs/Bitmaps_HC.hrc +++ b/chart2/source/controller/dialogs/Bitmaps_HC.hrc @@ -41,15 +41,22 @@ //----------------------------------------------------------------------------- // chart types +// Images: #define IMG_TYPE_COLUMN_HC (RID_SCH_START + 1) #define IMG_TYPE_BAR_HC (RID_SCH_START + 2) #define IMG_TYPE_PIE_HC (RID_SCH_START + 3) -#define IMG_TYPE_LINE_HC (RID_SCH_START + 4) -#define IMG_TYPE_AREA_HC (RID_SCH_START + 5) -#define IMG_TYPE_NET_HC (RID_SCH_START + 6) -#define IMG_TYPE_STOCK_HC (RID_SCH_START + 7) -#define IMG_TYPE_COLUMN_LINE_HC (RID_SCH_START + 8) +#define IMG_TYPE_AREA_HC (RID_SCH_START + 4) +#define IMG_TYPE_LINE_HC (RID_SCH_START + 5) +#define IMG_TYPE_XY_HC (RID_SCH_START + 6) +#define IMG_TYPE_BUBBLE_HC (RID_SCH_START + 7) +#define IMG_TYPE_NET_HC (RID_SCH_START + 8) +#define IMG_TYPE_STOCK_HC (RID_SCH_START + 9) +#define IMG_TYPE_COLUMN_LINE_HC (RID_SCH_START + 10) + +//----------------------------------------------------------------------------- +//Chart Subtypes +// Bitmaps: //---------------------- // Column Chart Subtypes @@ -183,7 +190,13 @@ #define BMP_COLUMN_LINE_HC (RID_SCH_START + 86) #define BMP_COLUMN_LINE_STACKED_HC (RID_SCH_START + 87) +//---------------------- +// Bubble Chart Subtypes +#define BMP_BUBBLE_1_HC (RID_SCH_START + 88) + //----------------------------------------------------------------------------- +//further Images: + //SchStatisticTabPage and SchDataStatisticsDlg part 1 #define BMP_INDICATE_BOTH_VERTI_HC (RID_SCH_START + 89) #define BMP_INDICATE_UP_HC (RID_SCH_START + 90) @@ -199,6 +212,5 @@ #define BMP_REGRESSION_EXP_HC (RID_SCH_START + 95) #define BMP_REGRESSION_POWER_HC (RID_SCH_START + 96) -//----------------------------------------------------------------------------- // hide-button for range-choosing -#define IMG_SELECTRANGE_HC (RID_SCH_START + 9) +#define IMG_SELECTRANGE_HC (RID_SCH_START + 100) diff --git a/chart2/source/controller/dialogs/Bitmaps_HC.src b/chart2/source/controller/dialogs/Bitmaps_HC.src index 1e2fe5f4ba14..0fb7ef5e5a1a 100644 --- a/chart2/source/controller/dialogs/Bitmaps_HC.src +++ b/chart2/source/controller/dialogs/Bitmaps_HC.src @@ -49,6 +49,11 @@ Image IMG_TYPE_LINE_HC ImageBitmap = Bitmap { File = "typepointline_16.png" ; }; MaskColor = SC_HC_MASKCOLOR; }; +Image IMG_TYPE_XY_HC +{ + ImageBitmap = Bitmap { File = "typexy_16.png" ; }; + MaskColor = SC_HC_MASKCOLOR; +}; Image IMG_TYPE_AREA_HC { ImageBitmap = Bitmap { File = "typearea_16.png" ; }; @@ -69,6 +74,15 @@ Image IMG_TYPE_COLUMN_LINE_HC ImageBitmap = Bitmap { File = "typecolumnline_16.png" ; }; MaskColor = SC_HC_MASKCOLOR; }; +Image IMG_TYPE_BUBBLE_HC +{ + ImageBitmap = Bitmap { File = "typebubble_16.png" ; }; + MaskColor = SC_HC_MASKCOLOR; +}; +Bitmap BMP_BUBBLE_1_HC +{ + File = "bubble_52x60_h.png" ; +}; Bitmap BMP_AREAS_2D_HC { File = "areas_52x60_h.png" ; diff --git a/chart2/source/controller/dialogs/ChartTypeDialogController.cxx b/chart2/source/controller/dialogs/ChartTypeDialogController.cxx index 79efe0b04919..de57e82e58da 100644 --- a/chart2/source/controller/dialogs/ChartTypeDialogController.cxx +++ b/chart2/source/controller/dialogs/ChartTypeDialogController.cxx @@ -808,7 +808,7 @@ String XYChartDialogController::getName() } Image XYChartDialogController::getImage( bool bIsHighContrast ) { - return SELECT_IMAGE( IMG_TYPE_LINE ); + return SELECT_IMAGE( IMG_TYPE_XY ); } const tTemplateServiceChartTypeParameterMap& XYChartDialogController::getTemplateMap() const { @@ -1238,6 +1238,40 @@ void CombiColumnLineChartDialogController::adjustParameterToSubType( ChartTypePa break; } } +//-------------------------------------------------------------------------- +BubbleChartDialogController::BubbleChartDialogController() +{ +} +BubbleChartDialogController::~BubbleChartDialogController() +{ +} +String BubbleChartDialogController::getName() +{ + return String( SchResId( STR_TYPE_BUBBLE )); +} +Image BubbleChartDialogController::getImage( bool bIsHighContrast ) +{ + return SELECT_IMAGE( IMG_TYPE_BUBBLE ); +} +const tTemplateServiceChartTypeParameterMap& BubbleChartDialogController::getTemplateMap() const +{ + static tTemplateServiceChartTypeParameterMap m_aTemplateMap = + tTemplateServiceChartTypeParameterMap + ( C2U( "com.sun.star.chart2.template.Bubble" ), ChartTypeParameter(1,true) ) ; + return m_aTemplateMap; +} +void BubbleChartDialogController::fillSubTypeList( ValueSet& rSubTypeList, bool bIsHighContrast, const ChartTypeParameter& /*rParameter*/ ) +{ + rSubTypeList.Clear(); + rSubTypeList.InsertItem( 1, SELECT_BITMAP( BMP_BUBBLE_1 ) ); + + rSubTypeList.SetItemText( 1, String( SchResId( STR_BUBBLE_1 )) ); +} +void BubbleChartDialogController::adjustParameterToSubType( ChartTypeParameter& rParameter ) +{ + rParameter.b3DLook = false; + rParameter.eStackMode = GlobalStackMode_NONE; +} //............................................................................. } //namespace chart //............................................................................. diff --git a/chart2/source/controller/dialogs/ChartTypeDialogController.hxx b/chart2/source/controller/dialogs/ChartTypeDialogController.hxx index 0f6c7a8ae2c0..cdbda807813f 100644 --- a/chart2/source/controller/dialogs/ChartTypeDialogController.hxx +++ b/chart2/source/controller/dialogs/ChartTypeDialogController.hxx @@ -301,6 +301,19 @@ private: MetricField* m_pMF_NumberOfLines; }; +class BubbleChartDialogController : public ChartTypeDialogController +{ +public: + BubbleChartDialogController(); + virtual ~BubbleChartDialogController(); + + virtual String getName(); + virtual Image getImage( bool bIsHighContrast ); + virtual const tTemplateServiceChartTypeParameterMap& getTemplateMap() const; + virtual void fillSubTypeList( ValueSet& rSubTypeList, bool bIsHighContrast, const ChartTypeParameter& rParameter ); + virtual void adjustParameterToSubType( ChartTypeParameter& rParameter ); +}; + //............................................................................. } //namespace chart //............................................................................. diff --git a/chart2/source/controller/dialogs/DataBrowser.cxx b/chart2/source/controller/dialogs/DataBrowser.cxx index cf61b88a63ac..0a9b58758de6 100644 --- a/chart2/source/controller/dialogs/DataBrowser.cxx +++ b/chart2/source/controller/dialogs/DataBrowser.cxx @@ -407,8 +407,7 @@ Image SeriesHeader::GetChartTypeImage( } else if( aChartTypeName.equals( CHART2_SERVICE_NAME_CHARTTYPE_SCATTER )) { - // @todo: correct image for scatter chart type - aResult = SELECT_IMAGE( IMG_TYPE_LINE, bHC ); + aResult = SELECT_IMAGE( IMG_TYPE_XY, bHC ); } else if( aChartTypeName.equals( CHART2_SERVICE_NAME_CHARTTYPE_PIE )) { @@ -423,6 +422,10 @@ Image SeriesHeader::GetChartTypeImage( // @todo: correct image for candle-stick type aResult = SELECT_IMAGE( IMG_TYPE_STOCK, bHC ); } + else if( aChartTypeName.equals( CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE )) + { + aResult = SELECT_IMAGE( IMG_TYPE_BUBBLE, bHC ); + } return aResult; } @@ -1068,6 +1071,7 @@ sal_Bool DataBrowser::IsTabAllowed( sal_Bool bForward ) const if( CellContainsNumbers( nRow, nCol )) { + m_aNumberEditField.UseInputStringForFormatting(); m_aNumberEditField.SetFormatKey( GetNumberFormatKey( nRow, nCol )); return m_rNumberEditController; } diff --git a/chart2/source/controller/dialogs/DataBrowserModel.cxx b/chart2/source/controller/dialogs/DataBrowserModel.cxx index e612edc0901b..1db67c6721af 100644 --- a/chart2/source/controller/dialogs/DataBrowserModel.cxx +++ b/chart2/source/controller/dialogs/DataBrowserModel.cxx @@ -41,6 +41,8 @@ #include "macros.hxx" #include "StatisticsHelper.hxx" #include "ContainerHelper.hxx" +#include "ChartTypeHelper.hxx" +#include "chartview/ExplicitValueProvider.hxx" #include <com/sun/star/container/XIndexReplace.hpp> #include <com/sun/star/chart2/XDataSeriesContainer.hpp> @@ -329,6 +331,8 @@ void DataBrowserModel::insertDataSeries( sal_Int32 nAfterColumnIndex ) Reference< chart2::XDataSeries > xSeries; if( static_cast< tDataColumnVector::size_type >( nAfterColumnIndex ) <= m_aColumns.size()) xSeries.set( m_aColumns[nAfterColumnIndex].m_xDataSeries ); + + sal_Int32 nSeriesNumberFormat = 0; if( xSeries.is()) { xChartType.set( DiagramHelper::getChartTypeOfSeries( xDiagram, xSeries )); @@ -337,6 +341,10 @@ void DataBrowserModel::insertDataSeries( sal_Int32 nAfterColumnIndex ) lcl_DataSeriesOfHeaderMatches( xSeries ))); if( aIt != m_aHeaders.end()) nStartCol = aIt->m_nEndColumn; + + Reference< beans::XPropertySet > xSeriesProps( xSeries, uno::UNO_QUERY ); + if( xSeriesProps.is() ) + xSeriesProps->getPropertyValue( C2U( "NumberFormat" )) >>= nSeriesNumberFormat; } else { @@ -404,6 +412,14 @@ void DataBrowserModel::insertDataSeries( sal_Int32 nAfterColumnIndex ) } } } + if( nSeriesNumberFormat != 0 ) + { + //give the new series the same number format as the former series especially for bubble charts thus the bubble size values can be edited with same format immidiately + Reference< beans::XPropertySet > xNewSeriesProps( xNewSeries, uno::UNO_QUERY ); + if( xNewSeriesProps.is() ) + xNewSeriesProps->setPropertyValue( C2U( "NumberFormat" ), uno::makeAny( nSeriesNumberFormat ) ); + } + updateFromModel(); } } @@ -724,11 +740,15 @@ void DataBrowserModel::updateFromModel() { Reference< chart2::XChartTypeContainer > xCTCnt( aCooSysSeq[nCooSysIdx], uno::UNO_QUERY_THROW ); Sequence< Reference< chart2::XChartType > > aChartTypes( xCTCnt->getChartTypes()); + sal_Int32 nXAxisNumberFormat = DataSeriesHelper::getNumberFormatKeyFromAxis( 0, aCooSysSeq[nCooSysIdx], 0, 0 ); + for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx ) { Reference< chart2::XDataSeriesContainer > xSeriesCnt( aChartTypes[nCTIdx], uno::UNO_QUERY ); if( xSeriesCnt.is()) { + rtl::OUString aRoleForDataLabelNumberFormat = ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( aChartTypes[nCTIdx] ); + Sequence< Reference< chart2::XDataSeries > > aSeries( xSeriesCnt->getDataSeries()); lcl_tSharedSeqVec aSharedSequences( lcl_getSharedSequences( aSeries )); for( lcl_tSharedSeqVec::const_iterator aIt( aSharedSequences.begin()); @@ -741,16 +761,15 @@ void DataBrowserModel::updateFromModel() // as the sequences are shared it should be ok to take the first series // @todo: dimension index 0 for x-values used here. This is just a guess. // Also, the axis index is 0, as there is usually only one x-axis - aSharedSequence.m_nNumberFormatKey = - DataSeriesHelper::getNumberFormatKeyFromAxis( - aSeries[0], aCooSysSeq[nCooSysIdx], 0, 0 ); + aSharedSequence.m_nNumberFormatKey = nXAxisNumberFormat; m_aColumns.push_back( aSharedSequence ); ++nHeaderStart; } for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aSeries.getLength(); ++nSeriesIdx ) { tDataColumnVector::size_type nStartColIndex = m_aColumns.size(); - Reference< chart2::data::XDataSource > xSource( aSeries[nSeriesIdx], uno::UNO_QUERY ); + Reference< chart2::XDataSeries > xSeries( aSeries[nSeriesIdx] ); + Reference< chart2::data::XDataSource > xSource( xSeries, uno::UNO_QUERY ); if( xSource.is()) { Sequence< Reference< chart2::data::XLabeledDataSequence > > aLSeqs( xSource->getDataSequences()); @@ -768,9 +787,14 @@ void DataBrowserModel::updateFromModel() { sal_Int32 nSequenceNumberFormatKey = nYAxisNumberFormatKey; OUString aRole = lcl_getRole( aLSeqs[nSeqIdx] ); - if( aRole.equals( C2U( "values-x" ) ) ) - nSequenceNumberFormatKey = DataSeriesHelper::getNumberFormatKeyFromAxis( - aSeries[nSeriesIdx], aCooSysSeq[nCooSysIdx], 0, 0 ); + + if( aRole.equals( aRoleForDataLabelNumberFormat ) ) + { + nSequenceNumberFormatKey = ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel( + Reference< beans::XPropertySet >( xSeries, uno::UNO_QUERY ), xSeries, -1, xDiagram ); + } + else if( aRole.equals( C2U( "values-x" ) ) ) + nSequenceNumberFormatKey = nXAxisNumberFormat; if( ::std::find_if( aSharedSequences.begin(), aSharedSequences.end(), lcl_RepresentationsOfLSeqMatch( aLSeqs[nSeqIdx] )) == aSharedSequences.end()) diff --git a/chart2/source/controller/dialogs/DialogModel.cxx b/chart2/source/controller/dialogs/DialogModel.cxx index 1a7e8675f5bc..69e693911c22 100644 --- a/chart2/source/controller/dialogs/DialogModel.cxx +++ b/chart2/source/controller/dialogs/DialogModel.cxx @@ -108,6 +108,7 @@ OUString lcl_ConvertRole( const OUString & rRoleString, bool bFromInternalToUI ) aTranslationMap[ C2U( "values-min" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_MIN ))); aTranslationMap[ C2U( "values-x" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_X ))); aTranslationMap[ C2U( "values-y" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_Y ))); + aTranslationMap[ C2U( "values-size" ) ] = OUString( String( ::chart::SchResId( STR_DATA_ROLE_SIZE ))); } if( bFromInternalToUI ) @@ -155,6 +156,7 @@ void lcl_createRoleIndexMap( lcl_tRoleIndexMap & rOutMap ) rOutMap[ C2U( "values-min" ) ] = ++nIndex; rOutMap[ C2U( "values-max" ) ] = ++nIndex; rOutMap[ C2U( "values-last" ) ] = ++nIndex; + rOutMap[ C2U( "values-size" ) ] = ++nIndex; } struct lcl_DataSeriesContainerAppend : public diff --git a/chart2/source/controller/dialogs/ObjectNameProvider.cxx b/chart2/source/controller/dialogs/ObjectNameProvider.cxx index 7ee4ae67761d..1ed974814ea7 100644 --- a/chart2/source/controller/dialogs/ObjectNameProvider.cxx +++ b/chart2/source/controller/dialogs/ObjectNameProvider.cxx @@ -109,7 +109,7 @@ OUString lcl_getDataPointValueText( const Reference< XDataSeries >& xSeries, sal Sequence< Reference< data::XLabeledDataSequence > > aDataSequences( xDataSource->getDataSequences() ); - rtl::OUString aX, aY, aY_Min, aY_Max, aY_First, aY_Last; + rtl::OUString aX, aY, aY_Min, aY_Max, aY_First, aY_Last, a_Size; double fValue = 0; uno::Reference< util::XNumberFormatsSupplier > xNumberFormatsSupplier( xChartModel, uno::UNO_QUERY ); @@ -170,6 +170,12 @@ OUString lcl_getDataPointValueText( const Reference< XDataSeries >& xSeries, sal sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex ); aY_Last = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged ); } + else if( aRole.equals(C2U("values-size")) ) + { + aData[nPointIndex]>>= fValue; + sal_Int32 nNumberFormatKey = xDataSequence->getNumberFormatKeyByIndex( nPointIndex ); + a_Size = aNumberFormatterWrapper.getFormattedString( nNumberFormatKey, fValue, nLabelColor, bColorChanged ); + } } catch( uno::Exception& e ) { @@ -201,6 +207,7 @@ OUString lcl_getDataPointValueText( const Reference< XDataSeries >& xSeries, sal lcl_addText( aRet, aSeparator, aY_Min ); lcl_addText( aRet, aSeparator, aY_Max ); lcl_addText( aRet, aSeparator, aY_Last ); + lcl_addText( aRet, aSeparator, a_Size ); return aRet; } diff --git a/chart2/source/controller/dialogs/Strings.src b/chart2/source/controller/dialogs/Strings.src index b08fe754513f..3b384915f2d0 100644 --- a/chart2/source/controller/dialogs/Strings.src +++ b/chart2/source/controller/dialogs/Strings.src @@ -471,6 +471,11 @@ String STR_DATA_ROLE_Y Text [ en-US ] = "Y-Values" ; }; +String STR_DATA_ROLE_SIZE +{ + Text [ en-US ] = "Bubble Sizes" ; +}; + String STR_DATA_ROLE_X_ERROR { Text [ en-US ] = "X-Error-Bars" ; diff --git a/chart2/source/controller/dialogs/Strings_ChartTypes.src b/chart2/source/controller/dialogs/Strings_ChartTypes.src index 1e18f0e8724f..2234f04a3fcd 100644 --- a/chart2/source/controller/dialogs/Strings_ChartTypes.src +++ b/chart2/source/controller/dialogs/Strings_ChartTypes.src @@ -140,4 +140,13 @@ String STR_DEEP Text [ en-US ] = "Deep" ; }; //----------------------------------------------------------------------------- +String STR_TYPE_BUBBLE +{ + Text [ en-US ] = "Bubble" ; +}; +String STR_BUBBLE_1 +{ + Text [ en-US ] = "Bubble Chart" ; +}; +//----------------------------------------------------------------------------- //----------------------------------------------------------------------------- diff --git a/chart2/source/controller/dialogs/res_DataLabel.cxx b/chart2/source/controller/dialogs/res_DataLabel.cxx index a93711151ac1..c6129629a51a 100644 --- a/chart2/source/controller/dialogs/res_DataLabel.cxx +++ b/chart2/source/controller/dialogs/res_DataLabel.cxx @@ -215,6 +215,13 @@ DataLabelResources::DataLabelResources( Window* pWindow, const SfxItemSet& rInAt m_bNumberFormatMixedState = !lcl_ReadNumberFormatFromItemSet( rInAttrs, SID_ATTR_NUMBERFORMAT_VALUE, SID_ATTR_NUMBERFORMAT_SOURCE, m_nNumberFormatForValue, m_bSourceFormatForValue, m_bSourceFormatMixedState ); m_bPercentFormatMixedState = !lcl_ReadNumberFormatFromItemSet( rInAttrs, SCHATTR_PERCENT_NUMBERFORMAT_VALUE, SCHATTR_PERCENT_NUMBERFORMAT_SOURCE, m_nNumberFormatForPercent, m_bSourceFormatForPercent , m_bPercentSourceMixedState); + if( rInAttrs.GetItemState(SCHATTR_DATADESCR_NO_PERCENTVALUE, TRUE, &pPoolItem) == SFX_ITEM_SET ) + { + bool bForbidPercentValue = (static_cast< const SfxBoolItem & >( rInAttrs.Get( SCHATTR_DATADESCR_NO_PERCENTVALUE )).GetValue() ); + if( bForbidPercentValue ) + m_aCBPercent.Enable(false); + } + m_aDC_Dial.SetLinkedField( &m_aNF_Degrees ); } @@ -286,14 +293,14 @@ IMPL_LINK( DataLabelResources, CheckHdl, CheckBox*, pBox ) void DataLabelResources::EnableControls() { - m_aCBSymbol.Enable( m_aCBNumber.IsChecked() || m_aCBPercent.IsChecked() || m_aCBCategory.IsChecked() ); + m_aCBSymbol.Enable( m_aCBNumber.IsChecked() || (m_aCBPercent.IsChecked() && m_aCBPercent.IsEnabled()) || m_aCBCategory.IsChecked() ); //enable separator { long nNumberOfCheckedLabelParts = 0; if( m_aCBNumber.IsChecked() ) ++nNumberOfCheckedLabelParts; - if( m_aCBPercent.IsChecked() ) + if( m_aCBPercent.IsChecked() && m_aCBPercent.IsEnabled() ) ++nNumberOfCheckedLabelParts; if( m_aCBCategory.IsChecked() ) ++nNumberOfCheckedLabelParts; @@ -307,7 +314,7 @@ void DataLabelResources::EnableControls() } m_aPB_NumberFormatForValue.Enable( m_pNumberFormatter && m_aCBNumber.IsChecked() ); - m_aPB_NumberFormatForPercent.Enable( m_pNumberFormatter && m_aCBPercent.IsChecked() ); + m_aPB_NumberFormatForPercent.Enable( m_pNumberFormatter && m_aCBPercent.IsChecked() && m_aCBPercent.IsEnabled() ); bool bEnableRotation = ( m_aCBNumber.IsChecked() || m_aCBPercent.IsChecked() || m_aCBCategory.IsChecked() ); m_aFL_Rotate.Enable( bEnableRotation ); diff --git a/chart2/source/controller/dialogs/tp_ChartType.cxx b/chart2/source/controller/dialogs/tp_ChartType.cxx index f60637af4c44..b2d64400ef98 100644 --- a/chart2/source/controller/dialogs/tp_ChartType.cxx +++ b/chart2/source/controller/dialogs/tp_ChartType.cxx @@ -862,6 +862,7 @@ ChartTypeTabPage::ChartTypeTabPage( Window* pParent m_aChartTypeDialogControllerList.push_back(new AreaChartDialogController() ); m_aChartTypeDialogControllerList.push_back(new LineChartDialogController() ); m_aChartTypeDialogControllerList.push_back(new XYChartDialogController() ); + m_aChartTypeDialogControllerList.push_back(new BubbleChartDialogController() ); m_aChartTypeDialogControllerList.push_back(new NetChartDialogController() ); m_aChartTypeDialogControllerList.push_back(new StockChartDialogController() ); m_aChartTypeDialogControllerList.push_back(new CombiColumnLineChartDialogController() ); diff --git a/chart2/source/controller/inc/DataPointItemConverter.hxx b/chart2/source/controller/inc/DataPointItemConverter.hxx index a59170f4d699..4eec81bd20b5 100644 --- a/chart2/source/controller/inc/DataPointItemConverter.hxx +++ b/chart2/source/controller/inc/DataPointItemConverter.hxx @@ -103,6 +103,7 @@ private: sal_Int32 m_nNumberFormat; sal_Int32 m_nPercentNumberFormat; ::com::sun::star::uno::Sequence< sal_Int32 > m_aAvailableLabelPlacements; + bool m_bForbidPercentValue; }; } // namespace wrapper diff --git a/chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx b/chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx index 0c0ea2d0dbdd..af062cf3b93c 100644 --- a/chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx +++ b/chart2/source/controller/itemsetwrapper/DataPointItemConverter.cxx @@ -239,7 +239,8 @@ DataPointItemConverter::DataPointItemConverter( m_nSpecialFillColor(nSpecialFillColor), m_nNumberFormat(nNumberFormat), m_nPercentNumberFormat(nPercentNumberFormat), - m_aAvailableLabelPlacements() + m_aAvailableLabelPlacements(), + m_bForbidPercentValue(true) { m_aConverters.push_back( new GraphicPropertyItemConverter( rPropertySet, rItemPool, rDrawModel, xNamedPropertyContainerFactory, eMapTo )); @@ -257,6 +258,8 @@ DataPointItemConverter::DataPointItemConverter( bool bAmbiguous = false; sal_Bool bSwapXAndY = DiagramHelper::getVertical( xDiagram, bFound, bAmbiguous ); m_aAvailableLabelPlacements = ChartTypeHelper::getSupportedLabelPlacements( xChartType, DiagramHelper::getDimension( xDiagram ), bSwapXAndY, xSeries ); + + m_bForbidPercentValue = AxisType::CATEGORY != ChartTypeHelper::getAxisType( xChartType, 0 ); } DataPointItemConverter::~DataPointItemConverter() @@ -648,6 +651,12 @@ void DataPointItemConverter::FillSpecialItem( } break; + case SCHATTR_DATADESCR_NO_PERCENTVALUE: + { + rOutItemSet.Put( SfxBoolItem( nWhichId, m_bForbidPercentValue )); + } + break; + case SCHATTR_STYLE_SYMBOL: { chart2::Symbol aSymbol; diff --git a/chart2/source/controller/itemsetwrapper/MultipleChartConverters.cxx b/chart2/source/controller/itemsetwrapper/MultipleChartConverters.cxx index 9f300e8febc1..4b626e1be839 100644 --- a/chart2/source/controller/itemsetwrapper/MultipleChartConverters.cxx +++ b/chart2/source/controller/itemsetwrapper/MultipleChartConverters.cxx @@ -141,9 +141,8 @@ AllDataLabelItemConverter::AllDataLabelItemConverter( uno::Reference< beans::XPropertySet > xObjectProperties( *aIt, uno::UNO_QUERY); uno::Reference< uno::XComponentContext> xContext(0);//do not need Context for label properties - sal_Int32 nNumberFormat=ExplicitValueProvider::getExplicitNumberFormatKeyForLabel( xObjectProperties, *aIt, -1/*nPointIndex*/, - uno::Reference< beans::XPropertySet >( DiagramHelper::getAttachedAxis( *aIt, ChartModelHelper::findDiagram( xChartModel ) ), uno::UNO_QUERY ) ); - sal_Int32 nPercentNumberFormat=ExplicitValueProvider::getExplicitPercentageNumberFormatKeyForLabel( + sal_Int32 nNumberFormat=ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel( xObjectProperties, *aIt, -1/*nPointIndex*/, ChartModelHelper::findDiagram( xChartModel ) ); + sal_Int32 nPercentNumberFormat=ExplicitValueProvider::getExplicitPercentageNumberFormatKeyForDataLabel( xObjectProperties,uno::Reference< util::XNumberFormatsSupplier >(xChartModel, uno::UNO_QUERY)); m_aConverters.push_back( new ::chart::wrapper::DataPointItemConverter( diff --git a/chart2/source/controller/itemsetwrapper/SchWhichPairs.hxx b/chart2/source/controller/itemsetwrapper/SchWhichPairs.hxx index 0321df6035f2..dbefb0e7f025 100644 --- a/chart2/source/controller/itemsetwrapper/SchWhichPairs.hxx +++ b/chart2/source/controller/itemsetwrapper/SchWhichPairs.hxx @@ -128,8 +128,6 @@ const USHORT nDataLabelWhichPairs[] = SID_ATTR_NUMBERFORMAT_SOURCE, SID_ATTR_NUMBERFORMAT_SOURCE, /* 11432 svx/svxids.hrc */ \ SCHATTR_PERCENT_NUMBERFORMAT_VALUE, SCHATTR_PERCENT_NUMBERFORMAT_VALUE, /* 40 sch/schattr.hxx*/ \ SCHATTR_PERCENT_NUMBERFORMAT_SOURCE, SCHATTR_PERCENT_NUMBERFORMAT_SOURCE, /* 41 sch/schattr.hxx*/ \ - SCHATTR_DATADESCR_PLACEMENT, SCHATTR_DATADESCR_PLACEMENT, - SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS, SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS, SCHATTR_TEXT_DEGREES,SCHATTR_TEXT_DEGREES, EE_PARA_WRITINGDIR,EE_PARA_WRITINGDIR, 0 @@ -145,8 +143,6 @@ const USHORT nDataLabelWhichPairs[] = SID_ATTR_NUMBERFORMAT_SOURCE, SID_ATTR_NUMBERFORMAT_SOURCE, /* 11432 svx/svxids.hrc */ \ SCHATTR_PERCENT_NUMBERFORMAT_VALUE, SCHATTR_PERCENT_NUMBERFORMAT_VALUE, /* 40 sch/schattr.hxx*/ \ SCHATTR_PERCENT_NUMBERFORMAT_SOURCE, SCHATTR_PERCENT_NUMBERFORMAT_SOURCE, /* 41 sch/schattr.hxx*/ \ - SCHATTR_DATADESCR_PLACEMENT, SCHATTR_DATADESCR_PLACEMENT, \ - SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS, SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS, \ SCHATTR_TEXT_DEGREES, SCHATTR_TEXT_DEGREES, \ SCHATTR_STYLE_START,SCHATTR_STYLE_END, /* 59 - 68 sch/schattr.hxx*/ \ SCHATTR_SYMBOL_BRUSH,SCHATTR_SYMBOL_BRUSH, /* 94 sch/schattr.hxx*/ \ diff --git a/chart2/source/controller/main/ChartController.cxx b/chart2/source/controller/main/ChartController.cxx index c56a0317b4dc..b104e232b3b6 100644 --- a/chart2/source/controller/main/ChartController.cxx +++ b/chart2/source/controller/main/ChartController.cxx @@ -480,7 +480,7 @@ void SAL_CALL ChartController::modeChanged( const util::ModeChangeEvent& rEvent { //the view has become dirty, we should repaint it if we have a window if( m_pChartWindow ) - m_pChartWindow->Invalidate(); + m_pChartWindow->ForceInvalidate(); } else if( rEvent.NewMode.equals(C2U("invalid")) ) { @@ -490,8 +490,11 @@ void SAL_CALL ChartController::modeChanged( const util::ModeChangeEvent& rEvent if( m_pDrawViewWrapper && m_pDrawViewWrapper->IsTextEdit() ) this->EndTextEdit(); if( m_pDrawViewWrapper ) + { m_pDrawViewWrapper->UnmarkAll(); //m_pDrawViewWrapper->hideMarkHandles(); todo?? + m_pDrawViewWrapper->HideSdrPage(); + } } else { diff --git a/chart2/source/controller/main/ChartController_Properties.cxx b/chart2/source/controller/main/ChartController_Properties.cxx index 3b5b3d6fa7ba..530cd6f0aeb8 100644 --- a/chart2/source/controller/main/ChartController_Properties.cxx +++ b/chart2/source/controller/main/ChartController_Properties.cxx @@ -240,9 +240,8 @@ namespace } } } - sal_Int32 nNumberFormat=ExplicitValueProvider::getExplicitNumberFormatKeyForLabel( xObjectProperties, xSeries, nPointIndex, - uno::Reference< beans::XPropertySet >( DiagramHelper::getAttachedAxis( xSeries, xDiagram ), uno::UNO_QUERY ) ); - sal_Int32 nPercentNumberFormat=ExplicitValueProvider::getExplicitPercentageNumberFormatKeyForLabel( + sal_Int32 nNumberFormat=ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel( xObjectProperties, xSeries, nPointIndex, xDiagram ); + sal_Int32 nPercentNumberFormat=ExplicitValueProvider::getExplicitPercentageNumberFormatKeyForDataLabel( xObjectProperties,uno::Reference< util::XNumberFormatsSupplier >(xChartModel, uno::UNO_QUERY)); pItemConverter = new wrapper::DataPointItemConverter( xChartModel, xContext, diff --git a/chart2/source/controller/main/ChartWindow.cxx b/chart2/source/controller/main/ChartWindow.cxx index 5c9e201aebd8..10b999df8f43 100644 --- a/chart2/source/controller/main/ChartWindow.cxx +++ b/chart2/source/controller/main/ChartWindow.cxx @@ -60,6 +60,7 @@ namespace chart ChartWindow::ChartWindow( WindowController* pWindowController, Window* pParent, WinBits nStyle ) : Window(pParent, nStyle) , m_pWindowController( pWindowController ) + , m_bInPaint(false) { this->SetSmartHelpId( SmartId( HID_SCH_WIN_DOCUMENT ) ); this->SetMapMode( MapMode(MAP_100TH_MM) ); @@ -67,7 +68,7 @@ ChartWindow::ChartWindow( WindowController* pWindowController, Window* pParent, // chart does not depend on exact pixel painting => enable antialiased drawing SetAntialiasing( ANTIALIASING_ENABLE_B2DDRAW | GetAntialiasing() ); EnableRTL( FALSE ); - if( pParent )
+ if( pParent ) pParent->EnableRTL( FALSE );// #i96215# necessary for a correct position of the context menu in rtl mode } @@ -92,10 +93,12 @@ void ChartWindow::PrePaint() void ChartWindow::Paint( const Rectangle& rRect ) { + m_bInPaint = true; if( m_pWindowController ) m_pWindowController->execute_Paint( rRect ); else Window::Paint( rRect ); + m_bInPaint = false; } void ChartWindow::MouseButtonDown(const MouseEvent& rMEvt) @@ -243,6 +246,29 @@ void ChartWindow::adjustHighContrastMode() SetDrawMode( bUseContrast ? nContrastMode : DRAWMODE_DEFAULT ); } +void ChartWindow::ForceInvalidate() +{ + ::Window::Invalidate(); +} +void ChartWindow::Invalidate( USHORT nFlags ) +{ + if( m_bInPaint ) // #i101928# superfluous paint calls while entering and editing charts" + return; + ::Window::Invalidate( nFlags ); +} +void ChartWindow::Invalidate( const Rectangle& rRect, USHORT nFlags ) +{ + if( m_bInPaint ) // #i101928# superfluous paint calls while entering and editing charts" + return; + ::Window::Invalidate( rRect, nFlags ); +} +void ChartWindow::Invalidate( const Region& rRegion, USHORT nFlags ) +{ + if( m_bInPaint ) // #i101928# superfluous paint calls while entering and editing charts" + return; + ::Window::Invalidate( rRegion, nFlags ); +} + //............................................................................. } //namespace chart //............................................................................. diff --git a/chart2/source/controller/main/ChartWindow.hxx b/chart2/source/controller/main/ChartWindow.hxx index 41cc7b514a07..543c0b13ffdc 100644 --- a/chart2/source/controller/main/ChartWindow.hxx +++ b/chart2/source/controller/main/ChartWindow.hxx @@ -70,10 +70,16 @@ public: virtual void DataChanged( const DataChangedEvent& rDCEvt ); virtual void RequestHelp( const HelpEvent& rHEvt ); + void ForceInvalidate(); + virtual void Invalidate( USHORT nFlags = 0 ); + virtual void Invalidate( const Rectangle& rRect, USHORT nFlags = 0 ); + virtual void Invalidate( const Region& rRegion, USHORT nFlags = 0 ); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::accessibility::XAccessible > CreateAccessible(); private: WindowController* m_pWindowController; + bool m_bInPaint; void adjustHighContrastMode(); }; diff --git a/chart2/source/inc/ChartTypeHelper.hxx b/chart2/source/inc/ChartTypeHelper.hxx index efa4758c4ccd..df43e24a9482 100644 --- a/chart2/source/inc/ChartTypeHelper.hxx +++ b/chart2/source/inc/ChartTypeHelper.hxx @@ -86,6 +86,17 @@ public: static sal_Int32 //one of ::com::sun::star::chart2::AxisType getAxisType( const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartType >& xChartType , sal_Int32 nDimensionIndex ); + + static rtl::OUString getRoleOfSequenceForYAxisNumberFormatDetection( const ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XChartType >& xChartType ); + + static rtl::OUString getRoleOfSequenceForDataLabelNumberFormatDetection( const ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XChartType >& xChartType ); + + static bool shouldLabelNumberFormatKeyBeDetectedFromYAxis( const ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XChartType >& xChartType ); + + static bool isSupportingOnlyDeepStackingFor3D( const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartType >& xChartType ); }; //............................................................................. diff --git a/chart2/source/inc/CommonFunctors.hxx b/chart2/source/inc/CommonFunctors.hxx index 1c4a76efd229..2ec4efa41b8c 100644 --- a/chart2/source/inc/CommonFunctors.hxx +++ b/chart2/source/inc/CommonFunctors.hxx @@ -100,8 +100,11 @@ struct OOO_DLLPUBLIC_CHARTTOOLS AnyToString : public ::std::unary_function< ::co ::com::sun::star::uno::TypeClass eClass( rAny.getValueType().getTypeClass() ); if( eClass == ::com::sun::star::uno::TypeClass_DOUBLE ) { + const double* pDouble = reinterpret_cast< const double * >( rAny.getValue() ); + if( ::rtl::math::isNan(*pDouble) ) + return ::rtl::OUString(); return ::rtl::math::doubleToUString( - * reinterpret_cast< const double * >( rAny.getValue() ), + * pDouble, rtl_math_StringFormat_Automatic, -1, // use maximum decimal places available sal_Char( '.' ), // decimal separator diff --git a/chart2/source/inc/Strings.hrc b/chart2/source/inc/Strings.hrc index 0af8f7e1ae04..133f5bcc255b 100644 --- a/chart2/source/inc/Strings.hrc +++ b/chart2/source/inc/Strings.hrc @@ -33,8 +33,8 @@ // this includes no link dependency #include <svtools/solar.hrc> +//next free is 285 //single free is: 134 -//next free is 282 //#define RID_APP_START 30000 ////#define STR_NULL (RID_APP_START + 1) @@ -129,6 +129,9 @@ #define STR_STOCK_3 (RID_APP_START + 145) #define STR_STOCK_4 (RID_APP_START + 146) +#define STR_TYPE_BUBBLE (RID_APP_START + 282) +#define STR_BUBBLE_1 (RID_APP_START + 283) + //----------------------------------------------------------------------------- //additional controls for wizard: @@ -181,6 +184,7 @@ #define STR_DATA_ROLE_MIN (RID_APP_START + 248) #define STR_DATA_ROLE_MAX (RID_APP_START + 249) #define STR_DATA_ROLE_CATEGORIES (RID_APP_START + 260) +#define STR_DATA_ROLE_SIZE (RID_APP_START + 284) #define STR_DATA_UNNAMED_SERIES (RID_APP_START + 250) #define STR_DATA_UNNAMED_SERIES_WITH_INDEX (RID_APP_START + 251) diff --git a/chart2/source/inc/chartview/ChartSfxItemIds.hxx b/chart2/source/inc/chartview/ChartSfxItemIds.hxx index d1a738d84e94..e4afc0d9efbd 100644 --- a/chart2/source/inc/chartview/ChartSfxItemIds.hxx +++ b/chart2/source/inc/chartview/ChartSfxItemIds.hxx @@ -51,7 +51,8 @@ #define SCHATTR_DATADESCR_SEPARATOR (SCHATTR_DATADESCR_START + 4) #define SCHATTR_DATADESCR_PLACEMENT (SCHATTR_DATADESCR_START + 5) #define SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS (SCHATTR_DATADESCR_START + 6) -#define SCHATTR_DATADESCR_END SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS +#define SCHATTR_DATADESCR_NO_PERCENTVALUE (SCHATTR_DATADESCR_START + 7) //percentage values should not be offered +#define SCHATTR_DATADESCR_END SCHATTR_DATADESCR_NO_PERCENTVALUE #define SCHATTR_LEGEND_START (SCHATTR_DATADESCR_END + 1) #define SCHATTR_LEGEND_POS SCHATTR_LEGEND_START diff --git a/chart2/source/inc/chartview/ExplicitValueProvider.hxx b/chart2/source/inc/chartview/ExplicitValueProvider.hxx index 2f96bed91fa5..ab94e7e1c337 100644 --- a/chart2/source/inc/chartview/ExplicitValueProvider.hxx +++ b/chart2/source/inc/chartview/ExplicitValueProvider.hxx @@ -36,6 +36,7 @@ #include <com/sun/star/chart2/XAxis.hpp> #include <com/sun/star/chart2/XCoordinateSystem.hpp> #include <com/sun/star/chart2/XDataSeries.hpp> +#include <com/sun/star/chart2/XDiagram.hpp> #include <com/sun/star/awt/Rectangle.hpp> #include <com/sun/star/frame/XModel.hpp> #include <com/sun/star/drawing/XShape.hpp> @@ -94,13 +95,13 @@ public: SAL_DLLPRIVATE static sal_Int32 getPercentNumberFormat( const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier >& xNumberFormatsSupplier ); - static sal_Int32 getExplicitNumberFormatKeyForLabel( + static sal_Int32 getExplicitNumberFormatKeyForDataLabel( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& xSeriesOrPointProp , const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XDataSeries >& xSeries , sal_Int32 nPointIndex /*-1 for whole series*/ - , const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& xAttachedAxisProps ); + , const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XDiagram >& xDiagram ); - static sal_Int32 getExplicitPercentageNumberFormatKeyForLabel( + static sal_Int32 getExplicitPercentageNumberFormatKeyForDataLabel( const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& xSeriesOrPointProp , const ::com::sun::star::uno::Reference< ::com::sun::star::util::XNumberFormatsSupplier >& xNumberFormatsSupplier ); }; diff --git a/chart2/source/inc/servicenames_charttypes.hxx b/chart2/source/inc/servicenames_charttypes.hxx index 461483b46e0d..1c2782de3852 100644 --- a/chart2/source/inc/servicenames_charttypes.hxx +++ b/chart2/source/inc/servicenames_charttypes.hxx @@ -43,6 +43,7 @@ namespace chart #define CHART2_SERVICE_NAME_CHARTTYPE_PIE ::rtl::OUString::createFromAscii("com.sun.star.chart2.PieChartType") #define CHART2_SERVICE_NAME_CHARTTYPE_NET ::rtl::OUString::createFromAscii("com.sun.star.chart2.NetChartType") #define CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK ::rtl::OUString::createFromAscii("com.sun.star.chart2.CandleStickChartType") +#define CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE ::rtl::OUString::createFromAscii("com.sun.star.chart2.BubbleChartType") //............................................................................. } //namespace chart diff --git a/chart2/source/model/template/BubbleChartType.cxx b/chart2/source/model/template/BubbleChartType.cxx new file mode 100644 index 000000000000..09e629462d48 --- /dev/null +++ b/chart2/source/model/template/BubbleChartType.cxx @@ -0,0 +1,245 @@ +/************************************************************************* + * + * 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: ,v $ + * $Revision: $ + * + * 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_chart2.hxx" +#include "BubbleChartType.hxx" +#include "PropertyHelper.hxx" +#include "macros.hxx" +#include "servicenames_charttypes.hxx" +#include "ContainerHelper.hxx" +#include "CartesianCoordinateSystem.hxx" +#include "AxisHelper.hxx" +#include "AxisIndexDefines.hxx" +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <com/sun/star/chart2/AxisType.hpp> +#include <com/sun/star/chart2/CurveStyle.hpp> + +using namespace ::com::sun::star; + +using ::rtl::OUString; +using ::com::sun::star::beans::Property; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Any; +using ::osl::MutexGuard; + +namespace +{ + +void lcl_AddPropertiesToVector( + ::std::vector< Property > & /*rOutProperties*/ ) +{ +} + +void lcl_AddDefaultsToMap( + ::chart::tPropertyValueMap & /*rOutMap*/ ) +{ +} + +const Sequence< Property > & lcl_GetPropertySequence() +{ + static Sequence< Property > aPropSeq; + + // /-- + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if( 0 == aPropSeq.getLength() ) + { + // get properties + ::std::vector< ::com::sun::star::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + + // and sort them for access via bsearch + ::std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + // transfer result to static Sequence + aPropSeq = ::chart::ContainerHelper::ContainerToSequence( aProperties ); + } + + return aPropSeq; +} + +} // anonymous namespace + +namespace chart +{ + +BubbleChartType::BubbleChartType( + const uno::Reference< uno::XComponentContext > & xContext ) + : ChartType( xContext ) +{ +} + +BubbleChartType::BubbleChartType( const BubbleChartType & rOther ) : + ChartType( rOther ) +{ +} + +BubbleChartType::~BubbleChartType() +{} + +// ____ XCloneable ____ +uno::Reference< util::XCloneable > SAL_CALL BubbleChartType::createClone() + throw (uno::RuntimeException) +{ + return uno::Reference< util::XCloneable >( new BubbleChartType( *this )); +} + +// ____ XChartType ____ +Reference< chart2::XCoordinateSystem > SAL_CALL + BubbleChartType::createCoordinateSystem( ::sal_Int32 DimensionCount ) + throw (lang::IllegalArgumentException, + uno::RuntimeException) +{ + Reference< chart2::XCoordinateSystem > xResult( + new CartesianCoordinateSystem( + GetComponentContext(), DimensionCount, /* bSwapXAndYAxis */ sal_False )); + + for( sal_Int32 i=0; i<DimensionCount; ++i ) + { + Reference< chart2::XAxis > xAxis( xResult->getAxisByDimension( i, MAIN_AXIS_INDEX ) ); + if( !xAxis.is() ) + { + OSL_ENSURE(false,"a created coordinate system should have an axis for each dimension"); + continue; + } + + chart2::ScaleData aScaleData = xAxis->getScaleData(); + aScaleData.Orientation = chart2::AxisOrientation_MATHEMATICAL; + aScaleData.Scaling = AxisHelper::createLinearScaling(); + + if( i == 2 ) + aScaleData.AxisType = chart2::AxisType::SERIES; + else + aScaleData.AxisType = chart2::AxisType::REALNUMBER; + + xAxis->setScaleData( aScaleData ); + } + + return xResult; +} + +::rtl::OUString SAL_CALL BubbleChartType::getChartType() + throw (uno::RuntimeException) +{ + return CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE; +} + +uno::Sequence< ::rtl::OUString > SAL_CALL BubbleChartType::getSupportedMandatoryRoles() + throw (uno::RuntimeException) +{ + static uno::Sequence< ::rtl::OUString > aMandRolesSeq; + + if( aMandRolesSeq.getLength() == 0 ) + { + aMandRolesSeq.realloc( 4 ); + aMandRolesSeq[0] = C2U( "label" ); + aMandRolesSeq[1] = C2U( "values-x" ); + aMandRolesSeq[2] = C2U( "values-y" ); + aMandRolesSeq[3] = C2U( "values-size" ); + } + + return aMandRolesSeq; +} + +OUString SAL_CALL BubbleChartType::getRoleOfSequenceForSeriesLabel() + throw (uno::RuntimeException) +{ + return C2U( "values-size" ); +} + +// ____ OPropertySet ____ +uno::Any BubbleChartType::GetDefaultValue( sal_Int32 nHandle ) const + throw(beans::UnknownPropertyException) +{ + static tPropertyValueMap aStaticDefaults; + + // /-- + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if( 0 == aStaticDefaults.size() ) + { + // initialize defaults + lcl_AddDefaultsToMap( aStaticDefaults ); + } + + tPropertyValueMap::const_iterator aFound( + aStaticDefaults.find( nHandle )); + + if( aFound == aStaticDefaults.end()) + return uno::Any(); + + return (*aFound).second; + // \-- +} + +// ____ OPropertySet ____ +::cppu::IPropertyArrayHelper & SAL_CALL BubbleChartType::getInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aArrayHelper( lcl_GetPropertySequence(), + /* bSorted = */ sal_True ); + + return aArrayHelper; +} + + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL + BubbleChartType::getPropertySetInfo() + throw (uno::RuntimeException) +{ + static uno::Reference< beans::XPropertySetInfo > xInfo; + + // /-- + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if( !xInfo.is()) + { + xInfo = ::cppu::OPropertySetHelper::createPropertySetInfo( + getInfoHelper()); + } + + return xInfo; + // \-- +} + +uno::Sequence< ::rtl::OUString > BubbleChartType::getSupportedServiceNames_Static() +{ + uno::Sequence< ::rtl::OUString > aServices( 3 ); + aServices[ 0 ] = CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE; + aServices[ 1 ] = C2U( "com.sun.star.chart2.ChartType" ); + aServices[ 2 ] = C2U( "com.sun.star.beans.PropertySet" ); + return aServices; +} + +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +APPHELPER_XSERVICEINFO_IMPL( BubbleChartType, + C2U( "com.sun.star.comp.chart.BubbleChartType" )); + +} // namespace chart diff --git a/chart2/source/model/template/BubbleChartType.hxx b/chart2/source/model/template/BubbleChartType.hxx new file mode 100644 index 000000000000..3694ac1c955c --- /dev/null +++ b/chart2/source/model/template/BubbleChartType.hxx @@ -0,0 +1,89 @@ +/************************************************************************* + * + * 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: ,v $ + * $Revision: $ + * + * 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 CHART_BUBBLECHARTTYPE_HXX +#define CHART_BUBBLECHARTTYPE_HXX + +#include "ChartType.hxx" +#include "ServiceMacros.hxx" +#include <com/sun/star/chart2/CurveStyle.hpp> + +namespace chart +{ + +class BubbleChartType : public ChartType +{ +public: + BubbleChartType( + ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > const & xContext ); + virtual ~BubbleChartType(); + + APPHELPER_XSERVICEINFO_DECL() + + /// establish methods for factory instatiation + APPHELPER_SERVICE_FACTORY_HELPER( BubbleChartType ) + +protected: + explicit BubbleChartType( const BubbleChartType & rOther ); + + // ____ XChartType ____ + virtual ::rtl::OUString SAL_CALL getChartType() + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL + getSupportedMandatoryRoles() + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XCoordinateSystem > SAL_CALL + createCoordinateSystem( ::sal_Int32 DimensionCount ) + throw (::com::sun::star::lang::IllegalArgumentException, + ::com::sun::star::uno::RuntimeException); + virtual ::rtl::OUString SAL_CALL getRoleOfSequenceForSeriesLabel() + throw (::com::sun::star::uno::RuntimeException); + + // ____ OPropertySet ____ + virtual ::com::sun::star::uno::Any GetDefaultValue( sal_Int32 nHandle ) const + throw(::com::sun::star::beans::UnknownPropertyException); + + // ____ OPropertySet ____ + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper(); + + // ____ XPropertySet ____ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() + throw (::com::sun::star::uno::RuntimeException); + + // ____ XCloneable ____ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::util::XCloneable > SAL_CALL createClone() + throw (::com::sun::star::uno::RuntimeException); +}; + +} // namespace chart + +// CHART_BUBBLECHARTTYPE_HXX +#endif diff --git a/chart2/source/model/template/BubbleChartTypeTemplate.cxx b/chart2/source/model/template/BubbleChartTypeTemplate.cxx new file mode 100644 index 000000000000..0853cea6a5cb --- /dev/null +++ b/chart2/source/model/template/BubbleChartTypeTemplate.cxx @@ -0,0 +1,322 @@ +/************************************************************************* + * + * 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: ,v $ + * $Revision: $ + * + * 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_chart2.hxx" +#include "BubbleChartTypeTemplate.hxx" +#include "macros.hxx" +#include "BubbleDataInterpreter.hxx" +#include "CartesianCoordinateSystem.hxx" +#include "Scaling.hxx" +#include "DiagramHelper.hxx" +#include "servicenames_charttypes.hxx" +#include "ContainerHelper.hxx" +#include "DataSeriesHelper.hxx" +#include <com/sun/star/chart2/SymbolStyle.hpp> +#include <com/sun/star/chart2/Symbol.hpp> +#include <com/sun/star/drawing/LineStyle.hpp> +#include "PropertyHelper.hxx" +#include <com/sun/star/beans/PropertyAttribute.hpp> + +#include <algorithm> + +using namespace ::com::sun::star; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; +using ::com::sun::star::beans::Property; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Any; +using ::osl::MutexGuard; + +namespace +{ + +static const OUString lcl_aServiceName( + RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.chart2.BubbleChartTypeTemplate" )); + +void lcl_AddPropertiesToVector( + ::std::vector< Property > & /*rOutProperties*/ ) +{ +} + +void lcl_AddDefaultsToMap( + ::chart::tPropertyValueMap & /*rOutMap*/ ) +{ +} + +const Sequence< Property > & lcl_GetPropertySequence() +{ + static Sequence< Property > aPropSeq; + + // /-- + MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if( 0 == aPropSeq.getLength() ) + { + // get properties + ::std::vector< ::com::sun::star::beans::Property > aProperties; + lcl_AddPropertiesToVector( aProperties ); + + // and sort them for access via bsearch + ::std::sort( aProperties.begin(), aProperties.end(), + ::chart::PropertyNameLess() ); + + // transfer result to static Sequence + aPropSeq = ::chart::ContainerHelper::ContainerToSequence( aProperties ); + } + + return aPropSeq; +} + +::cppu::IPropertyArrayHelper & lcl_getInfoHelper() +{ + static ::cppu::OPropertyArrayHelper aArrayHelper( + lcl_GetPropertySequence(), + /* bSorted = */ sal_True ); + + return aArrayHelper; +} + +} // anonymous namespace + +namespace chart +{ + +BubbleChartTypeTemplate::BubbleChartTypeTemplate( + Reference< + uno::XComponentContext > const & xContext, + const OUString & rServiceName ) : + ChartTypeTemplate( xContext, rServiceName ), + ::property::OPropertySet( m_aMutex ) +{ +} + +BubbleChartTypeTemplate::~BubbleChartTypeTemplate() +{} + +// ____ OPropertySet ____ +uno::Any BubbleChartTypeTemplate::GetDefaultValue( sal_Int32 nHandle ) const + throw(beans::UnknownPropertyException) +{ + static tPropertyValueMap aStaticDefaults; + + // /-- + ::osl::MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if( 0 == aStaticDefaults.size() ) + { + // initialize defaults + lcl_AddDefaultsToMap( aStaticDefaults ); + } + + tPropertyValueMap::const_iterator aFound( + aStaticDefaults.find( nHandle )); + + if( aFound == aStaticDefaults.end()) + return uno::Any(); + + return (*aFound).second; + // \-- +} + +::cppu::IPropertyArrayHelper & SAL_CALL BubbleChartTypeTemplate::getInfoHelper() +{ + return lcl_getInfoHelper(); +} + + +// ____ XPropertySet ____ +uno::Reference< beans::XPropertySetInfo > SAL_CALL + BubbleChartTypeTemplate::getPropertySetInfo() + throw (uno::RuntimeException) +{ + static uno::Reference< beans::XPropertySetInfo > xInfo; + + // /-- + MutexGuard aGuard( ::osl::Mutex::getGlobalMutex() ); + if( !xInfo.is()) + { + xInfo = ::cppu::OPropertySetHelper::createPropertySetInfo( + getInfoHelper()); + } + + return xInfo; + // \-- +} + +sal_Int32 BubbleChartTypeTemplate::getDimension() const +{ + return 2; +} + +StackMode BubbleChartTypeTemplate::getStackMode( sal_Int32 /* nChartTypeIndex */ ) const +{ + return StackMode_NONE; +} + +bool BubbleChartTypeTemplate::supportsCategories() const +{ + return false; +} + + +void SAL_CALL BubbleChartTypeTemplate::applyStyle( + const Reference< chart2::XDataSeries >& xSeries, + ::sal_Int32 nChartTypeIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) + throw (uno::RuntimeException) +{ + ChartTypeTemplate::applyStyle( xSeries, nChartTypeIndex, nSeriesIndex, nSeriesCount ); + + try + { + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } +} + +// ____ XChartTypeTemplate ____ +Sequence< OUString > SAL_CALL BubbleChartTypeTemplate::getAvailableCreationParameterNames() + throw (uno::RuntimeException) +{ + return Sequence< OUString >(); +} + +sal_Bool SAL_CALL BubbleChartTypeTemplate::matchesTemplate( + const Reference< chart2::XDiagram >& xDiagram, + sal_Bool bAdaptProperties ) + throw (uno::RuntimeException) +{ + sal_Bool bResult = ChartTypeTemplate::matchesTemplate( xDiagram, bAdaptProperties ); + + if( bResult ) + { + ::std::vector< Reference< chart2::XDataSeries > > aSeriesVec( + DiagramHelper::getDataSeriesFromDiagram( xDiagram )); + + for( ::std::vector< Reference< chart2::XDataSeries > >::const_iterator aIt = + aSeriesVec.begin(); aIt != aSeriesVec.end(); ++aIt ) + { + try + { + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + } + + // adapt curve style, spline order and resolution + if( bResult && bAdaptProperties ) + { + try + { + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + + return bResult; +} + +Reference< chart2::XChartType > BubbleChartTypeTemplate::getChartTypeForIndex( sal_Int32 /*nChartTypeIndex*/ ) +{ + Reference< chart2::XChartType > xResult; + + try + { + Reference< lang::XMultiServiceFactory > xFact( + GetComponentContext()->getServiceManager(), uno::UNO_QUERY_THROW ); + xResult.set( xFact->createInstance( + CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE ), uno::UNO_QUERY_THROW ); + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + return xResult; +} + +Reference< chart2::XChartType > SAL_CALL BubbleChartTypeTemplate::getChartTypeForNewSeries( + const uno::Sequence< Reference< chart2::XChartType > >& aFormerlyUsedChartTypes ) + throw (uno::RuntimeException) +{ + Reference< chart2::XChartType > xResult; + + try + { + Reference< lang::XMultiServiceFactory > xFact( + GetComponentContext()->getServiceManager(), uno::UNO_QUERY_THROW ); + xResult.set( xFact->createInstance( + CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE ), uno::UNO_QUERY_THROW ); + + ChartTypeTemplate::copyPropertiesFromOldToNewCoordianteSystem( aFormerlyUsedChartTypes, xResult ); + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + + return xResult; +} + +Reference< chart2::XDataInterpreter > SAL_CALL BubbleChartTypeTemplate::getDataInterpreter() + throw (uno::RuntimeException) +{ + if( ! m_xDataInterpreter.is()) + m_xDataInterpreter.set( new BubbleDataInterpreter( GetComponentContext()) ); + + return m_xDataInterpreter; +} + +// ---------------------------------------- + +Sequence< OUString > BubbleChartTypeTemplate::getSupportedServiceNames_Static() +{ + Sequence< OUString > aServices( 2 ); + aServices[ 0 ] = lcl_aServiceName; + aServices[ 1 ] = C2U( "com.sun.star.chart2.ChartTypeTemplate" ); + return aServices; +} + +// implement XServiceInfo methods basing upon getSupportedServiceNames_Static +APPHELPER_XSERVICEINFO_IMPL( BubbleChartTypeTemplate, lcl_aServiceName ); + +IMPLEMENT_FORWARD_XINTERFACE2( BubbleChartTypeTemplate, ChartTypeTemplate, OPropertySet ) +IMPLEMENT_FORWARD_XTYPEPROVIDER2( BubbleChartTypeTemplate, ChartTypeTemplate, OPropertySet ) + +} // namespace chart diff --git a/chart2/source/model/template/BubbleChartTypeTemplate.hxx b/chart2/source/model/template/BubbleChartTypeTemplate.hxx new file mode 100644 index 000000000000..c094e38e28ac --- /dev/null +++ b/chart2/source/model/template/BubbleChartTypeTemplate.hxx @@ -0,0 +1,106 @@ +/************************************************************************* + * + * 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: ,v $ + * $Revision: $ + * + * 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 CHART_BUBBLECHARTTYPETEMPLATE_HXX +#define CHART_BUBBLECHARTTYPETEMPLATE_HXX + +#include "ChartTypeTemplate.hxx" +#include "OPropertySet.hxx" +#include "MutexContainer.hxx" +#include <comphelper/uno3.hxx> + +namespace chart +{ + +class BubbleChartTypeTemplate : + public MutexContainer, + public ChartTypeTemplate, + public ::property::OPropertySet +{ +public: + explicit BubbleChartTypeTemplate( + ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > const & xContext, + const ::rtl::OUString & rServiceName ); + virtual ~BubbleChartTypeTemplate(); + + /// XServiceInfo declarations + APPHELPER_XSERVICEINFO_DECL() + + /// merge XInterface implementations + DECLARE_XINTERFACE() + /// merge XTypeProvider implementations + DECLARE_XTYPEPROVIDER() + +protected: + // ____ OPropertySet ____ + virtual ::com::sun::star::uno::Any GetDefaultValue( sal_Int32 nHandle ) const + throw(::com::sun::star::beans::UnknownPropertyException); + virtual ::cppu::IPropertyArrayHelper & SAL_CALL getInfoHelper(); + + // ____ XPropertySet ____ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL + getPropertySetInfo() + throw (::com::sun::star::uno::RuntimeException); + + // ____ XChartTypeTemplate ____ + virtual ::com::sun::star::uno::Sequence< ::rtl::OUString > SAL_CALL getAvailableCreationParameterNames() + throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL matchesTemplate( + const ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XDiagram >& xDiagram, + sal_Bool bAdaptProperties ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartType > SAL_CALL + getChartTypeForNewSeries( const ::com::sun::star::uno::Sequence< + ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XChartType > >& aFormerlyUsedChartTypes ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XDataInterpreter > SAL_CALL getDataInterpreter() + throw (::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL applyStyle( + const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XDataSeries >& xSeries, + ::sal_Int32 nChartTypeGroupIndex, + ::sal_Int32 nSeriesIndex, + ::sal_Int32 nSeriesCount ) + throw (::com::sun::star::uno::RuntimeException); + + // ____ ChartTypeTemplate ____ + virtual ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartType > + getChartTypeForIndex( sal_Int32 nChartTypeIndex ); + virtual sal_Int32 getDimension() const; + virtual StackMode getStackMode( sal_Int32 nChartTypeIndex ) const; + + virtual bool supportsCategories() const; +}; + +} // namespace chart + +// CHART_BUBBLECHARTTYPETEMPLATE_HXX +#endif diff --git a/chart2/source/model/template/BubbleDataInterpreter.cxx b/chart2/source/model/template/BubbleDataInterpreter.cxx new file mode 100644 index 000000000000..a5ebb6b1ec2f --- /dev/null +++ b/chart2/source/model/template/BubbleDataInterpreter.cxx @@ -0,0 +1,317 @@ +/************************************************************************* + * + * 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: ,v $ + * $Revision: $ + * + * 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_chart2.hxx" + +#include "BubbleDataInterpreter.hxx" +#include "DataSeries.hxx" +#include "macros.hxx" +#include "DataSeriesHelper.hxx" +#include "CommonConverters.hxx" +#include "ContainerHelper.hxx" +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/chart2/data/XDataSink.hpp> +#include <com/sun/star/util/XCloneable.hpp> + +using namespace ::com::sun::star; +using namespace ::com::sun::star::chart2; +using namespace ::std; + +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +namespace chart +{ + +BubbleDataInterpreter::BubbleDataInterpreter( + const uno::Reference< uno::XComponentContext > & xContext ) : + DataInterpreter( xContext ) +{ +} + +BubbleDataInterpreter::~BubbleDataInterpreter() +{ +} + +// ____ XDataInterpreter ____ +chart2::InterpretedData SAL_CALL BubbleDataInterpreter::interpretDataSource( + const Reference< chart2::data::XDataSource >& xSource, + const Sequence< beans::PropertyValue >& aArguments, + const Sequence< Reference< XDataSeries > >& aSeriesToReUse ) + throw (uno::RuntimeException) +{ + if( ! xSource.is()) + return InterpretedData(); + + Sequence< Reference< data::XLabeledDataSequence > > aData( xSource->getDataSequences() ); + + Reference< data::XLabeledDataSequence > xValuesX; + vector< Reference< data::XLabeledDataSequence > > aYValuesVector; + vector< Reference< data::XLabeledDataSequence > > aSizeValuesVector; + + Reference< data::XLabeledDataSequence > xCategories; + bool bHasCategories = HasCategories( aArguments, aData ); + + Sequence< Reference< data::XLabeledDataSequence > > aUnusedData; + + bool bHasXValues = false; + sal_Int32 nDataSeqCount = aData.getLength(); + + bHasXValues = bHasCategories ? ( (nDataSeqCount-1) > 2 && (nDataSeqCount-1) % 2 != 0 ) + :( nDataSeqCount > 2 && nDataSeqCount % 2 != 0 ); + + bool bCategoriesUsed = false; + bool bNextIsYValues = bHasCategories ? nDataSeqCount>2 : nDataSeqCount>1; + for( sal_Int32 nDataIdx = 0; nDataIdx < aData.getLength(); ++nDataIdx ) + { + try + { + if( bHasCategories && !bCategoriesUsed ) + { + xCategories.set( aData[nDataIdx] ); + if( xCategories.is()) + SetRole( xCategories->getValues(), C2U("categories")); + bCategoriesUsed = true; + } + else if( !xValuesX.is() && bHasXValues ) + { + xValuesX.set( aData[nDataIdx] ); + if( xValuesX.is()) + SetRole( xValuesX->getValues(), C2U("values-x")); + } + else if( bNextIsYValues ) + { + aYValuesVector.push_back( aData[nDataIdx] ); + if( aData[nDataIdx].is()) + SetRole( aData[nDataIdx]->getValues(), C2U("values-y")); + bNextIsYValues = false; + } + else if( !bNextIsYValues ) + { + aSizeValuesVector.push_back( aData[nDataIdx] ); + if( aData[nDataIdx].is()) + SetRole( aData[nDataIdx]->getValues(), C2U("values-size")); + bNextIsYValues = true; + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + + // create DataSeries + sal_Int32 nSeriesIndex = 0; + vector< Reference< XDataSeries > > aSeriesVec; + aSeriesVec.reserve( aSizeValuesVector.size()); + + Reference< data::XLabeledDataSequence > xClonedXValues = xValuesX; + Reference< util::XCloneable > xCloneableX( xValuesX, uno::UNO_QUERY ); + + for( size_t nCount = 0; nCount < aSizeValuesVector.size(); ++nCount, ++nSeriesIndex ) + { + sal_Int32 nDataSequenceCount = 2; + if( xValuesX.is() ) + nDataSequenceCount = 3; + else if( aYValuesVector.empty() ) + nDataSequenceCount = 1; + + Sequence< Reference< data::XLabeledDataSequence > > aNewData( nDataSequenceCount ); + sal_Int32 nDataIndex = 0; + if( xValuesX.is() ) + { + if( nCount > 0 && xCloneableX.is() ) + xClonedXValues.set( xCloneableX->createClone(), uno::UNO_QUERY ); + aNewData[nDataIndex++] = xClonedXValues; + } + if( aYValuesVector.size() > nCount ) + aNewData[nDataIndex++] = aYValuesVector[nCount]; + if( aSizeValuesVector.size() > nCount ) + aNewData[nDataIndex++] = aSizeValuesVector[nCount]; + + Reference< XDataSeries > xSeries; + if( nSeriesIndex < aSeriesToReUse.getLength()) + xSeries.set( aSeriesToReUse[nSeriesIndex] ); + else + xSeries.set( new DataSeries( GetComponentContext() ) ); + OSL_ASSERT( xSeries.is() ); + Reference< data::XDataSink > xSink( xSeries, uno::UNO_QUERY ); + OSL_ASSERT( xSink.is() ); + xSink->setData( aNewData ); + + aSeriesVec.push_back( xSeries ); + } + + Sequence< Sequence< Reference< XDataSeries > > > aSeries(1); + aSeries[0] = ContainerHelper::ContainerToSequence( aSeriesVec ); + return InterpretedData( aSeries, xCategories, aUnusedData ); +} + +chart2::InterpretedData SAL_CALL BubbleDataInterpreter::reinterpretDataSeries( + const chart2::InterpretedData& aInterpretedData ) + throw (uno::RuntimeException) +{ + InterpretedData aResult( aInterpretedData ); + vector< Reference< data::XLabeledDataSequence > > aUnused( + ContainerHelper::SequenceToVector( aInterpretedData.UnusedData )); + + sal_Int32 i=0; + Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series )); + const sal_Int32 nCount = aSeries.getLength(); + for( ; i<nCount; ++i ) + { + try + { + Reference< data::XDataSource > xSeriesSource( aSeries[i], uno::UNO_QUERY_THROW ); + Sequence< Reference< data::XLabeledDataSequence > > aNewSequences; + + Reference< data::XLabeledDataSequence > xValuesSize( + DataSeriesHelper::getDataSequenceByRole( xSeriesSource, C2U("values-size"), false )); + Reference< data::XLabeledDataSequence > xValuesY( + DataSeriesHelper::getDataSequenceByRole( xSeriesSource, C2U("values-y"), false )); + Reference< data::XLabeledDataSequence > xValuesX( + DataSeriesHelper::getDataSequenceByRole( xSeriesSource, C2U("values-x"), false )); + + if( ! xValuesX.is() || + ! xValuesY.is() || + ! xValuesSize.is() ) + { + vector< Reference< data::XLabeledDataSequence > > aValueSeqVec( + DataSeriesHelper::getAllDataSequencesByRole( + xSeriesSource->getDataSequences(), C2U("values"), true )); + if( xValuesX.is()) + aValueSeqVec.erase( find( aValueSeqVec.begin(), aValueSeqVec.end(), xValuesX )); + if( xValuesY.is()) + aValueSeqVec.erase( find( aValueSeqVec.begin(), aValueSeqVec.end(), xValuesY )); + if( xValuesSize.is()) + aValueSeqVec.erase( find( aValueSeqVec.begin(), aValueSeqVec.end(), xValuesSize )); + + size_t nIndex = 0; + + if( ! xValuesSize.is() && + aValueSeqVec.size() > nIndex ) + { + xValuesSize.set( aValueSeqVec[nIndex++] ); + if( xValuesSize.is()) + SetRole( xValuesSize->getValues(), C2U("values-size")); + } + + if( ! xValuesY.is() && + aValueSeqVec.size() > nIndex ) + { + xValuesY.set( aValueSeqVec[nIndex++] ); + if( xValuesY.is()) + SetRole( xValuesY->getValues(), C2U("values-y")); + } + + if( ! xValuesX.is() && + aValueSeqVec.size() > nIndex ) + { + xValuesX.set( aValueSeqVec[nIndex++] ); + if( xValuesX.is()) + SetRole( xValuesY->getValues(), C2U("values-x")); + } + } + if( xValuesSize.is()) + { + if( xValuesY.is() ) + { + if( xValuesX.is() ) + { + aNewSequences.realloc(3); + aNewSequences[0] = xValuesX; + aNewSequences[1] = xValuesY; + aNewSequences[2] = xValuesSize; + } + else + { + aNewSequences.realloc(2); + aNewSequences[0] = xValuesY; + aNewSequences[1] = xValuesSize; + } + } + else + { + aNewSequences.realloc(1); + aNewSequences[0] = xValuesSize; + } + } + + Sequence< Reference< data::XLabeledDataSequence > > aSeqs( xSeriesSource->getDataSequences()); + if( aSeqs.getLength() != aNewSequences.getLength() ) + { + sal_Int32 j=0; + for( ; j<aSeqs.getLength(); ++j ) + { + if( aSeqs[j] != xValuesY && + aSeqs[j] != xValuesX && + aSeqs[j] != xValuesSize ) + aUnused.push_back( aSeqs[j] ); + } + Reference< data::XDataSink > xSink( xSeriesSource, uno::UNO_QUERY_THROW ); + xSink->setData( aNewSequences ); + aResult.UnusedData = ContainerHelper::ContainerToSequence( aUnused ); + } + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + + return aResult; +} + +sal_Bool SAL_CALL BubbleDataInterpreter::isDataCompatible( + const chart2::InterpretedData& aInterpretedData ) + throw (uno::RuntimeException) +{ + Sequence< Reference< XDataSeries > > aSeries( FlattenSequence( aInterpretedData.Series )); + for( sal_Int32 i=0; i<aSeries.getLength(); ++i ) + { + try + { + Reference< data::XDataSource > xSrc( aSeries[i], uno::UNO_QUERY_THROW ); + Sequence< Reference< data::XLabeledDataSequence > > aSeq( xSrc->getDataSequences()); + if( aSeq.getLength() != 3 ) + return sal_False; + } + catch( uno::Exception & ex ) + { + ASSERT_EXCEPTION( ex ); + } + } + + return sal_True; +} + +} // namespace chart diff --git a/chart2/source/model/template/BubbleDataInterpreter.hxx b/chart2/source/model/template/BubbleDataInterpreter.hxx new file mode 100644 index 000000000000..a173f801812c --- /dev/null +++ b/chart2/source/model/template/BubbleDataInterpreter.hxx @@ -0,0 +1,64 @@ +/************************************************************************* + * + * 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: ,v $ + * $Revision: $ + * + * 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 CHART_BUBBLEDATAINTERPRETER_HXX +#define CHART_BUBBLEDATAINTERPRETER_HXX + +#include "DataInterpreter.hxx" + +namespace chart +{ + +class BubbleDataInterpreter : public DataInterpreter +{ +public: + explicit BubbleDataInterpreter( + const ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XComponentContext > & xContext ); + virtual ~BubbleDataInterpreter(); + +protected: + // ____ XDataInterpreter ____ + virtual ::com::sun::star::chart2::InterpretedData SAL_CALL interpretDataSource( + const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::data::XDataSource >& xSource, + const ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& aArguments, + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XDataSeries > >& aSeriesToReUse ) + throw (::com::sun::star::uno::RuntimeException); + virtual ::com::sun::star::chart2::InterpretedData SAL_CALL reinterpretDataSeries( + const ::com::sun::star::chart2::InterpretedData& aInterpretedData ) + throw (::com::sun::star::uno::RuntimeException); + virtual sal_Bool SAL_CALL isDataCompatible( + const ::com::sun::star::chart2::InterpretedData& aInterpretedData ) + throw (::com::sun::star::uno::RuntimeException); +}; + +} // namespace chart + +// CHART_BUBBLEDATAINTERPRETER_HXX +#endif diff --git a/chart2/source/model/template/ChartTypeManager.cxx b/chart2/source/model/template/ChartTypeManager.cxx index 6365c08f4403..0e4a3a119a02 100644 --- a/chart2/source/model/template/ChartTypeManager.cxx +++ b/chart2/source/model/template/ChartTypeManager.cxx @@ -45,6 +45,7 @@ #include "ScatterChartTypeTemplate.hxx" #include "StockChartTypeTemplate.hxx" #include "NetChartTypeTemplate.hxx" +#include "BubbleChartTypeTemplate.hxx" #include <cppuhelper/component_context.hxx> #include <comphelper/InlineContainer.hxx> #include <com/sun/star/container/XContentEnumerationAccess.hpp> @@ -131,6 +132,7 @@ enum TemplateId TEMPLATE_STOCKOPENLOWHIGHCLOSE, TEMPLATE_STOCKVOLUMELOWHIGHCLOSE, TEMPLATE_STOCKVOLUMEOPENLOWHIGHCLOSE, + TEMPLATE_BUBBLE, // TEMPLATE_SURFACE, // TEMPLATE_ADDIN, TEMPLATE_NOT_FOUND = 0xffff @@ -202,6 +204,7 @@ const tTemplateMapType & lcl_DefaultChartTypeMap() ( C2U( "com.sun.star.chart2.template.StockOpenLowHighClose" ), TEMPLATE_STOCKOPENLOWHIGHCLOSE ) ( C2U( "com.sun.star.chart2.template.StockVolumeLowHighClose" ), TEMPLATE_STOCKVOLUMELOWHIGHCLOSE ) ( C2U( "com.sun.star.chart2.template.StockVolumeOpenLowHighClose" ), TEMPLATE_STOCKVOLUMEOPENLOWHIGHCLOSE ) + ( C2U( "com.sun.star.chart2.template.Bubble" ), TEMPLATE_BUBBLE ) // ( C2U( "com.sun.star.chart2.template.Surface" ), TEMPLATE_SURFACE ) // ( C2U( "com.sun.star.chart2.template.Addin" ), TEMPLATE_ADDIN ) ); @@ -518,6 +521,11 @@ uno::Reference< uno::XInterface > SAL_CALL ChartTypeManager::createInstance( StockChartTypeTemplate::VOL_OPEN_LOW_HI_CLOSE, true )); break; + //BubbleChart + case TEMPLATE_BUBBLE: + xTemplate.set( new BubbleChartTypeTemplate( m_xContext, aServiceSpecifier )); + break; + // case TEMPLATE_SURFACE: // case TEMPLATE_ADDIN: // break; diff --git a/chart2/source/model/template/ChartTypeTemplate.cxx b/chart2/source/model/template/ChartTypeTemplate.cxx index b5791baf6c0f..1996cc12830e 100644 --- a/chart2/source/model/template/ChartTypeTemplate.cxx +++ b/chart2/source/model/template/ChartTypeTemplate.cxx @@ -68,27 +68,6 @@ using ::com::sun::star::uno::Any; namespace { -sal_Int32 lcl_getSeriesLength( const Reference< XDataSeries > & xSeries ) -{ - sal_Int32 nResult = 0; - try - { - Reference< data::XDataSource > xDataSource( xSeries, uno::UNO_QUERY_THROW ); - Sequence< Reference< data::XLabeledDataSequence > > aLabSeq( xDataSource->getDataSequences()); - if( aLabSeq.getLength()) - { - Reference< data::XDataSequence > xSeq( aLabSeq[0]->getValues()); - if( xSeq.is()) - nResult = xSeq->getData().getLength(); - } - } - catch( const uno::Exception & ex ) - { - ASSERT_EXCEPTION( ex ); - } - return nResult; -} - void lcl_applyDefaultStyle( const Reference< XDataSeries > & xSeries, sal_Int32 nIndex, @@ -347,12 +326,9 @@ void SAL_CALL ChartTypeTemplate::changeDiagramData( Sequence< Sequence< Reference< XDataSeries > > > aSeriesSeq( aData.Series ); sal_Int32 i, j, nIndex = 0; - sal_Int32 nFirstSeriesLength = 0; for( i=0; i<aSeriesSeq.getLength(); ++i ) for( j=0; j<aSeriesSeq[i].getLength(); ++j, ++nIndex ) { - if( i==0 && j==0 ) - nFirstSeriesLength = lcl_getSeriesLength( aSeriesSeq[0][0] ); if( nIndex >= nFormerSeriesCount ) { lcl_applyDefaultStyle( aSeriesSeq[i][j], nIndex, xDiagram ); diff --git a/chart2/source/model/template/_serviceregistration_charttypes.cxx b/chart2/source/model/template/_serviceregistration_charttypes.cxx index b059eb24957a..6e5960410445 100644 --- a/chart2/source/model/template/_serviceregistration_charttypes.cxx +++ b/chart2/source/model/template/_serviceregistration_charttypes.cxx @@ -41,6 +41,7 @@ #include "NetChartType.hxx" #include "PieChartType.hxx" #include "ScatterChartType.hxx" +#include "BubbleChartType.hxx" namespace { @@ -110,6 +111,14 @@ static struct ::cppu::ImplementationEntry g_entries_chart2_charttypes[] = , 0 , 0 } + ,{ + ::chart::BubbleChartType::create + , ::chart::BubbleChartType::getImplementationName_Static + , ::chart::BubbleChartType::getSupportedServiceNames_Static + , ::cppu::createSingleComponentFactory + , 0 + , 0 + } ,{ 0, 0, 0, 0, 0, 0 } }; diff --git a/chart2/source/model/template/makefile.mk b/chart2/source/model/template/makefile.mk index 0913c42a89e2..ad8fcd552c8d 100644 --- a/chart2/source/model/template/makefile.mk +++ b/chart2/source/model/template/makefile.mk @@ -71,6 +71,9 @@ SLOFILES= \ $(SLO)$/PieChartTypeTemplate.obj \ $(SLO)$/ScatterChartType.obj \ $(SLO)$/ScatterChartTypeTemplate.obj \ + $(SLO)$/BubbleChartType.obj \ + $(SLO)$/BubbleChartTypeTemplate.obj \ + $(SLO)$/BubbleDataInterpreter.obj \ $(SLO)$/StockChartTypeTemplate.obj \ $(SLO)$/StockDataInterpreter.obj \ $(SLO)$/XYDataInterpreter.obj \ diff --git a/chart2/source/tools/ChartTypeHelper.cxx b/chart2/source/tools/ChartTypeHelper.cxx index d7bb3a15bdf6..357cf5c43d92 100644 --- a/chart2/source/tools/ChartTypeHelper.cxx +++ b/chart2/source/tools/ChartTypeHelper.cxx @@ -108,6 +108,8 @@ sal_Bool ChartTypeHelper::isSupportingStatisticProperties( const uno::Reference< return sal_False; if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) ) return sal_False; + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE) ) //todo: BubbleChart support error bars and trend lines + return sal_False; } return sal_True; } @@ -281,6 +283,7 @@ uno::Sequence < sal_Int32 > ChartTypeHelper::getSupportedLabelPlacements( const } else if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_LINE) + || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE) ) { aRet.realloc(5); @@ -509,7 +512,8 @@ sal_Int32 ChartTypeHelper::getAxisType( const uno::Reference< return AxisType::REALNUMBER; if(0==nDimensionIndex)//x-axis { - if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) ) + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) + || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE) ) return AxisType::REALNUMBER; return AxisType::CATEGORY; } @@ -558,7 +562,8 @@ uno::Sequence < sal_Int32 > ChartTypeHelper::getSupportedMissingValueTreatments( rtl::OUString aChartTypeName = xChartType->getChartType(); if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_COLUMN) || - aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR) ) + aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BAR) || + aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE) ) { aRet.realloc( 2 ); sal_Int32* pSeq = aRet.getArray(); @@ -604,6 +609,54 @@ uno::Sequence < sal_Int32 > ChartTypeHelper::getSupportedMissingValueTreatments( return aRet; } +rtl::OUString ChartTypeHelper::getRoleOfSequenceForYAxisNumberFormatDetection( const uno::Reference< XChartType >& xChartType ) +{ + rtl::OUString aRet( C2U( "values-y" ) ); + if( !xChartType.is() ) + return aRet; + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) ) + aRet = xChartType->getRoleOfSequenceForSeriesLabel(); + return aRet; +} + +rtl::OUString ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( const uno::Reference< XChartType >& xChartType ) +{ + rtl::OUString aRet( C2U( "values-y" ) ); + if( !xChartType.is() ) + return aRet; + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_CANDLESTICK) + || aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE) ) + aRet = xChartType->getRoleOfSequenceForSeriesLabel(); + return aRet; +} + +bool ChartTypeHelper::shouldLabelNumberFormatKeyBeDetectedFromYAxis( const uno::Reference< XChartType >& xChartType ) +{ + bool bRet = true; + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE) ) + bRet = false; + return bRet; +} + +bool ChartTypeHelper::isSupportingOnlyDeepStackingFor3D( const uno::Reference< XChartType >& xChartType ) +{ + bool bRet = false; + if( !xChartType.is() ) + return bRet; + + rtl::OUString aChartTypeName = xChartType->getChartType(); + if( aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_LINE) || + aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) || + aChartTypeName.match(CHART2_SERVICE_NAME_CHARTTYPE_AREA) ) + { + bRet = true; + } + return bRet; +} + //............................................................................. } //namespace chart //............................................................................. diff --git a/chart2/source/tools/DiagramHelper.cxx b/chart2/source/tools/DiagramHelper.cxx index 8af5b412c5c1..ac2a32f93298 100644 --- a/chart2/source/tools/DiagramHelper.cxx +++ b/chart2/source/tools/DiagramHelper.cxx @@ -503,8 +503,12 @@ void DiagramHelper::setDimension( try { - //change all coordinate systems: + bool rbFound = false; + bool rbAmbiguous = true; + StackMode eStackMode = DiagramHelper::getStackMode( xDiagram, rbFound, rbAmbiguous ); + bool bIsSupportingOnlyDeepStackingFor3D=false; + //change all coordinate systems: Reference< XCoordinateSystemContainer > xCooSysContainer( xDiagram, uno::UNO_QUERY_THROW ); Sequence< Reference< XCoordinateSystem > > aCooSysList( xCooSysContainer->getCoordinateSystems() ); for( sal_Int32 nCS = 0; nCS < aCooSysList.getLength(); ++nCS ) @@ -520,6 +524,7 @@ void DiagramHelper::setDimension( for( sal_Int32 nT = 0; nT < aChartTypeList.getLength(); ++nT ) { Reference< XChartType > xChartType( aChartTypeList[nT], uno::UNO_QUERY ); + bIsSupportingOnlyDeepStackingFor3D = ChartTypeHelper::isSupportingOnlyDeepStackingFor3D( xChartType ); if(!xNewCooSys.is()) { xNewCooSys = xChartType->createCoordinateSystem( nNewDimensionCount ); @@ -533,6 +538,12 @@ void DiagramHelper::setDimension( // replace the old coordinate system at all places where it was used DiagramHelper::replaceCoordinateSystem( xDiagram, xOldCooSys, xNewCooSys ); } + + //correct stack mode if necessary + if( nNewDimensionCount==3 && eStackMode != StackMode_Z_STACKED && bIsSupportingOnlyDeepStackingFor3D ) + DiagramHelper::setStackMode( xDiagram, StackMode_Z_STACKED ); + else if( nNewDimensionCount==2 && eStackMode == StackMode_Z_STACKED ) + DiagramHelper::setStackMode( xDiagram, StackMode_NONE ); } catch( uno::Exception & ex ) { @@ -556,6 +567,8 @@ void DiagramHelper::replaceCoordinateSystem( { try { + Reference< chart2::data::XLabeledDataSequence > xCategories = DiagramHelper::getCategoriesFromDiagram( xDiagram ); + // move chart types of xCooSysToReplace to xReplacement Reference< XChartTypeContainer > xCTCntCooSys( xCooSysToReplace, uno::UNO_QUERY_THROW ); Reference< XChartTypeContainer > xCTCntReplacement( xReplacement, uno::UNO_QUERY_THROW ); @@ -563,6 +576,9 @@ void DiagramHelper::replaceCoordinateSystem( xCont->removeCoordinateSystem( xCooSysToReplace ); xCont->addCoordinateSystem( xReplacement ); + + if( xCategories.is() ) + DiagramHelper::setCategoriesToDiagram( xCategories, xDiagram ); } catch( uno::Exception & ex ) { diff --git a/chart2/source/tools/TitleHelper.cxx b/chart2/source/tools/TitleHelper.cxx index 43006920951a..fe10c92e78cc 100644 --- a/chart2/source/tools/TitleHelper.cxx +++ b/chart2/source/tools/TitleHelper.cxx @@ -36,6 +36,7 @@ #include "AxisHelper.hxx" #include "DiagramHelper.hxx" #include <com/sun/star/chart2/XChartDocument.hpp> +#include <rtl/ustrbuf.hxx> //............................................................................. namespace chart @@ -269,13 +270,44 @@ void TitleHelper::setCompleteString( const rtl::OUString& rNewText if(!xTitle.is()) return; + rtl::OUString aNewText = rNewText; + + bool bStacked = false; + uno::Reference< beans::XPropertySet > xTitleProperties( xTitle, uno::UNO_QUERY ); + if( xTitleProperties.is() ) + xTitleProperties->getPropertyValue( C2U( "StackCharacters" ) ) >>= bStacked; + + if( bStacked ) + { + //#i99841# remove linebreaks that were added for vertical stacking + rtl::OUStringBuffer aUnstackedStr; + rtl::OUStringBuffer aSource(rNewText); + + bool bBreakIgnored = false; + sal_Int32 nLen = rNewText.getLength(); + for( sal_Int32 nPos = 0; nPos < nLen; ++nPos ) + { + sal_Unicode aChar = aSource.charAt( nPos ); + if( aChar != '\n' ) + { + aUnstackedStr.append( aChar ); + bBreakIgnored = false; + } + else if( aChar == '\n' && bBreakIgnored ) + aUnstackedStr.append( aChar ); + else + bBreakIgnored = true; + } + aNewText = aUnstackedStr.makeStringAndClear(); + } + uno::Sequence< uno::Reference< XFormattedString > > aNewStringList(1); uno::Sequence< uno::Reference< XFormattedString > > aOldStringList = xTitle->getText(); if( aOldStringList.getLength() ) { aNewStringList[0].set( aOldStringList[0] ); - aNewStringList[0]->setString( rNewText ); + aNewStringList[0]->setString( aNewText ); } else { @@ -286,7 +318,7 @@ void TitleHelper::setCompleteString( const rtl::OUString& rNewText if(xFormattedString.is()) { - xFormattedString->setString( rNewText ); + xFormattedString->setString( aNewText ); aNewStringList[0].set( xFormattedString ); if( pDefaultCharHeight != 0 ) { diff --git a/chart2/source/view/charttypes/AreaChart.cxx b/chart2/source/view/charttypes/AreaChart.cxx index 1401ab43a159..0b1a17ca7701 100644 --- a/chart2/source/view/charttypes/AreaChart.cxx +++ b/chart2/source/view/charttypes/AreaChart.cxx @@ -89,7 +89,6 @@ AreaChart::AreaChart( const uno::Reference<XChartType>& xChartTypeModel , m_bExpandIfValuesCloseToBorder( bExpandIfValuesCloseToBorder ) , m_nKeepAspectRatio(nKeepAspectRatio) , m_aGivenAspectRatio(rAspectRatio) - , m_eNanHandling( bCategoryXAxis ? NAN_AS_GAP : NAN_AS_INTERPOLATED ) , m_eCurveStyle(CurveStyle_LINES) , m_nCurveResolution(20) , m_nSplineOrder(3) @@ -103,9 +102,6 @@ AreaChart::AreaChart( const uno::Reference<XChartType>& xChartTypeModel PlotterBase::m_pPosHelper = m_pMainPosHelper; VSeriesPlotter::m_pMainPosHelper = m_pMainPosHelper; - if( m_bArea ) - m_eNanHandling = NAN_AS_ZERO; - try { if( m_xChartTypeModelProps.is() ) @@ -234,6 +230,12 @@ bool AreaChart::keepAspectRatio() const void AreaChart::addSeries( VDataSeries* pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot ) { + if( m_bArea && pSeries ) + { + sal_Int32 nMissingValueTreatment = pSeries->getMissingValueTreatment(); + if( nMissingValueTreatment == ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP ) + pSeries->setMissingValueTreatment( ::com::sun::star::chart::MissingValueTreatment::USE_ZERO ); + } if( m_nDimension == 3 && !m_bCategoryXAxis ) { //3D xy always deep @@ -351,9 +353,10 @@ bool AreaChart::impl_createLine( VDataSeries* pSeries if( m_bConnectLastToFirstPoint && !ShapeFactory::isPolygonEmptyOrSinglePoint(*pSeriesPoly) ) { // do NOT connect last and first point, if one is NAN, and NAN handling is NAN_AS_GAP - double fFirstY = pSeries->getY( 0 ); - double fLastY = pSeries->getY( VSeriesPlotter::getPointCount() - 1 ); - if( (m_eNanHandling != NAN_AS_GAP) || (::rtl::math::isFinite( fFirstY ) && ::rtl::math::isFinite( fLastY )) ) + double fFirstY = pSeries->getYValue( 0 ); + double fLastY = pSeries->getYValue( VSeriesPlotter::getPointCount() - 1 ); + if( (pSeries->getMissingValueTreatment() != ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP) + || (::rtl::math::isFinite( fFirstY ) && ::rtl::math::isFinite( fLastY )) ) { // connect last point in last polygon with first point in first polygon ::basegfx::B2DRectangle aScaledLogicClipDoubleRect( pPosHelper->getScaledLogicClipDoubleRect() ); @@ -573,13 +576,6 @@ void lcl_reorderSeries( ::std::vector< ::std::vector< VDataSeriesGroup > >& rZS }//anonymous namespace -void AreaChart::impl_maybeReplaceNanWithZero( double& rfValue ) -{ - if( m_eNanHandling == NAN_AS_ZERO && - ( ::rtl::math::isNan(rfValue) || ::rtl::math::isInf(rfValue) ) ) - rfValue = 0.0; -} - //better performance for big data struct FormerPoint { @@ -676,8 +672,7 @@ void AreaChart::createShapes() pPosHelper = m_pMainPosHelper; PlotterBase::m_pPosHelper = pPosHelper; - double fAdd = pSeries->getY( nIndex ); - impl_maybeReplaceNanWithZero( fAdd ); + double fAdd = pSeries->getYValue( nIndex ); if( !::rtl::math::isNan(fAdd) && !::rtl::math::isInf(fAdd) ) aLogicYSumMap[nAttachedAxisIndex] += fabs( fAdd ); } @@ -709,23 +704,6 @@ void AreaChart::createShapes() if(!pSeries) continue; - sal_Int32 nMissingValueTreatment = pSeries->getMissingValueTreatment(); - switch( nMissingValueTreatment ) - { - case ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP: - if( !m_bArea ) - m_eNanHandling = NAN_AS_GAP; - break; - case ::com::sun::star::chart::MissingValueTreatment::USE_ZERO: - m_eNanHandling = NAN_AS_ZERO; - break; - case ::com::sun::star::chart::MissingValueTreatment::CONTINUE: - m_eNanHandling = NAN_AS_INTERPOLATED; - break; - default: - break; - } - /* #i70133# ignore points outside of series length in standard area charts. Stacked area charts will use missing points as zeros. In standard charts, pSeriesList contains only one series. */ @@ -745,10 +723,8 @@ void AreaChart::createShapes() (*aSeriesIter)->m_fLogicZPos = fLogicZ; //collect data point information (logic coordinates, style ): - double fLogicX = (*aSeriesIter)->getX(nIndex); - double fLogicY = (*aSeriesIter)->getY(nIndex); - impl_maybeReplaceNanWithZero( fLogicX ); - impl_maybeReplaceNanWithZero( fLogicY ); + double fLogicX = (*aSeriesIter)->getXValue(nIndex); + double fLogicY = (*aSeriesIter)->getYValue(nIndex); if( m_nDimension==3 && m_bArea && pSeriesList->size()!=1 ) fLogicY = fabs( fLogicY ); @@ -762,7 +738,7 @@ void AreaChart::createShapes() || ::rtl::math::isNan(fLogicY) || ::rtl::math::isInf(fLogicY) || ::rtl::math::isNan(fLogicZ) || ::rtl::math::isInf(fLogicZ) ) { - if( m_eNanHandling == NAN_AS_GAP ) + if( (*aSeriesIter)->getMissingValueTreatment() == ::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP ) { drawing::PolyPolygonShape3D& rPolygon = (*aSeriesIter)->m_aPolyPolygonShape3D; sal_Int32& rIndex = (*aSeriesIter)->m_nPolygonIndex; diff --git a/chart2/source/view/charttypes/AreaChart.hxx b/chart2/source/view/charttypes/AreaChart.hxx index 89790912893d..ec56d9e2390b 100644 --- a/chart2/source/view/charttypes/AreaChart.hxx +++ b/chart2/source/view/charttypes/AreaChart.hxx @@ -104,8 +104,6 @@ private: //methods , ::com::sun::star::drawing::PolyPolygonShape3D* pSeriesPoly , PlottingPositionHelper* pPosHelper ); - void impl_maybeReplaceNanWithZero( double& rfValue ); - private: //member PlottingPositionHelper* m_pMainPosHelper; @@ -118,14 +116,6 @@ private: //member sal_Int32 m_nKeepAspectRatio; //0->no 1->yes other value->automatic ::com::sun::star::drawing::Direction3D m_aGivenAspectRatio; //only used if nKeepAspectRatio==1 - enum tNanHandling - { - NAN_AS_ZERO, - NAN_AS_GAP, - NAN_AS_INTERPOLATED - }; - tNanHandling m_eNanHandling; - //Properties for splines: ::com::sun::star::chart2::CurveStyle m_eCurveStyle; sal_Int32 m_nCurveResolution; diff --git a/chart2/source/view/charttypes/BarChart.cxx b/chart2/source/view/charttypes/BarChart.cxx index baeac4a29cf1..41cef61561bb 100644 --- a/chart2/source/view/charttypes/BarChart.cxx +++ b/chart2/source/view/charttypes/BarChart.cxx @@ -45,7 +45,6 @@ #include "Clipping.hxx" #include <com/sun/star/chart/DataLabelPlacement.hpp> -#include <com/sun/star/chart/MissingValueTreatment.hpp> #include <com/sun/star/chart2/DataPointGeometry3D.hpp> #include <tools/debug.hxx> @@ -653,15 +652,10 @@ void BarChart::createShapes() getSeriesGroupShape(*aSeriesIter, xSeriesTarget) ); //collect data point information (logic coordinates, style ): - double fLogicX = pPosHelper->getSlotPos( (*aSeriesIter)->getX( nCatIndex ), fSlotX ); - double fLogicBarHeight = (*aSeriesIter)->getY( nCatIndex ); + double fLogicX = pPosHelper->getSlotPos( (*aSeriesIter)->getXValue( nCatIndex ), fSlotX ); + double fLogicBarHeight = (*aSeriesIter)->getYValue( nCatIndex ); if( ::rtl::math::isNan( fLogicBarHeight )) //no value at this category - { - if( pSeries->getMissingValueTreatment() == ::com::sun::star::chart::MissingValueTreatment::USE_ZERO ) - fLogicBarHeight = 0.0; - else - continue; - } + continue; double fLogicValueForLabeDisplay = fLogicBarHeight; fLogicBarHeight-=fBaseValue; diff --git a/chart2/source/view/charttypes/BubbleChart.cxx b/chart2/source/view/charttypes/BubbleChart.cxx new file mode 100644 index 000000000000..b63603ef403a --- /dev/null +++ b/chart2/source/view/charttypes/BubbleChart.cxx @@ -0,0 +1,420 @@ +/************************************************************************* + * + * 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: ,v $ + * $Revision: $ + * + * 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_chart2.hxx" + +#include "BubbleChart.hxx" +#include "PlottingPositionHelper.hxx" +#include "ShapeFactory.hxx" +#include "CommonConverters.hxx" +#include "macros.hxx" +#include "ViewDefines.hxx" +#include "ObjectIdentifier.hxx" +#include "Splines.hxx" +#include "LabelPositionHelper.hxx" +#include "Clipping.hxx" +#include "Stripe.hxx" + +#include <com/sun/star/chart2/Symbol.hpp> +#include <com/sun/star/chart/DataLabelPlacement.hpp> +#include <tools/debug.hxx> +#include <svx/unoprnms.hxx> +#include <rtl/math.hxx> +#include <com/sun/star/drawing/DoubleSequence.hpp> +#include <com/sun/star/drawing/NormalsKind.hpp> +#include <com/sun/star/lang/XServiceName.hpp> + +//............................................................................. +namespace chart +{ +//............................................................................. +using namespace ::com::sun::star; +using namespace ::rtl::math; +using namespace ::com::sun::star::chart2; + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- + +BubbleChart::BubbleChart( const uno::Reference<XChartType>& xChartTypeModel + , sal_Int32 nDimensionCount ) + : VSeriesPlotter( xChartTypeModel, nDimensionCount, false ) + , m_bShowNegativeValues(false) + , m_bBubbleSizeAsArea(true) + , m_fBubbleSizeScaling(1.0) + , m_fMaxLogicBubbleSize( 0.0 ) + , m_fBubbleSizeFactorToScreen( 1.0 ) +{ + if( !m_pMainPosHelper ) + m_pMainPosHelper = new PlottingPositionHelper(); + PlotterBase::m_pPosHelper = m_pMainPosHelper; + VSeriesPlotter::m_pMainPosHelper = m_pMainPosHelper; +} + +BubbleChart::~BubbleChart() +{ + delete m_pMainPosHelper; +} + +void BubbleChart::calculateMaximumLogicBubbleSize() +{ + double fMaxSize = 0.0; + + sal_Int32 nStartIndex = 0; + sal_Int32 nEndIndex = VSeriesPlotter::getPointCount(); + for( sal_Int32 nIndex = nStartIndex; nIndex < nEndIndex; nIndex++ ) + { + ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator aZSlotIter = m_aZSlots.begin(); + const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end(); + for( ; aZSlotIter != aZSlotEnd; aZSlotIter++ ) + { + ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin(); + const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end(); + for( ; aXSlotIter != aXSlotEnd; aXSlotIter++ ) + { + ::std::vector< VDataSeries* >* pSeriesList = &(aXSlotIter->m_aSeriesVector); + ::std::vector< VDataSeries* >::const_iterator aSeriesIter = pSeriesList->begin(); + const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = pSeriesList->end(); + for( ; aSeriesIter != aSeriesEnd; aSeriesIter++ ) + { + VDataSeries* pSeries( *aSeriesIter ); + if(!pSeries) + continue; + + double fSize = pSeries->getBubble_Size( nIndex ); + if( m_bShowNegativeValues ) + fSize = abs(fSize); + if( fSize > fMaxSize ) + fMaxSize = fSize; + } + } + } + } + + m_fMaxLogicBubbleSize = fMaxSize; +} + +void BubbleChart::calculateBubbleSizeScalingFactor() +{ + double fLogicZ=0.5; + drawing::Position3D aSceneMinPos( m_pMainPosHelper->transformLogicToScene( m_pMainPosHelper->getLogicMinX(),m_pMainPosHelper->getLogicMinY(),fLogicZ, false ) ); + drawing::Position3D aSceneMaxPos( m_pMainPosHelper->transformLogicToScene( m_pMainPosHelper->getLogicMaxX(),m_pMainPosHelper->getLogicMaxY(),fLogicZ, false ) ); + + awt::Point aScreenMinPos( LabelPositionHelper(m_pMainPosHelper,m_nDimension,m_xLogicTarget,m_pShapeFactory).transformSceneToScreenPosition( aSceneMinPos ) ); + awt::Point aScreenMaxPos( LabelPositionHelper(m_pMainPosHelper,m_nDimension,m_xLogicTarget,m_pShapeFactory).transformSceneToScreenPosition( aSceneMaxPos ) ); + + sal_Int32 nWidth = abs( aScreenMaxPos.X - aScreenMinPos.X ); + sal_Int32 nHeight = abs( aScreenMaxPos.Y - aScreenMinPos.Y ); + + sal_Int32 nMinExtend = std::min( nWidth, nHeight ); + m_fBubbleSizeFactorToScreen = nMinExtend * 0.25;//max bubble size is 25 percent of diagram size +} + +drawing::Direction3D BubbleChart::transformToScreenBubbleSize( double fLogicSize ) +{ + drawing::Direction3D aRet(0,0,0); + + if( ::rtl::math::isNan(fLogicSize) || ::rtl::math::isInf(fLogicSize) ) + return aRet; + + if( m_bShowNegativeValues ) + fLogicSize = abs(fLogicSize); + + double fMaxSize = m_fMaxLogicBubbleSize; + + double fMaxRadius = fMaxSize; + double fRaduis = fLogicSize; + if( m_bBubbleSizeAsArea ) + { + fMaxRadius = sqrt( fMaxSize / F_PI ); + fRaduis = sqrt( fLogicSize / F_PI ); + } + + aRet.DirectionX = m_fBubbleSizeScaling * m_fBubbleSizeFactorToScreen * fRaduis / fMaxRadius; + aRet.DirectionY = aRet.DirectionX; + + return aRet; +} + +bool BubbleChart::isExpandIfValuesCloseToBorder( sal_Int32 /*nDimensionIndex*/ ) +{ + return true; +} + +bool BubbleChart::isSeperateStackingForDifferentSigns( sal_Int32 /*nDimensionIndex*/ ) +{ + return false; +} + +//----------------------------------------------------------------- + +LegendSymbolStyle BubbleChart::getLegendSymbolStyle() +{ + return chart2::LegendSymbolStyle_CIRCLE; +} + +drawing::Direction3D BubbleChart::getPreferredDiagramAspectRatio() const +{ + return drawing::Direction3D(-1,-1,-1); +} + +void BubbleChart::addSeries( VDataSeries* pSeries, sal_Int32 zSlot, sal_Int32 xSlot, sal_Int32 ySlot ) +{ + VSeriesPlotter::addSeries( pSeries, zSlot, xSlot, ySlot ); +} + +//better performance for big data +struct FormerPoint +{ + FormerPoint( double fX, double fY, double fZ ) + : m_fX(fX), m_fY(fY), m_fZ(fZ) + {} + FormerPoint() + { + ::rtl::math::setNan( &m_fX ); + ::rtl::math::setNan( &m_fY ); + ::rtl::math::setNan( &m_fZ ); + } + + double m_fX; + double m_fY; + double m_fZ; +}; + +void BubbleChart::createShapes() +{ + if( m_aZSlots.begin() == m_aZSlots.end() ) //no series + return; + + DBG_ASSERT(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is(),"BubbleChart is not proper initialized"); + if(!(m_pShapeFactory&&m_xLogicTarget.is()&&m_xFinalTarget.is())) + return; + + //therefore create an own group for the texts and the error bars to move them to front + //(because the text group is created after the series group the texts are displayed on top) + uno::Reference< drawing::XShapes > xSeriesTarget( + createGroupShape( m_xLogicTarget,rtl::OUString() )); + uno::Reference< drawing::XShapes > xTextTarget( + m_pShapeFactory->createGroup2D( m_xFinalTarget,rtl::OUString() )); + + //update/create information for current group + double fLogicZ = 0.5;//as defined + + sal_Int32 nStartIndex = 0; // inclusive ;..todo get somehow from x scale + sal_Int32 nEndIndex = VSeriesPlotter::getPointCount(); + if(nEndIndex<=0) + nEndIndex=1; + + //better performance for big data + std::map< VDataSeries*, FormerPoint > aSeriesFormerPointMap; + m_bPointsWereSkipped = false; + sal_Int32 nSkippedPoints = 0; + sal_Int32 nCreatedPoints = 0; + // + + calculateMaximumLogicBubbleSize(); + calculateBubbleSizeScalingFactor(); + if( m_fMaxLogicBubbleSize <= 0 || m_fBubbleSizeFactorToScreen <= 0 ) + return; + +//============================================================================= + //iterate through all x values per indices + for( sal_Int32 nIndex = nStartIndex; nIndex < nEndIndex; nIndex++ ) + { + ::std::vector< ::std::vector< VDataSeriesGroup > >::iterator aZSlotIter = m_aZSlots.begin(); + const ::std::vector< ::std::vector< VDataSeriesGroup > >::const_iterator aZSlotEnd = m_aZSlots.end(); + + aZSlotIter = m_aZSlots.begin(); + for( sal_Int32 nZ=1; aZSlotIter != aZSlotEnd; aZSlotIter++, nZ++ ) + { + ::std::vector< VDataSeriesGroup >::iterator aXSlotIter = aZSlotIter->begin(); + const ::std::vector< VDataSeriesGroup >::const_iterator aXSlotEnd = aZSlotIter->end(); + + aXSlotIter = aZSlotIter->begin(); + for( sal_Int32 nX=0; aXSlotIter != aXSlotEnd; aXSlotIter++, nX++ ) + { + ::std::vector< VDataSeries* >* pSeriesList = &(aXSlotIter->m_aSeriesVector); + ::std::vector< VDataSeries* >::const_iterator aSeriesIter = pSeriesList->begin(); + const ::std::vector< VDataSeries* >::const_iterator aSeriesEnd = pSeriesList->end(); + + //============================================================================= + //iterate through all series + for( sal_Int32 nSeriesIndex = 0; aSeriesIter != aSeriesEnd; aSeriesIter++, nSeriesIndex++ ) + { + VDataSeries* pSeries( *aSeriesIter ); + if(!pSeries) + continue; + + uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShape(*aSeriesIter, xSeriesTarget); + + sal_Int32 nAttachedAxisIndex = pSeries->getAttachedAxisIndex(); + PlottingPositionHelper* pPosHelper = &(this->getPlottingPositionHelper( nAttachedAxisIndex )); + if(!pPosHelper) + pPosHelper = m_pMainPosHelper; + PlotterBase::m_pPosHelper = pPosHelper; + + if(m_nDimension==3) + fLogicZ = nZ+0.5; + + //collect data point information (logic coordinates, style ): + double fLogicX = pSeries->getXValue(nIndex); + double fLogicY = pSeries->getYValue(nIndex); + double fBubbleSize = pSeries->getBubble_Size( nIndex ); + + if( !m_bShowNegativeValues && fBubbleSize<0.0 ) + continue; + + if( ::rtl::math::approxEqual( fBubbleSize, 0.0 ) || ::rtl::math::isNan(fBubbleSize) ) + continue; + + if( ::rtl::math::isNan(fLogicX) || ::rtl::math::isInf(fLogicX) + || ::rtl::math::isNan(fLogicY) || ::rtl::math::isInf(fLogicY) ) + continue; + + bool bIsVisible = pPosHelper->isLogicVisible( fLogicX, fLogicY, fLogicZ ); + + drawing::Position3D aUnscaledLogicPosition( fLogicX, fLogicY, fLogicZ ); + drawing::Position3D aScaledLogicPosition(aUnscaledLogicPosition); + pPosHelper->doLogicScaling( aScaledLogicPosition ); + + //transformation 3) -> 4) + drawing::Position3D aScenePosition( pPosHelper->transformLogicToScene( fLogicX,fLogicY,fLogicZ, false ) ); + + //better performance for big data + FormerPoint aFormerPoint( aSeriesFormerPointMap[pSeries] ); + pPosHelper->setCoordinateSystemResolution( m_aCoordinateSystemResolution ); + if( !pSeries->isAttributedDataPoint(nIndex) + && + pPosHelper->isSameForGivenResolution( aFormerPoint.m_fX, aFormerPoint.m_fY, aFormerPoint.m_fZ + , aScaledLogicPosition.PositionX, aScaledLogicPosition.PositionY, aScaledLogicPosition.PositionZ ) ) + { + nSkippedPoints++; + m_bPointsWereSkipped = true; + continue; + } + aSeriesFormerPointMap[pSeries] = FormerPoint(aScaledLogicPosition.PositionX, aScaledLogicPosition.PositionY, aScaledLogicPosition.PositionZ); + + //create a single datapoint if point is visible + if( !bIsVisible ) + continue; + + //create a group shape for this point and add to the series shape: + rtl::OUString aPointCID = ObjectIdentifier::createPointCID( + pSeries->getPointCID_Stub(), nIndex ); + uno::Reference< drawing::XShapes > xPointGroupShape_Shapes( + createGroupShape(xSeriesGroupShape_Shapes,aPointCID) ); + uno::Reference<drawing::XShape> xPointGroupShape_Shape = + uno::Reference<drawing::XShape>( xPointGroupShape_Shapes, uno::UNO_QUERY ); + + { + nCreatedPoints++; + + //create data point + drawing::Direction3D aSymbolSize = transformToScreenBubbleSize( fBubbleSize ); + if(m_nDimension!=3) + { + uno::Reference<drawing::XShape> xShape; + xShape = m_pShapeFactory->createCircle2D( xPointGroupShape_Shapes + , aScenePosition, aSymbolSize ); + + this->setMappedProperties( xShape + , pSeries->getPropertiesOfPoint( nIndex ) + , PropertyMapper::getPropertyNameMapForFilledSeriesProperties() ); + + m_pShapeFactory->setShapeName( xShape, C2U("MarkHandles") ); + } + + //create data point label + if( (**aSeriesIter).getDataPointLabelIfLabel(nIndex) ) + { + LabelAlignment eAlignment = LABEL_ALIGN_TOP; + drawing::Position3D aScenePosition3D( aScenePosition.PositionX + , aScenePosition.PositionY + , aScenePosition.PositionZ+this->getTransformedDepth() ); + + sal_Int32 nLabelPlacement = pSeries->getLabelPlacement( nIndex, m_xChartTypeModel, m_nDimension, pPosHelper->isSwapXAndY() ); + + switch(nLabelPlacement) + { + case ::com::sun::star::chart::DataLabelPlacement::TOP: + aScenePosition3D.PositionY -= (aSymbolSize.DirectionY/2+1); + eAlignment = LABEL_ALIGN_TOP; + break; + case ::com::sun::star::chart::DataLabelPlacement::BOTTOM: + aScenePosition3D.PositionY += (aSymbolSize.DirectionY/2+1); + eAlignment = LABEL_ALIGN_BOTTOM; + break; + case ::com::sun::star::chart::DataLabelPlacement::LEFT: + aScenePosition3D.PositionX -= (aSymbolSize.DirectionX/2+1); + eAlignment = LABEL_ALIGN_LEFT; + break; + case ::com::sun::star::chart::DataLabelPlacement::RIGHT: + aScenePosition3D.PositionX += (aSymbolSize.DirectionX/2+1); + eAlignment = LABEL_ALIGN_RIGHT; + break; + case ::com::sun::star::chart::DataLabelPlacement::CENTER: + eAlignment = LABEL_ALIGN_CENTER; + break; + default: + DBG_ERROR("this label alignment is not implemented yet"); + aScenePosition3D.PositionY -= (aSymbolSize.DirectionY/2+1); + eAlignment = LABEL_ALIGN_TOP; + break; + } + + + awt::Point aScreenPosition2D( LabelPositionHelper(pPosHelper,m_nDimension,m_xLogicTarget,m_pShapeFactory) + .transformSceneToScreenPosition( aScenePosition3D ) ); + sal_Int32 nOffset = 0; + if(LABEL_ALIGN_CENTER!=eAlignment) + nOffset = 100;//add some spacing //@todo maybe get more intelligent values + this->createDataLabel( xTextTarget, **aSeriesIter, nIndex + , fBubbleSize, fBubbleSize, aScreenPosition2D, eAlignment, nOffset ); + } + } + + //remove PointGroupShape if empty + if(!xPointGroupShape_Shapes->getCount()) + xSeriesGroupShape_Shapes->remove(xPointGroupShape_Shape); + + }//next series in x slot (next y slot) + }//next x slot + }//next z slot + }//next category +//============================================================================= +//============================================================================= +//============================================================================= + OSL_TRACE( "\nPPPPPPPPP<<<<<<<<<<<< area chart :: createShapes():: skipped points: %d created points: %d", nSkippedPoints, nCreatedPoints ); +} + +//............................................................................. +} //namespace chart +//............................................................................. diff --git a/chart2/source/view/charttypes/BubbleChart.hxx b/chart2/source/view/charttypes/BubbleChart.hxx new file mode 100644 index 000000000000..4771a4cccee3 --- /dev/null +++ b/chart2/source/view/charttypes/BubbleChart.hxx @@ -0,0 +1,97 @@ +/************************************************************************* + * + * 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: ,v $ + * $Revision: $ + * + * 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 _CHART2_BUBBLECHART_HXX +#define _CHART2_BUBBLECHART_HXX + +#include "VSeriesPlotter.hxx" +#include <com/sun/star/drawing/Direction3D.hpp> + +//............................................................................. +namespace chart +{ +//............................................................................. + +class BubbleChart : public VSeriesPlotter +{ + //------------------------------------------------------------------------- + // public methods + //------------------------------------------------------------------------- +public: + BubbleChart( const ::com::sun::star::uno::Reference< + ::com::sun::star::chart2::XChartType >& xChartTypeModel + , sal_Int32 nDimensionCount ); + virtual ~BubbleChart(); + + //------------------------------------------------------------------------- + // chart2::XPlotter + //------------------------------------------------------------------------- + + virtual void SAL_CALL createShapes(); + + virtual void addSeries( VDataSeries* pSeries, sal_Int32 zSlot = -1, sal_Int32 xSlot = -1,sal_Int32 ySlot = -1 ); + + //------------------- + virtual ::com::sun::star::drawing::Direction3D getPreferredDiagramAspectRatio() const; + + //------------------------------------------------------------------------- + // MinimumAndMaximumSupplier + //------------------------------------------------------------------------- + virtual bool isExpandIfValuesCloseToBorder( sal_Int32 nDimensionIndex ); + virtual bool isSeperateStackingForDifferentSigns( sal_Int32 nDimensionIndex ); + + //------------------------------------------------------------------------- + + virtual ::com::sun::star::chart2::LegendSymbolStyle getLegendSymbolStyle(); + + //------------------------------------------------------------------------- + //------------------------------------------------------------------------- + //------------------------------------------------------------------------- +private: //methods + //no default constructor + BubbleChart(); + + void calculateMaximumLogicBubbleSize(); + void calculateBubbleSizeScalingFactor(); + + com::sun::star::drawing::Direction3D transformToScreenBubbleSize( double fLogicSize ); + +private: //member + + bool m_bShowNegativeValues;//input parameter + bool m_bBubbleSizeAsArea;//input parameter + double m_fBubbleSizeScaling;//input parameter + + double m_fMaxLogicBubbleSize;//calculated values + double m_fBubbleSizeFactorToScreen;//calculated values +}; +//............................................................................. +} //namespace chart +//............................................................................. +#endif diff --git a/chart2/source/view/charttypes/CandleStickChart.cxx b/chart2/source/view/charttypes/CandleStickChart.cxx index 46fdf3d8f04d..e19a44cdcda6 100644 --- a/chart2/source/view/charttypes/CandleStickChart.cxx +++ b/chart2/source/view/charttypes/CandleStickChart.cxx @@ -250,7 +250,7 @@ void CandleStickChart::createShapes() for( ; aSeriesIter != aSeriesEnd; aSeriesIter++ ) { //collect data point information (logic coordinates, style ): - double fLogicX = pPosHelper->getSlotPos( (*aSeriesIter)->getX( nIndex ), fSlotX ); + double fLogicX = pPosHelper->getSlotPos( (*aSeriesIter)->getXValue( nIndex ), fSlotX ); double fY_First = (*aSeriesIter)->getY_First( nIndex ); double fY_Last = (*aSeriesIter)->getY_Last( nIndex ); double fY_Min = (*aSeriesIter)->getY_Min( nIndex ); diff --git a/chart2/source/view/charttypes/PieChart.cxx b/chart2/source/view/charttypes/PieChart.cxx index 7759f3110cbd..608adb49290b 100644 --- a/chart2/source/view/charttypes/PieChart.cxx +++ b/chart2/source/view/charttypes/PieChart.cxx @@ -376,7 +376,7 @@ void PieChart::createShapes() sal_Int32 nPointCount=pSeries->getTotalPointCount(); for( nPointIndex = 0; nPointIndex < nPointCount; nPointIndex++ ) { - double fY = pSeries->getY( nPointIndex ); + double fY = pSeries->getYValue( nPointIndex ); if(fY<0.0) { //@todo warn somehow that negative values are treated as positive @@ -402,7 +402,7 @@ void PieChart::createShapes() uno::Reference< drawing::XShapes > xSeriesGroupShape_Shapes = getSeriesGroupShape(pSeries, xSeriesTarget); //collect data point information (logic coordinates, style ): - double fLogicYValue = fabs(pSeries->getY( nPointIndex )); + double fLogicYValue = fabs(pSeries->getYValue( nPointIndex )); if( ::rtl::math::isNan(fLogicYValue) ) continue; if(fLogicYValue==0.0)//@todo: continue also if the resolution to small diff --git a/chart2/source/view/charttypes/Splines.cxx b/chart2/source/view/charttypes/Splines.cxx index a684b9a3228e..6d37d7444868 100644 --- a/chart2/source/view/charttypes/Splines.cxx +++ b/chart2/source/view/charttypes/Splines.cxx @@ -318,108 +318,133 @@ void SplineCalculater::CalculateCubicSplines( , sal_Int32 nGranularity ) { DBG_ASSERT( nGranularity > 0, "Granularity is invalid" ); + rResult.SequenceX.realloc(0); rResult.SequenceY.realloc(0); rResult.SequenceZ.realloc(0); - if( !rInput.SequenceX.getLength() ) + sal_Int32 nOuterCount = rInput.SequenceX.getLength();
+ if( !nOuterCount )
return; - if( rInput.SequenceX[0].getLength() <= 1 ) - return; //we need at least two points - - sal_Int32 nMaxIndexPoints = rInput.SequenceX[0].getLength()-1; // is >=1 - const double* pOldX = rInput.SequenceX[0].getConstArray(); - const double* pOldY = rInput.SequenceY[0].getConstArray(); - const double* pOldZ = rInput.SequenceZ[0].getConstArray(); - - // #i13699# The curve gets a parameter and then for each coordinate a - // separate spline will be calculated using the parameter as first argument - // and the point coordinate as second argument. Therefore the points need - // not to be sorted in its x-coordinates. The parameter is sorted by - // construction. - - ::std::vector < double > aParameter(nMaxIndexPoints+1); - aParameter[0]=0.0; - for( sal_Int32 nIndex=1; nIndex<=nMaxIndexPoints; nIndex++ ) - { - // The euclidian distance leads to curve loops for functions having single extreme points -// aParameter[nIndex]=aParameter[nIndex-1]+ -// sqrt( (pOldX[nIndex]-pOldX[nIndex-1])*(pOldX[nIndex]-pOldX[nIndex-1])+ -// (pOldY[nIndex]-pOldY[nIndex-1])*(pOldY[nIndex]-pOldY[nIndex-1])+ -// (pOldZ[nIndex]-pOldZ[nIndex-1])*(pOldZ[nIndex]-pOldZ[nIndex-1])); - - // use increment of 1 instead - aParameter[nIndex]=aParameter[nIndex-1]+1; - } - // Split the calculation to X, Y and Z coordinate - tPointVecType aInputX; - aInputX.resize(nMaxIndexPoints+1); - tPointVecType aInputY; - aInputY.resize(nMaxIndexPoints+1); - tPointVecType aInputZ; - aInputZ.resize(nMaxIndexPoints+1); - for (sal_Int32 nN=0;nN<=nMaxIndexPoints; nN++ ) - { - aInputX[ nN ].first=aParameter[nN]; - aInputX[ nN ].second=pOldX[ nN ]; - aInputY[ nN ].first=aParameter[nN]; - aInputY[ nN ].second=pOldY[ nN ]; - aInputZ[ nN ].first=aParameter[nN]; - aInputZ[ nN ].second=pOldZ[ nN ]; - } - // generate a spline for each coordinate. It holds the complete - // information to calculate each point of the curve - - // generate the kind "natural spline" - double fInfty; - ::rtl::math::setInf( &fInfty, sal_False ); - lcl_SplineCalculation aSplineX( aInputX, fInfty, fInfty ); - lcl_SplineCalculation aSplineY( aInputY, fInfty, fInfty ); - lcl_SplineCalculation aSplineZ( aInputZ, fInfty, fInfty ); - - // fill result polygon with calculated values - rResult.SequenceX.realloc(1); - rResult.SequenceY.realloc(1); - rResult.SequenceZ.realloc(1); - rResult.SequenceX[0].realloc( nMaxIndexPoints*nGranularity + 1); - rResult.SequenceY[0].realloc( nMaxIndexPoints*nGranularity + 1); - rResult.SequenceZ[0].realloc( nMaxIndexPoints*nGranularity + 1); - - double* pNewX = rResult.SequenceX[0].getArray(); - double* pNewY = rResult.SequenceY[0].getArray(); - double* pNewZ = rResult.SequenceZ[0].getArray(); - - sal_Int32 nNewPointIndex = 0; // Index in result points - // needed for inner loop - double fInc; // step for intermediate points - sal_Int32 nj; // for loop - double fParam; // a intermediate parameter value - - for( sal_Int32 ni = 0; ni < nMaxIndexPoints; ni++ ) - { - // given point is surely a curve point - pNewX[nNewPointIndex] = pOldX[ni]; - pNewY[nNewPointIndex] = pOldY[ni]; - pNewZ[nNewPointIndex] = pOldZ[ni]; - nNewPointIndex++; - - // calculate intermediate points - fInc = ( aParameter[ ni+1 ] - aParameter[ni] ) / static_cast< double >( nGranularity ); - for(nj = 1; nj < nGranularity; nj++) + rResult.SequenceX.realloc(nOuterCount);
+ rResult.SequenceY.realloc(nOuterCount);
+ rResult.SequenceZ.realloc(nOuterCount); + + for( sal_Int32 nOuter = 0; nOuter < nOuterCount; ++nOuter )
+ {
+ if( rInput.SequenceX[nOuter].getLength() <= 1 )
+ continue; //we need at least two points + + sal_Int32 nMaxIndexPoints = rInput.SequenceX[nOuter].getLength()-1; // is >=1 + const double* pOldX = rInput.SequenceX[nOuter].getConstArray(); + const double* pOldY = rInput.SequenceY[nOuter].getConstArray(); + const double* pOldZ = rInput.SequenceZ[nOuter].getConstArray(); + + // #i13699# The curve gets a parameter and then for each coordinate a + // separate spline will be calculated using the parameter as first argument + // and the point coordinate as second argument. Therefore the points need + // not to be sorted in its x-coordinates. The parameter is sorted by + // construction. + + ::std::vector < double > aParameter(nMaxIndexPoints+1); + aParameter[0]=0.0; + for( sal_Int32 nIndex=1; nIndex<=nMaxIndexPoints; nIndex++ ) + { + // The euclidian distance leads to curve loops for functions having single extreme points + //aParameter[nIndex]=aParameter[nIndex-1]+ + //sqrt( (pOldX[nIndex]-pOldX[nIndex-1])*(pOldX[nIndex]-pOldX[nIndex-1])+ + //(pOldY[nIndex]-pOldY[nIndex-1])*(pOldY[nIndex]-pOldY[nIndex-1])+ + //(pOldZ[nIndex]-pOldZ[nIndex-1])*(pOldZ[nIndex]-pOldZ[nIndex-1])); + + // use increment of 1 instead + aParameter[nIndex]=aParameter[nIndex-1]+1; + } + // Split the calculation to X, Y and Z coordinate + tPointVecType aInputX; + aInputX.resize(nMaxIndexPoints+1); + tPointVecType aInputY; + aInputY.resize(nMaxIndexPoints+1); + tPointVecType aInputZ; + aInputZ.resize(nMaxIndexPoints+1); + for (sal_Int32 nN=0;nN<=nMaxIndexPoints; nN++ ) { - fParam = aParameter[ni] + ( fInc * static_cast< double >( nj ) ); + aInputX[ nN ].first=aParameter[nN]; + aInputX[ nN ].second=pOldX[ nN ]; + aInputY[ nN ].first=aParameter[nN]; + aInputY[ nN ].second=pOldY[ nN ]; + aInputZ[ nN ].first=aParameter[nN]; + aInputZ[ nN ].second=pOldZ[ nN ]; + } - pNewX[nNewPointIndex]=aSplineX.GetInterpolatedValue( fParam ); - pNewY[nNewPointIndex]=aSplineY.GetInterpolatedValue( fParam ); - pNewZ[nNewPointIndex]=aSplineZ.GetInterpolatedValue( fParam ); + // generate a spline for each coordinate. It holds the complete + // information to calculate each point of the curve + double fXDerivation; + double fYDerivation; + double fZDerivation; + if( pOldX[ 0 ] == pOldX[nMaxIndexPoints] && + pOldY[ 0 ] == pOldY[nMaxIndexPoints] && + pOldZ[ 0 ] == pOldZ[nMaxIndexPoints] ) + { + // #i101050# avoid a corner in closed lines, which are smoothed by spline + // This derivation are special for parameter of kind 0,1,2,3... If you + // change generating parameters (see above), then adapt derivations too.) + fXDerivation = 0.5 * (pOldX[1]-pOldX[nMaxIndexPoints-1]); + fYDerivation = 0.5 * (pOldY[1]-pOldY[nMaxIndexPoints-1]); + fZDerivation = 0.5 * (pOldZ[1]-pOldZ[nMaxIndexPoints-1]); + } + else // generate the kind "natural spline" + { + double fInfty; + ::rtl::math::setInf( &fInfty, sal_False ); + fXDerivation = fInfty; + fYDerivation = fInfty; + fZDerivation = fInfty; + } + lcl_SplineCalculation aSplineX( aInputX, fXDerivation, fXDerivation ); + lcl_SplineCalculation aSplineY( aInputY, fYDerivation, fYDerivation ); + lcl_SplineCalculation aSplineZ( aInputZ, fZDerivation, fZDerivation ); + + // fill result polygon with calculated values + rResult.SequenceX[nOuter].realloc( nMaxIndexPoints*nGranularity + 1); + rResult.SequenceY[nOuter].realloc( nMaxIndexPoints*nGranularity + 1); + rResult.SequenceZ[nOuter].realloc( nMaxIndexPoints*nGranularity + 1); + + double* pNewX = rResult.SequenceX[nOuter].getArray(); + double* pNewY = rResult.SequenceY[nOuter].getArray(); + double* pNewZ = rResult.SequenceZ[nOuter].getArray(); + + sal_Int32 nNewPointIndex = 0; // Index in result points + // needed for inner loop + double fInc; // step for intermediate points + sal_Int32 nj; // for loop + double fParam; // a intermediate parameter value + + for( sal_Int32 ni = 0; ni < nMaxIndexPoints; ni++ ) + { + // given point is surely a curve point + pNewX[nNewPointIndex] = pOldX[ni]; + pNewY[nNewPointIndex] = pOldY[ni]; + pNewZ[nNewPointIndex] = pOldZ[ni]; nNewPointIndex++; + + // calculate intermediate points + fInc = ( aParameter[ ni+1 ] - aParameter[ni] ) / static_cast< double >( nGranularity ); + for(nj = 1; nj < nGranularity; nj++) + { + fParam = aParameter[ni] + ( fInc * static_cast< double >( nj ) ); + + pNewX[nNewPointIndex]=aSplineX.GetInterpolatedValue( fParam ); + pNewY[nNewPointIndex]=aSplineY.GetInterpolatedValue( fParam ); + pNewZ[nNewPointIndex]=aSplineZ.GetInterpolatedValue( fParam ); + nNewPointIndex++; + } } + // add last point + pNewX[nNewPointIndex] = pOldX[nMaxIndexPoints]; + pNewY[nNewPointIndex] = pOldY[nMaxIndexPoints]; + pNewZ[nNewPointIndex] = pOldZ[nMaxIndexPoints]; } - // add last point - pNewX[nNewPointIndex] = pOldX[nMaxIndexPoints]; - pNewY[nNewPointIndex] = pOldY[nMaxIndexPoints]; - pNewZ[nNewPointIndex] = pOldZ[nMaxIndexPoints]; } void SplineCalculater::CalculateBSplines( @@ -436,80 +461,85 @@ void SplineCalculater::CalculateBSplines( rResult.SequenceY.realloc(0); rResult.SequenceZ.realloc(0); - if( !rInput.SequenceX.getLength() ) + sal_Int32 nOuterCount = rInput.SequenceX.getLength();
+ if( !nOuterCount )
return; // no input - if( rInput.SequenceX[0].getLength() <= 1 ) - return; // need at least 2 control points - - sal_Int32 n = rInput.SequenceX[0].getLength()-1; // maximum index of control points - - double fCurveparam =0.0; // parameter for the curve - // 0<= fCurveparam < fMaxCurveparam - double fMaxCurveparam = 2.0+ n - k; - if (fMaxCurveparam <= 0.0) - return; // not enough control points for desired spline order - - if (nGranularity < 1) - return; //need at least 1 line for each part beween the control points - - const double* pOldX = rInput.SequenceX[0].getConstArray(); - const double* pOldY = rInput.SequenceY[0].getConstArray(); - const double* pOldZ = rInput.SequenceZ[0].getConstArray(); - - // keep this amount of steps to go well with old version - sal_Int32 nNewSectorCount = nGranularity * n; - double fCurveStep = fMaxCurveparam/static_cast< double >(nNewSectorCount); - - double *b = new double [n + k + 1]; // values of blending functions - - const double* t = createTVector(n, k); // knot vector - - rResult.SequenceX.realloc(1); - rResult.SequenceY.realloc(1); - rResult.SequenceZ.realloc(1); - rResult.SequenceX[0].realloc(nNewSectorCount+1); - rResult.SequenceY[0].realloc(nNewSectorCount+1); - rResult.SequenceZ[0].realloc(nNewSectorCount+1); - double* pNewX = rResult.SequenceX[0].getArray(); - double* pNewY = rResult.SequenceY[0].getArray(); - double* pNewZ = rResult.SequenceZ[0].getArray(); - - // variables needed inside loop, when calculating one point of output - sal_Int32 nPointIndex =0; //index of given contol points - double fX=0.0; - double fY=0.0; - double fZ=0.0; //coordinates of a new BSpline point - - for(sal_Int32 nNewSector=0; nNewSector<nNewSectorCount; nNewSector++) - { // in first looping fCurveparam has value 0.0 - - // Calculate the values of the blending functions for actual curve parameter - BVector(fCurveparam, n, k, b, t); - - // output point(fCurveparam) = sum over {input point * value of blending function} - fX = 0.0; - fY = 0.0; - fZ = 0.0; - for (nPointIndex=0;nPointIndex<=n;nPointIndex++) - { - fX +=pOldX[nPointIndex]*b[nPointIndex]; - fY +=pOldY[nPointIndex]*b[nPointIndex]; - fZ +=pOldZ[nPointIndex]*b[nPointIndex]; + rResult.SequenceX.realloc(nOuterCount);
+ rResult.SequenceY.realloc(nOuterCount);
+ rResult.SequenceZ.realloc(nOuterCount); + + for( sal_Int32 nOuter = 0; nOuter < nOuterCount; ++nOuter )
+ {
+ if( rInput.SequenceX[nOuter].getLength() <= 1 )
+ continue; // need at least 2 control points + + sal_Int32 n = rInput.SequenceX[nOuter].getLength()-1; // maximum index of control points + + double fCurveparam =0.0; // parameter for the curve + // 0<= fCurveparam < fMaxCurveparam + double fMaxCurveparam = 2.0+ n - k; + if (fMaxCurveparam <= 0.0) + return; // not enough control points for desired spline order + + if (nGranularity < 1) + return; //need at least 1 line for each part beween the control points + + const double* pOldX = rInput.SequenceX[nOuter].getConstArray(); + const double* pOldY = rInput.SequenceY[nOuter].getConstArray(); + const double* pOldZ = rInput.SequenceZ[nOuter].getConstArray(); + + // keep this amount of steps to go well with old version + sal_Int32 nNewSectorCount = nGranularity * n; + double fCurveStep = fMaxCurveparam/static_cast< double >(nNewSectorCount); + + double *b = new double [n + k + 1]; // values of blending functions + + const double* t = createTVector(n, k); // knot vector + + rResult.SequenceX[nOuter].realloc(nNewSectorCount+1); + rResult.SequenceY[nOuter].realloc(nNewSectorCount+1); + rResult.SequenceZ[nOuter].realloc(nNewSectorCount+1); + double* pNewX = rResult.SequenceX[nOuter].getArray(); + double* pNewY = rResult.SequenceY[nOuter].getArray(); + double* pNewZ = rResult.SequenceZ[nOuter].getArray(); + + // variables needed inside loop, when calculating one point of output + sal_Int32 nPointIndex =0; //index of given contol points + double fX=0.0; + double fY=0.0; + double fZ=0.0; //coordinates of a new BSpline point + + for(sal_Int32 nNewSector=0; nNewSector<nNewSectorCount; nNewSector++) + { // in first looping fCurveparam has value 0.0 + + // Calculate the values of the blending functions for actual curve parameter + BVector(fCurveparam, n, k, b, t); + + // output point(fCurveparam) = sum over {input point * value of blending function} + fX = 0.0; + fY = 0.0; + fZ = 0.0; + for (nPointIndex=0;nPointIndex<=n;nPointIndex++) + { + fX +=pOldX[nPointIndex]*b[nPointIndex]; + fY +=pOldY[nPointIndex]*b[nPointIndex]; + fZ +=pOldZ[nPointIndex]*b[nPointIndex]; + } + pNewX[nNewSector] = fX; + pNewY[nNewSector] = fY; + pNewZ[nNewSector] = fZ; + + fCurveparam += fCurveStep; //for next looping } - pNewX[nNewSector] = fX; - pNewY[nNewSector] = fY; - pNewZ[nNewSector] = fZ; + // add last control point to BSpline curve + pNewX[nNewSectorCount] = pOldX[n]; + pNewY[nNewSectorCount] = pOldY[n]; + pNewZ[nNewSectorCount] = pOldZ[n]; - fCurveparam += fCurveStep; //for next looping + delete[] t; + delete[] b; } - // add last control point to BSpline curve - pNewX[nNewSectorCount] = pOldX[n]; - pNewY[nNewSectorCount] = pOldY[n]; - pNewZ[nNewSectorCount] = pOldZ[n]; - - delete[] t; - delete[] b; } //............................................................................. diff --git a/chart2/source/view/charttypes/VSeriesPlotter.cxx b/chart2/source/view/charttypes/VSeriesPlotter.cxx index 71f753afa5c6..73fa9039bf44 100644 --- a/chart2/source/view/charttypes/VSeriesPlotter.cxx +++ b/chart2/source/view/charttypes/VSeriesPlotter.cxx @@ -61,6 +61,7 @@ #include "PieChart.hxx" #include "AreaChart.hxx" #include "CandleStickChart.hxx" +#include "BubbleChart.hxx" // #include <com/sun/star/chart/ErrorBarStyle.hpp> @@ -389,7 +390,7 @@ OUString VSeriesPlotter::getLabelTextForValue( VDataSeries& rDataSeries } else { - if( m_aAxesNumberFormats.hasFormat(1,rDataSeries.getAttachedAxisIndex()) ) //y-axis + if( rDataSeries.shouldLabelNumberFormatKeyBeDetectedFromYAxis() && m_aAxesNumberFormats.hasFormat(1,rDataSeries.getAttachedAxisIndex()) ) //y-axis nNumberFormatKey = m_aAxesNumberFormats.getFormat(1,rDataSeries.getAttachedAxisIndex()); else nNumberFormatKey = rDataSeries.detectNumberFormatKey( nPointIndex ); @@ -1409,7 +1410,7 @@ void VDataSeriesGroup::getMinimumAndMaximiumX( double& rfMinimum, double& rfMaxi sal_Int32 nPointCount = (*aSeriesIter)->getTotalPointCount(); for(sal_Int32 nN=0;nN<nPointCount;nN++) { - double fX = (*aSeriesIter)->getX( nN ); + double fX = (*aSeriesIter)->getXValue( nN ); if( ::rtl::math::isNan(fX) ) continue; if(rfMaximum<fX) @@ -1441,12 +1442,12 @@ void VDataSeriesGroup::getMinimumAndMaximiumYInContinuousXRange( double& rfMinY, if( nAxisIndex != (*aSeriesIter)->getAttachedAxisIndex() ) continue; - double fX = (*aSeriesIter)->getX( nN ); + double fX = (*aSeriesIter)->getXValue( nN ); if( ::rtl::math::isNan(fX) ) continue; if( fX < fMinX || fX > fMaxX ) continue; - double fY = (*aSeriesIter)->getY( nN ); + double fY = (*aSeriesIter)->getYValue( nN ); if( ::rtl::math::isNan(fY) ) continue; if(rfMaxY<fY) @@ -2063,6 +2064,8 @@ VSeriesPlotter* VSeriesPlotter::createSeriesPlotter( pRet = new AreaChart(xChartTypeModel,nDimensionCount,true,true); else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_SCATTER) ) pRet = new AreaChart(xChartTypeModel,nDimensionCount,false,true); + else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_BUBBLE) ) + pRet = new BubbleChart(xChartTypeModel,nDimensionCount); else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_PIE) ) pRet = new PieChart(xChartTypeModel,nDimensionCount); else if( aChartType.equalsIgnoreAsciiCase(CHART2_SERVICE_NAME_CHARTTYPE_NET) ) diff --git a/chart2/source/view/charttypes/makefile.mk b/chart2/source/view/charttypes/makefile.mk index 434db9304788..1da5697fd25f 100644 --- a/chart2/source/view/charttypes/makefile.mk +++ b/chart2/source/view/charttypes/makefile.mk @@ -51,7 +51,8 @@ SLOFILES = $(SLO)$/Splines.obj \ $(SLO)$/BarChart.obj \ $(SLO)$/PieChart.obj \ $(SLO)$/AreaChart.obj \ - $(SLO)$/CandleStickChart.obj + $(SLO)$/CandleStickChart.obj \ + $(SLO)$/BubbleChart.obj # --- Targets ----------------------------------------------------------------- diff --git a/chart2/source/view/diagram/VDiagram.cxx b/chart2/source/view/diagram/VDiagram.cxx index 70f930aa8623..5e0db2644cc5 100644 --- a/chart2/source/view/diagram/VDiagram.cxx +++ b/chart2/source/view/diagram/VDiagram.cxx @@ -553,13 +553,13 @@ void VDiagram::createShapes_3d() CuboidPlanePosition eLeftWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardLeftWall( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) ); if( CuboidPlanePosition_Right==eLeftWallPos ) xPos = FIXED_SIZE_FOR_3D_CHART_VOLUME; - Stripe aStripe( drawing::Position3D(xPos,0,0) - , drawing::Direction3D(0,FIXED_SIZE_FOR_3D_CHART_VOLUME,0) + Stripe aStripe( drawing::Position3D(xPos,FIXED_SIZE_FOR_3D_CHART_VOLUME,0) + , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0) , drawing::Direction3D(0,0,FIXED_SIZE_FOR_3D_CHART_VOLUME) ); uno::Reference< drawing::XShape > xShape = m_pShapeFactory->createStripe( xWallGroup_Shapes, aStripe - , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), true ); + , xWallProp, PropertyMapper::getPropertyNameMapForFillAndLineProperties(), true, true ); if( !bAddFloorAndWall ) { //we always need this object as dummy object for correct scene dimensions @@ -573,9 +573,9 @@ void VDiagram::createShapes_3d() CuboidPlanePosition eBackWallPos( ThreeDHelper::getAutomaticCuboidPlanePositionForStandardBackWall( uno::Reference< beans::XPropertySet >( m_xDiagram, uno::UNO_QUERY ) ) ); if( CuboidPlanePosition_Front==eBackWallPos ) zPos = FIXED_SIZE_FOR_3D_CHART_VOLUME; - Stripe aStripe( drawing::Position3D(0,0,zPos) + Stripe aStripe( drawing::Position3D(0,FIXED_SIZE_FOR_3D_CHART_VOLUME,zPos) , drawing::Direction3D(FIXED_SIZE_FOR_3D_CHART_VOLUME,0,0) - , drawing::Direction3D(0,FIXED_SIZE_FOR_3D_CHART_VOLUME,0) ); + , drawing::Direction3D(0,-FIXED_SIZE_FOR_3D_CHART_VOLUME,0) ); uno::Reference< drawing::XShape > xShape = m_pShapeFactory->createStripe(xWallGroup_Shapes, aStripe diff --git a/chart2/source/view/inc/ShapeFactory.hxx b/chart2/source/view/inc/ShapeFactory.hxx index 63a7c7558a5b..a03bbd3237d8 100644 --- a/chart2/source/view/inc/ShapeFactory.hxx +++ b/chart2/source/view/inc/ShapeFactory.hxx @@ -122,7 +122,7 @@ public: , const Stripe& rStripe , const ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet >& xSourceProp , const tPropertyNameMap& rPropertyNameMap - , sal_Bool bDoubleSided = true); + , sal_Bool bDoubleSided = true, bool bRotatedTexture=false ); ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > createArea3D( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget @@ -159,6 +159,11 @@ public: , const ::com::sun::star::drawing::PolyPolygonShape3D& rPoints , const VLineProperties& rLineProperties ); + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > + createCircle2D( const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& xTarget + , const ::com::sun::star::drawing::Position3D& rPos + , const ::com::sun::star::drawing::Direction3D& rSize ); + //------------------- create 2D elements: ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > diff --git a/chart2/source/view/inc/Stripe.hxx b/chart2/source/view/inc/Stripe.hxx index fe3a728daa02..dc017fc7aaba 100644 --- a/chart2/source/view/inc/Stripe.hxx +++ b/chart2/source/view/inc/Stripe.hxx @@ -65,7 +65,7 @@ public: ::com::sun::star::uno::Any getPolyPolygonShape3D() const; ::com::sun::star::uno::Any getNormalsPolygon() const; - ::com::sun::star::uno::Any getTexturePolygon() const; + ::com::sun::star::uno::Any getTexturePolygon( bool bRotatedTexture ) const; ::com::sun::star::drawing::Position3D GetPosition1() const { return m_aPoint1; } ::com::sun::star::drawing::Position3D GetPosition2() const { return m_aPoint2; } diff --git a/chart2/source/view/inc/VDataSeries.hxx b/chart2/source/view/inc/VDataSeries.hxx index 61c0a15bc402..9426c1e9256c 100644 --- a/chart2/source/view/inc/VDataSeries.hxx +++ b/chart2/source/view/inc/VDataSeries.hxx @@ -89,14 +89,16 @@ public: void setPageReferenceSize( const ::com::sun::star::awt::Size & rPageRefSize ); sal_Int32 getTotalPointCount() const; - double getX( sal_Int32 index ) const; - double getY( sal_Int32 index ) const; + double getXValue( sal_Int32 index ) const; + double getYValue( sal_Int32 index ) const; double getY_Min( sal_Int32 index ) const; double getY_Max( sal_Int32 index ) const; double getY_First( sal_Int32 index ) const; double getY_Last( sal_Int32 index ) const; + double getBubble_Size( sal_Int32 index ) const; + double getMinimumofAllDifferentYValues( sal_Int32 index ) const; double getMaximumofAllDifferentYValues( sal_Int32 index ) const; @@ -108,6 +110,7 @@ public: bool hasExplicitNumberFormat( sal_Int32 nPointIndex, bool bForPercentage ) const; sal_Int32 getExplicitNumberFormat( sal_Int32 nPointIndex, bool bForPercentage ) const; sal_Int32 detectNumberFormatKey( sal_Int32 nPointIndex ) const; + bool shouldLabelNumberFormatKeyBeDetectedFromYAxis() const; sal_Int32 getLabelPlacement( sal_Int32 nPointIndex, const ::com::sun::star::uno::Reference< ::com::sun::star::chart2::XChartType >& xChartType , sal_Int32 nDimensionCount, sal_Bool bSwapXAndY ) const; @@ -141,6 +144,8 @@ public: void setStartingAngle( sal_Int32 nStartingAngle ); sal_Int32 getStartingAngle() const; + void setRoleOfSequenceForDataLabelNumberFormatDetection( const rtl::OUString& rRole ); + //this is only temporarily here for area chart: ::com::sun::star::drawing::PolyPolygonShape3D m_aPolyPolygonShape3D; sal_Int32 m_nPolygonIndex; @@ -207,6 +212,10 @@ private: //member VDataSequence m_aValues_Y_First; VDataSequence m_aValues_Y_Last; + VDataSequence m_aValues_Bubble_Size; + + VDataSequence* m_pValueSequenceForDataLabelNumberFormatDetection; + mutable double m_fYMeanValue; ::com::sun::star::uno::Sequence< sal_Int32 > m_aAttributedDataPointIndexList; @@ -248,7 +257,8 @@ private: //member ::com::sun::star::awt::Size m_aReferenceSize; // - sal_Int32 m_nMissingValueTreatment; + sal_Int32 m_nMissingValueTreatment; + bool m_bAllowPercentValueInDataLabel; }; //............................................................................. diff --git a/chart2/source/view/main/ChartItemPool.cxx b/chart2/source/view/main/ChartItemPool.cxx index 63c5656a83e0..f3024a10e958 100644 --- a/chart2/source/view/main/ChartItemPool.cxx +++ b/chart2/source/view/main/ChartItemPool.cxx @@ -66,6 +66,7 @@ ChartItemPool::ChartItemPool(): ppPoolDefaults[SCHATTR_DATADESCR_PLACEMENT - SCHATTR_START] = new SfxInt32Item(SCHATTR_DATADESCR_PLACEMENT,0); SvULongs aTmp; ppPoolDefaults[SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS - SCHATTR_START] = new SfxIntegerListItem(SCHATTR_DATADESCR_AVAILABLE_PLACEMENTS,aTmp); + ppPoolDefaults[SCHATTR_DATADESCR_NO_PERCENTVALUE - SCHATTR_START] = new SfxBoolItem(SCHATTR_DATADESCR_NO_PERCENTVALUE); ppPoolDefaults[SCHATTR_LEGEND_POS - SCHATTR_START] = new SvxChartLegendPosItem( CHLEGEND_RIGHT, SCHATTR_LEGEND_POS ); // ppPoolDefaults[SCHATTR_TEXT_ORIENT - SCHATTR_START] = new SvxChartTextOrientItem; diff --git a/chart2/source/view/main/ChartView.cxx b/chart2/source/view/main/ChartView.cxx index 237985cd160c..31e44dbc245b 100644 --- a/chart2/source/view/main/ChartView.cxx +++ b/chart2/source/view/main/ChartView.cxx @@ -86,7 +86,6 @@ #include <com/sun/star/chart2/XCoordinateSystemContainer.hpp> #include <com/sun/star/chart2/XChartTypeContainer.hpp> #include <com/sun/star/chart2/XDataSeriesContainer.hpp> -#include <com/sun/star/chart2/XDiagram.hpp> #include <com/sun/star/chart2/XTitled.hpp> #include <com/sun/star/chart2/RelativePosition.hpp> #include <com/sun/star/chart2/RelativeSize.hpp> @@ -726,6 +725,9 @@ void SeriesPlotterContainer::initializeCooSysAndSeriesPlotter( rtl::OUString aSeriesParticle( ObjectIdentifier::createParticleForSeries( nDiagramIndex, nCS, nT, nS ) ); pSeries->setParticle(aSeriesParticle); + OUString aRole( ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( xChartType ) ); + pSeries->setRoleOfSequenceForDataLabelNumberFormatDetection(aRole); + //ignore secondary axis for charttypes that do not suppoert them if( pSeries->getAttachedAxisIndex() != MAIN_AXIS_INDEX && !ChartTypeHelper::isSupportingSecondaryAxis( xChartType, nDimensionCount, 1 ) ) @@ -1743,7 +1745,7 @@ sal_Int32 lcl_getExplicitNumberFormatKeyForAxis( for( sal_Int32 nCTIdx=0; nCTIdx<aChartTypes.getLength(); ++nCTIdx ) { if( nDimensionIndex != 0 ) - aRoleToMatch = aChartTypes[nCTIdx]->getRoleOfSequenceForSeriesLabel(); + aRoleToMatch = ChartTypeHelper::getRoleOfSequenceForYAxisNumberFormatDetection( aChartTypes[nCTIdx] ); Reference< XDataSeriesContainer > xDSCnt( aChartTypes[nCTIdx], uno::UNO_QUERY_THROW ); Sequence< Reference< XDataSeries > > aDataSeriesSeq( xDSCnt->getDataSeries()); for( sal_Int32 nSeriesIdx=0; nSeriesIdx<aDataSeriesSeq.getLength(); ++nSeriesIdx ) @@ -1856,24 +1858,36 @@ sal_Int32 ExplicitValueProvider::getPercentNumberFormat( const Reference< util:: } -sal_Int32 ExplicitValueProvider::getExplicitNumberFormatKeyForLabel( +sal_Int32 ExplicitValueProvider::getExplicitNumberFormatKeyForDataLabel( const uno::Reference< beans::XPropertySet >& xSeriesOrPointProp, const uno::Reference< XDataSeries >& xSeries, sal_Int32 nPointIndex /*-1 for whole series*/, - const uno::Reference< beans::XPropertySet >& xAttachedAxisProps + const uno::Reference< XDiagram >& xDiagram ) { sal_Int32 nFormat=0; if( !xSeriesOrPointProp.is() ) return nFormat; + rtl::OUString aPropName( C2U( "NumberFormat" ) ); if( !(xSeriesOrPointProp->getPropertyValue(aPropName) >>= nFormat) ) { - if( xAttachedAxisProps.is() && !( xAttachedAxisProps->getPropertyValue( aPropName ) >>= nFormat ) ) + uno::Reference< chart2::XChartType > xChartType( DataSeriesHelper::getChartTypeOfSeries( xSeries, xDiagram ) ); + + bool bFormatFound = false; + if( ChartTypeHelper::shouldLabelNumberFormatKeyBeDetectedFromYAxis( xChartType ) ) + { + uno::Reference< beans::XPropertySet > xAttachedAxisProps( DiagramHelper::getAttachedAxis( xSeries, xDiagram ), uno::UNO_QUERY ); + if( xAttachedAxisProps.is() && ( xAttachedAxisProps->getPropertyValue( aPropName ) >>= nFormat ) ) + bFormatFound = true; + } + if( !bFormatFound ) { Reference< chart2::data::XDataSource > xSeriesSource( xSeries, uno::UNO_QUERY ); + OUString aRole( ChartTypeHelper::getRoleOfSequenceForDataLabelNumberFormatDetection( xChartType ) ); + Reference< data::XLabeledDataSequence > xLabeledSequence( - DataSeriesHelper::getDataSequenceByRole( xSeriesSource, C2U("values-y"), false )); + DataSeriesHelper::getDataSequenceByRole( xSeriesSource, aRole, false )); if( xLabeledSequence.is() ) { Reference< data::XDataSequence > xValues( xLabeledSequence->getValues() ); @@ -1887,7 +1901,7 @@ sal_Int32 ExplicitValueProvider::getExplicitNumberFormatKeyForLabel( return nFormat; } -sal_Int32 ExplicitValueProvider::getExplicitPercentageNumberFormatKeyForLabel( +sal_Int32 ExplicitValueProvider::getExplicitPercentageNumberFormatKeyForDataLabel( const uno::Reference< beans::XPropertySet >& xSeriesOrPointProp, const uno::Reference< util::XNumberFormatsSupplier >& xNumberFormatsSupplier ) { diff --git a/chart2/source/view/main/PlottingPositionHelper.cxx b/chart2/source/view/main/PlottingPositionHelper.cxx index 2d58a25f3808..e99c260c6d04 100644 --- a/chart2/source/view/main/PlottingPositionHelper.cxx +++ b/chart2/source/view/main/PlottingPositionHelper.cxx @@ -142,19 +142,6 @@ uno::Reference< XTransformation > PlottingPositionHelper::getTransformationScale std::swap(nXAxisOrientation,nYAxisOrientation); } - if( AxisOrientation_MATHEMATICAL==nXAxisOrientation ) - aMatrix.translate(-MinX, 0.0, 0.0); - else - aMatrix.translate(-MaxX, 0.0, 0.0); - if( AxisOrientation_MATHEMATICAL==nYAxisOrientation ) - aMatrix.translate(0.0, -MinY, 0.0); - else - aMatrix.translate(0.0, -MaxY, 0.0); - if( AxisOrientation_MATHEMATICAL==nZAxisOrientation ) - aMatrix.translate(0.0, 0.0, -MaxZ);//z direction in draw is reverse mathematical direction - else - aMatrix.translate(0.0, 0.0, -MinZ); - double fWidthX = MaxX - MinX; double fWidthY = MaxY - MinY; double fWidthZ = MaxZ - MinZ; @@ -163,9 +150,24 @@ uno::Reference< XTransformation > PlottingPositionHelper::getTransformationScale double fScaleDirectionY = AxisOrientation_MATHEMATICAL==nYAxisOrientation ? 1.0 : -1.0; double fScaleDirectionZ = AxisOrientation_MATHEMATICAL==nZAxisOrientation ? -1.0 : 1.0; - aMatrix.scale(fScaleDirectionX*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthX, - fScaleDirectionY*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthY, - fScaleDirectionZ*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthZ); + double fScaleX = fScaleDirectionX*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthX; + double fScaleY = fScaleDirectionY*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthY; + double fScaleZ = fScaleDirectionZ*FIXED_SIZE_FOR_3D_CHART_VOLUME/fWidthZ; + + aMatrix.scale(fScaleX, fScaleY, fScaleZ); + + if( AxisOrientation_MATHEMATICAL==nXAxisOrientation ) + aMatrix.translate(-MinX*fScaleX, 0.0, 0.0); + else + aMatrix.translate(-MaxX*fScaleX, 0.0, 0.0); + if( AxisOrientation_MATHEMATICAL==nYAxisOrientation ) + aMatrix.translate(0.0, -MinY*fScaleY, 0.0); + else + aMatrix.translate(0.0, -MaxY*fScaleY, 0.0); + if( AxisOrientation_MATHEMATICAL==nZAxisOrientation ) + aMatrix.translate(0.0, 0.0, -MaxZ*fScaleZ);//z direction in draw is reverse mathematical direction + else + aMatrix.translate(0.0, 0.0, -MinZ*fScaleZ); aMatrix = m_aMatrixScreenToScene*aMatrix; diff --git a/chart2/source/view/main/ShapeFactory.cxx b/chart2/source/view/main/ShapeFactory.cxx index 21bf943c9899..8a19e66334fb 100644 --- a/chart2/source/view/main/ShapeFactory.cxx +++ b/chart2/source/view/main/ShapeFactory.cxx @@ -1023,7 +1023,8 @@ uno::Reference< drawing::XShape > , const Stripe& rStripe , const uno::Reference< beans::XPropertySet >& xSourceProp , const tPropertyNameMap& rPropertyNameMap - , sal_Bool bDoubleSided ) + , sal_Bool bDoubleSided + , bool bRotatedTexture ) { if( !xTarget.is() ) return 0; @@ -1047,7 +1048,7 @@ uno::Reference< drawing::XShape > //TexturePolygon xProp->setPropertyValue( C2U( UNO_NAME_3D_TEXTUREPOLYGON3D ) - , rStripe.getTexturePolygon() ); + , rStripe.getTexturePolygon( bRotatedTexture ) ); //Normals Polygon @@ -1573,6 +1574,53 @@ uno::Reference< drawing::XShapes > } uno::Reference< drawing::XShape > + ShapeFactory::createCircle2D( const uno::Reference< drawing::XShapes >& xTarget + , const drawing::Position3D& rPosition + , const drawing::Direction3D& rSize ) +{ + if( !xTarget.is() ) + return 0; + + //create shape + uno::Reference< drawing::XShape > xShape( + m_xShapeFactory->createInstance( C2U( + "com.sun.star.drawing.EllipseShape") ), uno::UNO_QUERY ); + xTarget->add(xShape); + + try + { + drawing::Position3D aCenterPosition( + rPosition.PositionX - (rSize.DirectionX / 2.0), + rPosition.PositionY - (rSize.DirectionY / 2.0), + rPosition.PositionZ ); + xShape->setPosition( Position3DToAWTPoint( aCenterPosition )); + xShape->setSize( Direction3DToAWTSize( rSize )); + } + catch( const uno::Exception & e ) + { + ASSERT_EXCEPTION( e ); + } + + //set properties + uno::Reference< beans::XPropertySet > xProp( xShape, uno::UNO_QUERY ); + DBG_ASSERT(xProp.is(), "created shape offers no XPropertySet"); + if( xProp.is()) + { + try + { + drawing::CircleKind eKind = drawing::CircleKind_FULL; + xProp->setPropertyValue( C2U( UNO_NAME_CIRCKIND ) + , uno::makeAny( eKind ) ); + } + catch( uno::Exception& e ) + { + ASSERT_EXCEPTION( e ); + } + } + return xShape; +} + +uno::Reference< drawing::XShape > ShapeFactory::createLine3D( const uno::Reference< drawing::XShapes >& xTarget , const drawing::PolyPolygonShape3D& rPoints , const VLineProperties& rLineProperties ) diff --git a/chart2/source/view/main/Stripe.cxx b/chart2/source/view/main/Stripe.cxx index 67b2396682aa..cb35e0e010b9 100644 --- a/chart2/source/view/main/Stripe.cxx +++ b/chart2/source/view/main/Stripe.cxx @@ -161,7 +161,7 @@ uno::Any Stripe::getNormalsPolygon() const return uno::Any( &aPP, ::getCppuType((const drawing::PolyPolygonShape3D*)0) ); } -uno::Any Stripe::getTexturePolygon() const +uno::Any Stripe::getTexturePolygon( bool bRotatedTexture ) const { drawing::PolyPolygonShape3D aPP; @@ -181,21 +181,42 @@ uno::Any Stripe::getTexturePolygon() const double* pInnerSequenceY = pOuterSequenceY->getArray(); double* pInnerSequenceZ = pOuterSequenceZ->getArray(); - *pInnerSequenceX++ = 0.0; - *pInnerSequenceY++ = 0.0; - *pInnerSequenceZ++ = 0.0; + if( !bRotatedTexture ) + { + *pInnerSequenceX++ = 0.0; + *pInnerSequenceY++ = 0.0; + *pInnerSequenceZ++ = 0.0; + + *pInnerSequenceX++ = 1.0; + *pInnerSequenceY++ = 0.0; + *pInnerSequenceZ++ = 0.0; - *pInnerSequenceX++ = 1.0; - *pInnerSequenceY++ = 0.0; - *pInnerSequenceZ++ = 0.0; + *pInnerSequenceX++ = 1.0; + *pInnerSequenceY++ = 1.0; + *pInnerSequenceZ++ = 0.0; - *pInnerSequenceX++ = 1.0; - *pInnerSequenceY++ = 1.0; - *pInnerSequenceZ++ = 0.0; + *pInnerSequenceX++ = 0.0; + *pInnerSequenceY++ = 1.0; + *pInnerSequenceZ++ = 0.0; + } + else + { + *pInnerSequenceX++ = 1.0; + *pInnerSequenceY++ = 0.0; + *pInnerSequenceZ++ = 0.0; - *pInnerSequenceX++ = 0.0; - *pInnerSequenceY++ = 1.0; - *pInnerSequenceZ++ = 0.0; + *pInnerSequenceX++ = 1.0; + *pInnerSequenceY++ = 1.0; + *pInnerSequenceZ++ = 0.0; + + *pInnerSequenceX++ = 0.0; + *pInnerSequenceY++ = 1.0; + *pInnerSequenceZ++ = 0.0; + + *pInnerSequenceX++ = 0.0; + *pInnerSequenceY++ = 0.0; + *pInnerSequenceZ++ = 0.0; + } return uno::Any( &aPP, ::getCppuType((const drawing::PolyPolygonShape3D*)0) ); } diff --git a/chart2/source/view/main/VDataSeries.cxx b/chart2/source/view/main/VDataSeries.cxx index f3e8f4a19739..d2456110b79b 100644 --- a/chart2/source/view/main/VDataSeries.cxx +++ b/chart2/source/view/main/VDataSeries.cxx @@ -124,20 +124,35 @@ struct lcl_LessXOfPoint } }; -void lcl_clearIfTextIsContained( VDataSequence& rData, const uno::Reference<data::XDataSequence>& xDataSequence ) +void lcl_clearIfNoValuesButTextIsContained( VDataSequence& rData, const uno::Reference<data::XDataSequence>& xDataSequence ) { + //#i71686#, #i101968#, #i102428# + sal_Int32 nCount = rData.Doubles.getLength(); + for( sal_Int32 i = 0; i < nCount; ++i ) + { + if( !::rtl::math::isNan( rData.Doubles[i] ) ) + return; + } + //no double value is countained + //is there any text? uno::Sequence< rtl::OUString > aStrings( DataSequenceToStringSequence( xDataSequence ) ); - for( sal_Int32 i = 0; i < rData.Doubles.getLength(); ++i ) + sal_Int32 nTextCount = aStrings.getLength(); + for( sal_Int32 j = 0; j < nTextCount; ++j ) { - if( ::rtl::math::isNan( rData.Doubles[i] ) ) + if( aStrings[j].getLength() ) { - if( i < aStrings.getLength() && aStrings[i].getLength() ) - { - rData.clear(); - break; - } + rData.clear(); + return; } } + //no content at all +} + +void lcl_maybeReplaceNanWithZero( double& rfValue, sal_Int32 nMissingValueTreatment ) +{ + if( nMissingValueTreatment == ::com::sun::star::chart::MissingValueTreatment::USE_ZERO + && ::rtl::math::isNan(rfValue) || ::rtl::math::isInf(rfValue) ) + rfValue = 0.0; } } @@ -163,6 +178,8 @@ VDataSeries::VDataSeries( const uno::Reference< XDataSeries >& xDataSeries ) , m_aValues_Y_Max() , m_aValues_Y_First() , m_aValues_Y_Last() + , m_aValues_Bubble_Size() + , m_pValueSequenceForDataLabelNumberFormatDetection(&m_aValues_Y) , m_fYMeanValue(1.0) @@ -193,6 +210,7 @@ VDataSeries::VDataSeries( const uno::Reference< XDataSeries >& xDataSeries ) , m_apSymbolProperties_InvisibleSymbolForSelection(NULL) , m_nCurrentAttributedPoint(-1) , m_nMissingValueTreatment(::com::sun::star::chart::MissingValueTreatment::LEAVE_GAP) + , m_bAllowPercentValueInDataLabel(false) { ::rtl::math::setNan( & m_fYMeanValue ); @@ -218,7 +236,7 @@ VDataSeries::VDataSeries( const uno::Reference< XDataSeries >& xDataSeries ) if( aRole.equals(C2U("values-x")) ) { m_aValues_X.init( xDataSequence ); - lcl_clearIfTextIsContained( m_aValues_X, xDataSequence ); + lcl_clearIfNoValuesButTextIsContained( m_aValues_X, xDataSequence ); } else if( aRole.equals(C2U("values-y")) ) m_aValues_Y.init( xDataSequence ); @@ -230,7 +248,8 @@ VDataSeries::VDataSeries( const uno::Reference< XDataSeries >& xDataSeries ) m_aValues_Y_First.init( xDataSequence ); else if( aRole.equals(C2U("values-last")) ) m_aValues_Y_Last.init( xDataSequence ); - //@todo assign the other roles (+ error for unknown?) + else if( aRole.equals(C2U("values-size")) ) + m_aValues_Bubble_Size.init( xDataSequence ); } catch( uno::Exception& e ) { @@ -242,13 +261,15 @@ VDataSeries::VDataSeries( const uno::Reference< XDataSeries >& xDataSeries ) //determine the point count m_nPointCount = m_aValues_Y.getLength(); { + if( m_nPointCount < m_aValues_Bubble_Size.getLength() ) + m_nPointCount = m_aValues_Bubble_Size.getLength(); if( m_nPointCount < m_aValues_Y_Min.getLength() ) m_nPointCount = m_aValues_Y_Min.getLength(); - if( m_nPointCount < m_aValues_Y_Max.getLength() ) + if( m_nPointCount < m_aValues_Y_Max.getLength() ) m_nPointCount = m_aValues_Y_Max.getLength(); - if( m_nPointCount < m_aValues_Y_First.getLength() ) + if( m_nPointCount < m_aValues_Y_First.getLength() ) m_nPointCount = m_aValues_Y_First.getLength(); - if( m_nPointCount < m_aValues_Y_Last.getLength() ) + if( m_nPointCount < m_aValues_Y_Last.getLength() ) m_nPointCount = m_aValues_Y_Last.getLength(); } @@ -331,6 +352,7 @@ void VDataSeries::releaseShapes() void VDataSeries::setCategoryXAxis() { m_aValues_X.clear(); + m_bAllowPercentValueInDataLabel = true; } void VDataSeries::setGlobalSeriesIndex( sal_Int32 nGlobalSeriesIndex ) @@ -445,27 +467,48 @@ sal_Int32 VDataSeries::getTotalPointCount() const return m_nPointCount; } -double VDataSeries::getX( sal_Int32 index ) const +double VDataSeries::getXValue( sal_Int32 index ) const { + double fRet = 0.0; if(m_aValues_X.is()) { if( 0<=index && index<m_aValues_X.getLength() ) - return m_aValues_X.Doubles[index]; + fRet = m_aValues_X.Doubles[index]; + else + ::rtl::math::setNan( &fRet ); } else { // #i70133# always return correct X position - needed for short data series if( 0<=index /*&& index < m_nPointCount*/ ) - return index+1;//first category (index 0) matches with real number 1.0 + fRet = index+1;//first category (index 0) matches with real number 1.0 + else + ::rtl::math::setNan( &fRet ); } - double fNan; - ::rtl::math::setNan( & fNan ); - return fNan; + lcl_maybeReplaceNanWithZero( fRet, getMissingValueTreatment() ); + return fRet; } -double VDataSeries::getY( sal_Int32 index ) const +double VDataSeries::getYValue( sal_Int32 index ) const { - return m_aValues_Y.getValue( index ); + double fRet = 0.0; + if(m_aValues_Y.is()) + { + if( 0<=index && index<m_aValues_Y.getLength() ) + fRet = m_aValues_Y.Doubles[index]; + else + ::rtl::math::setNan( &fRet ); + } + else + { + // #i70133# always return correct X position - needed for short data series + if( 0<=index /*&& index < m_nPointCount*/ ) + fRet = index+1;//first category (index 0) matches with real number 1.0 + else + ::rtl::math::setNan( &fRet ); + } + lcl_maybeReplaceNanWithZero( fRet, getMissingValueTreatment() ); + return fRet; } double VDataSeries::getY_Min( sal_Int32 index ) const @@ -484,6 +527,10 @@ double VDataSeries::getY_Last( sal_Int32 index ) const { return m_aValues_Y_Last.getValue( index ); } +double VDataSeries::getBubble_Size( sal_Int32 index ) const +{ + return m_aValues_Bubble_Size.getValue( index ); +} bool VDataSeries::hasExplicitNumberFormat( sal_Int32 nPointIndex, bool bForPercentage ) const { @@ -504,9 +551,37 @@ sal_Int32 VDataSeries::getExplicitNumberFormat( sal_Int32 nPointIndex, bool bFor xPointProp->getPropertyValue(aPropName) >>= nNumberFormat; return nNumberFormat; } +void VDataSeries::setRoleOfSequenceForDataLabelNumberFormatDetection( const rtl::OUString& rRole ) +{ + if( rRole.equals(C2U("values-y")) ) + m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y; + else if( rRole.equals(C2U("values-size")) ) + m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Bubble_Size; + else if( rRole.equals(C2U("values-min")) ) + m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_Min; + else if( rRole.equals(C2U("values-max")) ) + m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_Max; + else if( rRole.equals(C2U("values-first")) ) + m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_First; + else if( rRole.equals(C2U("values-last")) ) + m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_Y_Last; + else if( rRole.equals(C2U("values-x")) ) + m_pValueSequenceForDataLabelNumberFormatDetection = &m_aValues_X; +} +bool VDataSeries::shouldLabelNumberFormatKeyBeDetectedFromYAxis() const +{ + if( m_pValueSequenceForDataLabelNumberFormatDetection == &m_aValues_Bubble_Size ) + return false; + else if( m_pValueSequenceForDataLabelNumberFormatDetection == &m_aValues_X ) + return false; + return true; +} sal_Int32 VDataSeries::detectNumberFormatKey( sal_Int32 index ) const { - return m_aValues_Y.detectNumberFormatKey( index ); + sal_Int32 nRet = 0; + if( m_pValueSequenceForDataLabelNumberFormatDetection ) + nRet = m_pValueSequenceForDataLabelNumberFormatDetection->detectNumberFormatKey( index ); + return nRet; } sal_Int32 VDataSeries::getLabelPlacement( sal_Int32 nPointIndex, const uno::Reference< chart2::XChartType >& xChartType, sal_Int32 nDimensionCount, sal_Bool bSwapXAndY ) const @@ -545,7 +620,7 @@ sal_Int32 VDataSeries::getLabelPlacement( sal_Int32 nPointIndex, const uno::Refe double VDataSeries::getMinimumofAllDifferentYValues( sal_Int32 index ) const { - double fY = getY( index ); + double fY = getYValue( index ); double fY_Min = getY_Min( index ); double fY_Max = getY_Max( index ); double fY_First = getY_First( index ); @@ -572,7 +647,7 @@ double VDataSeries::getMinimumofAllDifferentYValues( sal_Int32 index ) const double VDataSeries::getMaximumofAllDifferentYValues( sal_Int32 index ) const { - double fY = getY( index ); + double fY = getYValue( index ); double fY_Min = getY_Min( index ); double fY_Max = getY_Max( index ); double fY_First = getY_First( index ); @@ -612,6 +687,14 @@ uno::Sequence< double > VDataSeries::getAllX() const uno::Sequence< double > VDataSeries::getAllY() const { + if(!m_aValues_Y.is() && !m_aValues_Y.getLength() && m_nPointCount) + { + //init y values from indexes + //first y-value (index 0) matches with real number 1.0 + m_aValues_Y.Doubles.realloc( m_nPointCount ); + for(sal_Int32 nN=m_aValues_Y.getLength();nN--;) + m_aValues_Y.Doubles[nN] = nN+1; + } return m_aValues_Y.Doubles; } @@ -806,6 +889,11 @@ DataPointLabel* VDataSeries::getDataPointLabel( sal_Int32 index ) const m_apLabel_Series = getDataPointLabelFromPropertySet( this->getPropertiesOfPoint( index ) ); pRet = m_apLabel_Series.get(); } + if( !m_bAllowPercentValueInDataLabel ) + { + if( pRet ) + pRet->ShowNumberInPercent = false; + } return pRet; } diff --git a/sc/inc/address.hxx b/sc/inc/address.hxx index 7ba5aa9c1f32..f1859be15fcf 100644 --- a/sc/inc/address.hxx +++ b/sc/inc/address.hxx @@ -791,12 +791,14 @@ template< typename T > void PutInOrder( T& nStart, T& nEnd ) bool ConvertSingleRef( ScDocument* pDoc, const String& rRefString, SCTAB nDefTab, ScRefAddress& rRefAddress, - const ScAddress::Details& rDetails = ScAddress::detailsOOOa1); + const ScAddress::Details& rDetails = ScAddress::detailsOOOa1, + ScAddress::ExternalInfo* pExtInfo = NULL ); bool ConvertDoubleRef(ScDocument* pDoc, const String& rRefString, SCTAB nDefTab, ScRefAddress& rStartRefAddress, ScRefAddress& rEndRefAddress, - const ScAddress::Details& rDetails = ScAddress::detailsOOOa1); + const ScAddress::Details& rDetails = ScAddress::detailsOOOa1, + ScAddress::ExternalInfo* pExtInfo = NULL ); /// append alpha representation of column to buffer SC_DLLPUBLIC void ScColToAlpha( rtl::OUStringBuffer& rBuffer, SCCOL nCol); diff --git a/sc/inc/cell.hxx b/sc/inc/cell.hxx index 2d4bba295547..10de035abf7c 100644 --- a/sc/inc/cell.hxx +++ b/sc/inc/cell.hxx @@ -102,7 +102,7 @@ public: /** Returns a clone of this cell, clones cell note and caption object too (unless SC_CLONECELL_NOCAPTION flag is set). Broadcaster will not be cloned. */ - ScBaseCell* CloneWithNote( ScDocument& rDestDoc, const ScAddress& rDestPos, int nCloneFlags = SC_CLONECELL_DEFAULT ) const; + ScBaseCell* CloneWithNote( const ScAddress& rOwnPos, ScDocument& rDestDoc, const ScAddress& rDestPos, int nCloneFlags = SC_CLONECELL_DEFAULT ) const; /** Due to the fact that ScBaseCell does not have a vtable, this function deletes the cell by calling the appropriate d'tor of the derived class. */ @@ -387,13 +387,23 @@ public: inline USHORT GetSeenInIteration() const { return nSeenInIteration; } BOOL HasOneReference( ScRange& r ) const; + /* Checks if the formula contains reference list that can be + expressed by one reference (like A1;A2;A3:A5 -> A1:A5). The + reference list is not required to be sorted (i.e. A3;A1;A2 is + still recognized as A1:A3), but no overlapping is allowed. + If one reference is recognized, the rRange is filled. + + It is similar to HasOneReference(), but more general. + */ + bool HasRefListExpressibleAsOneReference(ScRange& rRange) const; BOOL HasRelNameReference() const; BOOL HasColRowName() const; void UpdateReference(UpdateRefMode eUpdateRefMode, const ScRange& r, SCsCOL nDx, SCsROW nDy, SCsTAB nDz, - ScDocument* pUndoDoc = NULL ); + ScDocument* pUndoDoc = NULL, + const ScAddress* pUndoCellPos = NULL ); void TransposeReference(); void UpdateTranspose( const ScRange& rSource, const ScAddress& rDest, diff --git a/sc/inc/cellsuno.hxx b/sc/inc/cellsuno.hxx index e73869489ebc..2dd0bd6cc16e 100644 --- a/sc/inc/cellsuno.hxx +++ b/sc/inc/cellsuno.hxx @@ -629,9 +629,10 @@ protected: throw(::com::sun::star::lang::IndexOutOfBoundsException, ::com::sun::star::uno::RuntimeException); - void SetArrayFormula_Impl( const rtl::OUString& aFormula, - const formula::FormulaGrammar::Grammar eGrammar ) - throw(::com::sun::star::uno::RuntimeException); + void SetArrayFormula_Impl( const rtl::OUString& rFormula, + const rtl::OUString& rFormulaNmsp, + const formula::FormulaGrammar::Grammar eGrammar ) + throw(::com::sun::star::uno::RuntimeException); public: ScCellRangeObj(ScDocShell* pDocSh, const ScRange& rR); @@ -650,7 +651,8 @@ public: virtual void RefChanged(); // via getImplementation() - virtual void SetArrayFormulaWithGrammar( const ::rtl::OUString& aFormula, + virtual void SetArrayFormulaWithGrammar( const ::rtl::OUString& rFormula, + const ::rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar ) throw(::com::sun::star::uno::RuntimeException); @@ -869,7 +871,7 @@ public: void SetFormulaResultString( const ::rtl::OUString& rResult ); void SetFormulaResultDouble( double fResult ); void SetFormulaWithGrammar( const ::rtl::OUString& rFormula, - const formula::FormulaGrammar::Grammar ); + const ::rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar ); const ScAddress& GetPosition() const { return aCellPos; } // XText diff --git a/sc/inc/compiler.hxx b/sc/inc/compiler.hxx index c026e0cb5cf9..76293479660c 100644 --- a/sc/inc/compiler.hxx +++ b/sc/inc/compiler.hxx @@ -311,9 +311,11 @@ private: const CharClass* pCharClass; // which character classification is used for parseAnyToken USHORT mnPredetectedReference; // reference when reading ODF, 0 (none), 1 (single) or 2 (double) SCsTAB nMaxTab; // last sheet in document + sal_Int32 mnRangeOpPosInSymbol; // if and where a range operator is in symbol const Convention *pConv; bool mbCloseBrackets; // whether to close open brackets automatically, default TRUE bool mbExtendedErrorDetection; + bool mbRewind; // whether symbol is to be rewound to some step during lexical analysis BOOL NextNewToken(bool bInArray = false); @@ -352,14 +354,14 @@ public: const formula::FormulaGrammar::AddressConvention eConv = formula::FormulaGrammar::CONV_OOO ); static BOOL EnQuote( String& rStr ); + sal_Unicode GetNativeAddressSymbol( Convention::SpecialSymbolType eType ) const; // Check if it is a valid english function name bool IsEnglishSymbol( const String& rName ); //! _either_ CompileForFAP _or_ AutoCorrection, _not_ both - void SetCompileForFAP( BOOL bVal ) - { bCompileForFAP = bVal; bIgnoreErrors = bVal; } + // #i101512# SetCompileForFAP is in formula::FormulaCompiler void SetAutoCorrection( BOOL bVal ) { bAutoCorrect = bVal; bIgnoreErrors = bVal; } void SetCloseBrackets( bool bVal ) { mbCloseBrackets = bVal; } @@ -394,6 +396,8 @@ public: maExternalLinks = rLinks; } + void CreateStringFromXMLTokenArray( String& rFormula, String& rFormulaNmsp ); + void SetExtendedErrorDetection( bool bVal ) { mbExtendedErrorDetection = bVal; } BOOL IsCorrected() { return bCorrected; } @@ -401,12 +405,13 @@ public: // Use convention from this->aPos by default ScTokenArray* CompileString( const String& rFormula ); + ScTokenArray* CompileString( const String& rFormula, const String& rFormulaNmsp ); const ScDocument* GetDoc() const { return pDoc; } const ScAddress& GetPos() const { return aPos; } - void MoveRelWrap(); - static void MoveRelWrap( ScTokenArray& rArr, ScDocument* pDoc, - const ScAddress& rPos ); + void MoveRelWrap( SCCOL nMaxCol, SCROW nMaxRow ); + static void MoveRelWrap( ScTokenArray& rArr, ScDocument* pDoc, const ScAddress& rPos, + SCCOL nMaxCol, SCROW nMaxRow ); BOOL UpdateNameReference( UpdateRefMode eUpdateRefMode, const ScRange&, diff --git a/sc/inc/conditio.hxx b/sc/inc/conditio.hxx index 42a030b8e809..edb0f9371788 100644 --- a/sc/inc/conditio.hxx +++ b/sc/inc/conditio.hxx @@ -84,7 +84,10 @@ class SC_DLLPUBLIC ScConditionEntry double nVal2; String aStrVal1; // eingegeben oder berechnet String aStrVal2; - formula::FormulaGrammar::Grammar eTempGrammar; // grammar to be used on (re)compilation, e.g. in XML import + String aStrNmsp1; // namespace to be used on (re)compilation, e.g. in XML import + String aStrNmsp2; // namespace to be used on (re)compilation, e.g. in XML import + formula::FormulaGrammar::Grammar eTempGrammar1; // grammar to be used on (re)compilation, e.g. in XML import + formula::FormulaGrammar::Grammar eTempGrammar2; // grammar to be used on (re)compilation, e.g. in XML import BOOL bIsStr1; // um auch leere Strings zu erkennen BOOL bIsStr2; ScTokenArray* pFormula1; // eingegebene Formel @@ -101,7 +104,10 @@ class SC_DLLPUBLIC ScConditionEntry void MakeCells( const ScAddress& rPos ); void Compile( const String& rExpr1, const String& rExpr2, - const formula::FormulaGrammar::Grammar eGrammar, BOOL bTextToReal ); + const String& rExprNmsp1, const String& rExprNmsp2, + formula::FormulaGrammar::Grammar eGrammar1, + formula::FormulaGrammar::Grammar eGrammar2, + BOOL bTextToReal ); void Interpret( const ScAddress& rPos ); BOOL IsValid( double nArg ) const; @@ -111,7 +117,9 @@ public: ScConditionEntry( ScConditionMode eOper, const String& rExpr1, const String& rExpr2, ScDocument* pDocument, const ScAddress& rPos, - const formula::FormulaGrammar::Grammar eGrammar ); + const String& rExprNmsp1, const String& rExprNmsp2, + formula::FormulaGrammar::Grammar eGrammar1, + formula::FormulaGrammar::Grammar eGrammar2 ); ScConditionEntry( ScConditionMode eOper, const ScTokenArray* pArr1, const ScTokenArray* pArr2, ScDocument* pDocument, const ScAddress& rPos ); @@ -174,7 +182,10 @@ public: const String& rExpr1, const String& rExpr2, ScDocument* pDocument, const ScAddress& rPos, const String& rStyle, - const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT ); + const String& rExprNmsp1 = EMPTY_STRING, + const String& rExprNmsp2 = EMPTY_STRING, + formula::FormulaGrammar::Grammar eGrammar1 = formula::FormulaGrammar::GRAM_DEFAULT, + formula::FormulaGrammar::Grammar eGrammar2 = formula::FormulaGrammar::GRAM_DEFAULT ); ScCondFormatEntry( ScConditionMode eOper, const ScTokenArray* pArr1, const ScTokenArray* pArr2, ScDocument* pDocument, const ScAddress& rPos, diff --git a/sc/inc/datauno.hxx b/sc/inc/datauno.hxx index 405d49e2a6b2..a93bfc341573 100644 --- a/sc/inc/datauno.hxx +++ b/sc/inc/datauno.hxx @@ -50,6 +50,7 @@ #include <com/sun/star/lang/XUnoTunnel.hpp> #include <com/sun/star/container/XNamed.hpp> #include <com/sun/star/util/XRefreshable.hpp> +#include <com/sun/star/sheet/XSheetFilterDescriptor2.hpp> #include <cppuhelper/implbase2.hxx> #include <cppuhelper/implbase3.hxx> #include <cppuhelper/implbase4.hxx> @@ -340,8 +341,9 @@ public: // to uno, all three look the same -class ScFilterDescriptorBase : public cppu::WeakImplHelper3< +class ScFilterDescriptorBase : public cppu::WeakImplHelper4< com::sun::star::sheet::XSheetFilterDescriptor, + com::sun::star::sheet::XSheetFilterDescriptor2, com::sun::star::beans::XPropertySet, com::sun::star::lang::XServiceInfo >, public SfxListener @@ -368,6 +370,13 @@ public: ::com::sun::star::sheet::TableFilterField >& aFilterFields ) throw(::com::sun::star::uno::RuntimeException); + // XSheetFilterDescriptor2 + virtual ::com::sun::star::uno::Sequence< ::com::sun::star::sheet::TableFilterField2 > SAL_CALL + getFilterFields2() throw(::com::sun::star::uno::RuntimeException); + virtual void SAL_CALL setFilterFields2( const ::com::sun::star::uno::Sequence< + ::com::sun::star::sheet::TableFilterField2 >& aFilterFields ) + throw(::com::sun::star::uno::RuntimeException); + // XPropertySet virtual ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySetInfo > SAL_CALL getPropertySetInfo() diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 66f52fa5c2a8..c8d3751a7aaf 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -90,6 +90,7 @@ class ScDBData; class ScDetOpData; class ScDetOpList; class ScDocOptions; +class ScDocProtection; class ScDocumentPool; class ScDrawLayer; class ScExtDocOptions; @@ -108,6 +109,7 @@ class ScRangeName; class ScStyleSheet; class ScStyleSheetPool; class ScTable; +class ScTableProtection; class ScTokenArray; class ScValidationData; class ScValidationDataList; @@ -137,6 +139,7 @@ class ScTemporaryChartLock; class ScLookupCache; struct ScLookupCacheMapImpl; class SfxUndoManager; +class ScFormulaParserPool; namespace com { namespace sun { namespace star { namespace lang { @@ -286,9 +289,14 @@ private: ScFieldEditEngine* pCacheFieldEditEngine; - com::sun::star::uno::Sequence<sal_Int8> aProtectPass; + ::std::auto_ptr<ScDocProtection> pDocProtection; ::std::auto_ptr<ScExternalRefManager> pExternalRefMgr; + + // mutable for lazy construction + mutable ::std::auto_ptr< ScFormulaParserPool > + mxFormulaParserPool; /// Pool for all external formula parsers used by this document. + String aDocName; // opt: Dokumentname ScRangePairListRef xColNameRanges; ScRangePairListRef xRowNameRanges; @@ -350,7 +358,6 @@ private: ScLkUpdMode eLinkMode; - BOOL bProtected; BOOL bAutoCalc; // Automatisch Berechnen BOOL bAutoCalcShellDisabled; // in/von/fuer ScDocShell disabled // ob noch ForcedFormulas berechnet werden muessen, @@ -530,13 +537,14 @@ public: SC_DLLPUBLIC inline SCTAB GetTableCount() const { return nMaxTableNumber; } SvNumberFormatterIndexTable* GetFormatExchangeList() const { return pFormatExchangeList; } - SC_DLLPUBLIC void SetDocProtection( BOOL bProtect, const com::sun::star::uno::Sequence <sal_Int8>& aPass ); - SC_DLLPUBLIC void SetTabProtection( SCTAB nTab, BOOL bProtect, const com::sun::star::uno::Sequence <sal_Int8>& aPass ); + SC_DLLPUBLIC ScDocProtection* GetDocProtection() const; + SC_DLLPUBLIC void SetDocProtection(const ScDocProtection* pProtect); SC_DLLPUBLIC BOOL IsDocProtected() const; BOOL IsDocEditable() const; SC_DLLPUBLIC BOOL IsTabProtected( SCTAB nTab ) const; - const com::sun::star::uno::Sequence <sal_Int8>& GetDocPassword() const; - const com::sun::star::uno::Sequence <sal_Int8>& GetTabPassword( SCTAB nTab ) const; + SC_DLLPUBLIC ScTableProtection* GetTabProtection( SCTAB nTab ) const; + SC_DLLPUBLIC void SetTabProtection(SCTAB nTab, const ScTableProtection* pProtect); + void CopyTabProtection(SCTAB nTabSrc, SCTAB nTabDest); void LockTable(SCTAB nTab); void UnlockTable(SCTAB nTab); @@ -578,6 +586,8 @@ public: SC_DLLPUBLIC void TransferDrawPage(ScDocument* pSrcDoc, SCTAB nSrcPos, SCTAB nDestPos); SC_DLLPUBLIC void SetVisible( SCTAB nTab, BOOL bVisible ); SC_DLLPUBLIC BOOL IsVisible( SCTAB nTab ) const; + BOOL IsPendingRowHeights( SCTAB nTab ) const; + void SetPendingRowHeights( SCTAB nTab, BOOL bSet ); SC_DLLPUBLIC void SetLayoutRTL( SCTAB nTab, BOOL bRTL ); SC_DLLPUBLIC BOOL IsLayoutRTL( SCTAB nTab ) const; BOOL IsNegativePage( SCTAB nTab ) const; @@ -591,7 +601,7 @@ public: SC_DLLPUBLIC BOOL IsActiveScenario( SCTAB nTab ) const; SC_DLLPUBLIC void SetActiveScenario( SCTAB nTab, BOOL bActive ); // nur fuer Undo etc. SC_DLLPUBLIC formula::FormulaGrammar::AddressConvention GetAddressConvention() const; - formula::FormulaGrammar::Grammar GetGrammar() const; + SC_DLLPUBLIC formula::FormulaGrammar::Grammar GetGrammar() const; void SetGrammar( formula::FormulaGrammar::Grammar eGram ); SC_DLLPUBLIC BYTE GetLinkMode( SCTAB nTab ) const; BOOL IsLinked( SCTAB nTab ) const; @@ -615,6 +625,10 @@ public: void MarkUsedExternalReferences(); bool MarkUsedExternalReferences( ScTokenArray & rArr ); + /** Returns the pool containing external formula parsers. Creates the pool + on first call. */ + ScFormulaParserPool& GetFormulaParserPool() const; + BOOL HasDdeLinks() const; BOOL HasAreaLinks() const; void UpdateExternalRefLinks(); @@ -772,6 +786,12 @@ public: SC_DLLPUBLIC ScPostIt* GetOrCreateNote( const ScAddress& rPos ); /** Deletes the note at the passed cell address. */ void DeleteNote( const ScAddress& rPos ); + /** Creates the captions of all uninitialized cell notes in the specified sheet. + @param bForced True = always create all captions, false = skip when Undo is disabled. */ + void InitializeNoteCaptions( SCTAB nTab, bool bForced = false ); + /** Creates the captions of all uninitialized cell notes in all sheets. + @param bForced True = always create all captions, false = skip when Undo is disabled. */ + void InitializeAllNoteCaptions( bool bForced = false ); BOOL ExtendMergeSel( SCCOL nStartCol, SCROW nStartRow, SCCOL& rEndCol, SCROW& rEndRow, const ScMarkData& rMark, @@ -889,22 +909,26 @@ public: BOOL InsertRow( SCCOL nStartCol, SCTAB nStartTab, SCCOL nEndCol, SCTAB nEndTab, - SCROW nStartRow, SCSIZE nSize, ScDocument* pRefUndoDoc = NULL ); + SCROW nStartRow, SCSIZE nSize, ScDocument* pRefUndoDoc = NULL, + const ScMarkData* pTabMark = NULL ); SC_DLLPUBLIC BOOL InsertRow( const ScRange& rRange, ScDocument* pRefUndoDoc = NULL ); void DeleteRow( SCCOL nStartCol, SCTAB nStartTab, SCCOL nEndCol, SCTAB nEndTab, SCROW nStartRow, SCSIZE nSize, - ScDocument* pRefUndoDoc = NULL, BOOL* pUndoOutline = NULL ); + ScDocument* pRefUndoDoc = NULL, BOOL* pUndoOutline = NULL, + const ScMarkData* pTabMark = NULL ); void DeleteRow( const ScRange& rRange, ScDocument* pRefUndoDoc = NULL, BOOL* pUndoOutline = NULL ); BOOL InsertCol( SCROW nStartRow, SCTAB nStartTab, SCROW nEndRow, SCTAB nEndTab, - SCCOL nStartCol, SCSIZE nSize, ScDocument* pRefUndoDoc = NULL ); + SCCOL nStartCol, SCSIZE nSize, ScDocument* pRefUndoDoc = NULL, + const ScMarkData* pTabMark = NULL ); SC_DLLPUBLIC BOOL InsertCol( const ScRange& rRange, ScDocument* pRefUndoDoc = NULL ); void DeleteCol( SCROW nStartRow, SCTAB nStartTab, SCROW nEndRow, SCTAB nEndTab, SCCOL nStartCol, SCSIZE nSize, - ScDocument* pRefUndoDoc = NULL, BOOL* pUndoOutline = NULL ); + ScDocument* pRefUndoDoc = NULL, BOOL* pUndoOutline = NULL, + const ScMarkData* pTabMark = NULL ); void DeleteCol( const ScRange& rRange, ScDocument* pRefUndoDoc = NULL, BOOL* pUndoOutline = NULL ); @@ -1234,7 +1258,8 @@ public: BOOL bShrink ); void UpdateAllRowHeights( OutputDevice* pDev, double nPPTX, double nPPTY, - const Fraction& rZoomX, const Fraction& rZoomY ); + const Fraction& rZoomX, const Fraction& rZoomY, + const ScMarkData* pTabMark = NULL ); long GetNeededSize( SCCOL nCol, SCROW nRow, SCTAB nTab, OutputDevice* pDev, double nPPTX, double nPPTY, @@ -1471,7 +1496,8 @@ public: private: -//UNUSED2008-05 void SetAutoFilterFlags(); + ScDocument(const ScDocument& r); // disabled with no definition + void FindMaxRotCol( SCTAB nTab, RowInfo* pRowInfo, SCSIZE nArrCount, SCCOL nX1, SCCOL nX2 ) const; diff --git a/sc/inc/docuno.hxx b/sc/inc/docuno.hxx index 3f960e446611..defe627dd812 100644 --- a/sc/inc/docuno.hxx +++ b/sc/inc/docuno.hxx @@ -125,7 +125,7 @@ public: ScDocument* GetDocument() const; SfxObjectShell* GetEmbeddedObject() const; - void UpdateAllRowHeights(); + void UpdateAllRowHeights( const ScMarkData* pTabMark = NULL ); ScDrawLayer* MakeDrawLayer(); void BeforeXMLLoading(); diff --git a/sc/inc/dpobject.hxx b/sc/inc/dpobject.hxx index 5f3dfe9eb489..cffe735f287a 100644 --- a/sc/inc/dpobject.hxx +++ b/sc/inc/dpobject.hxx @@ -126,7 +126,8 @@ public: void InvalidateData(); void InvalidateSource(); - void Output(); + + void Output( const ScAddress& rPos ); ScRange GetNewOutputRange( BOOL& rOverflow ); const ScRange GetOutputRangeByType( sal_Int32 nType ); diff --git a/sc/inc/drwlayer.hxx b/sc/inc/drwlayer.hxx index cf1c151fa05d..a0492d82a2f3 100644 --- a/sc/inc/drwlayer.hxx +++ b/sc/inc/drwlayer.hxx @@ -115,11 +115,7 @@ private: void MoveCells( SCTAB nTab, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SCROW nRow2, SCsCOL nDx,SCsROW nDy ); - void RecalcPos( SdrObject* pObj, - const ScDrawObjData& rData, - const ScAddress& rOldStart, - const ScAddress& rOldEnd, - bool bNegativePage ); + void RecalcPos( SdrObject* pObj, const ScDrawObjData& rData, bool bNegativePage ); public: ScDrawLayer( ScDocument* pDocument, const String& rName ); diff --git a/sc/inc/externalrefmgr.hxx b/sc/inc/externalrefmgr.hxx index 07c8a6a6697f..9b12dba52f1f 100644 --- a/sc/inc/externalrefmgr.hxx +++ b/sc/inc/externalrefmgr.hxx @@ -132,15 +132,27 @@ public: class Table { public: + + enum ReferencedFlag + { + UNREFERENCED, + REFERENCED_MARKED, // marked as referenced during store to file + REFERENCED_PERMANENT // permanently marked, e.g. from within interpreter + }; + Table(); ~Table(); SC_DLLPUBLIC void setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex = 0); TokenRef getCell(SCCOL nCol, SCROW nRow, sal_uInt32* pnFmtIndex = NULL) const; bool hasRow( SCROW nRow ) const; - /// A temporary state used only during store to file. - bool isReferenced() const; + /** Set/clear referenced status flag only if current status is not + REFERENCED_PERMANENT. */ void setReferenced( bool bReferenced ); + /// Unconditionally set the reference status flag. + void setReferencedFlag( ReferencedFlag eFlag ); + ReferencedFlag getReferencedFlag() const; + bool isReferenced() const; /// Obtain a sorted vector of rows. void getAllRows(::std::vector<SCROW>& rRows) const; /// Obtain a sorted vector of columns. @@ -148,8 +160,8 @@ public: void getAllNumberFormats(::std::vector<sal_uInt32>& rNumFmts) const; private: - RowsDataType maRows; - bool mbReferenced; + RowsDataType maRows; + ReferencedFlag meReferenced; }; typedef ::boost::shared_ptr<Table> TableTypeRef; @@ -219,9 +231,16 @@ public: * Set a table as referenced, used only during store-to-file. * @returns <TRUE/> if ALL tables of ALL documents are marked. */ - bool setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName ); + bool setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets, bool bPermanent ); void setAllCacheTableReferencedStati( bool bReferenced ); bool areAllCacheTablesReferenced() const; + + /** + * Set a table as permanently referenced, to be called if not in + * mark-during-store-to-file cycle. + */ + void setCacheTableReferencedPermanently( sal_uInt16 nFileId, const String& rTabName, size_t nSheets ); + private: struct ReferencedStatus { @@ -497,10 +516,16 @@ public: * Set a table as referenced, used only during store-to-file. * @returns <TRUE/> if ALL tables of ALL external documents are marked. */ - bool setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName ); + bool setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets ); void setAllCacheTableReferencedStati( bool bReferenced ); /** + * Set a table as permanently referenced, to be called if not in + * mark-during-store-to-file cycle. + */ + void setCacheTableReferencedPermanently( sal_uInt16 nFileId, const String& rTabName, size_t nSheets ); + + /** * @returns <TRUE/> if setAllCacheTableReferencedStati(false) was called, * <FALSE/> if setAllCacheTableReferencedStati(true) was called. */ diff --git a/sc/inc/fmtuno.hxx b/sc/inc/fmtuno.hxx index ba4e02041faa..6005a849fb0f 100644 --- a/sc/inc/fmtuno.hxx +++ b/sc/inc/fmtuno.hxx @@ -32,7 +32,8 @@ #define SC_FMTUNO_HXX #include "address.hxx" -#include "formula/grammar.hxx" +#include "conditio.hxx" +#include <formula/grammar.hxx> #include <tools/list.hxx> #include <svtools/itemprop.hxx> #include <com/sun/star/sheet/XSheetConditionalEntries.hpp> @@ -61,16 +62,19 @@ struct ScCondFormatEntryItem { ::com::sun::star::uno::Sequence< ::com::sun::star::sheet::FormulaToken > maTokens1; ::com::sun::star::uno::Sequence< ::com::sun::star::sheet::FormulaToken > maTokens2; - String maExpr1; - String maExpr2; - String maPosStr; // formula position as text - String maStyle; // display name as stored in ScStyleSheet - ScAddress maPos; - formula::FormulaGrammar::Grammar meGrammar; // grammar used with maExpr1 and maExpr2 - USHORT mnMode; // stores enum ScConditionMode + String maExpr1; + String maExpr2; + String maExprNmsp1; + String maExprNmsp2; + String maPosStr; // formula position as text + String maStyle; // display name as stored in ScStyleSheet + ScAddress maPos; + formula::FormulaGrammar::Grammar meGrammar1; // grammar used with maExpr1 + formula::FormulaGrammar::Grammar meGrammar2; // grammar used with maExpr2 + ScConditionMode meMode; // Make sure the grammar is initialized for API calls. - ScCondFormatEntryItem() : meGrammar( formula::FormulaGrammar::GRAM_UNSPECIFIED ) {} + ScCondFormatEntryItem(); }; class ScTableConditionalFormat : public cppu::WeakImplHelper5< @@ -89,11 +93,11 @@ private: ScTableConditionalFormat(); // disable public: ScTableConditionalFormat(ScDocument* pDoc, ULONG nKey, - const formula::FormulaGrammar::Grammar eGrammar); + formula::FormulaGrammar::Grammar eGrammar); virtual ~ScTableConditionalFormat(); - void FillFormat( ScConditionalFormat& rFormat, - ScDocument* pDoc, formula::FormulaGrammar::Grammar eGrammar ) const; + void FillFormat( ScConditionalFormat& rFormat, ScDocument* pDoc, + formula::FormulaGrammar::Grammar eGrammar) const; void DataChanged(); // XSheetConditionalEntries @@ -211,7 +215,10 @@ private: USHORT nMode; // enum ScConditionMode String aExpr1; String aExpr2; - formula::FormulaGrammar::Grammar meGrammar; // grammar used with aExpr1 and aExpr2 + String maExprNmsp1; + String maExprNmsp2; + formula::FormulaGrammar::Grammar meGrammar1; // grammar used with aExpr1 and aExpr2 + formula::FormulaGrammar::Grammar meGrammar2; // grammar used with aExpr1 and aExpr2 ::com::sun::star::uno::Sequence< ::com::sun::star::sheet::FormulaToken > aTokens1; ::com::sun::star::uno::Sequence< ::com::sun::star::sheet::FormulaToken > aTokens2; ScAddress aSrcPos; diff --git a/sc/inc/formulaparserpool.hxx b/sc/inc/formulaparserpool.hxx new file mode 100644 index 000000000000..af6b0ed3ebf1 --- /dev/null +++ b/sc/inc/formulaparserpool.hxx @@ -0,0 +1,70 @@ +/************************************************************************* + * + * 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: formulaparserpool.hxx,v $ + * $Revision: 1.1 $ + * + * 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_FORMULAPARSERPOOL_HXX +#define SC_FORMULAPARSERPOOL_HXX + +#include <hash_map> +#include <com/sun/star/sheet/XFormulaParser.hpp> + +class ScDocument; + +// ============================================================================ + +/** Stores the used instances of the FilterFormulaParser service + implementations, mapped by the formula namespace they support. */ +class ScFormulaParserPool +{ +public: + explicit ScFormulaParserPool( const ScDocument& rDoc ); + ~ScFormulaParserPool(); + + /** Returns true, if a formula parser is registered for the passed namespace. */ + bool hasFormulaParser( const ::rtl::OUString& rNamespace ); + + /** Returns the formula parser that is registered for the passed namespace. */ + ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XFormulaParser > + getFormulaParser( const ::rtl::OUString& rNamespace ); + +private: + typedef ::std::hash_map< + ::rtl::OUString, + ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XFormulaParser >, + ::rtl::OUStringHash, + ::std::equal_to< ::rtl::OUString > > ParserMap; + + const ScDocument& mrDoc; + ParserMap maParsers; +}; + +// ============================================================================ + +#endif + diff --git a/sc/inc/global.hxx b/sc/inc/global.hxx index 45df07deaf6c..e329f477d824 100644 --- a/sc/inc/global.hxx +++ b/sc/inc/global.hxx @@ -238,6 +238,7 @@ const USHORT IDF_ATTRIB = IDF_HARDATTR | IDF_STYLES; const USHORT IDF_CONTENTS = IDF_VALUE | IDF_DATETIME | IDF_STRING | IDF_NOTE | IDF_FORMULA; const USHORT IDF_ALL = IDF_CONTENTS | IDF_ATTRIB | IDF_OBJECTS; const USHORT IDF_NOCAPTIONS = 0x0200; /// Internal use only (undo etc.): do not copy/delete caption objects of cell notes. +const USHORT IDF_ADDNOTES = 0x0400; /// Internal use only (copy from clip): do not delete existing cell contents when pasting notes. /// Copy flags for auto/series fill functions: do not touch notes and drawing objects. const USHORT IDF_AUTOFILL = IDF_ALL & ~(IDF_NOTE | IDF_OBJECTS); @@ -727,7 +728,13 @@ enum ScQueryOp SC_TOPVAL, SC_BOTVAL, SC_TOPPERC, - SC_BOTPERC + SC_BOTPERC, + SC_CONTAINS, + SC_DOES_NOT_CONTAIN, + SC_BEGINS_WITH, + SC_DOES_NOT_BEGIN_WITH, + SC_ENDS_WITH, + SC_DOES_NOT_END_WITH }; // ----------------------------------------------------------------------- diff --git a/sc/inc/globstr.hrc b/sc/inc/globstr.hrc index db35cb50969e..97d77dc06fc5 100644 --- a/sc/inc/globstr.hrc +++ b/sc/inc/globstr.hrc @@ -84,7 +84,6 @@ #define STR_MSSG_PASTEFROMCLIP_0 48 #define STR_MSSG_PASTEFROMCLIP_1 49 #define STR_MSSG_MOVEBLOCKTO_0 50 -#define STR_MSSG_APPLYPATTLINES_0 51 #define STR_MSSG_INSERTCELLS_0 52 #define STR_MSSG_DELETECELLS_0 53 #define STR_MSSG_MERGECELLS_0 54 diff --git a/sc/inc/pch/precompiled_sc.hxx b/sc/inc/pch/precompiled_sc.hxx index db4e87d3cdb7..b905bb19db03 100644 --- a/sc/inc/pch/precompiled_sc.hxx +++ b/sc/inc/pch/precompiled_sc.hxx @@ -36,6 +36,7 @@ #include <algorithm> #include <assert.h> +#include <deque> #include <stdarg.h> #include <stddef.h> #include <stdio.h> @@ -49,6 +50,8 @@ #include <new> #include <cfloat> +#include <boost/bind.hpp> + #include <basegfx/polygon/b2dpolygon.hxx> #include <basegfx/polygon/b3dpolygon.hxx> #include <basegfx/polygon/b3dpolypolygon.hxx> diff --git a/sc/inc/postit.hxx b/sc/inc/postit.hxx index 979fea65264f..ee90a71375b4 100644 --- a/sc/inc/postit.hxx +++ b/sc/inc/postit.hxx @@ -31,30 +31,42 @@ #ifndef SC_POSTIT_HXX #define SC_POSTIT_HXX +#include <boost/shared_ptr.hpp> +#include <rtl/ustring.hxx> #include <tools/gen.hxx> #include "address.hxx" #include "scdllapi.h" class EditTextObject; +class OutlinerParaObject; class SdrCaptionObj; class SdrPage; class SfxItemSet; class ScDocument; +struct ScCaptionInitData; // ============================================================================ +/** Internal data for a cell annotation. */ struct SC_DLLPUBLIC ScNoteData { - String maDate; /// Creation date of the note. - String maAuthor; /// Author of the note. + typedef ::boost::shared_ptr< ScCaptionInitData > ScCaptionInitDataRef; + + ::rtl::OUString maDate; /// Creation date of the note. + ::rtl::OUString maAuthor; /// Author of the note. + ScCaptionInitDataRef mxInitData; /// Initial data for invisible notes without SdrObject. SdrCaptionObj* mpCaption; /// Drawing object representing the cell note. bool mbShown; /// True = note is visible. explicit ScNoteData( bool bShown = false ); + ~ScNoteData(); }; // ============================================================================ +/** An additional class held by an ScBaseCell instance containing all + information for a cell annotation. + */ class SC_DLLPUBLIC ScPostIt { public: @@ -65,76 +77,98 @@ public: /** Copy constructor. Clones the note and its caption to a new document. */ explicit ScPostIt( ScDocument& rDoc, const ScAddress& rPos, const ScPostIt& rNote ); - /** Creates a note from the passed note data with existing caption object. */ - explicit ScPostIt( ScDocument& rDoc, const ScNoteData& rNoteData ); + /** Creates a note from the passed note data with existing caption object. + + @param bAlwaysCreateCaption Instead of a pointer to an existing + caption object, the passed note data structure may contain a + reference to an ScCaptionInitData structure containing information + about how to construct a missing caption object. If TRUE is passed, + the caption drawing object will be created immediately from that + data. If FALSE is passed and the note is not visible, it will + continue to cache that data until the caption object is requested. + */ + explicit ScPostIt( + ScDocument& rDoc, const ScAddress& rPos, + const ScNoteData& rNoteData, bool bAlwaysCreateCaption ); /** Removes the caption object from drawing layer, if this note is its owner. */ ~ScPostIt(); - /** Returns the data struct containing note settings. */ + /** Clones this note and its caption object, if specified. + + @param bCloneCaption If TRUE is passed, clones the caption object and + inserts it into the drawing layer of the destination document. If + FALSE is passed, the cloned note will refer to the old caption + object (used e.g. in Undo documents to restore the pointer to the + existing caption object). + */ + ScPostIt* Clone( + const ScAddress& rOwnPos, + ScDocument& rDestDoc, const ScAddress& rDestPos, + bool bCloneCaption ) const; + + /** Returns the data struct containing all note settings. */ inline const ScNoteData& GetNoteData() const { return maNoteData; } /** Returns the creation date of this note. */ - inline const String& GetDate() const { return maNoteData.maDate; } + inline const ::rtl::OUString& GetDate() const { return maNoteData.maDate; } /** Sets a new creation date for this note. */ - inline void SetDate( const String& rDate ) { maNoteData.maDate = rDate; } + inline void SetDate( const ::rtl::OUString& rDate ) { maNoteData.maDate = rDate; } /** Returns the author date of this note. */ - inline const String& GetAuthor() const { return maNoteData.maAuthor; } + inline const ::rtl::OUString& GetAuthor() const { return maNoteData.maAuthor; } /** Sets a new author date for this note. */ - inline void SetAuthor( const String& rAuthor ) { maNoteData.maAuthor = rAuthor; } + inline void SetAuthor( const ::rtl::OUString& rAuthor ) { maNoteData.maAuthor = rAuthor; } /** Sets date and author from system settings. */ void AutoStamp(); + /** Returns the pointer to the current outliner object, or null. */ + const OutlinerParaObject* GetOutlinerObject() const; /** Returns the pointer to the current edit text object, or null. */ const EditTextObject* GetEditTextObject() const; + /** Returns the caption text of this note. */ - String GetText() const; + ::rtl::OUString GetText() const; /** Returns true, if the caption text of this note contains line breaks. */ bool HasMultiLineText() const; /** Changes the caption text of this note. All text formatting will be lost. */ - void SetText( const String& rText ); + void SetText( const ScAddress& rPos, const ::rtl::OUString& rText ); - /** Returns the note caption object. */ + /** Returns an existing note caption object. returns null, if the note + contains initial caption data needed to construct a caption object. */ inline SdrCaptionObj* GetCaption() const { return maNoteData.mpCaption; } - /** Returns and forgets the note caption object. */ - inline SdrCaptionObj* ForgetCaption() { SdrCaptionObj* pCapt = maNoteData.mpCaption; maNoteData.mpCaption = 0; return pCapt; } + /** Returns the caption object of this note. Creates the caption object, if + the note contains initial caption data instead of the caption. */ + SdrCaptionObj* GetOrCreateCaption( const ScAddress& rPos ) const; + /** Forgets the pointer to the note caption object. */ + void ForgetCaption(); /** Shows or hides the note caption object. */ - void ShowCaption( bool bShow = true ); - /** Hides the note caption object. */ - inline void HideCaption() { ShowCaption( false ); } + void ShowCaption( const ScAddress& rPos, bool bShow = true ); /** Returns true, if the caption object is visible. */ inline bool IsCaptionShown() const { return maNoteData.mbShown; } /** Shows or hides the caption temporarily (does not change internal visibility state). */ - void ShowCaptionTemp( bool bShow = true ); - /** Hides caption if it has been shown temporarily (does not change internal visibility state). */ - inline void HideCaptionTemp() { ShowCaptionTemp( false ); } + void ShowCaptionTemp( const ScAddress& rPos, bool bShow = true ); /** Updates caption position according to position of the passed cell. */ void UpdateCaptionPos( const ScAddress& rPos ); - /** Sets caption itemset to default items. */ - void SetCaptionDefaultItems(); - /** Updates caption itemset according to the passed item set while removing shadow items. */ - void SetCaptionItems( const SfxItemSet& rItemSet ); - private: ScPostIt( const ScPostIt& ); ScPostIt& operator=( const ScPostIt& ); + /** Creates the caption object from initial caption data if existing. */ + void CreateCaptionFromInitData( const ScAddress& rPos ) const; /** Creates a new caption object at the passed cell position, clones passed existing caption. */ void CreateCaption( const ScAddress& rPos, const SdrCaptionObj* pCaption = 0 ); /** Removes the caption object from the drawing layer, if this note is its owner. */ void RemoveCaption(); - /** Updates caption visibility. */ - void UpdateCaptionLayer( bool bShow ); private: ScDocument& mrDoc; /// Parent document containing the note. - ScNoteData maNoteData; /// Note data with pointer to caption object. + mutable ScNoteData maNoteData; /// Note data with pointer to caption object. }; // ============================================================================ @@ -142,24 +176,89 @@ private: class SC_DLLPUBLIC ScNoteUtil { public: - /** Clones the note and its caption object, if specified. - @param bCloneCaption True = clones the caption object and inserts it - into the drawing layer of the destination document. False = the - cloned note will refer to the old caption object. */ - static ScPostIt* CloneNote( ScDocument& rDoc, const ScAddress& rPos, - const ScPostIt& rNote, bool bCloneCaption ); - /** Tries to update the position of note caption objects in the specified range. */ static void UpdateCaptionPositions( ScDocument& rDoc, const ScRange& rRange ); /** Creates and returns a caption object for a temporary caption. */ static SdrCaptionObj* CreateTempCaption( ScDocument& rDoc, const ScAddress& rPos, - SdrPage& rPage, const String& rUserText, + SdrPage& rDrawPage, const ::rtl::OUString& rUserText, const Rectangle& rVisRect, bool bTailFront ); - /** Creates a cell note based on the passed string and inserts it into the document. */ - static ScPostIt* CreateNoteFromString( ScDocument& rDoc, const ScAddress& rPos, - const String& rNoteText, bool bShown ); + /** Creates a cell note using the passed caption drawing object. + + This function is used in import filters to reuse the imported drawing + object as note caption object. + + @param rCaption The drawing object for the cell note. This object MUST + be inserted into the document at the correct drawing page already. + + @return Pointer to the new cell note object if insertion was + successful (i.e. the passed cell position was valid), null + otherwise. The Calc document is the owner of the note object. The + passed item set and outliner object are deleted automatically if + creation of the note was not successful. + */ + static ScPostIt* CreateNoteFromCaption( + ScDocument& rDoc, const ScAddress& rPos, + SdrCaptionObj& rCaption, bool bShown ); + + /** Creates a cell note based on the passed caption object data. + + This function is used in import filters to use an existing imported + item set and outliner object to create a note caption object. For + performance reasons, it is possible to specify that the caption drawing + object for the cell note is not created yet but the note caches the + passed data needed to create the caption object on demand (see + parameter bAlwaysCreateCaption). + + @param pItemSet Pointer to an item set on heap memory containing all + formatting attributes of the caption object. This function takes + ownership of the passed item set. + + @param pOutlinerObj Pointer to an outliner object on heap memory + containing (formatted) text for the caption object. This function + takes ownership of the passed outliner object. + + @param rCaptionRect The absolute position and size of the caption + object. The rectangle may be empty, in this case the default + position and size is used. + + @param bAlwaysCreateCaption If TRUE is passed, the caption drawing + object will be created immediately. If FALSE is passed, the caption + drawing object will not be created if the note is not visible + (bShown = FALSE), but the cell note will cache the passed data. + MUST be set to FALSE outside of import filter implementations! + + @return Pointer to the new cell note object if insertion was + successful (i.e. the passed cell position was valid), null + otherwise. The Calc document is the owner of the note object. + */ + static ScPostIt* CreateNoteFromObjectData( + ScDocument& rDoc, const ScAddress& rPos, + SfxItemSet* pItemSet, OutlinerParaObject* pOutlinerObj, + const Rectangle& rCaptionRect, bool bShown, + bool bAlwaysCreateCaption ); + + /** Creates a cell note based on the passed string and inserts it into the + document. + + @param rNoteText The text used to create the note caption object. Must + not be empty. + + @param bAlwaysCreateCaption If TRUE is passed, the caption drawing + object will be created immediately. If FALSE is passed, the caption + drawing object will not be created if the note is not visible + (bShown = FALSE), but the cell note will cache the passed data. + MUST be set to FALSE outside of import filter implementations! + + @return Pointer to the new cell note object if insertion was + successful (i.e. the passed cell position was valid), null + otherwise. The Calc document is the owner of the note object. + */ + static ScPostIt* CreateNoteFromString( + ScDocument& rDoc, const ScAddress& rPos, + const ::rtl::OUString& rNoteText, bool bShown, + bool bAlwaysCreateCaption ); }; // ============================================================================ diff --git a/sc/inc/progress.hxx b/sc/inc/progress.hxx index b30cf6d9dc70..c7706c2bc26b 100644 --- a/sc/inc/progress.hxx +++ b/sc/inc/progress.hxx @@ -36,6 +36,17 @@ class ScDocument; +/* + * #i102566 + * Drawing a progress bar update is not cheap, so if we draw it on every + * percentage change of 200 calculations we get one progress draw per 2 + * calculations which is slower than doing the calculations themselves. So as a + * rough guide only do an update per MIN_NO_CODES_PER_PROGRESS_UPDATE + * calculations + */ +#define MIN_NO_CODES_PER_PROGRESS_UPDATE 100 + + class SC_DLLPUBLIC ScProgress { private: diff --git a/sc/inc/rangenam.hxx b/sc/inc/rangenam.hxx index 962aff918e7b..002adf9b77ce 100644 --- a/sc/inc/rangenam.hxx +++ b/sc/inc/rangenam.hxx @@ -81,6 +81,11 @@ private: USHORT nIndex; BOOL bModified; // wird bei UpdateReference gesetzt/geloescht + // max row and column to use for wrapping of references. If -1 use the + // application's default. + SCROW mnMaxRow; + SCCOL mnMaxCol; + friend class ScRangeName; ScRangeData( USHORT nIndex ); public: @@ -153,6 +158,11 @@ public: static void MakeValidName( String& rName ); SC_DLLPUBLIC static BOOL IsNameValid( const String& rName, ScDocument* pDoc ); + + SC_DLLPUBLIC void SetMaxRow(SCROW nRow); + SCROW GetMaxRow() const; + SC_DLLPUBLIC void SetMaxCol(SCCOL nCol); + SCCOL GetMaxCol() const; }; inline BOOL ScRangeData::HasType( RangeType nType ) const diff --git a/sc/inc/refdata.hxx b/sc/inc/refdata.hxx index 6a51d66fdc07..12f29943fce0 100644 --- a/sc/inc/refdata.hxx +++ b/sc/inc/refdata.hxx @@ -109,6 +109,8 @@ struct SC_DLLPUBLIC ScSingleRefData // Single reference (one address) int inline BOOL IsRelName() const { return Flags.bRelName; } inline BOOL Valid() const; + /// In external references nTab is -1 + inline bool ValidExternal() const; void SmartRelAbs( const ScAddress& rPos ); void CalcRelFromAbs( const ScAddress& rPos ); @@ -147,6 +149,13 @@ inline BOOL ScSingleRefData::Valid() const nTab >= 0 && nTab <= MAXTAB; } +inline bool ScSingleRefData::ValidExternal() const +{ + return nCol >= 0 && nCol <= MAXCOL && + nRow >= 0 && nRow <= MAXROW && + nTab == -1; +} + struct ScComplexRefData // Complex reference (a range) into the sheet { @@ -181,6 +190,10 @@ struct ScComplexRefData // Complex reference (a range) into the sheet { return Ref1.IsDeleted() || Ref2.IsDeleted(); } inline BOOL Valid() const { return Ref1.Valid() && Ref2.Valid(); } + /** In external references nTab is -1 for the start tab and -1 for the end + tab if one sheet, or >=0 if more than one sheets. */ + inline bool ValidExternal() const; + /// Absolute references have to be up-to-date when calling this! void PutInOrder(); inline BOOL operator==( const ScComplexRefData& r ) const @@ -192,4 +205,12 @@ struct ScComplexRefData // Complex reference (a range) into the sheet ScComplexRefData& Extend( const ScComplexRefData & rRef, const ScAddress & rPos ); }; +inline bool ScComplexRefData::ValidExternal() const +{ + return Ref1.ValidExternal() && + Ref2.nCol >= 0 && Ref2.nCol <= MAXCOL && + Ref2.nRow >= 0 && Ref2.nRow <= MAXROW && + Ref2.nTab >= Ref1.nTab; +} + #endif diff --git a/sc/inc/reftokenhelper.hxx b/sc/inc/reftokenhelper.hxx index 37f82337f654..5b06450ea56f 100644 --- a/sc/inc/reftokenhelper.hxx +++ b/sc/inc/reftokenhelper.hxx @@ -56,7 +56,8 @@ public: * The source range may consist of multiple ranges separated by ';'s. */ static void compileRangeRepresentation( - ::std::vector<ScSharedTokenRef>& rRefTokens, const ::rtl::OUString& rRangeStr, ScDocument* pDoc); + ::std::vector<ScSharedTokenRef>& rRefTokens, const ::rtl::OUString& rRangeStr, ScDocument* pDoc, + ::formula::FormulaGrammar::Grammar eGrammar = ::formula::FormulaGrammar::GRAM_ENGLISH); static bool getRangeFromToken(ScRange& rRange, const ScSharedTokenRef& pToken, bool bExternal = false); diff --git a/sc/inc/sc.hrc b/sc/inc/sc.hrc index 35b6a403816d..8fb6b929337b 100644 --- a/sc/inc/sc.hrc +++ b/sc/inc/sc.hrc @@ -1630,8 +1630,13 @@ #define RID_SCDLG_CONFLICTS (SC_DIALOGS_START + 145) #define RID_SCDLG_SHAREDOCUMENT (SC_DIALOGS_START + 146) +#define RID_SCDLG_SORT_WARNING (SC_DIALOGS_START + 147) +#define RID_SCDLG_TABPROTECTION (SC_DIALOGS_START + 148) +#define RID_SCDLG_DOCPROTECTION (SC_DIALOGS_START + 149) +#define RID_SCDLG_RETYPEPASS (SC_DIALOGS_START + 150) +#define RID_SCDLG_RETYPEPASS_INPUT (SC_DIALOGS_START + 151) -#define SC_DIALOGS_END (SC_DIALOGS_START + 150) +#define SC_DIALOGS_END (SC_DIALOGS_START + 152) #ifndef STD_MASKCOLOR #define STD_MASKCOLOR Color { Red = 0xFF00; Green = 0x0000; Blue = 0xFF00; } diff --git a/sc/inc/scabstdlg.hxx b/sc/inc/scabstdlg.hxx index ec381ce2ef07..f9895ff15ebb 100644 --- a/sc/inc/scabstdlg.hxx +++ b/sc/inc/scabstdlg.hxx @@ -314,6 +314,7 @@ public: const String& rStrLabel, int nId, BOOL bColDefault = TRUE ) = 0; + virtual VclAbstractDialog * CreateScSortWarningDlg ( Window* pParent, const String& rExtendText, const String& rCurrentText, int nId ) = 0; //add for ScSortWarningDlg virtual AbstractScDataPilotDatabaseDlg * CreateScDataPilotDatabaseDlg (Window* pParent ,int nId ) = 0; //add for ScDataPilotDatabaseDlg virtual AbstractScDataPilotSourceTypeDlg * CreateScDataPilotSourceTypeDlg ( Window* pParent, BOOL bEnableExternal, int nId ) = 0; //add for ScDataPilotSourceTypeDlg diff --git a/sc/inc/scextopt.hxx b/sc/inc/scextopt.hxx index 4b3f763b4e8c..fdf05430cc69 100644 --- a/sc/inc/scextopt.hxx +++ b/sc/inc/scextopt.hxx @@ -46,8 +46,6 @@ struct ScExtDocSettings double mfTabBarWidth; /// Width of the tabbar, relative to frame window width (0.0 ... 1.0). sal_uInt32 mnLinkCnt; /// Recursive counter for loading external documents. SCTAB mnDisplTab; /// Index of displayed sheet. - bool mbWinProtected; /// true = Window properties are protected. - bool mbEncrypted; /// true = Imported file was encrypted. explicit ScExtDocSettings(); }; diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index e738ff5fbdb8..8b2227d48dbb 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -32,6 +32,8 @@ #define SC_TABLE_HXX #include <vector> +#include <memory> +#include <utility> #include <tools/gen.hxx> #include <tools/color.hxx> #include <com/sun/star/uno/Sequence.hxx> @@ -39,6 +41,8 @@ #include "sortparam.hxx" #include "compressedarray.hxx" +#include <memory> + namespace utl { class SearchParam; class TextSearch; @@ -65,6 +69,7 @@ class ScRangeList; class ScSortInfoArray; class ScStyleSheet; class ScTableLink; +class ScTableProtection; class ScUserListData; class ScIndexMap; struct RowInfo; @@ -77,6 +82,10 @@ class ScTable { private: typedef ::std::vector< ScRange > ScRangeVec; + typedef ::std::pair< SCCOL, SCROW > ScAddress2D; + typedef ::std::vector< ScAddress2D > ScAddress2DVec; + typedef ::std::auto_ptr< ScAddress2DVec > ScAddress2DVecPtr; + // Daten pro Tabelle ------------------ ScColumn aCol[MAXCOLCOUNT]; @@ -102,8 +111,7 @@ private: SCROW nRepeatStartY; SCROW nRepeatEndY; - BOOL bProtected; - com::sun::star::uno::Sequence<sal_Int8> aProtectPass; + ::std::auto_ptr<ScTableProtection> pTabProtection; USHORT* pColWidth; ScSummableCompressedArray< SCROW, USHORT>* pRowHeight; @@ -119,6 +127,7 @@ private: // interne Verwaltung ------------------ BOOL bVisible; + BOOL bPendingRowHeights; SCTAB nTab; USHORT nRecalcLvl; // Rekursionslevel Size-Recalc @@ -128,6 +137,8 @@ private: mutable String aUpperName; // #i62977# filled only on demand, reset in SetName + ScAddress2DVecPtr mxUninitNotes; + // SortierParameter um den Stackbedarf von Quicksort zu Minimieren ScSortParam aSortParam; CollatorWrapper* pSortCollator; @@ -182,6 +193,9 @@ public: BOOL IsVisible() const { return bVisible; } void SetVisible( BOOL bVis ); + BOOL IsPendingRowHeights() const { return bPendingRowHeights; } + void SetPendingRowHeights( BOOL bSet ); + BOOL IsLayoutRTL() const { return bLayoutRTL; } BOOL IsLoadingRTL() const { return bLoadingRTL; } void SetLayoutRTL( BOOL bSet ); @@ -218,10 +232,9 @@ public: void SetPageStyle( const String& rName ); void PageStyleModified( const String& rNewName ); - BOOL IsProtected() const { return bProtected; } - const com::sun::star::uno::Sequence<sal_Int8>& GetPassword() const { return aProtectPass; } - void SetProtection( BOOL bProtect, const com::sun::star::uno::Sequence<sal_Int8>& rPasswd ) - { bProtected = bProtect; aProtectPass = rPasswd; } + BOOL IsProtected() const; + void SetProtection(const ScTableProtection* pProtect); + ScTableProtection* GetProtection(); Size GetPageSize() const; void SetPageSize( const Size& rSize ); @@ -254,16 +267,28 @@ public: void GetString( SCCOL nCol, SCROW nRow, String& rString ); void GetInputString( SCCOL nCol, SCROW nRow, String& rString ); double GetValue( const ScAddress& rPos ) const - { return aCol[rPos.Col()].GetValue( rPos.Row() ); } + { + return ValidColRow(rPos.Col(),rPos.Row()) ? + aCol[rPos.Col()].GetValue( rPos.Row() ) : + 0.0; + } double GetValue( SCCOL nCol, SCROW nRow ); void GetFormula( SCCOL nCol, SCROW nRow, String& rFormula, BOOL bAsciiExport = FALSE ); CellType GetCellType( const ScAddress& rPos ) const - { return aCol[rPos.Col()].GetCellType( rPos.Row() ); } + { + return ValidColRow(rPos.Col(),rPos.Row()) ? + aCol[rPos.Col()].GetCellType( rPos.Row() ) : + CELLTYPE_NONE; + } CellType GetCellType( SCCOL nCol, SCROW nRow ) const; ScBaseCell* GetCell( const ScAddress& rPos ) const - { return aCol[rPos.Col()].GetCell( rPos.Row() ); } + { + return ValidColRow(rPos.Col(),rPos.Row()) ? + aCol[rPos.Col()].GetCell( rPos.Row() ) : + NULL; + } ScBaseCell* GetCell( SCCOL nCol, SCROW nRow ) const; void GetLastDataPos(SCCOL& rCol, SCROW& rRow) const; @@ -276,6 +301,9 @@ public: ScPostIt* ReleaseNote( SCCOL nCol, SCROW nRow ); /** Deletes the note at the passed cell address. */ void DeleteNote( SCCOL nCol, SCROW nRow ); + /** Creates the captions of all uninitialized cell notes. + @param bForced True = always create all captions, false = skip when Undo is disabled. */ + void InitializeNoteCaptions( bool bForced = false ); BOOL TestInsertRow( SCCOL nStartCol, SCCOL nEndCol, SCSIZE nSize ); void InsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize ); @@ -362,7 +390,11 @@ public: SCCOL nEndCol, SCROW nEndRow ) const; USHORT GetErrCode( const ScAddress& rPos ) const - { return aCol[rPos.Col()].GetErrCode( rPos.Row() ); } + { + return ValidColRow(rPos.Col(),rPos.Row()) ? + aCol[rPos.Col()].GetErrCode( rPos.Row() ) : + 0; + } //UNUSED2008-05 USHORT GetErrCode( SCCOL nCol, SCROW nRow ) const; void ResetChanged( const ScRange& rRange ); @@ -438,7 +470,11 @@ public: const ScPatternAttr* GetMostUsedPattern( SCCOL nCol, SCROW nStartRow, SCROW nEndRow ) const; ULONG GetNumberFormat( const ScAddress& rPos ) const - { return aCol[rPos.Col()].GetNumberFormat( rPos.Row() ); } + { + return ValidColRow(rPos.Col(),rPos.Row()) ? + aCol[rPos.Col()].GetNumberFormat( rPos.Row() ) : + 0; + } ULONG GetNumberFormat( SCCOL nCol, SCROW nRow ) const; void MergeSelectionPattern( ScMergePatternState& rState, const ScMarkData& rMark, BOOL bDeep ) const; @@ -457,7 +493,10 @@ public: void ApplyPattern( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr ); void ApplyPatternArea( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SCROW nEndRow, const ScPatternAttr& rAttr ); void SetPattern( const ScAddress& rPos, const ScPatternAttr& rAttr, BOOL bPutToPool = FALSE ) - { aCol[rPos.Col()].SetPattern( rPos.Row(), rAttr, bPutToPool ); } + { + if (ValidColRow(rPos.Col(),rPos.Row())) + aCol[rPos.Col()].SetPattern( rPos.Row(), rAttr, bPutToPool ); + } void SetPattern( SCCOL nCol, SCROW nRow, const ScPatternAttr& rAttr, BOOL bPutToPool = FALSE ); void ApplyPatternIfNumberformatIncompatible( const ScRange& rRange, const ScPatternAttr& rPattern, short nNewType ); diff --git a/sc/inc/tabprotection.hxx b/sc/inc/tabprotection.hxx new file mode 100644 index 000000000000..a11355833e4c --- /dev/null +++ b/sc/inc/tabprotection.hxx @@ -0,0 +1,180 @@ +/************************************************************************* + * + * 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: tabprotection.hxx,v $ + * $Revision: 1.1.4.6 $ + * + * 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_TAB_PROTECTION_HXX +#define SC_TAB_PROTECTION_HXX + +#include "sal/types.h" +#include <com/sun/star/uno/Sequence.hxx> + +#include "global.hxx" +#include <vector> +#include <boost/shared_ptr.hpp> + +#define ENABLE_SHEET_PROTECTION 0 + +class ScDocument; +class ScTableProtectionImpl; + +enum ScPasswordHash +{ + PASSHASH_OOO = 0, + PASSHASH_XL +}; + +class ScPassHashHelper +{ +public: + /** Check for the compatibility of all password hashes. If there is at + least one hash that needs to be regenerated, it returns true. If all + hash values are compatible with the specified hash type, then it + returns false. */ + static bool needsPassHashRegen(const ScDocument& rDoc, ScPasswordHash eHash); + +private: + ScPassHashHelper(); + ~ScPassHashHelper(); +}; + +// ============================================================================ + +class SAL_NO_VTABLE ScPassHashProtectable +{ +public: + virtual ~ScPassHashProtectable() = 0; + + virtual bool isProtected() const = 0; + virtual bool isProtectedWithPass() const = 0; + virtual void setProtected(bool bProtected) = 0; + + virtual bool isPasswordEmpty() const = 0; + virtual bool hasPasswordHash(ScPasswordHash eHash) const = 0; + virtual void setPassword(const String& aPassText) = 0; + virtual ::com::sun::star::uno::Sequence<sal_Int8> getPasswordHash(ScPasswordHash eHash) const = 0; + virtual void setPasswordHash(const ::com::sun::star::uno::Sequence<sal_Int8>& aPassword, + ScPasswordHash eHash = PASSHASH_OOO) = 0; + virtual bool verifyPassword(const String& aPassText) const = 0; +}; + +// ============================================================================ + +class SC_DLLPUBLIC ScDocProtection : public ScPassHashProtectable +{ +public: + enum Option + { + STRUCTURE = 0, + WINDOWS, + CONTENT, + NONE // last item - used to resize the vector + }; + + explicit ScDocProtection(); + explicit ScDocProtection(const ScDocProtection& r); + virtual ~ScDocProtection(); + + virtual bool isProtected() const; + virtual bool isProtectedWithPass() const; + virtual void setProtected(bool bProtected); + + virtual bool isPasswordEmpty() const; + virtual bool hasPasswordHash(ScPasswordHash eHash) const; + virtual void setPassword(const String& aPassText); + virtual ::com::sun::star::uno::Sequence<sal_Int8> getPasswordHash(ScPasswordHash eHash) const; + virtual void setPasswordHash(const ::com::sun::star::uno::Sequence<sal_Int8>& aPassword, + ScPasswordHash eHash = PASSHASH_OOO); + virtual bool verifyPassword(const String& aPassText) const; + + bool isOptionEnabled(Option eOption) const; + void setOption(Option eOption, bool bEnabled); + +private: + ::boost::shared_ptr<ScTableProtectionImpl> mpImpl; +}; + +// ============================================================================ + +/** sheet protection state container + + This class stores sheet's protection state: 1) whether the protection + is on, 2) password and/or password hash, and 3) any associated + protection options. This class is also used as a protection state + container for the undo/redo stack, in which case the password, hash and + the options need to be preserved even when the protection flag is + off. */ +class SC_DLLPUBLIC ScTableProtection : public ScPassHashProtectable +{ +public: + enum Option + { + AUTOFILTER = 0, + DELETE_COLUMNS, + DELETE_ROWS, + FORMAT_CELLS, + FORMAT_COLUMNS, + FORMAT_ROWS, + INSERT_COLUMNS, + INSERT_HYPERLINKS, + INSERT_ROWS, + OBJECTS, + PIVOT_TABLES, + SCENARIOS, + SELECT_LOCKED_CELLS, + SELECT_UNLOCKED_CELLS, + SHEET, + SORT, + NONE // last item - used to resize the vector + }; + + explicit ScTableProtection(); + explicit ScTableProtection(const ScTableProtection& r); + virtual ~ScTableProtection(); + + virtual bool isProtected() const; + virtual bool isProtectedWithPass() const; + virtual void setProtected(bool bProtected); + + virtual bool isPasswordEmpty() const; + virtual bool hasPasswordHash(ScPasswordHash eHash) const; + virtual void setPassword(const String& aPassText); + virtual ::com::sun::star::uno::Sequence<sal_Int8> getPasswordHash(ScPasswordHash eHash) const; + virtual void setPasswordHash(const ::com::sun::star::uno::Sequence<sal_Int8>& aPassword, + ScPasswordHash eHash = PASSHASH_OOO); + virtual bool verifyPassword(const String& aPassText) const; + + bool isOptionEnabled(Option eOption) const; + void setOption(Option eOption, bool bEnabled); + +private: + ::boost::shared_ptr<ScTableProtectionImpl> mpImpl; +}; + + +#endif diff --git a/sc/inc/tokenuno.hxx b/sc/inc/tokenuno.hxx index abb9d1d06a22..bcd3435668be 100644 --- a/sc/inc/tokenuno.hxx +++ b/sc/inc/tokenuno.hxx @@ -31,15 +31,14 @@ #ifndef SC_TOKENUNO_HXX #define SC_TOKENUNO_HXX -#include <svtools/lstner.hxx> -#include <com/sun/star/sheet/FormulaToken.hpp> #include <com/sun/star/uno/Sequence.hxx> #include <com/sun/star/lang/XServiceInfo.hpp> #include <com/sun/star/beans/XPropertySet.hpp> -#include <com/sun/star/sheet/XFormulaParser.hpp> -#include <com/sun/star/sheet/XFormulaOpCodeMapper.hpp> #include <com/sun/star/sheet/FormulaOpCodeMapEntry.hpp> +#include <com/sun/star/sheet/FormulaToken.hpp> +#include <com/sun/star/sheet/XFormulaParser.hpp> #include <cppuhelper/implbase3.hxx> +#include <svtools/lstner.hxx> #include <formula/FormulaOpCodeMapperObj.hxx> #include "address.hxx" #include "compiler.hxx" @@ -47,6 +46,7 @@ class ScTokenArray; class ScDocShell; +// ============================================================================ class ScTokenConversion { @@ -61,6 +61,7 @@ public: const ScTokenArray& rTokenArray ); }; +// ============================================================================ class ScFormulaParserObj : public ::cppu::WeakImplHelper3< ::com::sun::star::sheet::XFormulaParser, @@ -73,7 +74,6 @@ private: ::com::sun::star::uno::Sequence< const ::com::sun::star::sheet::ExternalLinkInfo > maExternalLinks; ScCompiler::OpCodeMapPtr mxOpCodeMap; ScDocShell* mpDocShell; - ScAddress maRefPos; sal_Int16 mnConv; bool mbEnglish; bool mbIgnoreSpaces; @@ -89,10 +89,12 @@ public: // XFormulaParser virtual ::com::sun::star::uno::Sequence< ::com::sun::star::sheet::FormulaToken > SAL_CALL parseFormula( - const ::rtl::OUString& aFormula ) + const ::rtl::OUString& aFormula, + const ::com::sun::star::table::CellAddress& rReferencePos ) throw (::com::sun::star::uno::RuntimeException); virtual ::rtl::OUString SAL_CALL printFormula( const ::com::sun::star::uno::Sequence< - ::com::sun::star::sheet::FormulaToken >& aTokens ) + ::com::sun::star::sheet::FormulaToken >& aTokens, + const ::com::sun::star::table::CellAddress& rReferencePos ) throw (::com::sun::star::uno::RuntimeException); // XPropertySet @@ -145,11 +147,15 @@ public: throw(::com::sun::star::uno::RuntimeException); }; +// ============================================================================ + class ScFormulaOpCodeMapperObj : public formula::FormulaOpCodeMapperObj { public: ScFormulaOpCodeMapperObj(::std::auto_ptr<formula::FormulaCompiler> _pCompiler); }; +// ============================================================================ + #endif diff --git a/sc/inc/unonames.hxx b/sc/inc/unonames.hxx index 367e7d7cfe35..010e420feb42 100644 --- a/sc/inc/unonames.hxx +++ b/sc/inc/unonames.hxx @@ -318,7 +318,10 @@ #define SC_UNONAME_FORMULA2 "Formula2" #define SC_UNONAME_SOURCEPOS "SourcePosition" #define SC_UNONAME_SOURCESTR "SourcePositionAsString" // only for use in XML filter -#define SC_UNONAME_GRAMMAR "Grammar" // only for use in XML filter +#define SC_UNONAME_FORMULANMSP1 "FormulaNamespace1" // only for use in XML filter +#define SC_UNONAME_FORMULANMSP2 "FormulaNamespace2" // only for use in XML filter +#define SC_UNONAME_GRAMMAR1 "Grammar1" // only for use in XML filter +#define SC_UNONAME_GRAMMAR2 "Grammar2" // only for use in XML filter #define SC_UNONAME_STYLENAME "StyleName" // validation @@ -599,7 +602,6 @@ // <-- // FormulaParser -#define SC_UNO_REFERENCEPOS "ReferencePosition" #define SC_UNO_COMPILEENGLISH "CompileEnglish" #define SC_UNO_FORMULACONVENTION "FormulaConvention" #define SC_UNO_IGNORELEADING "IgnoreLeadingSpaces" diff --git a/sc/inc/validat.hxx b/sc/inc/validat.hxx index d3588c366a7c..cea9c154f04a 100644 --- a/sc/inc/validat.hxx +++ b/sc/inc/validat.hxx @@ -93,7 +93,9 @@ public: ScValidationData( ScValidationMode eMode, ScConditionMode eOper, const String& rExpr1, const String& rExpr2, ScDocument* pDocument, const ScAddress& rPos, - const formula::FormulaGrammar::Grammar eGrammar = formula::FormulaGrammar::GRAM_DEFAULT ); + const String& rExprNmsp1 = EMPTY_STRING, const String& rExprNmsp2 = EMPTY_STRING, + formula::FormulaGrammar::Grammar eGrammar1 = formula::FormulaGrammar::GRAM_DEFAULT, + formula::FormulaGrammar::Grammar eGrammar2 = formula::FormulaGrammar::GRAM_DEFAULT ); ScValidationData( ScValidationMode eMode, ScConditionMode eOper, const ScTokenArray* pArr1, const ScTokenArray* pArr2, ScDocument* pDocument, const ScAddress& rPos ); diff --git a/sc/prj/build.lst b/sc/prj/build.lst index 066d2883d1f7..c893349232e7 100644 --- a/sc/prj/build.lst +++ b/sc/prj/build.lst @@ -1,4 +1,4 @@ -sc sc : oovbaapi svx stoc uui BOOST:boost formula oox NULL +sc sc : l10n oovbaapi svx stoc uui BOOST:boost formula oox NULL sc sc usr1 - all sc_mkout NULL sc sc\inc nmake - all sc_inc NULL sc sc\prj get - all sc_prj NULL diff --git a/sc/source/core/data/attarray.cxx b/sc/source/core/data/attarray.cxx index fc33c75306cc..00992cbf962a 100644 --- a/sc/source/core/data/attarray.cxx +++ b/sc/source/core/data/attarray.cxx @@ -2104,9 +2104,8 @@ void ScAttrArray::InsertRow( SCROW nStartRow, SCSIZE nSize ) // im eingefuegten Bereich ist nichts zusammengefasst } - // Flags nicht duplizieren - //! direkt am Pattern testen ?? - RemoveFlags( nStartRow, nStartRow+nSize-1, SC_MF_HOR | SC_MF_VER | SC_MF_AUTO ); + // Don't duplicate the merge flags in the inserted row. + RemoveFlags( nStartRow, nStartRow+nSize-1, SC_MF_ALL ); } diff --git a/sc/source/core/data/bcaslot.cxx b/sc/source/core/data/bcaslot.cxx index 75699e8b0a10..ff82d1fd362f 100644 --- a/sc/source/core/data/bcaslot.cxx +++ b/sc/source/core/data/bcaslot.cxx @@ -113,7 +113,7 @@ bool ScBroadcastAreaSlot::CheckHardRecalcStateCondition() const DBG_ASSERT( pShell, "Missing DocShell :-/" ); if ( pShell ) - pShell->SetError( SCWARN_CORE_HARD_RECALC ); + pShell->SetError( SCWARN_CORE_HARD_RECALC, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); pDoc->SetAutoCalc( FALSE ); pDoc->SetHardRecalcState( 2 ); diff --git a/sc/source/core/data/cell.cxx b/sc/source/core/data/cell.cxx index c43e1eebc6cd..da2de0b68099 100644 --- a/sc/source/core/data/cell.cxx +++ b/sc/source/core/data/cell.cxx @@ -148,7 +148,7 @@ ScBaseCell* ScBaseCell::CloneWithoutNote( ScDocument& rDestDoc, const ScAddress& return lclCloneCell( *this, rDestDoc, rDestPos, nCloneFlags ); } -ScBaseCell* ScBaseCell::CloneWithNote( ScDocument& rDestDoc, const ScAddress& rDestPos, int nCloneFlags ) const +ScBaseCell* ScBaseCell::CloneWithNote( const ScAddress& rOwnPos, ScDocument& rDestDoc, const ScAddress& rDestPos, int nCloneFlags ) const { ScBaseCell* pNewCell = lclCloneCell( *this, rDestDoc, rDestPos, nCloneFlags ); if( mpNote ) @@ -156,7 +156,7 @@ ScBaseCell* ScBaseCell::CloneWithNote( ScDocument& rDestDoc, const ScAddress& rD if( !pNewCell ) pNewCell = new ScNoteCell; bool bCloneCaption = (nCloneFlags & SC_CLONECELL_NOCAPTION) == 0; - pNewCell->TakeNote( ScNoteUtil::CloneNote( rDestDoc, rDestPos, *mpNote, bCloneCaption ) ); + pNewCell->TakeNote( mpNote->Clone( rOwnPos, rDestDoc, rDestPos, bCloneCaption ) ); } return pNewCell; } @@ -1016,15 +1016,15 @@ void ScFormulaCell::CompileXML( ScProgress& rProgress ) ScCompiler aComp( pDocument, aPos, *pCode); aComp.SetGrammar(eTempGrammar); - String aFormula; - aComp.CreateStringFromTokenArray( aFormula ); + String aFormula, aFormulaNmsp; + aComp.CreateStringFromXMLTokenArray( aFormula, aFormulaNmsp ); pDocument->DecXMLImportedFormulaCount( aFormula.Len() ); rProgress.SetStateCountDownOnPercent( pDocument->GetXMLImportedFormulaCount() ); // pCode darf fuer Abfragen noch nicht geloescht, muss aber leer sein if ( pCode ) pCode->Clear(); ScTokenArray* pCodeOld = pCode; - pCode = aComp.CompileString( aFormula ); + pCode = aComp.CompileString( aFormula, aFormulaNmsp ); delete pCodeOld; if( !pCode->GetCodeError() ) { @@ -1701,7 +1701,7 @@ void ScFormulaCell::InterpretTail( ScInterpretTailParameter eTailParam ) // Reschedule verlangsamt das ganze erheblich, nur bei Prozentaenderung ausfuehren ScProgress::GetInterpretProgress()->SetStateCountDownOnPercent( - pDocument->GetFormulaCodeInTree() ); + pDocument->GetFormulaCodeInTree()/MIN_NO_CODES_PER_PROGRESS_UPDATE ); } else { diff --git a/sc/source/core/data/cell2.cxx b/sc/source/core/data/cell2.cxx index 86c87c0445d8..a0e776458ca2 100644 --- a/sc/source/core/data/cell2.cxx +++ b/sc/source/core/data/cell2.cxx @@ -34,6 +34,11 @@ // INCLUDE --------------------------------------------------------------- +#include <algorithm> +#include <deque> + +#include <boost/bind.hpp> + #include <vcl/mapmod.hxx> #include <svx/editobj.hxx> #include <svx/editstat.hxx> @@ -175,6 +180,223 @@ void ScEditCell::SetTextObject( const EditTextObject* pObject, // ============================================================================ +namespace +{ + +using std::deque; + +typedef SCCOLROW(*DimensionSelector)(const ScSingleRefData&); + + +static SCCOLROW lcl_GetCol(const ScSingleRefData& rData) +{ + return rData.nCol; +} + + +static SCCOLROW lcl_GetRow(const ScSingleRefData& rData) +{ + return rData.nRow; +} + + +static SCCOLROW lcl_GetTab(const ScSingleRefData& rData) +{ + return rData.nTab; +} + + +/** Check if both references span the same range in selected dimension. + */ +static bool +lcl_checkRangeDimension( + const SingleDoubleRefProvider& rRef1, + const SingleDoubleRefProvider& rRef2, + const DimensionSelector aWhich) +{ + return + aWhich(rRef1.Ref1) == aWhich(rRef2.Ref1) + && aWhich(rRef1.Ref2) == aWhich(rRef2.Ref2); +} + + +static bool +lcl_checkRangeDimensions( + const SingleDoubleRefProvider& rRef1, + const SingleDoubleRefProvider& rRef2, + bool& bCol, bool& bRow, bool& bTab) +{ + const bool bSameCols(lcl_checkRangeDimension(rRef1, rRef2, lcl_GetCol)); + const bool bSameRows(lcl_checkRangeDimension(rRef1, rRef2, lcl_GetRow)); + const bool bSameTabs(lcl_checkRangeDimension(rRef1, rRef2, lcl_GetTab)); + + // Test if exactly two dimensions are equal + if (!(bSameCols ^ bSameRows ^ bSameTabs) + && (bSameCols || bSameRows || bSameTabs)) + { + bCol = !bSameCols; + bRow = !bSameRows; + bTab = !bSameTabs; + return true; + } + return false; +} + + +/** Check if references in given reference list can possibly + form a range. To do that, two of their dimensions must be the same. + */ +static bool +lcl_checkRangeDimensions( + const deque<ScToken*>::const_iterator aBegin, + const deque<ScToken*>::const_iterator aEnd, + bool& bCol, bool& bRow, bool& bTab) +{ + deque<ScToken*>::const_iterator aCur(aBegin); + ++aCur; + const SingleDoubleRefProvider aRef(**aBegin); + bool bOk(false); + { + const SingleDoubleRefProvider aRefCur(**aCur); + bOk = lcl_checkRangeDimensions(aRef, aRefCur, bCol, bRow, bTab); + } + while (bOk && aCur != aEnd) + { + const SingleDoubleRefProvider aRefCur(**aCur); + bool bColTmp(false); + bool bRowTmp(false); + bool bTabTmp(false); + bOk = lcl_checkRangeDimensions(aRef, aRefCur, bColTmp, bRowTmp, bTabTmp); + bOk = bOk && (bCol == bColTmp && bRow == bRowTmp && bTab == bTabTmp); + ++aCur; + } + + if (bOk && aCur == aEnd) + { + bCol = bCol; + bRow = bRow; + bTab = bTab; + return true; + } + return false; +} + + +bool +lcl_lessReferenceBy( + const ScToken* const pRef1, const ScToken* const pRef2, + const DimensionSelector aWhich) +{ + const SingleDoubleRefProvider rRef1(*pRef1); + const SingleDoubleRefProvider rRef2(*pRef2); + return aWhich(rRef1.Ref1) < aWhich(rRef2.Ref1); +} + + +/** Returns true if range denoted by token pRef2 starts immediately after + range denoted by token pRef1. Dimension, in which the comparison takes + place, is given by aWhich. + */ +bool +lcl_isImmediatelyFollowing( + const ScToken* const pRef1, const ScToken* const pRef2, + const DimensionSelector aWhich) +{ + const SingleDoubleRefProvider rRef1(*pRef1); + const SingleDoubleRefProvider rRef2(*pRef2); + return aWhich(rRef2.Ref1) - aWhich(rRef1.Ref2) == 1; +} + + +static bool +lcl_checkIfAdjacent( + const deque<ScToken*>& rReferences, + const DimensionSelector aWhich) +{ + typedef deque<ScToken*>::const_iterator Iter; + Iter aBegin(rReferences.begin()); + Iter aEnd(rReferences.end()); + Iter aBegin1(aBegin); + ++aBegin1, --aEnd; + return std::equal( + aBegin, aEnd, aBegin1, + boost::bind(lcl_isImmediatelyFollowing, _1, _2, aWhich)); +} + + +static void +lcl_fillRangeFromRefList( + const deque<ScToken*>& rReferences, ScRange& rRange) +{ + const ScSingleRefData aStart( + SingleDoubleRefProvider(*rReferences.front()).Ref1); + rRange.aStart.Set(aStart.nCol, aStart.nRow, aStart.nTab); + const ScSingleRefData aEnd( + SingleDoubleRefProvider(*rReferences.back()).Ref2); + rRange.aEnd.Set(aEnd.nCol, aEnd.nRow, aEnd.nTab); +} + + +static bool +lcl_refListFormsOneRange( + const ScAddress& aPos, deque<ScToken*>& rReferences, + ScRange& rRange) +{ + std::for_each( + rReferences.begin(), rReferences.end(), + bind(&ScToken::CalcAbsIfRel, _1, aPos)) + ; + if (rReferences.size() == 1) { + lcl_fillRangeFromRefList(rReferences, rRange); + return true; + } + + bool bCell(false); + bool bRow(false); + bool bTab(false); + if (lcl_checkRangeDimensions(rReferences.begin(), rReferences.end(), + bCell, bRow, bTab)) + { + DimensionSelector aWhich; + if (bCell) + { + aWhich = lcl_GetCol; + } + else if (bRow) + { + aWhich = lcl_GetRow; + } + else if (bTab) + { + aWhich = lcl_GetTab; + } + else + { + OSL_ENSURE(false, "lcl_checkRangeDimensions shouldn't allow that!"); + aWhich = lcl_GetRow; // initialize to avoid warning + } + // Sort the references by start of range + std::sort(rReferences.begin(), rReferences.end(), + boost::bind(lcl_lessReferenceBy, _1, _2, aWhich)); + if (lcl_checkIfAdjacent(rReferences, aWhich)) + { + lcl_fillRangeFromRefList(rReferences, rRange); + return true; + } + } + return false; +} + + +bool lcl_isReference(const FormulaToken& rToken) +{ + return + rToken.GetType() == svSingleRef || + rToken.GetType() == svDoubleRef; +} + +} + BOOL ScFormulaCell::IsEmpty() { if (IsDirtyOrInTableOpDirty() && pDocument->GetAutoCalc()) @@ -449,6 +671,52 @@ BOOL ScFormulaCell::HasOneReference( ScRange& r ) const return FALSE; } +bool +ScFormulaCell::HasRefListExpressibleAsOneReference(ScRange& rRange) const +{ + /* If there appears just one reference in the formula, it's the same + as HasOneReference(). If there are more of them, they can denote + one range if they are (sole) arguments of one function. + Union of these references must form one range and their + intersection must be empty set. + */ + pCode->Reset(); + // Get first reference, if any + ScToken* const pFirstReference( + dynamic_cast<ScToken*>(pCode->GetNextReferenceRPN())); + if (pFirstReference) + { + // Collect all consecutive references, starting by the one + // already found + std::deque<ScToken*> aReferences; + aReferences.push_back(pFirstReference); + FormulaToken* pToken(pCode->NextRPN()); + FormulaToken* pFunction(0); + while (pToken) + { + if (lcl_isReference(*pToken)) + { + aReferences.push_back(dynamic_cast<ScToken*>(pToken)); + pToken = pCode->NextRPN(); + } + else + { + if (pToken->IsFunction()) + { + pFunction = pToken; + } + break; + } + } + if (pFunction && !pCode->GetNextReferenceRPN() + && (pFunction->GetParamCount() == aReferences.size())) + { + return lcl_refListFormsOneRange(aPos, aReferences, rRange); + } + } + return false; +} + BOOL ScFormulaCell::HasRelNameReference() const { pCode->Reset(); @@ -472,7 +740,7 @@ BOOL ScFormulaCell::HasColRowName() const void ScFormulaCell::UpdateReference(UpdateRefMode eUpdateRefMode, const ScRange& r, SCsCOL nDx, SCsROW nDy, SCsTAB nDz, - ScDocument* pUndoDoc ) + ScDocument* pUndoDoc, const ScAddress* pUndoCellPos ) { SCCOL nCol1 = r.aStart.Col(); SCROW nRow1 = r.aStart.Row(); @@ -484,6 +752,8 @@ void ScFormulaCell::UpdateReference(UpdateRefMode eUpdateRefMode, SCROW nRow = aPos.Row(); SCTAB nTab = aPos.Tab(); ScAddress aUndoPos( aPos ); // position for undo cell in pUndoDoc + if ( pUndoCellPos ) + aUndoPos = *pUndoCellPos; ScAddress aOldPos( aPos ); // BOOL bPosChanged = FALSE; // ob diese Zelle bewegt wurde BOOL bIsInsert = FALSE; @@ -706,10 +976,15 @@ void ScFormulaCell::UpdateReference(UpdateRefMode eUpdateRefMode, // (InsertCells/DeleteCells - aPos is changed above) as well as when UpdateReference // is called after moving the cells (MoveBlock/PasteFromClip - aOldPos is changed). - ScFormulaCell* pFCell = new ScFormulaCell( pUndoDoc, aUndoPos, - pOld, eTempGrammar, cMatrixFlag ); - pFCell->aResult.SetToken( NULL); // to recognize it as changed later (Cut/Paste!) - pUndoDoc->PutCell( aUndoPos, pFCell ); + // If there is already a formula cell in the undo document, don't overwrite it, + // the first (oldest) is the important cell. + if ( pUndoDoc->GetCellType( aUndoPos ) != CELLTYPE_FORMULA ) + { + ScFormulaCell* pFCell = new ScFormulaCell( pUndoDoc, aUndoPos, + pOld, eTempGrammar, cMatrixFlag ); + pFCell->aResult.SetToken( NULL); // to recognize it as changed later (Cut/Paste!) + pUndoDoc->PutCell( aUndoPos, pFCell ); + } } bValChanged = FALSE; if ( pRangeData ) @@ -792,7 +1067,7 @@ void ScFormulaCell::UpdateInsertTab(SCTAB nTable) pCode = new ScTokenArray( *pRangeData->GetCode() ); ScCompiler aComp2(pDocument, aPos, *pCode); aComp2.SetGrammar(pDocument->GetGrammar()); - aComp2.MoveRelWrap(); + aComp2.MoveRelWrap(pRangeData->GetMaxCol(), pRangeData->GetMaxRow()); aComp2.UpdateInsertTab( nTable, FALSE ); // If the shared formula contained a named range/formula containing // an absolute reference to a sheet, those have to be readjusted. @@ -828,7 +1103,7 @@ BOOL ScFormulaCell::UpdateDeleteTab(SCTAB nTable, BOOL bIsMove) ScCompiler aComp2(pDocument, aPos, *pCode); aComp2.SetGrammar(pDocument->GetGrammar()); aComp2.CompileTokenArray(); - aComp2.MoveRelWrap(); + aComp2.MoveRelWrap(pRangeData->GetMaxCol(), pRangeData->GetMaxRow()); aComp2.UpdateDeleteTab( nTable, FALSE, FALSE, bRefChanged ); // If the shared formula contained a named range/formula containing // an absolute reference to a sheet, those have to be readjusted. @@ -865,7 +1140,7 @@ void ScFormulaCell::UpdateMoveTab( SCTAB nOldPos, SCTAB nNewPos, SCTAB nTabNo ) ScCompiler aComp2(pDocument, aPos, *pCode); aComp2.SetGrammar(pDocument->GetGrammar()); aComp2.CompileTokenArray(); - aComp2.MoveRelWrap(); + aComp2.MoveRelWrap(pRangeData->GetMaxCol(), pRangeData->GetMaxRow()); aComp2.UpdateMoveTab( nOldPos, nNewPos, TRUE ); bCompile = TRUE; } diff --git a/sc/source/core/data/column.cxx b/sc/source/core/data/column.cxx index 4c3c86c51971..3238607fd613 100644 --- a/sc/source/core/data/column.cxx +++ b/sc/source/core/data/column.cxx @@ -1272,11 +1272,14 @@ void ScColumn::CopyToClip(SCROW nRow1, SCROW nRow2, ScColumn& rColumn, BOOL bKee { int nCloneFlags = bCloneNoteCaptions ? SC_CLONECELL_DEFAULT : SC_CLONECELL_NOCAPTION; rColumn.Resize( rColumn.GetCellCount() + nBlockCount ); - ScAddress aPos( rColumn.nCol, 0, rColumn.nTab ); + ScAddress aOwnPos( nCol, 0, nTab ); + ScAddress aDestPos( rColumn.nCol, 0, rColumn.nTab ); for (i = nStartIndex; i <= nEndIndex; i++) { - aPos.SetRow( pItems[i].nRow ); - rColumn.Append( aPos.Row(), pItems[i].pCell->CloneWithNote( *rColumn.pDocument, aPos, nCloneFlags ) ); + aOwnPos.SetRow( pItems[i].nRow ); + aDestPos.SetRow( pItems[i].nRow ); + ScBaseCell* pNewCell = pItems[i].pCell->CloneWithNote( aOwnPos, *rColumn.pDocument, aDestPos, nCloneFlags ); + rColumn.Append( aDestPos.Row(), pNewCell ); } } } @@ -1376,16 +1379,18 @@ void ScColumn::UndoToColumn(SCROW nRow1, SCROW nRow2, USHORT nFlags, BOOL bMarke void ScColumn::CopyUpdated( const ScColumn& rPosCol, ScColumn& rDestCol ) const { ScDocument& rDestDoc = *rDestCol.pDocument; + ScAddress aOwnPos( nCol, 0, nTab ); ScAddress aDestPos( rDestCol.nCol, 0, rDestCol.nTab ); SCSIZE nPosCount = rPosCol.nCount; for (SCSIZE nPosIndex = 0; nPosIndex < nPosCount; nPosIndex++) { - aDestPos.SetRow( rPosCol.pItems[nPosIndex].nRow ); + aOwnPos.SetRow( rPosCol.pItems[nPosIndex].nRow ); + aDestPos.SetRow( aOwnPos.Row() ); SCSIZE nThisIndex; if ( Search( aDestPos.Row(), nThisIndex ) ) { - ScBaseCell* pNew = pItems[nThisIndex].pCell->CloneWithNote( rDestDoc, aDestPos ); + ScBaseCell* pNew = pItems[nThisIndex].pCell->CloneWithNote( aOwnPos, rDestDoc, aDestPos ); rDestCol.Insert( aDestPos.Row(), pNew ); } } @@ -1673,7 +1678,10 @@ void ScColumn::UpdateReference( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW if( pCell->GetCellType() == CELLTYPE_FORMULA) { SCROW nRow = pItems[i].nRow; - ((ScFormulaCell*)pCell)->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz, pUndoDoc ); + // When deleting rows on several sheets, the formula's position may be updated with the first call, + // so the undo position must be passed from here. + ScAddress aUndoPos( nCol, nRow, nTab ); + ((ScFormulaCell*)pCell)->UpdateReference( eUpdateRefMode, aRange, nDx, nDy, nDz, pUndoDoc, &aUndoPos ); if ( nRow != pItems[i].nRow ) Search( nRow, i ); // Listener removed/inserted? } diff --git a/sc/source/core/data/column3.cxx b/sc/source/core/data/column3.cxx index bfb1890d70b0..5726862366cf 100644 --- a/sc/source/core/data/column3.cxx +++ b/sc/source/core/data/column3.cxx @@ -521,6 +521,15 @@ void ScColumn::DeleteRange( SCSIZE nStartIndex, SCSIZE nEndIndex, USHORT nDelFla for ( FormulaCellVector::iterator aIt = aDelCells.begin(), aEnd = aDelCells.end(); aIt != aEnd; ++aIt ) (*aIt)->EndListeningTo( pDocument ); + // #i101869# if the note cell with the broadcaster was deleted in EndListening, + // forget the pointer to the broadcaster + for ( FormulaCellVector::iterator aIt = aDelCells.begin(), aEnd = aDelCells.end(); aIt != aEnd; ++aIt ) + { + SCSIZE nIndex; + if ( !Search( (*aIt)->aPos.Row(), nIndex ) ) + (*aIt)->ReleaseBroadcaster(); + } + // broadcast SC_HINT_DYING for all cells and delete them for ( FormulaCellVector::iterator aIt = aDelCells.begin(), aEnd = aDelCells.end(); aIt != aEnd; ++aIt ) { @@ -739,6 +748,9 @@ void ScColumn::CopyFromClip(SCROW nRow1, SCROW nRow2, long nDy, Resize( nNew ); } + // IDF_ADDNOTES must be passed without other content flags than IDF_NOTE + bool bAddNotes = (nInsFlag & (IDF_CONTENTS | IDF_ADDNOTES)) == (IDF_NOTE | IDF_ADDNOTES); + BOOL bAtEnd = FALSE; for (SCSIZE i = 0; i < nColCount && !bAtEnd; i++) { @@ -751,12 +763,38 @@ void ScColumn::CopyFromClip(SCROW nRow1, SCROW nRow2, long nDy, // nDestRow may be negative then ScAddress aDestPos( nCol, (SCROW)nDestRow, nTab ); - ScBaseCell* pNew = bAsLink ? - rColumn.CreateRefCell( pDocument, aDestPos, i, nInsFlag ) : - rColumn.CloneCell( i, nInsFlag, *pDocument, aDestPos ); - if (pNew) - Insert((SCROW)nDestRow, pNew); + /* #i102056# Paste from clipboard needs to paste the cell notes in + a second pass. This must not overwrite the existing cells + already copied to the destination position in the first pass. + To indicate this special case, the modifier IDF_ADDNOTES is + passed together with IDF_NOTE in nInsFlag. Of course, there is + still the need to create a new cell, if there is no cell at the + destination position at all. */ + ScBaseCell* pAddNoteCell = bAddNotes ? GetCell( aDestPos.Row() ) : 0; + if (pAddNoteCell) + { + // do nothing if source cell does not contain a note + const ScBaseCell* pSourceCell = rColumn.pItems[i].pCell; + const ScPostIt* pSourceNote = pSourceCell ? pSourceCell->GetNote() : 0; + if (pSourceNote) + { + DBG_ASSERT( !pAddNoteCell->HasNote(), "ScColumn::CopyFromClip - unexpected note at destination cell" ); + bool bCloneCaption = (nInsFlag & IDF_NOCAPTIONS) == 0; + // #i52342# if caption is cloned, the note must be constructed with the destination document + ScAddress aSourcePos( rColumn.nCol, rColumn.pItems[i].nRow, rColumn.nTab ); + ScPostIt* pNewNote = pSourceNote->Clone( aSourcePos, *pDocument, aDestPos, bCloneCaption ); + pAddNoteCell->TakeNote( pNewNote ); + } + } + else + { + ScBaseCell* pNewCell = bAsLink ? + rColumn.CreateRefCell( pDocument, aDestPos, i, nInsFlag ) : + rColumn.CloneCell( i, nInsFlag, *pDocument, aDestPos ); + if (pNewCell) + Insert( aDestPos.Row(), pNewCell ); + } } } } @@ -870,7 +908,8 @@ ScBaseCell* ScColumn::CloneCell(SCSIZE nIndex, USHORT nFlags, ScDocument& rDestD { bool bCloneCaption = (nFlags & IDF_NOCAPTIONS) == 0; // #i52342# if caption is cloned, the note must be constructed with the destination document - ScPostIt* pNewNote = ScNoteUtil::CloneNote( rDestDoc, rDestPos, *pNote, bCloneCaption ); + ScAddress aOwnPos( nCol, pItems[nIndex].nRow, nTab ); + ScPostIt* pNewNote = pNote->Clone( aOwnPos, rDestDoc, rDestPos, bCloneCaption ); if (!pNew) pNew = new ScNoteCell( pNewNote ); else diff --git a/sc/source/core/data/conditio.cxx b/sc/source/core/data/conditio.cxx index 12dbf77e88e6..3c636d9049d4 100644 --- a/sc/source/core/data/conditio.cxx +++ b/sc/source/core/data/conditio.cxx @@ -130,7 +130,10 @@ ScConditionEntry::ScConditionEntry( const ScConditionEntry& r ) : nVal2(r.nVal2), aStrVal1(r.aStrVal1), aStrVal2(r.aStrVal2), - eTempGrammar(r.eTempGrammar), + aStrNmsp1(r.aStrNmsp1), + aStrNmsp2(r.aStrNmsp2), + eTempGrammar1(r.eTempGrammar1), + eTempGrammar2(r.eTempGrammar2), bIsStr1(r.bIsStr1), bIsStr2(r.bIsStr2), pFormula1(NULL), @@ -161,7 +164,10 @@ ScConditionEntry::ScConditionEntry( ScDocument* pDocument, const ScConditionEntr nVal2(r.nVal2), aStrVal1(r.aStrVal1), aStrVal2(r.aStrVal2), - eTempGrammar(r.eTempGrammar), + aStrNmsp1(r.aStrNmsp1), + aStrNmsp2(r.aStrNmsp2), + eTempGrammar1(r.eTempGrammar1), + eTempGrammar2(r.eTempGrammar2), bIsStr1(r.bIsStr1), bIsStr2(r.bIsStr2), pFormula1(NULL), @@ -187,14 +193,17 @@ ScConditionEntry::ScConditionEntry( ScDocument* pDocument, const ScConditionEntr } ScConditionEntry::ScConditionEntry( ScConditionMode eOper, - const String& rExpr1, const String& rExpr2, - ScDocument* pDocument, const ScAddress& rPos, - const FormulaGrammar::Grammar eGrammar ) : + const String& rExpr1, const String& rExpr2, ScDocument* pDocument, const ScAddress& rPos, + const String& rExprNmsp1, const String& rExprNmsp2, + FormulaGrammar::Grammar eGrammar1, FormulaGrammar::Grammar eGrammar2 ) : eOp(eOper), nOptions(0), // spaeter... nVal1(0.0), nVal2(0.0), - eTempGrammar(eGrammar), + aStrNmsp1(rExprNmsp1), + aStrNmsp2(rExprNmsp2), + eTempGrammar1(eGrammar1), + eTempGrammar2(eGrammar2), bIsStr1(FALSE), bIsStr2(FALSE), pFormula1(NULL), @@ -207,7 +216,7 @@ ScConditionEntry::ScConditionEntry( ScConditionMode eOper, bRelRef2(FALSE), bFirstRun(TRUE) { - Compile( rExpr1, rExpr2, eGrammar, FALSE ); + Compile( rExpr1, rExpr2, rExprNmsp1, rExprNmsp2, eGrammar1, eGrammar2, FALSE ); // Formelzellen werden erst bei IsValid angelegt } @@ -219,7 +228,8 @@ ScConditionEntry::ScConditionEntry( ScConditionMode eOper, nOptions(0), // spaeter... nVal1(0.0), nVal2(0.0), - eTempGrammar(FormulaGrammar::GRAM_DEFAULT), + eTempGrammar1(FormulaGrammar::GRAM_DEFAULT), + eTempGrammar2(FormulaGrammar::GRAM_DEFAULT), bIsStr1(FALSE), bIsStr2(FALSE), pFormula1(NULL), @@ -294,15 +304,16 @@ ScConditionEntry::~ScConditionEntry() } void ScConditionEntry::Compile( const String& rExpr1, const String& rExpr2, - const FormulaGrammar::Grammar eGrammar, BOOL bTextToReal ) + const String& rExprNmsp1, const String& rExprNmsp2, + FormulaGrammar::Grammar eGrammar1, FormulaGrammar::Grammar eGrammar2, BOOL bTextToReal ) { if ( rExpr1.Len() || rExpr2.Len() ) { ScCompiler aComp( pDoc, aSrcPos ); - aComp.SetGrammar(eGrammar); if ( rExpr1.Len() ) { + aComp.SetGrammar( eGrammar1 ); if ( pDoc->IsImportingXML() && !bTextToReal ) { // temporary formula string as string tokens @@ -313,7 +324,7 @@ void ScConditionEntry::Compile( const String& rExpr1, const String& rExpr2, } else { - pFormula1 = aComp.CompileString( rExpr1 ); + pFormula1 = aComp.CompileString( rExpr1, rExprNmsp1 ); if ( pFormula1->GetLen() == 1 ) { // einzelne (konstante Zahl) ? @@ -339,6 +350,7 @@ void ScConditionEntry::Compile( const String& rExpr1, const String& rExpr2, if ( rExpr2.Len() ) { + aComp.SetGrammar( eGrammar2 ); if ( pDoc->IsImportingXML() && !bTextToReal ) { // temporary formula string as string tokens @@ -349,7 +361,7 @@ void ScConditionEntry::Compile( const String& rExpr1, const String& rExpr2, } else { - pFormula2 = aComp.CompileString( rExpr2 ); + pFormula2 = aComp.CompileString( rExpr2, rExprNmsp2 ); if ( pFormula2->GetLen() == 1 ) { // einzelne (konstante Zahl) ? @@ -429,9 +441,9 @@ void ScConditionEntry::CompileXML() // Convert the text tokens that were created during XML import into real tokens. - Compile( GetExpression(aSrcPos, 0, 0, eTempGrammar), - GetExpression(aSrcPos, 1, 0, eTempGrammar), - eTempGrammar, TRUE ); + Compile( GetExpression(aSrcPos, 0, 0, eTempGrammar1), + GetExpression(aSrcPos, 1, 0, eTempGrammar2), + aStrNmsp1, aStrNmsp2, eTempGrammar1, eTempGrammar2, TRUE ); } void ScConditionEntry::SetSrcString( const String& rNew ) @@ -1129,8 +1141,10 @@ ScCondFormatEntry::ScCondFormatEntry( ScConditionMode eOper, const String& rExpr1, const String& rExpr2, ScDocument* pDocument, const ScAddress& rPos, const String& rStyle, - const FormulaGrammar::Grammar eGrammar ) : - ScConditionEntry( eOper, rExpr1, rExpr2, pDocument, rPos, eGrammar ), + const String& rExprNmsp1, const String& rExprNmsp2, + FormulaGrammar::Grammar eGrammar1, + FormulaGrammar::Grammar eGrammar2 ) : + ScConditionEntry( eOper, rExpr1, rExpr2, pDocument, rPos, rExprNmsp1, rExprNmsp2, eGrammar1, eGrammar2 ), aStyleName( rStyle ), pParent( NULL ) { diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx index f5dbb14e9ff9..16613fbcbab4 100644 --- a/sc/source/core/data/documen2.cxx +++ b/sc/source/core/data/documen2.cxx @@ -94,6 +94,8 @@ #include "recursionhelper.hxx" #include "lookupcache.hxx" #include "externalrefmgr.hxx" +#include "tabprotection.hxx" +#include "formulaparserpool.hxx" // pImpl because including lookupcache.hxx in document.hxx isn't wanted, and // dtor plus helpers are convenient. @@ -152,7 +154,7 @@ ScDocument::ScDocument( ScDocumentMode eMode, pChangeViewSettings( NULL ), pScriptTypeData( NULL ), pCacheFieldEditEngine( NULL ), - pExternalRefMgr( NULL ), + pDocProtection( NULL ), pViewOptions( NULL ), pDocOptions( NULL ), pExtDocOptions( NULL ), @@ -175,7 +177,6 @@ ScDocument::ScDocument( ScDocumentMode eMode, nHardRecalcState(0), nVisibleTab( 0 ), eLinkMode(LM_UNKNOWN), - bProtected( FALSE ), bAutoCalc( eMode == SCDOCMODE_DOCUMENT ), bAutoCalcShellDisabled( FALSE ), bForcedFormulaPending( FALSE ), @@ -383,15 +384,14 @@ ScDocument::~ScDocument() pLinkManager->Remove( 0, pLinkManager->GetLinks().Count() ); } - if (pExternalRefMgr.get()) - // Destroy the external ref mgr instance here because it has a timer - // which needs to be stopped before the app closes. - pExternalRefMgr.reset(NULL); + mxFormulaParserPool.reset(); + // Destroy the external ref mgr instance here because it has a timer + // which needs to be stopped before the app closes. + pExternalRefMgr.reset(); ScAddInAsync::RemoveDocument( this ); ScAddInListener::RemoveDocument( this ); - delete pChartListenerCollection; // vor pBASM wg. evtl. Listener! - pChartListenerCollection = NULL; + DELETEZ( pChartListenerCollection); // vor pBASM wg. evtl. Listener! DELETEZ( pLookupCacheMapImpl); // before pBASM because of listeners // BroadcastAreas vor allen Zellen zerstoeren um unnoetige // Einzel-EndListenings der Formelzellen zu vermeiden @@ -931,6 +931,7 @@ BOOL ScDocument::CopyTab( SCTAB nOldPos, SCTAB nNewPos, const ScMarkData* pOnlyM DrawCopyPage( static_cast<sal_uInt16>(nOldPos), static_cast<sal_uInt16>(nNewPos) ); pTab[nNewPos]->SetPageStyle( pTab[nOldPos]->GetPageStyle() ); + pTab[nNewPos]->SetPendingRowHeights( pTab[nOldPos]->IsPendingRowHeights() ); // Update cells containing external references. if (pExternalRefMgr.get()) @@ -1109,6 +1110,8 @@ ULONG ScDocument::TransferTab( ScDocument* pSrcDoc, SCTAB nSrcPos, if (bInsertNew) TransferDrawPage( pSrcDoc, nSrcPos, nDestPos ); + + pTab[nDestPos]->SetPendingRowHeights( pSrcDoc->pTab[nSrcPos]->IsPendingRowHeights() ); } if (!bValid) nRetVal = 0; diff --git a/sc/source/core/data/documen3.cxx b/sc/source/core/data/documen3.cxx index 2b3fbb359988..08170fd6cdc9 100644 --- a/sc/source/core/data/documen3.cxx +++ b/sc/source/core/data/documen3.cxx @@ -40,6 +40,7 @@ #include <sfx2/bindings.hxx> #include <sfx2/objsh.hxx> #include <svtools/zforlist.hxx> +#include <svtools/PasswordHelper.hxx> #include <vcl/svapp.hxx> #include "document.hxx" #include "attrib.hxx" @@ -77,6 +78,8 @@ #include "drwlayer.hxx" #include "unoreflist.hxx" #include "listenercalls.hxx" +#include "tabprotection.hxx" +#include "formulaparserpool.hxx" #include <memory> @@ -507,6 +510,13 @@ void ScDocument::MarkUsedExternalReferences() * collecting them during export. */ } +ScFormulaParserPool& ScDocument::GetFormulaParserPool() const +{ + if( !mxFormulaParserPool.get() ) + mxFormulaParserPool.reset( new ScFormulaParserPool( *this ) ); + return *mxFormulaParserPool; +} + ScOutlineTable* ScDocument::GetOutlineTable( SCTAB nTab, BOOL bCreate ) { ScOutlineTable* pVal = NULL; @@ -1701,28 +1711,28 @@ void ScDocument::SnapVisArea( Rectangle& rRect ) const ScDrawLayer::MirrorRectRTL( rRect ); // back to real rectangle } -void ScDocument::SetDocProtection( BOOL bProtect, const uno::Sequence<sal_Int8>& rPasswd ) +ScDocProtection* ScDocument::GetDocProtection() const { - bProtected = bProtect; - aProtectPass = rPasswd; + return pDocProtection.get(); } -void ScDocument::SetTabProtection( SCTAB nTab, BOOL bProtect, const uno::Sequence<sal_Int8>& rPasswd ) +void ScDocument::SetDocProtection(const ScDocProtection* pProtect) { - if (VALIDTAB(nTab)) - if (pTab[nTab]) - pTab[nTab]->SetProtection( bProtect, rPasswd ); + if (pProtect) + pDocProtection.reset(new ScDocProtection(*pProtect)); + else + pDocProtection.reset(NULL); } BOOL ScDocument::IsDocProtected() const { - return bProtected; + return pDocProtection.get() && pDocProtection->isProtected(); } BOOL ScDocument::IsDocEditable() const { // import into read-only document is possible - return !bProtected && ( bImportingXML || mbChangeReadOnlyEnabled || !pShell || !pShell->IsReadOnly() ); + return !IsDocProtected() && ( bImportingXML || mbChangeReadOnlyEnabled || !pShell || !pShell->IsReadOnly() ); } BOOL ScDocument::IsTabProtected( SCTAB nTab ) const @@ -1734,18 +1744,28 @@ BOOL ScDocument::IsTabProtected( SCTAB nTab ) const return FALSE; } -const uno::Sequence<sal_Int8>& ScDocument::GetDocPassword() const +ScTableProtection* ScDocument::GetTabProtection( SCTAB nTab ) const { - return aProtectPass; + if (VALIDTAB(nTab) && pTab[nTab]) + return pTab[nTab]->GetProtection(); + + return NULL; } -const uno::Sequence<sal_Int8>& ScDocument::GetTabPassword( SCTAB nTab ) const +void ScDocument::SetTabProtection(SCTAB nTab, const ScTableProtection* pProtect) { - if (VALIDTAB(nTab) && pTab[nTab]) - return pTab[nTab]->GetPassword(); + if (!ValidTab(nTab)) + return; - DBG_ERROR("Falsche Tabellennummer"); - return aProtectPass; + pTab[nTab]->SetProtection(pProtect); +} + +void ScDocument::CopyTabProtection(SCTAB nTabSrc, SCTAB nTabDest) +{ + if (!ValidTab(nTabSrc) || !ValidTab(nTabDest)) + return; + + pTab[nTabDest]->SetProtection( pTab[nTabSrc]->GetProtection() ); } const ScDocOptions& ScDocument::GetDocOptions() const diff --git a/sc/source/core/data/documen4.cxx b/sc/source/core/data/documen4.cxx index 3c72baff5ba4..7313ebbf83f5 100644 --- a/sc/source/core/data/documen4.cxx +++ b/sc/source/core/data/documen4.cxx @@ -311,9 +311,16 @@ bool ScDocument::MarkUsedExternalReferences( ScTokenArray & rArr ) switch (t->GetType()) { case svExternalSingleRef: - case svExternalDoubleRef: bAllMarked = pRefMgr->setCacheTableReferenced( - t->GetIndex(), t->GetString()); + t->GetIndex(), t->GetString(), 1); + break; + case svExternalDoubleRef: + { + const ScComplexRefData& rRef = t->GetDoubleRef(); + size_t nSheets = rRef.Ref2.nTab - rRef.Ref1.nTab + 1; + bAllMarked = pRefMgr->setCacheTableReferenced( + t->GetIndex(), t->GetString(), nSheets); + } break; case svExternalName: /* TODO: external names aren't supported yet, but would diff --git a/sc/source/core/data/documen5.cxx b/sc/source/core/data/documen5.cxx index 8d528db34118..0be1e6717891 100644 --- a/sc/source/core/data/documen5.cxx +++ b/sc/source/core/data/documen5.cxx @@ -130,6 +130,7 @@ void lcl_SetChartRanges( const uno::Reference< chart2::XChartDocument >& xChartD if( xLabel.is()) { + // the range string must be in Calc A1 format. uno::Reference< chart2::data::XDataSequence > xNewSeq( xDataProvider->createDataSequenceByRangeRepresentation( rRanges[nRange++] )); @@ -145,6 +146,7 @@ void lcl_SetChartRanges( const uno::Reference< chart2::XChartDocument >& xChartD if( xValues.is()) { + // the range string must be in Calc A1 format. uno::Reference< chart2::data::XDataSequence > xNewSeq( xDataProvider->createDataSequenceByRangeRepresentation( rRanges[nRange++] )); @@ -391,7 +393,7 @@ void ScDocument::GetChartRanges( const String& rChartName, ::std::vector< ScRang for( sal_Int32 nN=0; nN<aRangeStrings.getLength(); nN++ ) { ScRangeList aRanges; - aRanges.Parse( aRangeStrings[nN], pSheetNameDoc ); + aRanges.Parse( aRangeStrings[nN], pSheetNameDoc, SCA_VALID, pSheetNameDoc->GetAddressConvention() ); rRangesVector.push_back(aRanges); } } @@ -407,8 +409,8 @@ void ScDocument::SetChartRanges( const String& rChartName, const ::std::vector< for( sal_Int32 nN=0; nN<nCount; nN++ ) { ScRangeList aScRangeList( rRangesVector[nN] ); - String sRangeStr; - aScRangeList.Format( sRangeStr, SCR_ABS_3D, this, GetAddressConvention() ); + String sRangeStr; // This range must be in Calc A1 format. + aScRangeList.Format( sRangeStr, SCR_ABS_3D, this ); aRangeStrings[nN]=sRangeStr; } lcl_SetChartRanges( xChartDoc, aRangeStrings ); diff --git a/sc/source/core/data/documen8.cxx b/sc/source/core/data/documen8.cxx index 0d12c82dec87..c34e93f10d66 100644 --- a/sc/source/core/data/documen8.cxx +++ b/sc/source/core/data/documen8.cxx @@ -44,6 +44,7 @@ #include <svx/linkmgr.hxx> #include <svx/scripttypeitem.hxx> #include <svx/unolingu.hxx> +#include <sfx2/bindings.hxx> #include <sfx2/objsh.hxx> #include <sfx2/printer.hxx> #include <sfx2/viewfrm.hxx> @@ -1046,6 +1047,18 @@ void ScDocument::UpdateExternalRefLinks() TrackFormulas(); pShell->Broadcast( SfxSimpleHint(FID_DATACHANGED) ); ResetChanged( ScRange(0, 0, 0, MAXCOL, MAXROW, MAXTAB) ); + + // #i101960# set document modified, as in TrackTimeHdl for DDE links + if (!pShell->IsModified()) + { + pShell->SetModified( TRUE ); + SfxBindings* pBindings = GetViewBindings(); + if (pBindings) + { + pBindings->Invalidate( SID_SAVEDOC ); + pBindings->Invalidate( SID_DOC_MODIFIED ); + } + } } } diff --git a/sc/source/core/data/document.cxx b/sc/source/core/data/document.cxx index bdca03b861c1..61cf3ab94b35 100644 --- a/sc/source/core/data/document.cxx +++ b/sc/source/core/data/document.cxx @@ -93,6 +93,7 @@ #include "bcaslot.hxx" #include "postit.hxx" #include "externalrefmgr.hxx" +#include "tabprotection.hxx" namespace WritingMode2 = ::com::sun::star::text::WritingMode2; @@ -506,6 +507,22 @@ BOOL ScDocument::IsVisible( SCTAB nTab ) const } +BOOL ScDocument::IsPendingRowHeights( SCTAB nTab ) const +{ + if ( ValidTab(nTab) && pTab[nTab] ) + return pTab[nTab]->IsPendingRowHeights(); + + return FALSE; +} + + +void ScDocument::SetPendingRowHeights( SCTAB nTab, BOOL bSet ) +{ + if ( ValidTab(nTab) && pTab[nTab] ) + pTab[nTab]->SetPendingRowHeights( bSet ); +} + + void ScDocument::SetLayoutRTL( SCTAB nTab, BOOL bRTL ) { if ( ValidTab(nTab) && pTab[nTab] ) @@ -657,6 +674,43 @@ void ScDocument::LimitChartIfAll( ScRangeListRef& rRangeList ) } +void lcl_GetFirstTabRange( SCTAB& rTabRangeStart, SCTAB& rTabRangeEnd, const ScMarkData* pTabMark ) +{ + // without ScMarkData, leave start/end unchanged + if ( pTabMark ) + { + for (SCTAB nTab=0; nTab<=MAXTAB; ++nTab) + if (pTabMark->GetTableSelect(nTab)) + { + // find first range of consecutive selected sheets + rTabRangeStart = nTab; + while ( nTab+1 <= MAXTAB && pTabMark->GetTableSelect(nTab+1) ) + ++nTab; + rTabRangeEnd = nTab; + return; + } + } +} + +bool lcl_GetNextTabRange( SCTAB& rTabRangeStart, SCTAB& rTabRangeEnd, const ScMarkData* pTabMark ) +{ + if ( pTabMark ) + { + // find next range of consecutive selected sheets after rTabRangeEnd + for (SCTAB nTab=rTabRangeEnd+1; nTab<=MAXTAB; ++nTab) + if (pTabMark->GetTableSelect(nTab)) + { + rTabRangeStart = nTab; + while ( nTab+1 <= MAXTAB && pTabMark->GetTableSelect(nTab+1) ) + ++nTab; + rTabRangeEnd = nTab; + return true; + } + } + return false; +} + + BOOL ScDocument::CanInsertRow( const ScRange& rRange ) const { SCCOL nStartCol = rRange.aStart.Col(); @@ -681,39 +735,60 @@ BOOL ScDocument::CanInsertRow( const ScRange& rRange ) const BOOL ScDocument::InsertRow( SCCOL nStartCol, SCTAB nStartTab, SCCOL nEndCol, SCTAB nEndTab, - SCROW nStartRow, SCSIZE nSize, ScDocument* pRefUndoDoc ) + SCROW nStartRow, SCSIZE nSize, ScDocument* pRefUndoDoc, + const ScMarkData* pTabMark ) { SCTAB i; PutInOrder( nStartCol, nEndCol ); PutInOrder( nStartTab, nEndTab ); + if ( pTabMark ) + { + nStartTab = 0; + nEndTab = MAXTAB; + } BOOL bTest = TRUE; BOOL bRet = FALSE; BOOL bOldAutoCalc = GetAutoCalc(); SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden for ( i = nStartTab; i <= nEndTab && bTest; i++) - if (pTab[i]) + if (pTab[i] && (!pTabMark || pTabMark->GetTableSelect(i))) bTest &= pTab[i]->TestInsertRow( nStartCol, nEndCol, nSize ); if (bTest) { // UpdateBroadcastAreas muss vor UpdateReference gerufen werden, damit nicht // Eintraege verschoben werden, die erst bei UpdateReference neu erzeugt werden - UpdateBroadcastAreas( URM_INSDEL, ScRange( - ScAddress( nStartCol, nStartRow, nStartTab ), - ScAddress( nEndCol, MAXROW, nEndTab )), 0, static_cast<SCsROW>(nSize), 0 ); - UpdateReference( URM_INSDEL, nStartCol, nStartRow, nStartTab, - nEndCol, MAXROW, nEndTab, - 0, static_cast<SCsROW>(nSize), 0, pRefUndoDoc, FALSE ); // without drawing objects + // handle chunks of consecutive selected sheets together + SCTAB nTabRangeStart = nStartTab; + SCTAB nTabRangeEnd = nEndTab; + lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ); + do + { + UpdateBroadcastAreas( URM_INSDEL, ScRange( + ScAddress( nStartCol, nStartRow, nTabRangeStart ), + ScAddress( nEndCol, MAXROW, nTabRangeEnd )), 0, static_cast<SCsROW>(nSize), 0 ); + } + while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) ); + + lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ); + do + { + UpdateReference( URM_INSDEL, nStartCol, nStartRow, nTabRangeStart, + nEndCol, MAXROW, nTabRangeEnd, + 0, static_cast<SCsROW>(nSize), 0, pRefUndoDoc, FALSE ); // without drawing objects + } + while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) ); + for (i=nStartTab; i<=nEndTab; i++) - if (pTab[i]) + if (pTab[i] && (!pTabMark || pTabMark->GetTableSelect(i))) pTab[i]->InsertRow( nStartCol, nEndCol, nStartRow, nSize ); // #82991# UpdateRef for drawing layer must be after inserting, // when the new row heights are known. for (i=nStartTab; i<=nEndTab; i++) - if (pTab[i]) + if (pTab[i] && (!pTabMark || pTabMark->GetTableSelect(i))) pTab[i]->UpdateDrawRef( URM_INSDEL, nStartCol, nStartRow, nStartTab, nEndCol, MAXROW, nEndTab, 0, static_cast<SCsROW>(nSize), 0 ); @@ -756,42 +831,61 @@ BOOL ScDocument::InsertRow( const ScRange& rRange, ScDocument* pRefUndoDoc ) void ScDocument::DeleteRow( SCCOL nStartCol, SCTAB nStartTab, SCCOL nEndCol, SCTAB nEndTab, SCROW nStartRow, SCSIZE nSize, - ScDocument* pRefUndoDoc, BOOL* pUndoOutline ) + ScDocument* pRefUndoDoc, BOOL* pUndoOutline, + const ScMarkData* pTabMark ) { SCTAB i; PutInOrder( nStartCol, nEndCol ); PutInOrder( nStartTab, nEndTab ); + if ( pTabMark ) + { + nStartTab = 0; + nEndTab = MAXTAB; + } BOOL bOldAutoCalc = GetAutoCalc(); SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden - if ( ValidRow(nStartRow+nSize) ) + // handle chunks of consecutive selected sheets together + SCTAB nTabRangeStart = nStartTab; + SCTAB nTabRangeEnd = nEndTab; + lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ); + do { - DelBroadcastAreasInRange( ScRange( - ScAddress( nStartCol, nStartRow, nStartTab ), - ScAddress( nEndCol, nStartRow+nSize-1, nEndTab ) ) ); - UpdateBroadcastAreas( URM_INSDEL, ScRange( - ScAddress( nStartCol, nStartRow+nSize, nStartTab ), - ScAddress( nEndCol, MAXROW, nEndTab )), 0, -(static_cast<SCsROW>(nSize)), 0 ); + if ( ValidRow(nStartRow+nSize) ) + { + DelBroadcastAreasInRange( ScRange( + ScAddress( nStartCol, nStartRow, nTabRangeStart ), + ScAddress( nEndCol, nStartRow+nSize-1, nTabRangeEnd ) ) ); + UpdateBroadcastAreas( URM_INSDEL, ScRange( + ScAddress( nStartCol, nStartRow+nSize, nTabRangeStart ), + ScAddress( nEndCol, MAXROW, nTabRangeEnd )), 0, -(static_cast<SCsROW>(nSize)), 0 ); + } + else + DelBroadcastAreasInRange( ScRange( + ScAddress( nStartCol, nStartRow, nTabRangeStart ), + ScAddress( nEndCol, MAXROW, nTabRangeEnd ) ) ); } - else - DelBroadcastAreasInRange( ScRange( - ScAddress( nStartCol, nStartRow, nStartTab ), - ScAddress( nEndCol, MAXROW, nEndTab ) ) ); + while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) ); if ( ValidRow(nStartRow+nSize) ) { - UpdateReference( URM_INSDEL, nStartCol, nStartRow+nSize, nStartTab, - nEndCol, MAXROW, nEndTab, - 0, -(static_cast<SCsROW>(nSize)), 0, pRefUndoDoc ); + lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ); + do + { + UpdateReference( URM_INSDEL, nStartCol, nStartRow+nSize, nTabRangeStart, + nEndCol, MAXROW, nTabRangeEnd, + 0, -(static_cast<SCsROW>(nSize)), 0, pRefUndoDoc ); + } + while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) ); } if (pUndoOutline) *pUndoOutline = FALSE; for ( i = nStartTab; i <= nEndTab; i++) - if (pTab[i]) + if (pTab[i] && (!pTabMark || pTabMark->GetTableSelect(i))) pTab[i]->DeleteRow( nStartCol, nEndCol, nStartRow, nSize, pUndoOutline ); if ( ValidRow(nStartRow+nSize) ) @@ -844,30 +938,51 @@ BOOL ScDocument::CanInsertCol( const ScRange& rRange ) const BOOL ScDocument::InsertCol( SCROW nStartRow, SCTAB nStartTab, SCROW nEndRow, SCTAB nEndTab, - SCCOL nStartCol, SCSIZE nSize, ScDocument* pRefUndoDoc ) + SCCOL nStartCol, SCSIZE nSize, ScDocument* pRefUndoDoc, + const ScMarkData* pTabMark ) { SCTAB i; PutInOrder( nStartRow, nEndRow ); PutInOrder( nStartTab, nEndTab ); + if ( pTabMark ) + { + nStartTab = 0; + nEndTab = MAXTAB; + } BOOL bTest = TRUE; BOOL bRet = FALSE; BOOL bOldAutoCalc = GetAutoCalc(); SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden for ( i = nStartTab; i <= nEndTab && bTest; i++) - if (pTab[i]) + if (pTab[i] && (!pTabMark || pTabMark->GetTableSelect(i))) bTest &= pTab[i]->TestInsertCol( nStartRow, nEndRow, nSize ); if (bTest) { - UpdateBroadcastAreas( URM_INSDEL, ScRange( - ScAddress( nStartCol, nStartRow, nStartTab ), - ScAddress( MAXCOL, nEndRow, nEndTab )), static_cast<SCsCOL>(nSize), 0, 0 ); - UpdateReference( URM_INSDEL, nStartCol, nStartRow, nStartTab, - MAXCOL, nEndRow, nEndTab, - static_cast<SCsCOL>(nSize), 0, 0, pRefUndoDoc ); + // handle chunks of consecutive selected sheets together + SCTAB nTabRangeStart = nStartTab; + SCTAB nTabRangeEnd = nEndTab; + lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ); + do + { + UpdateBroadcastAreas( URM_INSDEL, ScRange( + ScAddress( nStartCol, nStartRow, nTabRangeStart ), + ScAddress( MAXCOL, nEndRow, nTabRangeEnd )), static_cast<SCsCOL>(nSize), 0, 0 ); + } + while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) ); + + lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ); + do + { + UpdateReference( URM_INSDEL, nStartCol, nStartRow, nTabRangeStart, + MAXCOL, nEndRow, nTabRangeEnd, + static_cast<SCsCOL>(nSize), 0, 0, pRefUndoDoc ); + } + while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) ); + for (i=nStartTab; i<=nEndTab; i++) - if (pTab[i]) + if (pTab[i] && (!pTabMark || pTabMark->GetTableSelect(i))) pTab[i]->InsertCol( nStartCol, nStartRow, nEndRow, nSize ); if ( pChangeTrack && pChangeTrack->IsInDeleteUndo() ) @@ -907,42 +1022,60 @@ BOOL ScDocument::InsertCol( const ScRange& rRange, ScDocument* pRefUndoDoc ) void ScDocument::DeleteCol(SCROW nStartRow, SCTAB nStartTab, SCROW nEndRow, SCTAB nEndTab, SCCOL nStartCol, SCSIZE nSize, ScDocument* pRefUndoDoc, - BOOL* pUndoOutline ) + BOOL* pUndoOutline, const ScMarkData* pTabMark ) { SCTAB i; PutInOrder( nStartRow, nEndRow ); PutInOrder( nStartTab, nEndTab ); + if ( pTabMark ) + { + nStartTab = 0; + nEndTab = MAXTAB; + } BOOL bOldAutoCalc = GetAutoCalc(); SetAutoCalc( FALSE ); // Mehrfachberechnungen vermeiden - if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) ) + // handle chunks of consecutive selected sheets together + SCTAB nTabRangeStart = nStartTab; + SCTAB nTabRangeEnd = nEndTab; + lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ); + do { - DelBroadcastAreasInRange( ScRange( - ScAddress( nStartCol, nStartRow, nStartTab ), - ScAddress( sal::static_int_cast<SCCOL>(nStartCol+nSize-1), nEndRow, nEndTab ) ) ); - UpdateBroadcastAreas( URM_INSDEL, ScRange( - ScAddress( sal::static_int_cast<SCCOL>(nStartCol+nSize), nStartRow, nStartTab ), - ScAddress( MAXCOL, nEndRow, nEndTab )), -static_cast<SCsCOL>(nSize), 0, 0 ); + if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) ) + { + DelBroadcastAreasInRange( ScRange( + ScAddress( nStartCol, nStartRow, nTabRangeStart ), + ScAddress( sal::static_int_cast<SCCOL>(nStartCol+nSize-1), nEndRow, nTabRangeEnd ) ) ); + UpdateBroadcastAreas( URM_INSDEL, ScRange( + ScAddress( sal::static_int_cast<SCCOL>(nStartCol+nSize), nStartRow, nTabRangeStart ), + ScAddress( MAXCOL, nEndRow, nTabRangeEnd )), -static_cast<SCsCOL>(nSize), 0, 0 ); + } + else + DelBroadcastAreasInRange( ScRange( + ScAddress( nStartCol, nStartRow, nTabRangeStart ), + ScAddress( MAXCOL, nEndRow, nTabRangeEnd ) ) ); } - else - DelBroadcastAreasInRange( ScRange( - ScAddress( nStartCol, nStartRow, nStartTab ), - ScAddress( MAXCOL, nEndRow, nEndTab ) ) ); + while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) ); if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) ) { - UpdateReference( URM_INSDEL, sal::static_int_cast<SCCOL>(nStartCol+nSize), nStartRow, nStartTab, - MAXCOL, nEndRow, nEndTab, - -static_cast<SCsCOL>(nSize), 0, 0, pRefUndoDoc ); + lcl_GetFirstTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ); + do + { + UpdateReference( URM_INSDEL, sal::static_int_cast<SCCOL>(nStartCol+nSize), nStartRow, nTabRangeStart, + MAXCOL, nEndRow, nTabRangeEnd, + -static_cast<SCsCOL>(nSize), 0, 0, pRefUndoDoc ); + } + while ( lcl_GetNextTabRange( nTabRangeStart, nTabRangeEnd, pTabMark ) ); } if (pUndoOutline) *pUndoOutline = FALSE; for ( i = nStartTab; i <= nEndTab; i++) - if (pTab[i]) + if (pTab[i] && (!pTabMark || pTabMark->GetTableSelect(i))) pTab[i]->DeleteCol( nStartCol, nStartRow, nEndRow, nSize, pUndoOutline ); if ( ValidCol(sal::static_int_cast<SCCOL>(nStartCol+nSize)) ) @@ -1781,9 +1914,17 @@ void ScDocument::CopyFromClip( const ScRange& rDestRange, const ScMarkData& rMar nXw = sal::static_int_cast<SCCOL>( nXw + nDestAddX ); nYw = sal::static_int_cast<SCROW>( nYw + nDestAddY ); // ClipArea, plus ExtendMerge value - // Inhalte entweder komplett oder gar nicht loeschen: + /* Decide which contents to delete before copying. Delete all + contents if nInsFlag contains any real content flag. + #i102056# Notes are pasted from clipboard in a second pass, + together with the special flag IDF_ADDNOTES that states to not + overwrite/delete existing cells but to insert the notes into + these cells. In this case, just delete old notes from the + destination area. */ USHORT nDelFlag = IDF_NONE; - if ( nInsFlag & IDF_CONTENTS ) + if ( (nInsFlag & (IDF_CONTENTS | IDF_ADDNOTES)) == (IDF_NOTE | IDF_ADDNOTES) ) + nDelFlag |= IDF_NOTE; + else if ( nInsFlag & IDF_CONTENTS ) nDelFlag |= IDF_CONTENTS; // With bSkipAttrForEmpty, don't remove attributes, copy // on top of existing attributes instead. @@ -2343,7 +2484,7 @@ void ScDocument::GetCell( SCCOL nCol, SCROW nRow, SCTAB nTab, ScBaseCell* ScDocument::GetCell( const ScAddress& rPos ) const { SCTAB nTab = rPos.Tab(); - if ( pTab[nTab] ) + if (ValidTab(nTab) && pTab[nTab]) return pTab[nTab]->GetCell( rPos ); DBG_ERROR("GetCell ohne Tabelle"); @@ -2443,6 +2584,18 @@ void ScDocument::DeleteNote( const ScAddress& rPos ) } +void ScDocument::InitializeNoteCaptions( SCTAB nTab, bool bForced ) +{ + if( ValidTab( nTab ) && pTab[ nTab ] ) + pTab[ nTab ]->InitializeNoteCaptions( bForced ); +} + +void ScDocument::InitializeAllNoteCaptions( bool bForced ) +{ + for( SCTAB nTab = 0; nTab < GetTableCount(); ++nTab ) + InitializeNoteCaptions( nTab, bForced ); +} + void ScDocument::SetDirty() { BOOL bOldAutoCalc = GetAutoCalc(); @@ -2808,14 +2961,20 @@ BOOL ScDocument::SetOptimalHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab, U void ScDocument::UpdateAllRowHeights( OutputDevice* pDev, double nPPTX, double nPPTY, - const Fraction& rZoomX, const Fraction& rZoomY ) + const Fraction& rZoomX, const Fraction& rZoomY, const ScMarkData* pTabMark ) { - // one progress across all sheets - ScProgress aProgress( GetDocumentShell(), ScGlobal::GetRscString(STR_PROGRESS_HEIGHTING), GetWeightedCount() ); + // one progress across all (selected) sheets + + ULONG nCellCount = 0; + for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ ) + if ( pTab[nTab] && ( !pTabMark || pTabMark->GetTableSelect(nTab) ) ) + nCellCount += pTab[nTab]->GetWeightedCount(); + + ScProgress aProgress( GetDocumentShell(), ScGlobal::GetRscString(STR_PROGRESS_HEIGHTING), nCellCount ); ULONG nProgressStart = 0; for ( SCTAB nTab=0; nTab<=MAXTAB; nTab++ ) - if ( pTab[nTab] ) + if ( pTab[nTab] && ( !pTabMark || pTabMark->GetTableSelect(nTab) ) ) { pTab[nTab]->SetOptimalHeight( 0, MAXROW, 0, pDev, nPPTX, nPPTY, rZoomX, rZoomY, FALSE, &aProgress, nProgressStart ); @@ -3980,24 +4139,6 @@ BOOL ScDocument::RefreshAutoFilter( SCCOL nStartCol, SCROW nStartRow, } -//UNUSED2008-05 void ScDocument::SetAutoFilterFlags() -//UNUSED2008-05 { -//UNUSED2008-05 USHORT nCount = pDBCollection->GetCount(); -//UNUSED2008-05 for (USHORT i=0; i<nCount; i++) -//UNUSED2008-05 { -//UNUSED2008-05 ScDBData* pData = (*pDBCollection)[i]; -//UNUSED2008-05 SCTAB nDBTab; -//UNUSED2008-05 SCCOL nDBStartCol; -//UNUSED2008-05 SCROW nDBStartRow; -//UNUSED2008-05 SCCOL nDBEndCol; -//UNUSED2008-05 SCROW nDBEndRow; -//UNUSED2008-05 pData->GetArea( nDBTab, nDBStartCol,nDBStartRow, nDBEndCol,nDBEndRow ); -//UNUSED2008-05 pData->SetAutoFilter( HasAttrib( nDBStartCol,nDBStartRow,nDBTab, -//UNUSED2008-05 nDBEndCol,nDBStartRow,nDBTab, HASATTR_AUTOFILTER ) ); -//UNUSED2008-05 } -//UNUSED2008-05 } - - BOOL ScDocument::IsHorOverlapped( SCCOL nCol, SCROW nRow, SCTAB nTab ) const { const ScMergeFlagAttr* pAttr = (const ScMergeFlagAttr*) @@ -4030,16 +4171,21 @@ void ScDocument::ApplySelectionFrame( const ScMarkData& rMark, const SvxBoxItem* pLineOuter, const SvxBoxInfoItem* pLineInner ) { - if (rMark.IsMarked()) + ScRangeList aRangeList; + rMark.FillRangeListWithMarks( &aRangeList, FALSE ); + ULONG nRangeCount = aRangeList.Count(); + for (SCTAB i=0; i<=MAXTAB; i++) { - ScRange aRange; - rMark.GetMarkArea(aRange); - for (SCTAB i=0; i<=MAXTAB; i++) - if (pTab[i]) - if (rMark.GetTableSelect(i)) - pTab[i]->ApplyBlockFrame( pLineOuter, pLineInner, - aRange.aStart.Col(), aRange.aStart.Row(), - aRange.aEnd.Col(), aRange.aEnd.Row() ); + if (pTab[i] && rMark.GetTableSelect(i)) + { + for (ULONG j=0; j<nRangeCount; j++) + { + ScRange aRange = *aRangeList.GetObject(j); + pTab[i]->ApplyBlockFrame( pLineOuter, pLineInner, + aRange.aStart.Col(), aRange.aStart.Row(), + aRange.aEnd.Col(), aRange.aEnd.Row() ); + } + } } } diff --git a/sc/source/core/data/dpobject.cxx b/sc/source/core/data/dpobject.cxx index 12af06a773ed..813a3381c901 100644 --- a/sc/source/core/data/dpobject.cxx +++ b/sc/source/core/data/dpobject.cxx @@ -466,7 +466,7 @@ ScRange ScDPObject::GetNewOutputRange( BOOL& rOverflow ) } } -void ScDPObject::Output() +void ScDPObject::Output( const ScAddress& rPos ) { // clear old output area pDoc->DeleteAreaTab( aOutRange.aStart.Col(), aOutRange.aStart.Row(), @@ -478,6 +478,8 @@ void ScDPObject::Output() CreateOutput(); // create xSource and pOutput if not already done + pOutput->SetPosition( rPos ); + pOutput->Output(); // aOutRange is always the range that was last output to the document @@ -2337,7 +2339,7 @@ ScDPCollection::ScDPCollection(const ScDPCollection& r) : ScCollection(r), pDoc(r.pDoc), maSharedString(r.maSharedString), - maCacheCellPool(r.maCacheCellPool) + maCacheCellPool() // #i101725# don't copy hash_set with pointers from the other collection { } @@ -2499,8 +2501,9 @@ void ScDPCollection::clearCacheCellPool() vector<ScDPCacheCell*> ps; ps.reserve(maCacheCellPool.size()); copy(maCacheCellPool.begin(), maCacheCellPool.end(), back_inserter(ps)); - for_each(ps.begin(), ps.end(), DeleteCacheCells()); maCacheCellPool.clear(); + // for correctness' sake, delete the elements after clearing the hash_set + for_each(ps.begin(), ps.end(), DeleteCacheCells()); } //------------------------------------------------------------------------ diff --git a/sc/source/core/data/drwlayer.cxx b/sc/source/core/data/drwlayer.cxx index 6d1e1eb70674..a5c571026e96 100644 --- a/sc/source/core/data/drwlayer.cxx +++ b/sc/source/core/data/drwlayer.cxx @@ -493,7 +493,7 @@ void ScDrawLayer::MoveCells( SCTAB nTab, SCCOL nCol1,SCROW nRow1, SCCOL nCol2,SC if ( pObj->ISA( SdrRectObj ) && pData->maStart.IsValid() && pData->maEnd.IsValid() ) pData->maStart.PutInOrder( pData->maEnd ); AddCalcUndo( new ScUndoObjData( pObj, aOldStt, aOldEnd, pData->maStart, pData->maEnd ) ); - RecalcPos( pObj, *pData, aOldStt, aOldEnd, bNegativePage ); + RecalcPos( pObj, *pData, bNegativePage ); } } } @@ -522,27 +522,33 @@ void ScDrawLayer::SetPageSize( USHORT nPageNo, const Size& rSize ) SdrObject* pObj = pPage->GetObj( i ); ScDrawObjData* pData = GetObjDataTab( pObj, static_cast<SCTAB>(nPageNo) ); if( pData ) - RecalcPos( pObj, *pData, pData->maStart, pData->maEnd, bNegativePage ); + RecalcPos( pObj, *pData, bNegativePage ); } } } -void ScDrawLayer::RecalcPos( SdrObject* pObj, const ScDrawObjData& rData, - const ScAddress& rOldStart, const ScAddress& /*rOldEnd*/, bool bNegativePage ) +void ScDrawLayer::RecalcPos( SdrObject* pObj, const ScDrawObjData& rData, bool bNegativePage ) { DBG_ASSERT( pDoc, "ScDrawLayer::RecalcPos - missing document" ); if( !pDoc ) return; + /* TODO CleanUp: Updating note position works just by chance currently... + When inserting rows/columns, this function is called after the + insertion, and the note is located at the new position contained in the + passed ScDrawObjData already. But when deleting rows/columns, this + function is called *before* the deletion, so the note is still at the + old cell position, and ScDocument::GetNote() will fail to get the note + or will get another note. But after the rows/columns are deleted, a + call to ScDrawLayer::SetPageSize() will call this function again, and + now the note is at the expected position in the document. */ if( rData.mbNote ) { - /* #i63671# while inserting/deleting cells/rows/columns: note has - not been moved yet in document, get it from old position. */ - DBG_ASSERT( rOldStart.IsValid(), "ScDrawLayer::RecalcPos - invalid position for cell note" ); + DBG_ASSERT( rData.maStart.IsValid(), "ScDrawLayer::RecalcPos - invalid position for cell note" ); /* When inside an undo action, there may be pending note captions where cell note is already deleted. The caption will be deleted later with drawing undo. */ - if( ScPostIt* pNote = pDoc->GetNote( rOldStart ) ) + if( ScPostIt* pNote = pDoc->GetNote( rData.maStart ) ) pNote->UpdateCaptionPos( rData.maStart ); return; } diff --git a/sc/source/core/data/makefile.mk b/sc/source/core/data/makefile.mk index 7129198c204f..29618da6630b 100644 --- a/sc/source/core/data/makefile.mk +++ b/sc/source/core/data/makefile.mk @@ -108,6 +108,7 @@ SLOFILES = \ $(SLO)$/table4.obj \ $(SLO)$/table5.obj \ $(SLO)$/table6.obj \ + $(SLO)$/tabprotection.obj \ $(SLO)$/userdat.obj \ $(SLO)$/validat.obj \ $(SLO)$/postit.obj @@ -127,7 +128,9 @@ EXCEPTIONSFILES= \ $(SLO)$/dptabdat.obj \ $(SLO)$/global2.obj \ $(SLO)$/table1.obj \ + $(SLO)$/table2.obj \ $(SLO)$/table3.obj \ + $(SLO)$/tabprotection.obj \ $(SLO)$/postit.obj \ $(SLO)$/documen3.obj \ $(SLO)$/documen5.obj \ diff --git a/sc/source/core/data/postit.cxx b/sc/source/core/data/postit.cxx index 068ec3ade5e5..c53694b7674c 100644 --- a/sc/source/core/data/postit.cxx +++ b/sc/source/core/data/postit.cxx @@ -33,6 +33,7 @@ #include "postit.hxx" +#include <rtl/ustrbuf.hxx> #include <svtools/useroptions.hxx> #include <svx/svdpage.hxx> #include <svx/svdocapt.hxx> @@ -57,6 +58,9 @@ #include "userdat.hxx" #include "detfunc.hxx" +using ::rtl::OUString; +using ::rtl::OUStringBuffer; + // ============================================================================ namespace { @@ -69,8 +73,107 @@ const long SC_NOTECAPTION_OFFSET_Y = -1500; /// Default Y offset of const long SC_NOTECAPTION_OFFSET_X = 1500; /// Default X offset of note captions to left border of anchor cell. const long SC_NOTECAPTION_BORDERDIST_TEMP = 100; /// Distance of temporary note captions to visible sheet area. +// ============================================================================ + +/** Static helper functions for caption objects. */ +class ScCaptionUtil +{ +public: + /** Moves the caption object to the correct layer according to passed visibility. */ + static void SetCaptionLayer( SdrCaptionObj& rCaption, bool bShown ); + /** Sets basic caption settings required for note caption objects. */ + static void SetBasicCaptionSettings( SdrCaptionObj& rCaption, bool bShown ); + /** Stores the cell position of the note in the user data area of the caption. */ + static void SetCaptionUserData( SdrCaptionObj& rCaption, const ScAddress& rPos ); + /** Sets all default formatting attributes to the caption object. */ + static void SetDefaultItems( SdrCaptionObj& rCaption, ScDocument& rDoc ); + /** Updates caption item set according to the passed item set while removing shadow items. */ + static void SetCaptionItems( SdrCaptionObj& rCaption, const SfxItemSet& rItemSet ); +}; + // ---------------------------------------------------------------------------- +void ScCaptionUtil::SetCaptionLayer( SdrCaptionObj& rCaption, bool bShown ) +{ + SdrLayerID nLayer = bShown ? SC_LAYER_INTERN : SC_LAYER_HIDDEN; + if( nLayer != rCaption.GetLayer() ) + rCaption.SetLayer( nLayer ); +} + +void ScCaptionUtil::SetBasicCaptionSettings( SdrCaptionObj& rCaption, bool bShown ) +{ + ScDrawLayer::SetAnchor( &rCaption, SCA_PAGE ); + SetCaptionLayer( rCaption, bShown ); + rCaption.SetFixedTail(); + rCaption.SetSpecialTextBoxShadow(); +} + +void ScCaptionUtil::SetCaptionUserData( SdrCaptionObj& rCaption, const ScAddress& rPos ) +{ + // pass true to ScDrawLayer::GetObjData() to create the object data entry + ScDrawObjData* pObjData = ScDrawLayer::GetObjData( &rCaption, true ); + OSL_ENSURE( pObjData, "ScCaptionUtil::SetCaptionUserData - missing drawing object user data" ); + pObjData->maStart = rPos; + pObjData->mbNote = true; +} + +void ScCaptionUtil::SetDefaultItems( SdrCaptionObj& rCaption, ScDocument& rDoc ) +{ + SfxItemSet aItemSet = rCaption.GetMergedItemSet(); + + // caption tail arrow + ::basegfx::B2DPolygon aTriangle; + aTriangle.append( ::basegfx::B2DPoint( 10.0, 0.0 ) ); + aTriangle.append( ::basegfx::B2DPoint( 0.0, 30.0 ) ); + aTriangle.append( ::basegfx::B2DPoint( 20.0, 30.0 ) ); + aTriangle.setClosed( true ); + /* #99319# Line ends are now created with an empty name. The + checkForUniqueItem() method then finds a unique name for the item's + value. */ + aItemSet.Put( XLineStartItem( String::EmptyString(), ::basegfx::B2DPolyPolygon( aTriangle ) ) ); + aItemSet.Put( XLineStartWidthItem( 200 ) ); + aItemSet.Put( XLineStartCenterItem( FALSE ) ); + aItemSet.Put( XFillStyleItem( XFILL_SOLID ) ); + aItemSet.Put( XFillColorItem( String::EmptyString(), ScDetectiveFunc::GetCommentColor() ) ); + aItemSet.Put( SdrCaptionEscDirItem( SDRCAPT_ESCBESTFIT ) ); + + // shadow + /* SdrShadowItem has FALSE, instead the shadow is set for the + rectangle only with SetSpecialTextBoxShadow() when the object is + created (item must be set to adjust objects from older files). */ + aItemSet.Put( SdrShadowItem( FALSE ) ); + aItemSet.Put( SdrShadowXDistItem( 100 ) ); + aItemSet.Put( SdrShadowYDistItem( 100 ) ); + + // text attributes + aItemSet.Put( SdrTextLeftDistItem( 100 ) ); + aItemSet.Put( SdrTextRightDistItem( 100 ) ); + aItemSet.Put( SdrTextUpperDistItem( 100 ) ); + aItemSet.Put( SdrTextLowerDistItem( 100 ) ); + aItemSet.Put( SdrTextAutoGrowWidthItem( FALSE ) ); + aItemSet.Put( SdrTextAutoGrowHeightItem( TRUE ) ); + // #78943# use the default cell style to be able to modify the caption font + const ScPatternAttr& rDefPattern = static_cast< const ScPatternAttr& >( rDoc.GetPool()->GetDefaultItem( ATTR_PATTERN ) ); + rDefPattern.FillEditItemSet( &aItemSet ); + + rCaption.SetMergedItemSet( aItemSet ); +} + +void ScCaptionUtil::SetCaptionItems( SdrCaptionObj& rCaption, const SfxItemSet& rItemSet ) +{ + // copy all items + rCaption.SetMergedItemSet( rItemSet ); + // reset shadow items + rCaption.SetMergedItem( SdrShadowItem( FALSE ) ); + rCaption.SetMergedItem( SdrShadowXDistItem( 100 ) ); + rCaption.SetMergedItem( SdrShadowYDistItem( 100 ) ); + rCaption.SetSpecialTextBoxShadow(); +} + +// ============================================================================ + +/** Helper for creation and manipulation of caption drawing objects independent + from cell annotations. */ class ScCaptionCreator { public: @@ -79,27 +182,32 @@ public: /** Manipulate an existing caption. */ explicit ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, SdrCaptionObj& rCaption ); + /** Returns the drawing layer page of the sheet contained in maPos. */ + SdrPage* GetDrawPage(); /** Returns the caption drawing obejct. */ inline SdrCaptionObj* GetCaption() { return mpCaption; } /** Moves the caption inside the passed rectangle. Uses page area if 0 is passed. */ void FitCaptionToRect( const Rectangle* pVisRect = 0 ); - /** Places the passed caption inside the passed rectangle, tries to keep the cell rectangle uncovered. Uses page area if 0 is passed. */ + /** Places the caption inside the passed rectangle, tries to keep the cell rectangle uncovered. Uses page area if 0 is passed. */ void AutoPlaceCaption( const Rectangle* pVisRect = 0 ); /** Updates caption tail and textbox according to current cell position. Uses page area if 0 is passed. */ void UpdateCaptionPos( const Rectangle* pVisRect = 0 ); - /** Sets all default formatting attributes to the caption object. */ - void SetDefaultItems(); - /** Updates caption itemset according to the passed item set while removing shadow items. */ - void SetCaptionItems( const SfxItemSet& rItemSet ); + +protected: + /** Helper constructor for derived classes. */ + explicit ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos ); + + /** Calculates the caption tail position according to current cell position. */ + Point CalcTailPos( bool bTailFront ); + /** Implements creation of the caption object. The caption will not be inserted into the document. */ + void CreateCaption( bool bShown, bool bTailFront ); private: /** Initializes all members. */ void Initialize(); /** Returns the passed rectangle if existing, page rectangle otherwise. */ inline const Rectangle& GetVisRect( const Rectangle* pVisRect ) const { return pVisRect ? *pVisRect : maPageRect; } - /** Calculates the caption tail position according to current cell position. */ - Point CalcTailPos( bool bTailFront ); private: ScDocument& mrDoc; @@ -118,17 +226,7 @@ ScCaptionCreator::ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, boo mpCaption( 0 ) { Initialize(); - - // create the caption drawing object - Rectangle aTextRect( Point( 0 , 0 ), Size( SC_NOTECAPTION_WIDTH, SC_NOTECAPTION_HEIGHT ) ); - Point aTailPos = CalcTailPos( bTailFront ); - mpCaption = new SdrCaptionObj( aTextRect, aTailPos ); - - // basic settings - ScDrawLayer::SetAnchor( mpCaption, SCA_PAGE ); - mpCaption->SetLayer( bShown ? SC_LAYER_INTERN : SC_LAYER_HIDDEN ); - mpCaption->SetFixedTail(); - mpCaption->SetSpecialTextBoxShadow(); + CreateCaption( bShown, bTailFront ); } ScCaptionCreator::ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, SdrCaptionObj& rCaption ) : @@ -139,6 +237,20 @@ ScCaptionCreator::ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, Sdr Initialize(); } +ScCaptionCreator::ScCaptionCreator( ScDocument& rDoc, const ScAddress& rPos ) : + mrDoc( rDoc ), + maPos( rPos ), + mpCaption( 0 ) +{ + Initialize(); +} + +SdrPage* ScCaptionCreator::GetDrawPage() +{ + ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer(); + return pDrawLayer ? pDrawLayer->GetPage( static_cast< sal_uInt16 >( maPos.Tab() ) ) : 0; +} + void ScCaptionCreator::FitCaptionToRect( const Rectangle* pVisRect ) { const Rectangle& rVisRect = GetVisRect( pVisRect ); @@ -269,98 +381,131 @@ void ScCaptionCreator::UpdateCaptionPos( const Rectangle* pVisRect ) } } -void ScCaptionCreator::SetDefaultItems() +Point ScCaptionCreator::CalcTailPos( bool bTailFront ) { - SfxItemSet aItemSet = mpCaption->GetMergedItemSet(); - - // caption tail arrow - ::basegfx::B2DPolygon aTriangle; - aTriangle.append( ::basegfx::B2DPoint( 10.0, 0.0 ) ); - aTriangle.append( ::basegfx::B2DPoint( 0.0, 30.0 ) ); - aTriangle.append( ::basegfx::B2DPoint( 20.0, 30.0 ) ); - aTriangle.setClosed( true ); - /* #99319# Line ends are now created with an empty name. The - checkForUniqueItem() method then finds a unique name for the item's - value. */ - aItemSet.Put( XLineStartItem( String::EmptyString(), ::basegfx::B2DPolyPolygon( aTriangle ) ) ); - aItemSet.Put( XLineStartWidthItem( 200 ) ); - aItemSet.Put( XLineStartCenterItem( FALSE ) ); - aItemSet.Put( XFillStyleItem( XFILL_SOLID ) ); - aItemSet.Put( XFillColorItem( String::EmptyString(), ScDetectiveFunc::GetCommentColor() ) ); - aItemSet.Put( SdrCaptionEscDirItem( SDRCAPT_ESCBESTFIT ) ); - - // shadow - /* SdrShadowItem has FALSE, instead the shadow is set for the - rectangle only with SetSpecialTextBoxShadow when the object is - created (item must be set to adjust objects from older files). */ - aItemSet.Put( SdrShadowItem( FALSE ) ); - aItemSet.Put( SdrShadowXDistItem( 100 ) ); - aItemSet.Put( SdrShadowYDistItem( 100 ) ); - - // text attributes - aItemSet.Put( SdrTextLeftDistItem( 100 ) ); - aItemSet.Put( SdrTextRightDistItem( 100 ) ); - aItemSet.Put( SdrTextUpperDistItem( 100 ) ); - aItemSet.Put( SdrTextLowerDistItem( 100 ) ); - aItemSet.Put( SdrTextAutoGrowWidthItem( FALSE ) ); - aItemSet.Put( SdrTextAutoGrowHeightItem( TRUE ) ); - // #78943# use the default cell style to be able to modify the caption font - const ScPatternAttr& rDefPattern = static_cast< const ScPatternAttr& >( mrDoc.GetPool()->GetDefaultItem( ATTR_PATTERN ) ); - rDefPattern.FillEditItemSet( &aItemSet ); - - mpCaption->SetMergedItemSet( aItemSet ); + // tail position + bool bTailLeft = bTailFront != mbNegPage; + Point aTailPos = bTailLeft ? maCellRect.TopLeft() : maCellRect.TopRight(); + // move caption point 1/10 mm inside cell + if( bTailLeft ) aTailPos.X() += 10; else aTailPos.X() -= 10; + aTailPos.Y() += 10; + return aTailPos; } -void ScCaptionCreator::SetCaptionItems( const SfxItemSet& rItemSet ) +void ScCaptionCreator::CreateCaption( bool bShown, bool bTailFront ) { - // copy all items - mpCaption->SetMergedItemSet( rItemSet ); - // reset shadow items - mpCaption->SetMergedItem( SdrShadowItem( FALSE ) ); - mpCaption->SetMergedItem( SdrShadowXDistItem( 100 ) ); - mpCaption->SetMergedItem( SdrShadowYDistItem( 100 ) ); - mpCaption->SetSpecialTextBoxShadow(); + // create the caption drawing object + Rectangle aTextRect( Point( 0 , 0 ), Size( SC_NOTECAPTION_WIDTH, SC_NOTECAPTION_HEIGHT ) ); + Point aTailPos = CalcTailPos( bTailFront ); + mpCaption = new SdrCaptionObj( aTextRect, aTailPos ); + // basic caption settings + ScCaptionUtil::SetBasicCaptionSettings( *mpCaption, bShown ); } void ScCaptionCreator::Initialize() { maCellRect = ScDrawLayer::GetCellRect( mrDoc, maPos, true ); mbNegPage = mrDoc.IsNegativePage( maPos.Tab() ); + if( SdrPage* pDrawPage = GetDrawPage() ) + { + maPageRect = Rectangle( Point( 0, 0 ), pDrawPage->GetSize() ); + /* #i98141# SdrPage::GetSize() returns negative width in RTL mode. + The call to Rectangle::Adjust() orders left/right coordinate + accordingly. */ + maPageRect.Justify(); + } +} + +// ============================================================================ - if( ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer() ) +/** Helper for creation of permanent caption drawing objects for cell notes. */ +class ScNoteCaptionCreator : public ScCaptionCreator +{ +public: + /** Create a new caption object and inserts it into the document. */ + explicit ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, ScNoteData& rNoteData ); + /** Manipulate an existing caption. */ + explicit ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, SdrCaptionObj& rCaption, bool bShown ); +}; + +// ---------------------------------------------------------------------------- + +ScNoteCaptionCreator::ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, ScNoteData& rNoteData ) : + ScCaptionCreator( rDoc, rPos ) // use helper c'tor that does not create the caption yet +{ + SdrPage* pDrawPage = GetDrawPage(); + OSL_ENSURE( pDrawPage, "ScNoteCaptionCreator::ScNoteCaptionCreator - no drawing page" ); + if( pDrawPage ) { - if( SdrPage* pPage = pDrawLayer->GetPage( static_cast< sal_uInt16 >( maPos.Tab() ) ) ) + // create the caption drawing object + CreateCaption( rNoteData.mbShown, false ); + rNoteData.mpCaption = GetCaption(); + OSL_ENSURE( rNoteData.mpCaption, "ScNoteCaptionCreator::ScNoteCaptionCreator - missing caption object" ); + if( rNoteData.mpCaption ) { - maPageRect = Rectangle( Point( 0, 0 ), pPage->GetSize() ); - /* #i98141# SdrPage::GetSize() returns negative width in RTL mode. - The call to Rectangle::Adjust() orders left/right coordinate - accordingly. */ - maPageRect.Justify(); + // store note position in user data of caption object + ScCaptionUtil::SetCaptionUserData( *rNoteData.mpCaption, rPos ); + // insert object into draw page + pDrawPage->InsertObject( rNoteData.mpCaption ); } } } -Point ScCaptionCreator::CalcTailPos( bool bTailFront ) +ScNoteCaptionCreator::ScNoteCaptionCreator( ScDocument& rDoc, const ScAddress& rPos, SdrCaptionObj& rCaption, bool bShown ) : + ScCaptionCreator( rDoc, rPos, rCaption ) { - // tail position - bool bTailLeft = bTailFront != mbNegPage; - Point aTailPos = bTailLeft ? maCellRect.TopLeft() : maCellRect.TopRight(); - // move caption point 1/10 mm inside cell - if( bTailLeft ) aTailPos.X() += 10; else aTailPos.X() -= 10; - aTailPos.Y() += 10; - return aTailPos; + SdrPage* pDrawPage = GetDrawPage(); + OSL_ENSURE( pDrawPage, "ScNoteCaptionCreator::ScNoteCaptionCreator - no drawing page" ); + OSL_ENSURE( rCaption.GetPage() == pDrawPage, "ScNoteCaptionCreator::ScNoteCaptionCreator - wrong drawing page in caption" ); + if( pDrawPage && (rCaption.GetPage() == pDrawPage) ) + { + // store note position in user data of caption object + ScCaptionUtil::SetCaptionUserData( rCaption, rPos ); + // basic caption settings + ScCaptionUtil::SetBasicCaptionSettings( rCaption, bShown ); + // set correct tail position + rCaption.SetTailPos( CalcTailPos( false ) ); + } } } // namespace // ============================================================================ +struct ScCaptionInitData +{ + typedef ::std::auto_ptr< SfxItemSet > SfxItemSetPtr; + typedef ::std::auto_ptr< OutlinerParaObject > OutlinerParaObjPtr; + + SfxItemSetPtr mxItemSet; /// Caption object formatting. + OutlinerParaObjPtr mxOutlinerObj; /// Text object with all text portion formatting. + ::rtl::OUString maSimpleText; /// Simple text without formatting. + Point maCaptionOffset; /// Caption position relative to cell corner. + Size maCaptionSize; /// Size of the caption object. + bool mbDefaultPosSize; /// True = use default position and size for caption. + + explicit ScCaptionInitData(); +}; + +// ---------------------------------------------------------------------------- + +ScCaptionInitData::ScCaptionInitData() : + mbDefaultPosSize( true ) +{ +} + +// ============================================================================ + ScNoteData::ScNoteData( bool bShown ) : mpCaption( 0 ), mbShown( bShown ) { } +ScNoteData::~ScNoteData() +{ +} + // ============================================================================ ScPostIt::ScPostIt( ScDocument& rDoc, const ScAddress& rPos, bool bShown ) : @@ -379,10 +524,12 @@ ScPostIt::ScPostIt( ScDocument& rDoc, const ScAddress& rPos, const ScPostIt& rNo CreateCaption( rPos, rNote.maNoteData.mpCaption ); } -ScPostIt::ScPostIt( ScDocument& rDoc, const ScNoteData& rNoteData ) : +ScPostIt::ScPostIt( ScDocument& rDoc, const ScAddress& rPos, const ScNoteData& rNoteData, bool bAlwaysCreateCaption ) : mrDoc( rDoc ), maNoteData( rNoteData ) { + if( bAlwaysCreateCaption || maNoteData.mbShown ) + CreateCaptionFromInitData( rPos ); } ScPostIt::~ScPostIt() @@ -390,164 +537,229 @@ ScPostIt::~ScPostIt() RemoveCaption(); } +ScPostIt* ScPostIt::Clone( const ScAddress& rOwnPos, ScDocument& rDestDoc, const ScAddress& rDestPos, bool bCloneCaption ) const +{ + CreateCaptionFromInitData( rOwnPos ); + return bCloneCaption ? new ScPostIt( rDestDoc, rDestPos, *this ) : new ScPostIt( rDestDoc, rDestPos, maNoteData, false ); +} + void ScPostIt::AutoStamp() { maNoteData.maDate = ScGlobal::pLocaleData->getDate( Date() ); maNoteData.maAuthor = SvtUserOptions().GetID(); } -const EditTextObject* ScPostIt::GetEditTextObject() const +const OutlinerParaObject* ScPostIt::GetOutlinerObject() const { if( maNoteData.mpCaption ) - if( const OutlinerParaObject* pOPO = maNoteData.mpCaption->GetOutlinerParaObject() ) - return &pOPO->GetTextObject(); + return maNoteData.mpCaption->GetOutlinerParaObject(); + if( maNoteData.mxInitData.get() ) + return maNoteData.mxInitData->mxOutlinerObj.get(); return 0; } -String ScPostIt::GetText() const +const EditTextObject* ScPostIt::GetEditTextObject() const +{ + const OutlinerParaObject* pOPO = GetOutlinerObject(); + return pOPO ? &pOPO->GetTextObject() : 0; +} + +OUString ScPostIt::GetText() const { - String aText; if( const EditTextObject* pEditObj = GetEditTextObject() ) { + OUStringBuffer aBuffer; for( USHORT nPara = 0, nParaCount = pEditObj->GetParagraphCount(); nPara < nParaCount; ++nPara ) { if( nPara > 0 ) - aText.Append( '\n' ); - aText.Append( pEditObj->GetText( nPara ) ); + aBuffer.append( sal_Unicode( '\n' ) ); + aBuffer.append( pEditObj->GetText( nPara ) ); } + return aBuffer.makeStringAndClear(); } - return aText; + if( maNoteData.mxInitData.get() ) + return maNoteData.mxInitData->maSimpleText; + return OUString(); } bool ScPostIt::HasMultiLineText() const { - const EditTextObject* pEditObj = GetEditTextObject(); - return pEditObj && (pEditObj->GetParagraphCount() > 1); + if( const EditTextObject* pEditObj = GetEditTextObject() ) + return pEditObj->GetParagraphCount() > 1; + if( maNoteData.mxInitData.get() ) + return maNoteData.mxInitData->maSimpleText.indexOf( '\n' ) >= 0; + return false; } -void ScPostIt::SetText( const String& rText ) +void ScPostIt::SetText( const ScAddress& rPos, const OUString& rText ) { + CreateCaptionFromInitData( rPos ); if( maNoteData.mpCaption ) maNoteData.mpCaption->SetText( rText ); } -void ScPostIt::ShowCaption( bool bShow ) +SdrCaptionObj* ScPostIt::GetOrCreateCaption( const ScAddress& rPos ) const { - maNoteData.mbShown = bShow; - UpdateCaptionLayer( maNoteData.mbShown ); + CreateCaptionFromInitData( rPos ); + return maNoteData.mpCaption; } -void ScPostIt::ShowCaptionTemp( bool bShow ) +void ScPostIt::ForgetCaption() { - UpdateCaptionLayer( maNoteData.mbShown || bShow ); + /* This function is used in undo actions to give up the responsibility for + the caption object which is handled by separate drawing undo actions. */ + maNoteData.mpCaption = 0; + maNoteData.mxInitData.reset(); } -void ScPostIt::UpdateCaptionPos( const ScAddress& rPos ) +void ScPostIt::ShowCaption( const ScAddress& rPos, bool bShow ) { + CreateCaptionFromInitData( rPos ); + // no separate drawing undo needed, handled completely inside ScUndoShowHideNote + maNoteData.mbShown = bShow; if( maNoteData.mpCaption ) - { - ScCaptionCreator aCreator( mrDoc, rPos, *maNoteData.mpCaption ); - aCreator.UpdateCaptionPos(); - } + ScCaptionUtil::SetCaptionLayer( *maNoteData.mpCaption, bShow ); } -void ScPostIt::SetCaptionDefaultItems() +void ScPostIt::ShowCaptionTemp( const ScAddress& rPos, bool bShow ) { + CreateCaptionFromInitData( rPos ); if( maNoteData.mpCaption ) - { - ScCaptionCreator aCreator( mrDoc, ScAddress(), *maNoteData.mpCaption ); - aCreator.SetDefaultItems(); - } + ScCaptionUtil::SetCaptionLayer( *maNoteData.mpCaption, maNoteData.mbShown || bShow ); } -void ScPostIt::SetCaptionItems( const SfxItemSet& rItemSet ) +void ScPostIt::UpdateCaptionPos( const ScAddress& rPos ) { + CreateCaptionFromInitData( rPos ); if( maNoteData.mpCaption ) { - ScCaptionCreator aCreator( mrDoc, ScAddress(), *maNoteData.mpCaption ); - aCreator.SetCaptionItems( rItemSet ); + ScCaptionCreator aCreator( mrDoc, rPos, *maNoteData.mpCaption ); + aCreator.UpdateCaptionPos(); } } // private -------------------------------------------------------------------- +void ScPostIt::CreateCaptionFromInitData( const ScAddress& rPos ) const +{ + OSL_ENSURE( maNoteData.mpCaption || maNoteData.mxInitData.get(), "ScPostIt::CreateCaptionFromInitData - need caption object or initial caption data" ); + if( maNoteData.mxInitData.get() ) + { + /* This function is called from ScPostIt::Clone() when copying cells + to the clipboard/undo document, and when copying cells from the + clipboard/undo document. The former should always be called first, + so if called in an clipboard/undo document, the caption should have + been created already. */ + OSL_ENSURE( !mrDoc.IsUndo() && !mrDoc.IsClipboard(), "ScPostIt::CreateCaptionFromInitData - note caption should not be created in undo/clip documents" ); + + if( !maNoteData.mpCaption ) + { + // ScNoteCaptionCreator c'tor creates the caption and inserts it into the document and maNoteData + ScNoteCaptionCreator aCreator( mrDoc, rPos, maNoteData ); + if( maNoteData.mpCaption ) + { + ScCaptionInitData& rInitData = *maNoteData.mxInitData; + + // transfer ownership of outliner object to caption, or set simple text + OSL_ENSURE( rInitData.mxOutlinerObj.get() || (rInitData.maSimpleText.getLength() > 0), + "ScPostIt::CreateCaptionFromInitData - need either outliner para object or simple text" ); + if( rInitData.mxOutlinerObj.get() ) + maNoteData.mpCaption->SetOutlinerParaObject( rInitData.mxOutlinerObj.release() ); + else + maNoteData.mpCaption->SetText( rInitData.maSimpleText ); + + // copy all items or set default items; reset shadow items + ScCaptionUtil::SetDefaultItems( *maNoteData.mpCaption, mrDoc ); + if( rInitData.mxItemSet.get() ) + ScCaptionUtil::SetCaptionItems( *maNoteData.mpCaption, *rInitData.mxItemSet ); + + // set position and size of the caption object + if( rInitData.mbDefaultPosSize ) + { + // set other items and fit caption size to text + maNoteData.mpCaption->SetMergedItem( SdrTextMinFrameWidthItem( SC_NOTECAPTION_WIDTH ) ); + maNoteData.mpCaption->SetMergedItem( SdrTextMaxFrameWidthItem( SC_NOTECAPTION_MAXWIDTH_TEMP ) ); + maNoteData.mpCaption->AdjustTextFrameWidthAndHeight(); + aCreator.AutoPlaceCaption(); + } + else + { + Rectangle aCellRect = ScDrawLayer::GetCellRect( mrDoc, rPos, true ); + bool bNegPage = mrDoc.IsNegativePage( rPos.Tab() ); + long nPosX = bNegPage ? (aCellRect.Left() - rInitData.maCaptionOffset.X()) : (aCellRect.Right() + rInitData.maCaptionOffset.X()); + long nPosY = aCellRect.Top() + rInitData.maCaptionOffset.Y(); + Rectangle aCaptRect( Point( nPosX, nPosY ), rInitData.maCaptionSize ); + maNoteData.mpCaption->SetLogicRect( aCaptRect ); + aCreator.FitCaptionToRect(); + } + } + } + // forget the initial caption data struct + maNoteData.mxInitData.reset(); + } +} + void ScPostIt::CreateCaption( const ScAddress& rPos, const SdrCaptionObj* pCaption ) { - DBG_ASSERT( !maNoteData.mpCaption, "ScPostIt::CreateCaption - unexpected caption object found" ); + OSL_ENSURE( !maNoteData.mpCaption, "ScPostIt::CreateCaption - unexpected caption object found" ); maNoteData.mpCaption = 0; // drawing layer may be missing, if a note is copied into a clipboard document - DBG_ASSERT( !mrDoc.IsUndo(), "ScPostIt::CreateCaption - note caption should not be created in undo documents" ); + OSL_ENSURE( !mrDoc.IsUndo(), "ScPostIt::CreateCaption - note caption should not be created in undo documents" ); if( mrDoc.IsClipboard() ) mrDoc.InitDrawLayer(); - if( ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer() ) + // ScNoteCaptionCreator c'tor creates the caption and inserts it into the document and maNoteData + ScNoteCaptionCreator aCreator( mrDoc, rPos, maNoteData ); + if( maNoteData.mpCaption ) { - SdrPage* pDrawPage = pDrawLayer->GetPage( static_cast< sal_uInt16 >( rPos.Tab() ) ); - DBG_ASSERT( pDrawPage, "ScPostIt::CreateCaption - no drawing page" ); - if( pDrawPage ) + // clone settings of passed caption + if( pCaption ) { - // create the caption drawing object - ScCaptionCreator aCreator( mrDoc, rPos, maNoteData.mbShown, false ); - maNoteData.mpCaption = aCreator.GetCaption(); - - // additional user data (pass true to create the object data entry) - ScDrawObjData* pData = ScDrawLayer::GetObjData( maNoteData.mpCaption, true ); - pData->maStart = rPos; - pData->mbNote = true; - - // insert object into draw page - pDrawPage->InsertObject( maNoteData.mpCaption ); - - // clone settings of passed caption - if( pCaption ) - { - // copy edit text object (object must be inserted into page already) - if( OutlinerParaObject* pOPO = pCaption->GetOutlinerParaObject() ) - maNoteData.mpCaption->SetOutlinerParaObject( new OutlinerParaObject( *pOPO ) ); - // copy formatting items (after text has been copied to apply font formatting) - maNoteData.mpCaption->SetMergedItemSetAndBroadcast( pCaption->GetMergedItemSet() ); - // move textbox position relative to new cell, copy textbox size - Rectangle aCaptRect = pCaption->GetLogicRect(); - Point aDist = maNoteData.mpCaption->GetTailPos() - pCaption->GetTailPos(); - aCaptRect.Move( aDist.X(), aDist.Y() ); - maNoteData.mpCaption->SetLogicRect( aCaptRect ); - aCreator.FitCaptionToRect(); - } - else - { - // set default formatting and default position - aCreator.SetDefaultItems(); - aCreator.AutoPlaceCaption(); - } + // copy edit text object (object must be inserted into page already) + if( OutlinerParaObject* pOPO = pCaption->GetOutlinerParaObject() ) + maNoteData.mpCaption->SetOutlinerParaObject( new OutlinerParaObject( *pOPO ) ); + // copy formatting items (after text has been copied to apply font formatting) + maNoteData.mpCaption->SetMergedItemSetAndBroadcast( pCaption->GetMergedItemSet() ); + // move textbox position relative to new cell, copy textbox size + Rectangle aCaptRect = pCaption->GetLogicRect(); + Point aDist = maNoteData.mpCaption->GetTailPos() - pCaption->GetTailPos(); + aCaptRect.Move( aDist.X(), aDist.Y() ); + maNoteData.mpCaption->SetLogicRect( aCaptRect ); + aCreator.FitCaptionToRect(); + } + else + { + // set default formatting and default position + ScCaptionUtil::SetDefaultItems( *maNoteData.mpCaption, mrDoc ); + aCreator.AutoPlaceCaption(); + } - // create undo action + // create undo action + if( ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer() ) if( pDrawLayer->IsRecording() ) pDrawLayer->AddCalcUndo( pDrawLayer->GetSdrUndoFactory().CreateUndoNewObject( *maNoteData.mpCaption ) ); - } } } void ScPostIt::RemoveCaption() { + /* Remove caption object only, if this note is its owner (e.g. notes in undo documents refer to captions in original document, do not remove them from drawing layer here). */ - if( maNoteData.mpCaption && (mrDoc.GetDrawLayer() == maNoteData.mpCaption->GetModel()) ) + ScDrawLayer* pDrawLayer = mrDoc.GetDrawLayer(); + if( maNoteData.mpCaption && (pDrawLayer == maNoteData.mpCaption->GetModel()) ) { + OSL_ENSURE( pDrawLayer, "ScPostIt::RemoveCaption - object without drawing layer" ); SdrPage* pDrawPage = maNoteData.mpCaption->GetPage(); - DBG_ASSERT( pDrawPage, "ScPostIt::RemoveCaption - object without drawing page" ); + OSL_ENSURE( pDrawPage, "ScPostIt::RemoveCaption - object without drawing page" ); if( pDrawPage ) { - pDrawPage->RecalcObjOrdNums(); - - ScDrawLayer* pDrawLayer = static_cast< ScDrawLayer* >( maNoteData.mpCaption->GetModel() ); - DBG_ASSERT( pDrawLayer, "ScPostIt::RemoveCaption - object without drawing layer" ); - + pDrawPage->RecalcObjOrdNums(); // create drawing undo action (before removing the object to have valid draw page in undo action) if( pDrawLayer && pDrawLayer->IsRecording() ) pDrawLayer->AddCalcUndo( pDrawLayer->GetSdrUndoFactory().CreateUndoDeleteObject( *maNoteData.mpCaption ) ); - // remove the object from the drawing page, delete if undo is disabled pDrawPage->RemoveObject( maNoteData.mpCaption->GetOrdNum() ); } @@ -555,21 +767,8 @@ void ScPostIt::RemoveCaption() maNoteData.mpCaption = 0; } -void ScPostIt::UpdateCaptionLayer( bool bShow ) -{ - // no separate drawing undo needed, handled completely inside ScUndoShowHideNote - SdrLayerID nLayer = bShow ? SC_LAYER_INTERN : SC_LAYER_HIDDEN; - if( maNoteData.mpCaption && (nLayer != maNoteData.mpCaption->GetLayer()) ) - maNoteData.mpCaption->SetLayer( nLayer ); -} - // ============================================================================ -ScPostIt* ScNoteUtil::CloneNote( ScDocument& rDoc, const ScAddress& rPos, const ScPostIt& rNote, bool bCloneCaption ) -{ - return bCloneCaption ? new ScPostIt( rDoc, rPos, rNote ) : new ScPostIt( rDoc, rNote.GetNoteData() ); -} - void ScNoteUtil::UpdateCaptionPositions( ScDocument& rDoc, const ScRange& rRange ) { // do not use ScCellIterator, it skips filtered and subtotal cells @@ -580,25 +779,26 @@ void ScNoteUtil::UpdateCaptionPositions( ScDocument& rDoc, const ScRange& rRange pNote->UpdateCaptionPos( aPos ); } -SdrCaptionObj* ScNoteUtil::CreateTempCaption( ScDocument& rDoc, const ScAddress& rPos, - SdrPage& rPage, const String& rUserText, const Rectangle& rVisRect, bool bTailFront ) +SdrCaptionObj* ScNoteUtil::CreateTempCaption( + ScDocument& rDoc, const ScAddress& rPos, SdrPage& rDrawPage, + const OUString& rUserText, const Rectangle& rVisRect, bool bTailFront ) { - String aFinalText = rUserText; + OUStringBuffer aBuffer( rUserText ); // add plain text of invisible (!) cell note (no formatting etc.) SdrCaptionObj* pNoteCaption = 0; - if( ScPostIt* pNote = rDoc.GetNote( rPos ) ) + if( const ScPostIt* pNote = rDoc.GetNote( rPos ) ) { if( !pNote->IsCaptionShown() ) { - if( aFinalText.Len() > 0 ) - aFinalText.AppendAscii( RTL_CONSTASCII_STRINGPARAM( "\n--------\n" ) ); - aFinalText.Append( pNote->GetText() ); - pNoteCaption = pNote->GetCaption(); + if( aBuffer.getLength() > 0 ) + aBuffer.appendAscii( RTL_CONSTASCII_STRINGPARAM( "\n--------\n" ) ); + aBuffer.append( pNote->GetText() ); + pNoteCaption = pNote->GetOrCreateCaption( rPos ); } } // create a caption if any text exists - if( aFinalText.Len() == 0 ) + if( aBuffer.getLength() == 0 ) return 0; // prepare visible rectangle (add default distance to all borders) @@ -612,12 +812,12 @@ SdrCaptionObj* ScNoteUtil::CreateTempCaption( ScDocument& rDoc, const ScAddress& ScCaptionCreator aCreator( rDoc, rPos, true, bTailFront ); SdrCaptionObj* pCaption = aCreator.GetCaption(); // insert caption into page (needed to set caption text) - rPage.InsertObject( pCaption ); + rDrawPage.InsertObject( pCaption ); // set the text to the object - pCaption->SetText( aFinalText ); + pCaption->SetText( aBuffer.makeStringAndClear() ); // set formatting (must be done after setting text) and resize the box to fit the text - if( pNoteCaption && (rUserText.Len() == 0) ) + if( pNoteCaption && (rUserText.getLength() == 0) ) { pCaption->SetMergedItemSetAndBroadcast( pNoteCaption->GetMergedItemSet() ); Rectangle aCaptRect( pCaption->GetLogicRect().TopLeft(), pNoteCaption->GetLogicRect().GetSize() ); @@ -625,7 +825,7 @@ SdrCaptionObj* ScNoteUtil::CreateTempCaption( ScDocument& rDoc, const ScAddress& } else { - aCreator.SetDefaultItems(); + ScCaptionUtil::SetDefaultItems( *pCaption, rDoc ); // adjust caption size to text size long nMaxWidth = ::std::min< long >( aVisRect.GetWidth() * 2 / 3, SC_NOTECAPTION_MAXWIDTH_TEMP ); pCaption->SetMergedItem( SdrTextAutoGrowWidthItem( TRUE ) ); @@ -640,19 +840,74 @@ SdrCaptionObj* ScNoteUtil::CreateTempCaption( ScDocument& rDoc, const ScAddress& return pCaption; } -ScPostIt* ScNoteUtil::CreateNoteFromString( ScDocument& rDoc, const ScAddress& rPos, const String& rNoteText, bool bShown ) +ScPostIt* ScNoteUtil::CreateNoteFromCaption( + ScDocument& rDoc, const ScAddress& rPos, SdrCaptionObj& rCaption, bool bShown ) { - if( rNoteText.Len() == 0 ) - return 0; - ScPostIt* pNote = new ScPostIt( rDoc, rPos, bShown ); + ScNoteData aNoteData( bShown ); + aNoteData.mpCaption = &rCaption; + ScPostIt* pNote = new ScPostIt( rDoc, rPos, aNoteData, false ); + pNote->AutoStamp(); rDoc.TakeNote( rPos, pNote ); - if( SdrCaptionObj* pCaption = pNote->GetCaption() ) + // if pNote still points to the note after TakeNote(), insertion was successful + if( pNote ) { - pCaption->SetText( rNoteText ); - pNote->SetCaptionDefaultItems(); // reformat text with default font - pCaption->SetMergedItem( SdrTextMinFrameWidthItem( SC_NOTECAPTION_WIDTH ) ); - pCaption->SetMergedItem( SdrTextMaxFrameWidthItem( SC_NOTECAPTION_MAXWIDTH_TEMP ) ); - pCaption->AdjustTextFrameWidthAndHeight(); + // ScNoteCaptionCreator c'tor updates the caption object to be part of a note + ScNoteCaptionCreator aCreator( rDoc, rPos, rCaption, bShown ); + } + return pNote; +} + +ScPostIt* ScNoteUtil::CreateNoteFromObjectData( + ScDocument& rDoc, const ScAddress& rPos, SfxItemSet* pItemSet, + OutlinerParaObject* pOutlinerObj, const Rectangle& rCaptionRect, + bool bShown, bool bAlwaysCreateCaption ) +{ + OSL_ENSURE( pItemSet && pOutlinerObj, "ScNoteUtil::CreateNoteFromObjectData - item set and outliner object expected" ); + ScNoteData aNoteData( bShown ); + aNoteData.mxInitData.reset( new ScCaptionInitData ); + ScCaptionInitData& rInitData = *aNoteData.mxInitData; + rInitData.mxItemSet.reset( pItemSet ); + rInitData.mxOutlinerObj.reset( pOutlinerObj ); + + // convert absolute caption position to relative position + rInitData.mbDefaultPosSize = rCaptionRect.IsEmpty(); + if( !rInitData.mbDefaultPosSize ) + { + Rectangle aCellRect = ScDrawLayer::GetCellRect( rDoc, rPos, true ); + bool bNegPage = rDoc.IsNegativePage( rPos.Tab() ); + rInitData.maCaptionOffset.X() = bNegPage ? (aCellRect.Left() - rCaptionRect.Right()) : (rCaptionRect.Left() - aCellRect.Right()); + rInitData.maCaptionOffset.Y() = rCaptionRect.Top() - aCellRect.Top(); + rInitData.maCaptionSize = rCaptionRect.GetSize(); + } + + /* Create the note and insert it into the document. If the note is + visible, the caption object will be created automatically. */ + ScPostIt* pNote = new ScPostIt( rDoc, rPos, aNoteData, bAlwaysCreateCaption ); + pNote->AutoStamp(); + rDoc.TakeNote( rPos, pNote ); + // if pNote still points to the note after TakeNote(), insertion was successful + return pNote; +} + +ScPostIt* ScNoteUtil::CreateNoteFromString( + ScDocument& rDoc, const ScAddress& rPos, const OUString& rNoteText, + bool bShown, bool bAlwaysCreateCaption ) +{ + ScPostIt* pNote = 0; + if( rNoteText.getLength() > 0 ) + { + ScNoteData aNoteData( bShown ); + aNoteData.mxInitData.reset( new ScCaptionInitData ); + ScCaptionInitData& rInitData = *aNoteData.mxInitData; + rInitData.maSimpleText = rNoteText; + rInitData.mbDefaultPosSize = true; + + /* Create the note and insert it into the document. If the note is + visible, the caption object will be created automatically. */ + pNote = new ScPostIt( rDoc, rPos, aNoteData, bAlwaysCreateCaption ); + pNote->AutoStamp(); + rDoc.TakeNote( rPos, pNote ); + // if pNote still points to the note after TakeNote(), insertion was successful } return pNote; } diff --git a/sc/source/core/data/stlsheet.cxx b/sc/source/core/data/stlsheet.cxx index 37dce231cbaf..bad2c664cc4d 100644 --- a/sc/source/core/data/stlsheet.cxx +++ b/sc/source/core/data/stlsheet.cxx @@ -176,14 +176,8 @@ SfxItemSet& __EXPORT ScStyleSheet::GetItemSet() if ( pDoc && pDoc->IsLoadingDone() ) { // Setzen von sinnvollen Default-Werten: - // SfxPrinter* pPrinter = pDoc->GetPrinter(); SvxPageItem aPageItem( ATTR_PAGE ); - // #50536# PaperBin auf Default lassen, - // nicht auf aktuelle Drucker-Einstellung umsetzen - // SvxSizeItem aPaperSizeItem(ATTR_PAGE_SIZE,SvxPaperInfo::GetPaperSize(pPrinter) ); - - SvxPaper aDefaultPaper = SvxPaperInfo::GetDefaultSvxPaper( Application::GetSettings().GetLanguage() ); - SvxSizeItem aPaperSizeItem( ATTR_PAGE_SIZE, SvxPaperInfo::GetPaperSize(aDefaultPaper) ); + SvxSizeItem aPaperSizeItem( ATTR_PAGE_SIZE, SvxPaperInfo::GetDefaultPaperSize() ); SvxSetItem aHFSetItem( (const SvxSetItem&) diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx index 03b9fc9d90be..38aabaa51a55 100644 --- a/sc/source/core/data/table1.cxx +++ b/sc/source/core/data/table1.cxx @@ -114,6 +114,7 @@ #include "progress.hxx" #include "hints.hxx" // fuer Paint-Broadcast #include "prnsave.hxx" +#include "tabprotection.hxx" // STATIC DATA ----------------------------------------------------------- @@ -132,7 +133,7 @@ ScTable::ScTable( ScDocument* pDoc, SCTAB nNewTab, const String& rNewName, bPageSizeValid( FALSE ), nRepeatStartX( SCCOL_REPEAT_NONE ), nRepeatStartY( SCROW_REPEAT_NONE ), - bProtected( FALSE ), + pTabProtection( NULL ), pColWidth( NULL ), pRowHeight( NULL ), pColFlags( NULL ), @@ -140,6 +141,7 @@ ScTable::ScTable( ScDocument* pDoc, SCTAB nNewTab, const String& rNewName, pOutlineTable( NULL ), bTableAreaValid( FALSE ), bVisible( TRUE ), + bPendingRowHeights( FALSE ), nTab( nNewTab ), nRecalcLvl( 0 ), pDocument( pDoc ), @@ -249,6 +251,11 @@ void ScTable::SetVisible( BOOL bVis ) bVisible = bVis; } +void ScTable::SetPendingRowHeights( BOOL bSet ) +{ + bPendingRowHeights = bSet; +} + void ScTable::SetLayoutRTL( BOOL bSet ) { bLayoutRTL = bSet; @@ -863,6 +870,10 @@ BOOL ScTable::ValidNextPos( SCCOL nCol, SCROW nRow, const ScMarkData& rMark, if (!ValidCol(nCol) || !ValidRow(nRow)) return FALSE; + if (pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED)) + // Skip an overlapped cell. + return false; + if (bMarked && !rMark.IsCellMarked(nCol,nRow)) return FALSE; @@ -905,7 +916,8 @@ void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY, { BOOL bUp = ( nMovY < 0 ); nRow = rMark.GetNextMarked( nCol, nRow, bUp ); - while ( VALIDROW(nRow) && pRowFlags && (pRowFlags->GetValue(nRow) & CR_HIDDEN) ) + while ( VALIDROW(nRow) && ((pRowFlags && (pRowFlags->GetValue(nRow) & CR_HIDDEN)) || + pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED)) ) { // #53697# ausgeblendete ueberspringen (s.o.) nRow += nMovY; @@ -934,7 +946,8 @@ void ScTable::GetNextPos( SCCOL& rCol, SCROW& rRow, SCsCOL nMovX, SCsROW nMovY, else if (nRow > MAXROW) nRow = 0; nRow = rMark.GetNextMarked( nCol, nRow, bUp ); - while ( VALIDROW(nRow) && pRowFlags && (pRowFlags->GetValue(nRow) & CR_HIDDEN) ) + while ( VALIDROW(nRow) && ((pRowFlags && (pRowFlags->GetValue(nRow) & CR_HIDDEN)) || + pDocument->HasAttrib(nCol, nRow, nTab, nCol, nRow, nTab, HASATTR_OVERLAPPED)) ) { // #53697# ausgeblendete ueberspringen (s.o.) nRow += nMovY; @@ -1095,6 +1108,7 @@ void ScTable::UpdateDrawRef( UpdateRefMode eUpdateRefMode, SCCOL nCol1, SCROW nR { if ( nTab >= nTab1 && nTab <= nTab2 && nDz == 0 ) // only within the table { + InitializeNoteCaptions(); ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer(); if ( eUpdateRefMode != URM_COPY && pDrawLayer ) { diff --git a/sc/source/core/data/table2.cxx b/sc/source/core/data/table2.cxx index 5b726467c3ba..59858796078c 100644 --- a/sc/source/core/data/table2.cxx +++ b/sc/source/core/data/table2.cxx @@ -117,6 +117,7 @@ BOOL ScTable::TestInsertRow( SCCOL nStartCol, SCCOL nEndCol, SCSIZE nSize ) void ScTable::InsertRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE nSize ) { nRecalcLvl++; + InitializeNoteCaptions(); if (nStartCol==0 && nEndCol==MAXCOL) { if (pRowHeight && pRowFlags) @@ -143,6 +144,7 @@ void ScTable::DeleteRow( SCCOL nStartCol, SCCOL nEndCol, SCROW nStartRow, SCSIZE BOOL* pUndoOutline ) { nRecalcLvl++; + InitializeNoteCaptions(); if (nStartCol==0 && nEndCol==MAXCOL) { if (pRowHeight && pRowFlags) @@ -186,6 +188,7 @@ BOOL ScTable::TestInsertCol( SCROW nStartRow, SCROW nEndRow, SCSIZE nSize ) void ScTable::InsertCol( SCCOL nStartCol, SCROW nStartRow, SCROW nEndRow, SCSIZE nSize ) { nRecalcLvl++; + InitializeNoteCaptions(); if (nStartRow==0 && nEndRow==MAXROW) { if (pColWidth && pColFlags) @@ -236,6 +239,7 @@ void ScTable::DeleteCol( SCCOL nStartCol, SCROW nStartRow, SCROW nEndRow, SCSIZE BOOL* pUndoOutline ) { nRecalcLvl++; + InitializeNoteCaptions(); if (nStartRow==0 && nEndRow==MAXROW) { if (pColWidth && pColFlags) @@ -292,7 +296,7 @@ void ScTable::DeleteArea(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, USH // Zellschutz auf geschuetzter Tabelle nicht setzen // - if ( bProtected && (nDelFlag & IDF_ATTRIB) ) + if ( IsProtected() && (nDelFlag & IDF_ATTRIB) ) { ScPatternAttr aPattern(pDocument->GetPool()); aPattern.GetItemSet().Put( ScProtectionAttr( FALSE ) ); @@ -318,7 +322,7 @@ void ScTable::DeleteSelection( USHORT nDelFlag, const ScMarkData& rMark ) // Zellschutz auf geschuetzter Tabelle nicht setzen // - if ( bProtected && (nDelFlag & IDF_ATTRIB) ) + if ( IsProtected() && (nDelFlag & IDF_ATTRIB) ) { ScDocumentPool* pPool = pDocument->GetPool(); SfxItemSet aSet( *pPool, ATTR_PATTERN_START, ATTR_PATTERN_END ); @@ -361,7 +365,7 @@ void ScTable::CopyToClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, // ggf. Formeln durch Werte ersetzen - if (bProtected) + if ( IsProtected() ) for (i = nCol1; i <= nCol2; i++) pTable->aCol[i].RemoveProtected(nRow1, nRow2); } @@ -406,7 +410,7 @@ void ScTable::CopyFromClip(SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, // Zellschutz auf geschuetzter Tabelle nicht setzen // - if ( bProtected && (nInsFlag & IDF_ATTRIB) ) + if ( IsProtected() && (nInsFlag & IDF_ATTRIB) ) { ScPatternAttr aPattern(pDocument->GetPool()); aPattern.GetItemSet().Put( ScProtectionAttr( FALSE ) ); @@ -484,9 +488,10 @@ void ScTable::TransposeClip( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, } else // kopieren { + ScAddress aOwnPos( nCol, nRow, nTab ); if (pCell->GetCellType() == CELLTYPE_FORMULA) { - pNew = pCell->CloneWithNote( *pDestDoc, aDestPos, SC_CLONECELL_STARTLISTENING ); + pNew = pCell->CloneWithNote( aOwnPos, *pDestDoc, aDestPos, SC_CLONECELL_STARTLISTENING ); // Referenzen drehen // bei Cut werden Referenzen spaeter per UpdateTranspose angepasst @@ -495,7 +500,9 @@ void ScTable::TransposeClip( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, SCROW nRow2, ((ScFormulaCell*)pNew)->TransposeReference(); } else - pNew = pCell->CloneWithNote( *pDestDoc, aDestPos ); + { + pNew = pCell->CloneWithNote( aOwnPos, *pDestDoc, aDestPos ); + } } pTransClip->PutCell( static_cast<SCCOL>(nRow-nRow1), static_cast<SCROW>(nCol-nCol1), pNew ); } @@ -900,7 +907,15 @@ ScPostIt* ScTable::GetNote( SCCOL nCol, SCROW nRow ) void ScTable::TakeNote( SCCOL nCol, SCROW nRow, ScPostIt*& rpNote ) { if( ValidColRow( nCol, nRow ) ) + { aCol[ nCol ].TakeNote( nRow, rpNote ); + if( rpNote && rpNote->GetNoteData().mxInitData.get() ) + { + if( !mxUninitNotes.get() ) + mxUninitNotes.reset( new ScAddress2DVec ); + mxUninitNotes->push_back( ScAddress2D( nCol, nRow ) ); + } + } else DELETEZ( rpNote ); } @@ -919,6 +934,17 @@ void ScTable::DeleteNote( SCCOL nCol, SCROW nRow ) } +void ScTable::InitializeNoteCaptions( bool bForced ) +{ + if( mxUninitNotes.get() && (bForced || pDocument->IsUndoEnabled()) ) + { + for( ScAddress2DVec::iterator aIt = mxUninitNotes->begin(), aEnd = mxUninitNotes->end(); aIt != aEnd; ++aIt ) + if( ScPostIt* pNote = GetNote( aIt->first, aIt->second ) ) + pNote->GetOrCreateCaption( ScAddress( aIt->first, aIt->second, nTab ) ); + mxUninitNotes.reset(); + } +} + CellType ScTable::GetCellType( SCCOL nCol, SCROW nRow ) const { if (ValidColRow( nCol, nRow )) @@ -1457,7 +1483,7 @@ BOOL ScTable::IsBlockEditable( SCCOL nCol1, SCROW nRow1, SCCOL nCol2, BOOL bIsEditable = TRUE; if ( nLockCount ) bIsEditable = FALSE; - else if ( bProtected && !pDocument->IsScenario(nTab) ) + else if ( IsProtected() && !pDocument->IsScenario(nTab) ) { if((bIsEditable = !HasAttrib( nCol1, nRow1, nCol2, nRow2, HASATTR_PROTECTED )) != FALSE) { @@ -1524,7 +1550,7 @@ BOOL ScTable::IsSelectionEditable( const ScMarkData& rMark, BOOL bIsEditable = TRUE; if ( nLockCount ) bIsEditable = FALSE; - else if ( bProtected && !pDocument->IsScenario(nTab)) + else if ( IsProtected() && !pDocument->IsScenario(nTab) ) { if((bIsEditable = !HasAttribSelection( rMark, HASATTR_PROTECTED )) != FALSE) { @@ -1918,6 +1944,7 @@ void ScTable::SetColWidth( SCCOL nCol, USHORT nNewWidth ) if ( nNewWidth != pColWidth[nCol] ) { nRecalcLvl++; + InitializeNoteCaptions(); ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer(); if (pDrawLayer) pDrawLayer->WidthChanged( nTab, nCol, ((long) nNewWidth) - (long) pColWidth[nCol] ); @@ -1947,6 +1974,7 @@ void ScTable::SetRowHeight( SCROW nRow, USHORT nNewHeight ) if ( nNewHeight != nOldHeight ) { nRecalcLvl++; + InitializeNoteCaptions(); ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer(); if (pDrawLayer) pDrawLayer->HeightChanged( nTab, nRow, ((long) nNewHeight) - (long) nOldHeight ); @@ -1969,6 +1997,7 @@ BOOL ScTable::SetRowHeightRange( SCROW nStartRow, SCROW nEndRow, USHORT nNewHeig if (VALIDROW(nStartRow) && VALIDROW(nEndRow) && pRowHeight) { nRecalcLvl++; + InitializeNoteCaptions(); if (!nNewHeight) { DBG_ERROR("Zeilenhoehe 0 in SetRowHeight"); @@ -2235,6 +2264,7 @@ void ScTable::ShowCol(SCCOL nCol, BOOL bShow) if (bWasVis != bShow) { nRecalcLvl++; + InitializeNoteCaptions(); ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer(); if (pDrawLayer) { @@ -2272,6 +2302,7 @@ void ScTable::ShowRow(SCROW nRow, BOOL bShow) if (bWasVis != bShow) { nRecalcLvl++; + InitializeNoteCaptions(); ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer(); if (pDrawLayer) { @@ -2307,6 +2338,7 @@ void ScTable::DBShowRow(SCROW nRow, BOOL bShow) BYTE nFlags = pRowFlags->GetValue(nRow); BOOL bWasVis = ( nFlags & CR_HIDDEN ) == 0; nRecalcLvl++; + InitializeNoteCaptions(); if (bWasVis != bShow) { ScDrawLayer* pDrawLayer = pDocument->GetDrawLayer(); @@ -2348,6 +2380,7 @@ void ScTable::DBShowRows(SCROW nRow1, SCROW nRow2, BOOL bShow) { SCROW nStartRow = nRow1; nRecalcLvl++; + InitializeNoteCaptions(); while (nStartRow <= nRow2) { BYTE nOldFlag = pRowFlags->GetValue(nStartRow) & CR_HIDDEN; @@ -2400,6 +2433,7 @@ void ScTable::ShowRows(SCROW nRow1, SCROW nRow2, BOOL bShow) { SCROW nStartRow = nRow1; nRecalcLvl++; + InitializeNoteCaptions(); while (nStartRow <= nRow2) { BYTE nOldFlag = pRowFlags->GetValue(nStartRow) & CR_HIDDEN; @@ -2667,7 +2701,7 @@ void ScTable::DoAutoOutline( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SC pCell = aCol[nCol].GetCell( nRow ); if (pCell) if ( pCell->GetCellType() == CELLTYPE_FORMULA ) - if (((ScFormulaCell*)pCell)->HasOneReference( aRef )) + if (((ScFormulaCell*)pCell)->HasRefListExpressibleAsOneReference( aRef )) if ( aRef.aStart.Col() == nCol && aRef.aEnd.Col() == nCol && aRef.aStart.Tab() == nTab && aRef.aEnd.Tab() == nTab && DiffSign( aRef.aStart.Row(), nRow ) == @@ -2698,7 +2732,7 @@ void ScTable::DoAutoOutline( SCCOL nStartCol, SCROW nStartRow, SCCOL nEndCol, SC while ( aIter.Next( nRow, pCell ) && !bFound ) { if ( pCell->GetCellType() == CELLTYPE_FORMULA ) - if (((ScFormulaCell*)pCell)->HasOneReference( aRef )) + if (((ScFormulaCell*)pCell)->HasRefListExpressibleAsOneReference( aRef )) if ( aRef.aStart.Row() == nRow && aRef.aEnd.Row() == nRow && aRef.aStart.Tab() == nTab && aRef.aEnd.Tab() == nTab && DiffSign( aRef.aStart.Col(), nCol ) == diff --git a/sc/source/core/data/table3.cxx b/sc/source/core/data/table3.cxx index 74f2a97e9c2e..ae299fdf5fca 100644 --- a/sc/source/core/data/table3.cxx +++ b/sc/source/core/data/table3.cxx @@ -1022,12 +1022,19 @@ BOOL ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam, } } else if ( (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL) || + (rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN || + rEntry.eOp == SC_BEGINS_WITH || rEntry.eOp == SC_ENDS_WITH || + rEntry.eOp == SC_DOES_NOT_BEGIN_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH) || (rEntry.bQueryByString && (pCell ? pCell->HasStringData() : HasStringData( static_cast<SCCOL>(rEntry.nField), nRow)))) { // by String String aCellStr; + if( rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN + || rEntry.eOp == SC_BEGINS_WITH || rEntry.eOp == SC_ENDS_WITH + || rEntry.eOp == SC_DOES_NOT_BEGIN_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH ) + bMatchWholeCell = FALSE; if ( pCell ) { if (pCell->GetCellType() != CELLTYPE_NOTE) @@ -1040,7 +1047,10 @@ BOOL ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam, GetInputString( static_cast<SCCOL>(rEntry.nField), nRow, aCellStr ); BOOL bRealRegExp = (rParam.bRegExp && ((rEntry.eOp == SC_EQUAL) - || (rEntry.eOp == SC_NOT_EQUAL))); + || (rEntry.eOp == SC_NOT_EQUAL) || (rEntry.eOp == SC_CONTAINS) + || (rEntry.eOp == SC_DOES_NOT_CONTAIN) || (rEntry.eOp == SC_BEGINS_WITH) + || (rEntry.eOp == SC_ENDS_WITH) || (rEntry.eOp == SC_DOES_NOT_BEGIN_WITH) + || (rEntry.eOp == SC_DOES_NOT_END_WITH))); BOOL bTestRegExp = (pbTestEqualCondition && rParam.bRegExp && ((rEntry.eOp == SC_LESS_EQUAL) || (rEntry.eOp == SC_GREATER_EQUAL))); @@ -1048,20 +1058,61 @@ BOOL ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam, { xub_StrLen nStart = 0; xub_StrLen nEnd = aCellStr.Len(); - BOOL bMatch = (BOOL) rEntry.GetSearchTextPtr( rParam.bCaseSens ) - ->SearchFrwrd( aCellStr, &nStart, &nEnd ); + // from 614 on, nEnd is behind the found text + BOOL bMatch = FALSE; + if ( rEntry.eOp == SC_ENDS_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH ) + { + nEnd = 0; + nStart = aCellStr.Len(); + bMatch = (BOOL) rEntry.GetSearchTextPtr( rParam.bCaseSens ) + ->SearchBkwrd( aCellStr, &nStart, &nEnd ); + } + else + { + bMatch = (BOOL) rEntry.GetSearchTextPtr( rParam.bCaseSens ) + ->SearchFrwrd( aCellStr, &nStart, &nEnd ); + } if ( bMatch && bMatchWholeCell && (nStart != 0 || nEnd != aCellStr.Len()) ) bMatch = FALSE; // RegExp must match entire cell string if ( bRealRegExp ) - bOk = ((rEntry.eOp == SC_NOT_EQUAL) ? !bMatch : bMatch); + switch (rEntry.eOp) + { + case SC_EQUAL: + case SC_CONTAINS: + bOk = bMatch; + break; + case SC_NOT_EQUAL: + case SC_DOES_NOT_CONTAIN: + bOk = !bMatch; + break; + case SC_BEGINS_WITH: + bOk = ( bMatch && (nStart == 0) ); + break; + case SC_DOES_NOT_BEGIN_WITH: + bOk = !( bMatch && (nStart == 0) ); + break; + case SC_ENDS_WITH: + bOk = ( bMatch && (nEnd == aCellStr.Len()) ); + break; + case SC_DOES_NOT_END_WITH: + bOk = !( bMatch && (nEnd == aCellStr.Len()) ); + break; + default: + { + // added to avoid warnings + } + } else bTestEqual = bMatch; } if ( !bRealRegExp ) { - if ( rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL ) + if ( rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL + || rEntry.eOp == SC_CONTAINS || rEntry.eOp == SC_DOES_NOT_CONTAIN + || rEntry.eOp == SC_BEGINS_WITH || rEntry.eOp == SC_ENDS_WITH + || rEntry.eOp == SC_DOES_NOT_BEGIN_WITH || rEntry.eOp == SC_DOES_NOT_END_WITH ) { if ( !rEntry.bQueryByString && rEntry.pStr->Len() == 0 ) { @@ -1069,22 +1120,54 @@ BOOL ScTable::ValidQuery(SCROW nRow, const ScQueryParam& rParam, // the query value is assigned directly, and the string is empty. In that case, // don't find any string (isEqual would find empty string results in formula cells). bOk = FALSE; + if ( rEntry.eOp == SC_NOT_EQUAL ) + bOk = !bOk; } else if ( bMatchWholeCell ) + { bOk = pTransliteration->isEqual( aCellStr, *rEntry.pStr ); + if ( rEntry.eOp == SC_NOT_EQUAL ) + bOk = !bOk; + } else { - ::com::sun::star::uno::Sequence< sal_Int32 > xOff; String aCell( pTransliteration->transliterate( aCellStr, ScGlobal::eLnge, 0, aCellStr.Len(), - &xOff ) ); + NULL ) ); String aQuer( pTransliteration->transliterate( *rEntry.pStr, ScGlobal::eLnge, 0, rEntry.pStr->Len(), - &xOff ) ); - bOk = (aCell.Search( aQuer ) != STRING_NOTFOUND); + NULL ) ); + xub_StrLen nIndex = (rEntry.eOp == SC_ENDS_WITH + || rEntry.eOp == SC_DOES_NOT_END_WITH)? (aCell.Len()-aQuer.Len()):0; + xub_StrLen nStrPos = aCell.Search( aQuer, nIndex ); + switch (rEntry.eOp) + { + case SC_EQUAL: + case SC_CONTAINS: + bOk = ( nStrPos != STRING_NOTFOUND ); + break; + case SC_NOT_EQUAL: + case SC_DOES_NOT_CONTAIN: + bOk = ( nStrPos == STRING_NOTFOUND ); + break; + case SC_BEGINS_WITH: + bOk = ( nStrPos == 0 ); + break; + case SC_DOES_NOT_BEGIN_WITH: + bOk = ( nStrPos != 0 ); + break; + case SC_ENDS_WITH: + bOk = ( nStrPos + aQuer.Len() == aCell.Len() ); + break; + case SC_DOES_NOT_END_WITH: + bOk = ( nStrPos + aQuer.Len() != aCell.Len() ); + break; + default: + { + // added to avoid warnings + } + } } - if ( rEntry.eOp == SC_NOT_EQUAL ) - bOk = !bOk; } else { // use collator here because data was probably sorted diff --git a/sc/source/core/data/table5.cxx b/sc/source/core/data/table5.cxx index a6ef174e326c..021385678160 100644 --- a/sc/source/core/data/table5.cxx +++ b/sc/source/core/data/table5.cxx @@ -51,8 +51,11 @@ #include "stlpool.hxx" #include "stlsheet.hxx" #include "brdcst.hxx" +#include "tabprotection.hxx" #include "globstr.hrc" +using ::com::sun::star::uno::Sequence; + // STATIC DATA ----------------------------------------------------------- #define GET_SCALEVALUE(set,id) ((const SfxUInt16Item&)(set.Get( id ))).GetValue() @@ -273,6 +276,24 @@ void ScTable::SetPageSize( const Size& rSize ) bPageSizeValid = FALSE; } +BOOL ScTable::IsProtected() const +{ + return pTabProtection.get() && pTabProtection->isProtected(); +} + +void ScTable::SetProtection(const ScTableProtection* pProtect) +{ + if (pProtect) + pTabProtection.reset(new ScTableProtection(*pProtect)); + else + pTabProtection.reset(NULL); +} + +ScTableProtection* ScTable::GetProtection() +{ + return pTabProtection.get(); +} + Size ScTable::GetPageSize() const { if ( bPageSizeValid ) diff --git a/sc/source/core/data/table6.cxx b/sc/source/core/data/table6.cxx index 443d0f23e3d0..9ca7b29b745e 100644 --- a/sc/source/core/data/table6.cxx +++ b/sc/source/core/data/table6.cxx @@ -219,7 +219,7 @@ BOOL ScTable::SearchCell(const SvxSearchItem& rSearchItem, SCCOL nCol, SCROW nRo // NB: rich text format is lost. // This is also true of Cells. if( ScPostIt* pNote = pCell->GetNote() ) - pNote->SetText( aString ); + pNote->SetText( ScAddress( nCol, nRow, nTab ), aString ); } else if ( cMatrixFlag != MM_NONE ) { // #60558# Matrix nicht zerreissen diff --git a/sc/source/core/data/tabprotection.cxx b/sc/source/core/data/tabprotection.cxx new file mode 100644 index 000000000000..1620c5194e92 --- /dev/null +++ b/sc/source/core/data/tabprotection.cxx @@ -0,0 +1,465 @@ +/************************************************************************* + * + * 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: tabprotection.cxx,v $ + * $Revision: 1.1.4.7 $ + * + * 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 --------------------------------------------------------------- + +#include "tabprotection.hxx" +#include "tools/debug.hxx" +#include "svtools/PasswordHelper.hxx" +#include "document.hxx" + +#define DEBUG_TAB_PROTECTION 0 + +using namespace ::com::sun::star; +using ::com::sun::star::uno::Sequence; +using ::rtl::OUString; + +// ============================================================================ + +bool ScPassHashHelper::needsPassHashRegen(const ScDocument& rDoc, ScPasswordHash eHash) +{ + if (rDoc.IsDocProtected()) + { + const ScDocProtection* p = rDoc.GetDocProtection(); + if (!p->isPasswordEmpty() && !p->hasPasswordHash(eHash)) + return true; + } + + SCTAB nTabCount = rDoc.GetTableCount(); + for (SCTAB i = 0; i < nTabCount; ++i) + { + const ScTableProtection* p = rDoc.GetTabProtection(i); + if (!p || !p->isProtected()) + // Sheet not protected. Skip it. + continue; + + if (!p->isPasswordEmpty() && !p->hasPasswordHash(eHash)) + return true; + } + + return false; +} + +// ============================================================================ + +ScPassHashProtectable::~ScPassHashProtectable() +{ +} + +// ============================================================================ + +static sal_uInt16 lcl_getXLHashFromChar(const sal_Char* szPassword) +{ + sal_uInt16 cchPassword = static_cast< sal_uInt16 >( strlen(szPassword) ); + sal_uInt16 wPasswordHash = 0; + if (!cchPassword) + return wPasswordHash; + + const char* pch = &szPassword[cchPassword]; + while (pch-- != szPassword) + { + wPasswordHash = ((wPasswordHash >> 14) & 0x01) | + ((wPasswordHash << 1) & 0x7fff); + wPasswordHash ^= *pch; + } + + wPasswordHash = ((wPasswordHash >> 14) & 0x01) | + ((wPasswordHash << 1) & 0x7fff); + + wPasswordHash ^= (0x8000 | ('N' << 8) | 'K'); + wPasswordHash ^= cchPassword; + + return wPasswordHash; +} + +static Sequence<sal_Int8> lcl_getXLHash(const String& aPassText) +{ + const sal_Char* szBuf = OUStringToOString(OUString(aPassText), RTL_TEXTENCODING_UTF8).getStr(); + sal_uInt16 nHash = lcl_getXLHashFromChar(szBuf); + Sequence<sal_Int8> aHash(2); + aHash[0] = (nHash >> 8) & 0xFF; + aHash[1] = nHash & 0xFF; + return aHash; +} + +class ScTableProtectionImpl +{ +public: + static ::com::sun::star::uno::Sequence<sal_Int8> hashPassword(const String& aPassText, ScPasswordHash eHash = PASSHASH_OOO); + + explicit ScTableProtectionImpl(SCSIZE nOptSize); + explicit ScTableProtectionImpl(const ScTableProtectionImpl& r); + + bool isProtected() const; + bool isProtectedWithPass() const; + void setProtected(bool bProtected); + + bool isPasswordEmpty() const; + bool hasPasswordHash(ScPasswordHash eHash) const; + void setPassword(const String& aPassText); + ::com::sun::star::uno::Sequence<sal_Int8> getPasswordHash(ScPasswordHash eHash) const; + void setPasswordHash(const ::com::sun::star::uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash = PASSHASH_OOO); + bool verifyPassword(const String& aPassText) const; + + bool isOptionEnabled(SCSIZE nOptId) const; + void setOption(SCSIZE nOptId, bool bEnabled); + +private: + String maPassText; + ::com::sun::star::uno::Sequence<sal_Int8> maPassHash; + ::std::vector<bool> maOptions; + bool mbEmptyPass; + bool mbProtected; + ScPasswordHash meHash; +}; + +Sequence<sal_Int8> ScTableProtectionImpl::hashPassword(const String& aPassText, ScPasswordHash eHash) +{ + Sequence<sal_Int8> aHash; + switch (eHash) + { + case PASSHASH_XL: + aHash = lcl_getXLHash(aPassText); + break; + case PASSHASH_OOO: + default: + SvPasswordHelper::GetHashPassword(aHash, aPassText); + break; + } + return aHash; +} + +ScTableProtectionImpl::ScTableProtectionImpl(SCSIZE nOptSize) : + maOptions(nOptSize), + mbEmptyPass(true), + mbProtected(false), + meHash(PASSHASH_OOO) +{ +} + +ScTableProtectionImpl::ScTableProtectionImpl(const ScTableProtectionImpl& r) : + maPassText(r.maPassText), + maPassHash(r.maPassHash), + maOptions(r.maOptions), + mbEmptyPass(r.mbEmptyPass), + mbProtected(r.mbProtected), + meHash(r.meHash) +{ +} + +bool ScTableProtectionImpl::isProtected() const +{ + return mbProtected; +} + +bool ScTableProtectionImpl::isProtectedWithPass() const +{ + if (!mbProtected) + return false; + + return maPassText.Len() || maPassHash.getLength(); +} + +void ScTableProtectionImpl::setProtected(bool bProtected) +{ + mbProtected = bProtected; + // We need to keep the old password even when the protection is off. So, + // don't erase the password data here. +} + +void ScTableProtectionImpl::setPassword(const String& aPassText) +{ + // We can't hash it here because we don't know whether this document will + // get saved to Excel or ODF, depending on which we will need to use a + // different hashing algorithm. One alternative is to hash it using all + // hash algorithms that we support, and store them all. + + maPassText = aPassText; + mbEmptyPass = aPassText.Len() == 0; + if (mbEmptyPass) + { + maPassHash = Sequence<sal_Int8>(); + } +} + +bool ScTableProtectionImpl::isPasswordEmpty() const +{ + return mbEmptyPass; +} + +bool ScTableProtectionImpl::hasPasswordHash(ScPasswordHash eHash) const +{ + if (mbEmptyPass) + return true; + + if (maPassText.Len()) + return true; + + if (meHash == eHash) + return true; + + return false; +} + +Sequence<sal_Int8> ScTableProtectionImpl::getPasswordHash(ScPasswordHash eHash) const +{ + if (mbEmptyPass) + // Flaged as empty. + return Sequence<sal_Int8>(); + + if (maPassText.Len()) + // Cleartext password exists. Hash it. + return hashPassword(maPassText, eHash); + + if (meHash == eHash) + // Stored hash exists. + return maPassHash; + + // Failed to find a matching hash. + return Sequence<sal_Int8>(); +} + +void ScTableProtectionImpl::setPasswordHash(const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash) +{ + sal_Int32 nLen = aPassword.getLength(); + mbEmptyPass = nLen <= 0 ? true : false; + meHash = eHash; + maPassHash = aPassword; + +#if DEBUG_TAB_PROTECTION + for (sal_Int32 i = 0; i < nLen; ++i) + printf("%2.2X ", static_cast<sal_uInt8>(aPassword[i])); + printf("\n"); +#endif +} + +bool ScTableProtectionImpl::verifyPassword(const String& aPassText) const +{ +#if DEBUG_TAB_PROTECTION + fprintf(stdout, "ScTableProtectionImpl::verifyPassword: input = '%s'\n", + OUStringToOString(rtl::OUString(aPassText), RTL_TEXTENCODING_UTF8).getStr()); +#endif + + if (mbEmptyPass) + return aPassText.Len() == 0; + + if (maPassText.Len()) + // Clear text password exists, and this one takes precedence. + return aPassText.Equals(maPassText); + + Sequence<sal_Int8> aHash = hashPassword(aPassText, meHash); + +#if DEBUG_TAB_PROTECTION + fprintf(stdout, "ScTableProtectionImpl::verifyPassword: hash = "); + for (sal_Int32 i = 0; i < aHash.getLength(); ++i) + printf("%2.2X ", static_cast<sal_uInt8>(aHash[i])); + printf("\n"); +#endif + + return aHash == maPassHash; +} + +bool ScTableProtectionImpl::isOptionEnabled(SCSIZE nOptId) const +{ + if ( maOptions.size() <= static_cast<size_t>(nOptId) ) + { + DBG_ERROR("ScTableProtectionImpl::isOptionEnabled: wrong size"); + return false; + } + + return maOptions[nOptId]; +} + +void ScTableProtectionImpl::setOption(SCSIZE nOptId, bool bEnabled) +{ + if ( maOptions.size() <= static_cast<size_t>(nOptId) ) + { + DBG_ERROR("ScTableProtectionImpl::setOption: wrong size"); + return; + } + + maOptions[nOptId] = bEnabled; +} + +// ============================================================================ + +ScDocProtection::ScDocProtection() : + mpImpl(new ScTableProtectionImpl(static_cast<SCSIZE>(ScDocProtection::NONE))) +{ +} + +ScDocProtection::ScDocProtection(const ScDocProtection& r) : + ScPassHashProtectable(), + mpImpl(new ScTableProtectionImpl(*r.mpImpl)) +{ +} + +ScDocProtection::~ScDocProtection() +{ +} + +bool ScDocProtection::isProtected() const +{ + return mpImpl->isProtected(); +} + +bool ScDocProtection::isProtectedWithPass() const +{ + return mpImpl->isProtectedWithPass(); +} + +void ScDocProtection::setProtected(bool bProtected) +{ + mpImpl->setProtected(bProtected); + + // Currently Calc doesn't support document protection options. So, let's + // assume that when the document is protected, its structure is protected. + // We need to do this for Excel export. + mpImpl->setOption(ScDocProtection::STRUCTURE, bProtected); +} + +bool ScDocProtection::isPasswordEmpty() const +{ + return mpImpl->isPasswordEmpty(); +} + +bool ScDocProtection::hasPasswordHash(ScPasswordHash eHash) const +{ + return mpImpl->hasPasswordHash(eHash); +} + +void ScDocProtection::setPassword(const String& aPassText) +{ + mpImpl->setPassword(aPassText); +} + +uno::Sequence<sal_Int8> ScDocProtection::getPasswordHash(ScPasswordHash eHash) const +{ + return mpImpl->getPasswordHash(eHash); +} + +void ScDocProtection::setPasswordHash(const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash) +{ + mpImpl->setPasswordHash(aPassword, eHash); +} + +bool ScDocProtection::verifyPassword(const String& aPassText) const +{ + return mpImpl->verifyPassword(aPassText); +} + +bool ScDocProtection::isOptionEnabled(Option eOption) const +{ + return mpImpl->isOptionEnabled(eOption); +} + +void ScDocProtection::setOption(Option eOption, bool bEnabled) +{ + mpImpl->setOption(eOption, bEnabled); +} + +// ============================================================================ + +ScTableProtection::ScTableProtection() : + mpImpl(new ScTableProtectionImpl(static_cast<SCSIZE>(ScTableProtection::NONE))) +{ + // Set default values for the options. + mpImpl->setOption(SELECT_LOCKED_CELLS, true); + mpImpl->setOption(SELECT_UNLOCKED_CELLS, true); +} + +ScTableProtection::ScTableProtection(const ScTableProtection& r) : + ScPassHashProtectable(), + mpImpl(new ScTableProtectionImpl(*r.mpImpl)) +{ +} + +ScTableProtection::~ScTableProtection() +{ +} + +bool ScTableProtection::isProtected() const +{ + return mpImpl->isProtected(); +} + +bool ScTableProtection::isProtectedWithPass() const +{ + return mpImpl->isProtectedWithPass(); +} + +void ScTableProtection::setProtected(bool bProtected) +{ + mpImpl->setProtected(bProtected); +} + +bool ScTableProtection::isPasswordEmpty() const +{ + return mpImpl->isPasswordEmpty(); +} + +bool ScTableProtection::hasPasswordHash(ScPasswordHash eHash) const +{ + return mpImpl->hasPasswordHash(eHash); +} + +void ScTableProtection::setPassword(const String& aPassText) +{ + mpImpl->setPassword(aPassText); +} + +Sequence<sal_Int8> ScTableProtection::getPasswordHash(ScPasswordHash eHash) const +{ + return mpImpl->getPasswordHash(eHash); +} + +void ScTableProtection::setPasswordHash(const uno::Sequence<sal_Int8>& aPassword, ScPasswordHash eHash) +{ + mpImpl->setPasswordHash(aPassword, eHash); +} + +bool ScTableProtection::verifyPassword(const String& aPassText) const +{ + return mpImpl->verifyPassword(aPassText); +} + +bool ScTableProtection::isOptionEnabled(Option eOption) const +{ + return mpImpl->isOptionEnabled(eOption); +} + +void ScTableProtection::setOption(Option eOption, bool bEnabled) +{ + mpImpl->setOption(eOption, bEnabled); +} + diff --git a/sc/source/core/data/validat.cxx b/sc/source/core/data/validat.cxx index 09c1db07c464..9bb8bff1081f 100644 --- a/sc/source/core/data/validat.cxx +++ b/sc/source/core/data/validat.cxx @@ -76,8 +76,9 @@ SV_IMPL_OP_PTRARR_SORT( ScValidationEntries_Impl, ScValidationDataPtr ); ScValidationData::ScValidationData( ScValidationMode eMode, ScConditionMode eOper, const String& rExpr1, const String& rExpr2, ScDocument* pDocument, const ScAddress& rPos, - const formula::FormulaGrammar::Grammar eGrammar ) : - ScConditionEntry( eOper, rExpr1, rExpr2, pDocument, rPos, eGrammar ), + const String& rExprNmsp1, const String& rExprNmsp2, + FormulaGrammar::Grammar eGrammar1, FormulaGrammar::Grammar eGrammar2 ) : + ScConditionEntry( eOper, rExpr1, rExpr2, pDocument, rPos, rExprNmsp1, rExprNmsp2, eGrammar1, eGrammar2 ), nKey( 0 ), eDataMode( eMode ), eErrorStyle( SC_VALERR_STOP ), @@ -695,6 +696,40 @@ bool ScValidationData::GetSelectionFromFormula( TypedScStrCollection* pStrings, SCSIZE nCol, nRow, nCols, nRows, n = 0; pValues->GetDimensions( nCols, nRows ); + BOOL bRef = FALSE; + ScRange aRange; + + ScTokenArray* pArr = (ScTokenArray*) &rTokArr; + pArr->Reset(); + ScToken* t = NULL; + if (pArr->GetLen() == 1 && (t = static_cast<ScToken*>(pArr->GetNextReferenceOrName())) != NULL) + { + if (t->GetOpCode() == ocDBArea) + { + if( ScDBData* pDBData = pDocument->GetDBCollection()->FindIndex( t->GetIndex() ) ) + { + pDBData->GetArea(aRange); + bRef = TRUE; + } + } + else if (t->GetOpCode() == ocName) + { + ScRangeData* pName = pDocument->GetRangeName()->FindIndex( t->GetIndex() ); + if (pName && pName->IsReference(aRange)) + { + bRef = TRUE; + } + } + else if (t->GetType() != svIndex) + { + t->CalcAbsIfRel(rPos); + if (pArr->IsValidReference(aRange)) + { + bRef = TRUE; + } + } + } + /* XL artificially limits things to a single col or row in the UI but does * not list the constraint in MOOXml. If a defined name or INDIRECT * resulting in 1D is entered in the UI and the definition later modified @@ -735,7 +770,15 @@ bool ScValidationData::GetSelectionFromFormula( TypedScStrCollection* pStrings, { // FIXME FIXME FIXME // Feature regression. Date formats are lost passing through the matrix - pFormatter->GetInputLineString( pMatVal->fVal, 0, aValStr ); + //pFormatter->GetInputLineString( pMatVal->fVal, 0, aValStr ); + //For external reference and a formula that results in an area or array, date formats are still lost. + if ( bRef ) + { + pDocument->GetInputString((SCCOL)(nCol+aRange.aStart.Col()), + (SCROW)(nRow+aRange.aStart.Row()), aRange.aStart.Tab() , aValStr); + } + else + pFormatter->GetInputLineString( pMatVal->fVal, 0, aValStr ); } if( pCell && rMatch < 0 ) diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx index 3d783e74c03d..9fcf743c1e85 100644 --- a/sc/source/core/inc/interpre.hxx +++ b/sc/source/core/inc/interpre.hxx @@ -70,6 +70,21 @@ struct ScCompare } }; +struct ScCompareOptions +{ + ScQueryEntry aQueryEntry; + bool bRegEx; + bool bMatchWholeCell; + bool bIgnoreCase; + + ScCompareOptions( ScDocument* pDoc, const ScQueryEntry& rEntry, bool bReg ); +private: + // Not implemented, prevent usage. + ScCompareOptions(); + ScCompareOptions( const ScCompareOptions & ); + ScCompareOptions& operator=( const ScCompareOptions & ); +}; + class ScToken; #define MAXSTACK (4096 / sizeof(formula::FormulaToken*)) @@ -356,9 +371,16 @@ void ScChoseJump(); // Returns true if last jump was executed and result matrix pushed. bool JumpMatrix( short nStackLevel ); -double CompareFunc( const ScCompare& rComp ); +/** @param pOptions + NULL means case sensitivity document option is to be used! + */ +double CompareFunc( const ScCompare& rComp, ScCompareOptions* pOptions = NULL ); double Compare(); -ScMatrixRef CompareMat(); +/** @param pOptions + NULL means case sensitivity document option is to be used! + */ +ScMatrixRef CompareMat( ScCompareOptions* pOptions = NULL ); +ScMatrixRef QueryMat( ScMatrix* pMat, ScCompareOptions& rOptions ); void ScEqual(); void ScNotEqual(); void ScLess(); diff --git a/sc/source/core/inc/refupdat.hxx b/sc/source/core/inc/refupdat.hxx index 0461578db0a6..2a8b17335fbf 100644 --- a/sc/source/core/inc/refupdat.hxx +++ b/sc/source/core/inc/refupdat.hxx @@ -82,7 +82,7 @@ public: ScComplexRefData& rRef, BOOL bWrap, BOOL bAbsolute ); static void MoveRelWrap( ScDocument* pDoc, const ScAddress& rPos, - ScComplexRefData& rRef ); + SCCOL nMaxCol, SCROW nMaxRow, ScComplexRefData& rRef ); /// Before calling, the absolute references must be up-to-date! static ScRefUpdateRes UpdateTranspose( ScDocument* pDoc, diff --git a/sc/source/core/tool/address.cxx b/sc/source/core/tool/address.cxx index 8b13374fe501..b38d5b52e4f5 100644 --- a/sc/source/core/tool/address.cxx +++ b/sc/source/core/tool/address.cxx @@ -1126,39 +1126,48 @@ lcl_ScAddress_Parse ( const sal_Unicode* p, ScDocument* pDoc, ScAddress& rAddr, bool ConvertSingleRef( ScDocument* pDoc, const String& rRefString, SCTAB nDefTab, ScRefAddress& rRefAddress, - const ScAddress::Details& rDetails ) + const ScAddress::Details& rDetails, + ScAddress::ExternalInfo* pExtInfo /* = NULL */ ) { - ScAddress aAddr( 0, 0, nDefTab ); - USHORT nRes = lcl_ScAddress_Parse( rRefString.GetBuffer(), pDoc, aAddr, rDetails, NULL ); - if( nRes & SCA_VALID ) + bool bRet = false; + if (pExtInfo || (ScGlobal::FindUnquoted( rRefString, SC_COMPILER_FILE_TAB_SEP) == STRING_NOTFOUND)) { - rRefAddress.Set( aAddr, - ((nRes & SCA_COL_ABSOLUTE) == 0), - ((nRes & SCA_ROW_ABSOLUTE) == 0), - ((nRes & SCA_TAB_ABSOLUTE) == 0)); - return TRUE; + ScAddress aAddr( 0, 0, nDefTab ); + USHORT nRes = aAddr.Parse( rRefString, pDoc, rDetails, pExtInfo); + if ( nRes & SCA_VALID ) + { + rRefAddress.Set( aAddr, + ((nRes & SCA_COL_ABSOLUTE) == 0), + ((nRes & SCA_ROW_ABSOLUTE) == 0), + ((nRes & SCA_TAB_ABSOLUTE) == 0)); + bRet = true; + } } - else - return FALSE; + return bRet; } bool ConvertDoubleRef( ScDocument* pDoc, const String& rRefString, SCTAB nDefTab, ScRefAddress& rStartRefAddress, ScRefAddress& rEndRefAddress, - const ScAddress::Details& rDetails ) + const ScAddress::Details& rDetails, + ScAddress::ExternalInfo* pExtInfo /* = NULL */ ) { - BOOL bRet = FALSE; - // FIXME : This will break for Lotus - xub_StrLen nPos = rRefString.Search(':'); - if (nPos != STRING_NOTFOUND) + bool bRet = false; + if (pExtInfo || (ScGlobal::FindUnquoted( rRefString, SC_COMPILER_FILE_TAB_SEP) == STRING_NOTFOUND)) { - String aTmp( rRefString ); - sal_Unicode* p = aTmp.GetBufferAccess(); - p[ nPos ] = 0; - if( ConvertSingleRef( pDoc, p, nDefTab, rStartRefAddress, rDetails ) ) + ScRange aRange( ScAddress( 0, 0, nDefTab)); + USHORT nRes = aRange.Parse( rRefString, pDoc, rDetails, pExtInfo); + if ( nRes & SCA_VALID ) { - nDefTab = rStartRefAddress.Tab(); - bRet = ConvertSingleRef( pDoc, p + nPos + 1, nDefTab, rEndRefAddress, rDetails ); + rStartRefAddress.Set( aRange.aStart, + ((nRes & SCA_COL_ABSOLUTE) == 0), + ((nRes & SCA_ROW_ABSOLUTE) == 0), + ((nRes & SCA_TAB_ABSOLUTE) == 0)); + rEndRefAddress.Set( aRange.aEnd, + ((nRes & SCA_COL2_ABSOLUTE) == 0), + ((nRes & SCA_ROW2_ABSOLUTE) == 0), + ((nRes & SCA_TAB2_ABSOLUTE) == 0)); + bRet = true; } } return bRet; diff --git a/sc/source/core/tool/compiler.cxx b/sc/source/core/tool/compiler.cxx index e148f3ab8516..bc2266cbd3c8 100644 --- a/sc/source/core/tool/compiler.cxx +++ b/sc/source/core/tool/compiler.cxx @@ -68,11 +68,14 @@ #include "cell.hxx" #include "dociter.hxx" #include "docoptio.hxx" -#include "formula/errorcodes.hxx" +#include <formula/errorcodes.hxx> #include "parclass.hxx" #include "autonamecache.hxx" #include "externalrefmgr.hxx" #include "rangeutl.hxx" +#include "convuno.hxx" +#include "tokenuno.hxx" +#include "formulaparserpool.hxx" using namespace formula; using namespace ::com::sun::star; @@ -408,28 +411,36 @@ void ScCompiler::InitCharClassEnglish() void ScCompiler::SetGrammar( const FormulaGrammar::Grammar eGrammar ) { - DBG_ASSERT( eGrammar != FormulaGrammar::GRAM_UNSPECIFIED, "ScCompiler::SetGrammar: don't passFormulaGrammar::GRAM_UNSPECIFIED"); + DBG_ASSERT( eGrammar != FormulaGrammar::GRAM_UNSPECIFIED, "ScCompiler::SetGrammar: don't pass FormulaGrammar::GRAM_UNSPECIFIED"); if (eGrammar == GetGrammar()) return; // nothing to be done - FormulaGrammar::Grammar eMyGrammar = eGrammar; - const sal_Int32 nFormulaLanguage = FormulaGrammar::extractFormulaLanguage( eMyGrammar); - OpCodeMapPtr xMap( GetOpCodeMap( nFormulaLanguage)); - DBG_ASSERT( xMap, "ScCompiler::SetGrammar: unknown formula language"); - if (!xMap) + if( eGrammar == FormulaGrammar::GRAM_EXTERNAL ) { - xMap = GetOpCodeMap( ::com::sun::star::sheet::FormulaLanguage::NATIVE); - eMyGrammar = xMap->getGrammar(); + meGrammar = eGrammar; + mxSymbols = GetOpCodeMap( ::com::sun::star::sheet::FormulaLanguage::NATIVE); } + else + { + FormulaGrammar::Grammar eMyGrammar = eGrammar; + const sal_Int32 nFormulaLanguage = FormulaGrammar::extractFormulaLanguage( eMyGrammar); + OpCodeMapPtr xMap = GetOpCodeMap( nFormulaLanguage); + DBG_ASSERT( xMap, "ScCompiler::SetGrammar: unknown formula language"); + if (!xMap) + { + xMap = GetOpCodeMap( ::com::sun::star::sheet::FormulaLanguage::NATIVE); + eMyGrammar = xMap->getGrammar(); + } - // Save old grammar for call to SetGrammarAndRefConvention(). - FormulaGrammar::Grammar eOldGrammar = GetGrammar(); - // This also sets the grammar associated with the map! - SetFormulaLanguage( xMap); + // Save old grammar for call to SetGrammarAndRefConvention(). + FormulaGrammar::Grammar eOldGrammar = GetGrammar(); + // This also sets the grammar associated with the map! + SetFormulaLanguage( xMap); - // Override if necessary. - if (eMyGrammar != GetGrammar()) - SetGrammarAndRefConvention( eMyGrammar, eOldGrammar); + // Override if necessary. + if (eMyGrammar != GetGrammar()) + SetGrammarAndRefConvention( eMyGrammar, eOldGrammar); + } } @@ -1811,9 +1822,11 @@ ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos,ScTokenArra aPos( rPos ), pCharClass( ScGlobal::pCharClass ), mnPredetectedReference(0), + mnRangeOpPosInSymbol(-1), pConv( pConvOOO_A1 ), mbCloseBrackets( true ), - mbExtendedErrorDetection( false ) + mbExtendedErrorDetection( false ), + mbRewind( false ) { nMaxTab = pDoc ? pDoc->GetTableCount() - 1 : 0; } @@ -1824,9 +1837,11 @@ ScCompiler::ScCompiler( ScDocument* pDocument, const ScAddress& rPos) aPos( rPos ), pCharClass( ScGlobal::pCharClass ), mnPredetectedReference(0), + mnRangeOpPosInSymbol(-1), pConv( pConvOOO_A1 ), mbCloseBrackets( true ), - mbExtendedErrorDetection( false ) + mbExtendedErrorDetection( false ), + mbRewind( false ) { nMaxTab = pDoc ? pDoc->GetTableCount() - 1 : 0; } @@ -1962,7 +1977,7 @@ xub_StrLen ScCompiler::NextSymbol(bool bInArray) sal_Unicode c = *pSrc; sal_Unicode cLast = 0; bool bQuote = false; - bool bRangeOp = false; + mnRangeOpPosInSymbol = -1; ScanState eState = ssGetChar; xub_StrLen nSpaces = 0; sal_Unicode cSep = mxSymbols->getSymbol( ocSep).GetChar(0); @@ -2110,11 +2125,11 @@ Label_MaskStateMachine: else *pSym++ = c; } - else if (c == ':' && !bRangeOp) + else if (c == ':' && mnRangeOpPosInSymbol < 0) { // One range operator may form Sheet1.A:A, which we need to // pass as one entity to IsReference(). - bRangeOp = true; + mnRangeOpPosInSymbol = pSym - &cSymbol[0]; if( pSym == &cSymbol[ MAXSTRLEN-1 ] ) { SetError(errStringOverflow); @@ -2409,7 +2424,7 @@ Label_MaskStateMachine: { nSrcPos = sal::static_int_cast<xub_StrLen>( nSrcPos + nSpaces ); String aSymbol; - bRangeOp = false; + mnRangeOpPosInSymbol = -1; USHORT nErr = 0; do { @@ -2438,9 +2453,9 @@ Label_MaskStateMachine: bi18n = (c == cSheetSep || c == SC_COMPILER_FILE_TAB_SEP); } // One range operator restarts parsing for second reference. - if (c == ':' && !bRangeOp) + if (c == ':' && mnRangeOpPosInSymbol < 0) { - bRangeOp = true; + mnRangeOpPosInSymbol = aSymbol.Len(); bi18n = true; } if ( bi18n ) @@ -2460,6 +2475,14 @@ Label_MaskStateMachine: nSrcPos = sal::static_int_cast<xub_StrLen>( pSrc - pStart ); *pSym = 0; } + if (mnRangeOpPosInSymbol >= 0 && mnRangeOpPosInSymbol == (pSym-1) - &cSymbol[0]) + { + // This is a trailing range operator, which is nonsense. Will be caught + // in next round. + mnRangeOpPosInSymbol = -1; + *--pSym = 0; + --nSrcPos; + } if ( bAutoCorrect ) aCorrectedSymbol = cSymbol; if (bAutoIntersection && nSpaces > 1) @@ -2835,8 +2858,21 @@ BOOL ScCompiler::IsReference( const String& rName ) // Though the range operator is handled explicitly, when encountering // something like Sheet1.A:A we will have to treat it as one entity if it // doesn't pass as single cell reference. - if (ScGlobal::FindUnquoted( rName, ':') != STRING_NOTFOUND) - return IsDoubleReference( rName); + if (mnRangeOpPosInSymbol > 0) // ":foo" would be nonsense + { + if (IsDoubleReference( rName)) + return true; + // Now try with a symbol up to the range operator, rewind source + // position. + sal_Int32 nLen = mnRangeOpPosInSymbol; + while (cSymbol[++nLen]) + ; + cSymbol[mnRangeOpPosInSymbol] = 0; + nSrcPos -= static_cast<xub_StrLen>(nLen - mnRangeOpPosInSymbol); + mnRangeOpPosInSymbol = -1; + mbRewind = true; + return true; // end all checks + } return false; } @@ -3551,54 +3587,65 @@ BOOL ScCompiler::NextNewToken( bool bInArray ) // #42016# Italian ARCTAN.2 resulted in #REF! => IsOpcode() before // IsReference(). - const String aOrg( cSymbol ); - - if (bAsciiNonAlnum && IsOpCode( aOrg, bInArray )) - return true; - String aUpper; - bool bAsciiUpper = false; - if (bMayBeFuncName) + + do { - bAsciiUpper = lcl_UpperAsciiOrI18n( aUpper, aOrg, meGrammar); - if (IsOpCode( aUpper, bInArray )) + mbRewind = false; + const String aOrg( cSymbol ); + + if (bAsciiNonAlnum && IsOpCode( aOrg, bInArray )) return true; - } - // Column 'DM' ("Deutsche Mark", German currency) couldn't be - // referred => IsReference() before IsValue(). - // Preserve case of file names in external references. - if (IsReference( aOrg )) - return true; + aUpper.Erase(); + bool bAsciiUpper = false; + if (bMayBeFuncName) + { + bAsciiUpper = lcl_UpperAsciiOrI18n( aUpper, aOrg, meGrammar); + if (IsOpCode( aUpper, bInArray )) + return true; + } - if (!aUpper.Len()) - bAsciiUpper = lcl_UpperAsciiOrI18n( aUpper, aOrg, meGrammar); + // Column 'DM' ("Deutsche Mark", German currency) couldn't be + // referred => IsReference() before IsValue(). + // Preserve case of file names in external references. + if (IsReference( aOrg )) + { + if (mbRewind) // Range operator, but no direct reference. + continue; // do; up to range operator. + return true; + } - // IsBoolean() before IsValue() to catch inline bools without the kludge - // for inline arrays. - if (bAllowBooleans && IsBoolean( aUpper )) - return true; + if (!aUpper.Len()) + bAsciiUpper = lcl_UpperAsciiOrI18n( aUpper, aOrg, meGrammar); - if (IsValue( aUpper )) - return true; + // IsBoolean() before IsValue() to catch inline bools without the kludge + // for inline arrays. + if (bAllowBooleans && IsBoolean( aUpper )) + return true; - // User defined names and such do need i18n upper also in ODF. - if (bAsciiUpper) - aUpper = ScGlobal::pCharClass->upper( aOrg ); + if (IsValue( aUpper )) + return true; - if (IsNamedRange( aUpper )) - return true; - // Preserve case of file names in external references. - if (IsExternalNamedRange( aOrg )) - return true; - if (IsDBRange( aUpper )) - return true; - if (IsColRowName( aUpper )) - return true; - if (bMayBeFuncName && IsMacro( aUpper )) - return true; - if (bMayBeFuncName && IsOpCode2( aUpper )) - return true; + // User defined names and such do need i18n upper also in ODF. + if (bAsciiUpper) + aUpper = ScGlobal::pCharClass->upper( aOrg ); + + if (IsNamedRange( aUpper )) + return true; + // Preserve case of file names in external references. + if (IsExternalNamedRange( aOrg )) + return true; + if (IsDBRange( aUpper )) + return true; + if (IsColRowName( aUpper )) + return true; + if (bMayBeFuncName && IsMacro( aUpper )) + return true; + if (bMayBeFuncName && IsOpCode2( aUpper )) + return true; + + } while (mbRewind); if ( mbExtendedErrorDetection ) { @@ -3620,6 +3667,21 @@ BOOL ScCompiler::NextNewToken( bool bInArray ) return true; } +void ScCompiler::CreateStringFromXMLTokenArray( String& rFormula, String& rFormulaNmsp ) +{ + bool bExternal = GetGrammar() == FormulaGrammar::GRAM_EXTERNAL; + USHORT nExpectedCount = bExternal ? 2 : 1; + DBG_ASSERT( pArr->GetLen() == nExpectedCount, "ScCompiler::CreateStringFromXMLTokenArray - wrong number of tokens" ); + if( pArr->GetLen() == nExpectedCount ) + { + FormulaToken** ppTokens = pArr->GetArray(); + // string tokens expected, GetString() will assert if token type is wrong + rFormula = ppTokens[ 0 ]->GetString(); + if( bExternal ) + rFormulaNmsp = ppTokens[ 1 ]->GetString(); + } +} + ScTokenArray* ScCompiler::CompileString( const String& rFormula ) { #if 0 @@ -3627,6 +3689,10 @@ ScTokenArray* ScCompiler::CompileString( const String& rFormula ) rtl::OUStringToOString( rFormula, RTL_TEXTENCODING_UTF8 ).getStr() ); #endif + OSL_ENSURE( meGrammar != FormulaGrammar::GRAM_EXTERNAL, "ScCompiler::CompileString - unexpected grammar GRAM_EXTERNAL" ); + if( meGrammar == FormulaGrammar::GRAM_EXTERNAL ) + SetGrammar( FormulaGrammar::GRAM_PODF ); + ScTokenArray aArr; pArr = &aArr; aFormula = rFormula; @@ -3829,6 +3895,34 @@ ScTokenArray* ScCompiler::CompileString( const String& rFormula ) } +ScTokenArray* ScCompiler::CompileString( const String& rFormula, const String& rFormulaNmsp ) +{ + DBG_ASSERT( (GetGrammar() == FormulaGrammar::GRAM_EXTERNAL) || (rFormulaNmsp.Len() == 0), + "ScCompiler::CompileString - unexpected formula namespace for internal grammar" ); + if( GetGrammar() == FormulaGrammar::GRAM_EXTERNAL ) try + { + ScFormulaParserPool& rParserPool = pDoc->GetFormulaParserPool(); + uno::Reference< sheet::XFormulaParser > xParser( rParserPool.getFormulaParser( rFormulaNmsp ), uno::UNO_SET_THROW ); + table::CellAddress aReferencePos; + ScUnoConversion::FillApiAddress( aReferencePos, aPos ); + uno::Sequence< sheet::FormulaToken > aTokenSeq = xParser->parseFormula( rFormula, aReferencePos ); + ScTokenArray aTokenArray; + if( ScTokenConversion::ConvertToTokenArray( *pDoc, aTokenArray, aTokenSeq ) ) + { + // remember pArr, in case a subsequent CompileTokenArray() is executed. + ScTokenArray* pNew = new ScTokenArray( aTokenArray ); + pArr = pNew; + return pNew; + } + } + catch( uno::Exception& ) + { + } + // no success - fallback to some internal grammar and hope the best + return CompileString( rFormula ); +} + + BOOL ScCompiler::HandleRange() { ScRangeData* pRangeData = pDoc->GetRangeName()->FindIndex( pToken->GetIndex() ); @@ -3865,7 +3959,7 @@ BOOL ScCompiler::HandleRange() if( pRangeData->HasReferences() ) { SetRelNameReference(); - MoveRelWrap(); + MoveRelWrap(pRangeData->GetMaxCol(), pRangeData->GetMaxRow()); } pNew->Reset(); if ( bAddPair ) @@ -3917,7 +4011,7 @@ BOOL ScCompiler::HandleExternalReference(const FormulaToken& _aToken) if (pNew->GetNextReference() != NULL) { SetRelNameReference(); - MoveRelWrap(); + MoveRelWrap(MAXCOL, MAXROW); } pNew->Reset(); return GetToken(); @@ -4012,33 +4106,33 @@ void ScCompiler::SetRelNameReference() // Wrap-adjust relative references of a RangeName to current position, // don't call for other token arrays! -void ScCompiler::MoveRelWrap() +void ScCompiler::MoveRelWrap( SCCOL nMaxCol, SCROW nMaxRow ) { pArr->Reset(); for( ScToken* t = static_cast<ScToken*>(pArr->GetNextReference()); t; t = static_cast<ScToken*>(pArr->GetNextReference()) ) { if ( t->GetType() == svSingleRef || t->GetType() == svExternalSingleRef ) - ScRefUpdate::MoveRelWrap( pDoc, aPos, SingleDoubleRefModifier( t->GetSingleRef() ).Ref() ); + ScRefUpdate::MoveRelWrap( pDoc, aPos, nMaxCol, nMaxRow, SingleDoubleRefModifier( t->GetSingleRef() ).Ref() ); else - ScRefUpdate::MoveRelWrap( pDoc, aPos, t->GetDoubleRef() ); + ScRefUpdate::MoveRelWrap( pDoc, aPos, nMaxCol, nMaxRow, t->GetDoubleRef() ); } } // static // Wrap-adjust relative references of a RangeName to current position, // don't call for other token arrays! -void ScCompiler::MoveRelWrap( ScTokenArray& rArr, ScDocument* pDoc, - const ScAddress& rPos ) +void ScCompiler::MoveRelWrap( ScTokenArray& rArr, ScDocument* pDoc, const ScAddress& rPos, + SCCOL nMaxCol, SCROW nMaxRow ) { rArr.Reset(); for( ScToken* t = static_cast<ScToken*>(rArr.GetNextReference()); t; t = static_cast<ScToken*>(rArr.GetNextReference()) ) { if ( t->GetType() == svSingleRef || t->GetType() == svExternalSingleRef ) - ScRefUpdate::MoveRelWrap( pDoc, rPos, SingleDoubleRefModifier( t->GetSingleRef() ).Ref() ); + ScRefUpdate::MoveRelWrap( pDoc, rPos, nMaxCol, nMaxRow, SingleDoubleRefModifier( t->GetSingleRef() ).Ref() ); else - ScRefUpdate::MoveRelWrap( pDoc, rPos, t->GetDoubleRef() ); + ScRefUpdate::MoveRelWrap( pDoc, rPos, nMaxCol, nMaxRow, t->GetDoubleRef() ); } } @@ -4213,7 +4307,7 @@ ScRangeData* ScCompiler::UpdateReference(UpdateRefMode eUpdateRefMode, SingleDoubleRefModifier aMod( rRef ); if ( rRef.IsRelName() ) { - ScRefUpdate::MoveRelWrap( pDoc, aPos, aMod.Ref() ); + ScRefUpdate::MoveRelWrap( pDoc, aPos, MAXCOL, MAXROW, aMod.Ref() ); rChanged = TRUE; } else @@ -4243,7 +4337,7 @@ ScRangeData* ScCompiler::UpdateReference(UpdateRefMode eUpdateRefMode, SCTAB nTabs = rRef.Ref2.nTab - rRef.Ref1.nTab; if ( rRef.Ref1.IsRelName() || rRef.Ref2.IsRelName() ) { - ScRefUpdate::MoveRelWrap( pDoc, aPos, rRef ); + ScRefUpdate::MoveRelWrap( pDoc, aPos, MAXCOL, MAXROW, rRef ); rChanged = TRUE; } else @@ -5060,6 +5154,11 @@ BOOL ScCompiler::EnQuote( String& rStr ) return TRUE; } +sal_Unicode ScCompiler::GetNativeAddressSymbol( Convention::SpecialSymbolType eType ) const +{ + return pConv->getSpecialSymbol(eType); +} + void ScCompiler::fillAddInToken(::std::vector< ::com::sun::star::sheet::FormulaOpCodeMapEntry >& _rVec,bool _bIsEnglish) const { // All known AddIn functions. diff --git a/sc/source/core/tool/detfunc.cxx b/sc/source/core/tool/detfunc.cxx index 20c534a0a556..2d337eab2eb3 100644 --- a/sc/source/core/tool/detfunc.cxx +++ b/sc/source/core/tool/detfunc.cxx @@ -1420,6 +1420,7 @@ void ScDetectiveFunc::UpdateAllComments( ScDocument& rDoc ) for( SCTAB nObjTab = 0, nTabCount = rDoc.GetTableCount(); nObjTab < nTabCount; ++nObjTab ) { + rDoc.InitializeNoteCaptions( nObjTab ); SdrPage* pPage = pModel->GetPage( static_cast< sal_uInt16 >( nObjTab ) ); DBG_ASSERT( pPage, "Page ?" ); if( pPage ) @@ -1430,6 +1431,7 @@ void ScDetectiveFunc::UpdateAllComments( ScDocument& rDoc ) if ( ScDrawObjData* pData = ScDrawLayer::GetNoteCaptionData( pObject, nObjTab ) ) { ScPostIt* pNote = rDoc.GetNote( pData->maStart ); + // caption should exist, we iterate over drawing objects... DBG_ASSERT( pNote && (pNote->GetCaption() == pObject), "ScDetectiveFunc::UpdateAllComments - invalid cell note" ); if( pNote ) { diff --git a/sc/source/core/tool/editutil.cxx b/sc/source/core/tool/editutil.cxx index d08f593aaf21..5519c679f84e 100644 --- a/sc/source/core/tool/editutil.cxx +++ b/sc/source/core/tool/editutil.cxx @@ -64,12 +64,13 @@ #include "patattr.hxx" #include "scmod.hxx" #include "inputopt.hxx" +#include "compiler.hxx" // STATIC DATA ----------------------------------------------------------- // Delimiters zusaetzlich zu EditEngine-Default: -const sal_Char __FAR_DATA ScEditUtil::pCalcDelimiters[] = "=();+-*/^&<>"; +const sal_Char __FAR_DATA ScEditUtil::pCalcDelimiters[] = "=()+-*/^&<>"; //------------------------------------------------------------------------ @@ -79,6 +80,7 @@ String ScEditUtil::ModifyDelimiters( const String& rOld ) String aRet = rOld; aRet.EraseAllChars( '_' ); // underscore is used in function argument names aRet.AppendAscii( RTL_CONSTASCII_STRINGPARAM( pCalcDelimiters ) ); + aRet.Append(ScCompiler::GetNativeSymbol(ocSep)); // argument separator is localized. return aRet; } diff --git a/sc/source/core/tool/formulaparserpool.cxx b/sc/source/core/tool/formulaparserpool.cxx new file mode 100644 index 000000000000..94259a56d6e2 --- /dev/null +++ b/sc/source/core/tool/formulaparserpool.cxx @@ -0,0 +1,171 @@ +/************************************************************************* + * + * 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: formulaparserpool.cxx,v $ + * $Revision: 1.1 $ + * + * 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 "formulaparserpool.hxx" +#include <com/sun/star/beans/XPropertySet.hpp> +#include <com/sun/star/container/XContentEnumerationAccess.hpp> +#include <com/sun/star/lang/XComponent.hpp> +#include <com/sun/star/lang/XSingleComponentFactory.hpp> +#include <com/sun/star/lang/XMultiServiceFactory.hpp> +#include <com/sun/star/sheet/XFilterFormulaParser.hpp> +#include <rtl/instance.hxx> +#include <comphelper/processfactory.hxx> +#include <sfx2/objsh.hxx> +#include "document.hxx" + +using ::rtl::OUString; +using ::rtl::OUStringHash; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; +using namespace ::com::sun::star::sheet; +using namespace ::com::sun::star::uno; + +// ============================================================================ + +namespace { + +class ScParserFactoryMap +{ +public: + explicit ScParserFactoryMap(); + + Reference< XFormulaParser > createFormulaParser( + const Reference< XComponent >& rxComponent, + const OUString& rNamespace ); + +private: + typedef ::std::hash_map< + OUString, + Reference< XSingleComponentFactory >, + OUStringHash, + ::std::equal_to< OUString > > FactoryMap; + + Reference< XComponentContext > mxContext; /// Default context of global process factory. + FactoryMap maFactories; /// All parser factories, mapped by formula namespace. +}; + +ScParserFactoryMap::ScParserFactoryMap() +{ + try + { + // get process factory and default component context + Reference< XMultiServiceFactory > xFactory( ::comphelper::getProcessServiceFactory(), UNO_SET_THROW ); + Reference< XPropertySet > xPropSet( xFactory, UNO_QUERY_THROW ); + mxContext.set( xPropSet->getPropertyValue( OUString( RTL_CONSTASCII_USTRINGPARAM( "DefaultContext" ) ) ), UNO_QUERY_THROW ); + + // enumerate all implementations of the FormulaParser service + Reference< XContentEnumerationAccess > xFactoryEA( xFactory, UNO_QUERY_THROW ); + Reference< XEnumeration > xEnum( xFactoryEA->createContentEnumeration( OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.sheet.FilterFormulaParser" ) ) ), UNO_SET_THROW ); + while( xEnum->hasMoreElements() ) try // single try/catch for every element + { + // create an instance of the formula parser implementation + Reference< XSingleComponentFactory > xCompFactory( xEnum->nextElement(), UNO_QUERY_THROW ); + Reference< XFilterFormulaParser > xParser( xCompFactory->createInstanceWithContext( mxContext ), UNO_QUERY_THROW ); + + // store factory in the map + OUString aNamespace = xParser->getSupportedNamespace(); + if( aNamespace.getLength() > 0 ) + maFactories[ aNamespace ] = xCompFactory; + } + catch( Exception& ) + { + } + } + catch( Exception& ) + { + } +} + +Reference< XFormulaParser > ScParserFactoryMap::createFormulaParser( + const Reference< XComponent >& rxComponent, const OUString& rNamespace ) +{ + Reference< XFormulaParser > xParser; + FactoryMap::const_iterator aIt = maFactories.find( rNamespace ); + if( aIt != maFactories.end() ) try + { + Sequence< Any > aArgs( 1 ); + aArgs[ 0 ] <<= rxComponent; + xParser.set( aIt->second->createInstanceWithArgumentsAndContext( aArgs, mxContext ), UNO_QUERY_THROW ); + } + catch( Exception& ) + { + } + return xParser; +} + +struct ScParserFactorySingleton : public ::rtl::Static< ScParserFactoryMap, ScParserFactorySingleton > {}; + +} // namespace + +// ============================================================================ + +ScFormulaParserPool::ScFormulaParserPool( const ScDocument& rDoc ) : + mrDoc( rDoc ) +{ +} + +ScFormulaParserPool::~ScFormulaParserPool() +{ +} + +bool ScFormulaParserPool::hasFormulaParser( const OUString& rNamespace ) +{ + return getFormulaParser( rNamespace ).is(); +} + +Reference< XFormulaParser > ScFormulaParserPool::getFormulaParser( const OUString& rNamespace ) +{ + // try to find an existing parser entry + ParserMap::iterator aIt = maParsers.find( rNamespace ); + if( aIt != maParsers.end() ) + return aIt->second; + + // always create a new entry in the map (even if the following initialization fails) + Reference< XFormulaParser >& rxParser = maParsers[ rNamespace ]; + + // try to create a new parser object + if( SfxObjectShell* pDocShell = mrDoc.GetDocumentShell() ) try + { + Reference< XComponent > xComponent( pDocShell->GetModel(), UNO_QUERY_THROW ); + ScParserFactoryMap& rFactoryMap = ScParserFactorySingleton::get(); + rxParser = rFactoryMap.createFormulaParser( xComponent, rNamespace ); + } + catch( Exception& )
+ { + } + return rxParser; +} + +// ============================================================================ + diff --git a/sc/source/core/tool/interpr1.cxx b/sc/source/core/tool/interpr1.cxx index ec4c4c293839..195366271f0d 100644 --- a/sc/source/core/tool/interpr1.cxx +++ b/sc/source/core/tool/interpr1.cxx @@ -71,6 +71,7 @@ #include "lookupcache.hxx" #include "rangenam.hxx" #include "compiler.hxx" +#include "externalrefmgr.hxx" #define SC_DOUBLE_MAXVALUE 1.7e307 @@ -626,7 +627,20 @@ bool ScInterpreter::JumpMatrix( short nStackLevel ) } -double ScInterpreter::CompareFunc( const ScCompare& rComp ) +ScCompareOptions::ScCompareOptions( ScDocument* pDoc, const ScQueryEntry& rEntry, bool bReg ) : + aQueryEntry(rEntry), + bRegEx(bReg), + bMatchWholeCell(pDoc->GetDocOptions().IsMatchWholeCell()), + bIgnoreCase(true) +{ + bRegEx = (bRegEx && (aQueryEntry.eOp == SC_EQUAL || aQueryEntry.eOp == SC_NOT_EQUAL)); + // Interpreter functions usually are case insensitive, except the simple + // comparison operators, for which these options aren't used. Override in + // struct if needed. +} + + +double ScInterpreter::CompareFunc( const ScCompare& rComp, ScCompareOptions* pOptions ) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::CompareFunc" ); // Keep DoubleError if encountered @@ -698,7 +712,53 @@ double ScInterpreter::CompareFunc( const ScCompare& rComp ) fRes = 1; // number is less than string else { - if (pDok->GetDocOptions().IsIgnoreCase()) + // Both strings. + if (pOptions) + { + // All similar to Sctable::ValidQuery(), *rComp.pVal[1] actually + // is/must be identical to *rEntry.pStr, which is essential for + // regex to work through GetSearchTextPtr(). + ScQueryEntry& rEntry = pOptions->aQueryEntry; + DBG_ASSERT( *rComp.pVal[1] == *rEntry.pStr, "ScInterpreter::CompareFunc: broken options"); + if (pOptions->bRegEx) + { + xub_StrLen nStart = 0; + xub_StrLen nStop = rComp.pVal[0]->Len(); + bool bMatch = rEntry.GetSearchTextPtr( + !pOptions->bIgnoreCase)->SearchFrwrd( *rComp.pVal[0], + &nStart, &nStop); + if (bMatch && pOptions->bMatchWholeCell && (nStart != 0 || nStop != rComp.pVal[0]->Len())) + bMatch = false; // RegEx must match entire string. + fRes = (bMatch ? 0 : 1); + } + else if (rEntry.eOp == SC_EQUAL || rEntry.eOp == SC_NOT_EQUAL) + { + ::utl::TransliterationWrapper* pTransliteration = + (pOptions->bIgnoreCase ? ScGlobal::pTransliteration : + ScGlobal::pCaseTransliteration); + bool bMatch; + if (pOptions->bMatchWholeCell) + bMatch = pTransliteration->isEqual( *rComp.pVal[0], *rComp.pVal[1]); + else + { + String aCell( pTransliteration->transliterate( + *rComp.pVal[0], ScGlobal::eLnge, 0, + rComp.pVal[0]->Len(), NULL)); + String aQuer( pTransliteration->transliterate( + *rComp.pVal[1], ScGlobal::eLnge, 0, + rComp.pVal[1]->Len(), NULL)); + bMatch = (aCell.Search( aQuer ) != STRING_NOTFOUND); + } + fRes = (bMatch ? 0 : 1); + } + else if (pOptions->bIgnoreCase) + fRes = (double) ScGlobal::pCollator->compareString( + *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] ); + else + fRes = (double) ScGlobal::pCaseCollator->compareString( + *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] ); + } + else if (pDok->GetDocOptions().IsIgnoreCase()) fRes = (double) ScGlobal::pCollator->compareString( *rComp.pVal[ 0 ], *rComp.pVal[ 1 ] ); else @@ -763,7 +823,7 @@ double ScInterpreter::Compare() } -ScMatrixRef ScInterpreter::CompareMat() +ScMatrixRef ScInterpreter::CompareMat( ScCompareOptions* pOptions ) { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::CompareMat" ); String aVal1, aVal2; @@ -855,7 +915,7 @@ ScMatrixRef ScInterpreter::CompareMat() aComp.bEmpty[i] = FALSE; } } - pResMat->PutDouble( CompareFunc( aComp ), j,k ); + pResMat->PutDouble( CompareFunc( aComp, pOptions ), j,k ); } else pResMat->PutString( ScGlobal::GetRscString(STR_NO_VALUE), j,k ); @@ -885,7 +945,7 @@ ScMatrixRef ScInterpreter::CompareMat() *aComp.pVal[i] = pMat[i]->GetString(j); aComp.bEmpty[i] = pMat[i]->IsEmpty(j); } - pResMat->PutDouble( CompareFunc( aComp ), j ); + pResMat->PutDouble( CompareFunc( aComp, pOptions ), j ); } } } @@ -894,6 +954,52 @@ ScMatrixRef ScInterpreter::CompareMat() } +ScMatrixRef ScInterpreter::QueryMat( ScMatrix* pMat, ScCompareOptions& rOptions ) +{ + short nSaveCurFmtType = nCurFmtType; + short nSaveFuncFmtType = nFuncFmtType; + PushMatrix( pMat); + if (rOptions.aQueryEntry.bQueryByString) + PushString( *rOptions.aQueryEntry.pStr); + else + PushDouble( rOptions.aQueryEntry.nVal); + ScMatrixRef pResultMatrix = CompareMat( &rOptions); + nCurFmtType = nSaveCurFmtType; + nFuncFmtType = nSaveFuncFmtType; + if (nGlobalError || !pResultMatrix) + { + SetError( errIllegalParameter); + return pResultMatrix; + } + + switch (rOptions.aQueryEntry.eOp) + { + case SC_EQUAL: + pResultMatrix->CompareEqual(); + break; + case SC_LESS: + pResultMatrix->CompareLess(); + break; + case SC_GREATER: + pResultMatrix->CompareGreater(); + break; + case SC_LESS_EQUAL: + pResultMatrix->CompareLessEqual(); + break; + case SC_GREATER_EQUAL: + pResultMatrix->CompareGreaterEqual(); + break; + case SC_NOT_EQUAL: + pResultMatrix->CompareNotEqual(); + break; + default: + SetError( errIllegalArgument); + DBG_ERROR1( "ScInterpreter::QueryMat: unhandled comparison operator: %d", (int)rOptions.aQueryEntry.eOp); + } + return pResultMatrix; +} + + void ScInterpreter::ScEqual() { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ScEqual" ); @@ -4310,6 +4416,7 @@ void ScInterpreter::ScCountIf() SCCOL nCol2; SCROW nRow2; SCTAB nTab2; + ScMatrixRef pQueryMatrix; switch ( GetStackType() ) { case svDoubleRef : @@ -4326,6 +4433,24 @@ void ScInterpreter::ScCountIf() nRow2 = nRow1; nTab2 = nTab1; break; + case svMatrix: + { + pQueryMatrix = PopMatrix(); + if (!pQueryMatrix) + { + PushIllegalParameter(); + return; + } + nCol1 = 0; + nRow1 = 0; + nTab1 = 0; + SCSIZE nC, nR; + pQueryMatrix->GetDimensions( nC, nR); + nCol2 = static_cast<SCCOL>(nC - 1); + nRow2 = static_cast<SCROW>(nR - 1); + nTab2 = 0; + } + break; default: PushIllegalParameter(); return ; @@ -4367,15 +4492,37 @@ void ScInterpreter::ScCountIf() rParam.nCol1 = nCol1; rParam.nCol2 = nCol2; rEntry.nField = nCol1; - ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE); - // Entry.nField im Iterator bei Spaltenwechsel weiterschalten - aCellIter.SetAdvanceQueryParamEntryField( TRUE ); - if ( aCellIter.GetFirst() ) + if (pQueryMatrix) { - do + // Never case-sensitive. + ScCompareOptions aOptions( pDok, rEntry, rParam.bRegExp); + ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions); + if (nGlobalError || !pResultMatrix) { - fSum++; - } while ( aCellIter.GetNext() ); + PushIllegalParameter(); + return; + } + + SCSIZE nSize = pResultMatrix->GetElementCount(); + for (SCSIZE nIndex = 0; nIndex < nSize; ++nIndex) + { + if (pResultMatrix->IsValue( nIndex) && + pResultMatrix->GetDouble( nIndex)) + ++fSum; + } + } + else + { + ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE); + // Entry.nField im Iterator bei Spaltenwechsel weiterschalten + aCellIter.SetAdvanceQueryParamEntryField( TRUE ); + if ( aCellIter.GetFirst() ) + { + do + { + fSum++; + } while ( aCellIter.GetNext() ); + } } } else @@ -4399,6 +4546,7 @@ void ScInterpreter::ScSumIf() SCROW nRow3 = 0; SCTAB nTab3 = 0; + ScMatrixRef pSumExtraMatrix; bool bSumExtraRange = (nParamCount == 3); if (bSumExtraRange) { @@ -4423,6 +4571,10 @@ void ScInterpreter::ScSumIf() case svSingleRef : PopSingleRef( nCol3, nRow3, nTab3 ); break; + case svMatrix: + pSumExtraMatrix = PopMatrix(); + //! nCol3, nRow3, nTab3 remain 0 + break; default: PushIllegalParameter(); return ; @@ -4498,6 +4650,7 @@ void ScInterpreter::ScSumIf() SCCOL nCol2; SCROW nRow2; SCTAB nTab2; + ScMatrixRef pQueryMatrix; switch ( GetStackType() ) { case svRefList : @@ -4522,13 +4675,31 @@ void ScInterpreter::ScSumIf() nRow2 = nRow1; nTab2 = nTab1; break; + case svMatrix: + { + pQueryMatrix = PopMatrix(); + if (!pQueryMatrix) + { + PushIllegalParameter(); + return; + } + nCol1 = 0; + nRow1 = 0; + nTab1 = 0; + SCSIZE nC, nR; + pQueryMatrix->GetDimensions( nC, nR); + nCol2 = static_cast<SCCOL>(nC - 1); + nRow2 = static_cast<SCROW>(nR - 1); + nTab2 = 0; + } + break; default: PushIllegalParameter(); return ; } if ( nTab1 != nTab2 ) { - PushIllegalParameter(); + PushIllegalArgument(); return; } @@ -4544,15 +4715,29 @@ void ScInterpreter::ScSumIf() // instead of the result range. SCCOL nColDelta = nCol2 - nCol1; SCROW nRowDelta = nRow2 - nRow1; - if (nCol3 + nColDelta > MAXCOL) + SCCOL nMaxCol; + SCROW nMaxRow; + if (pSumExtraMatrix) { - SCCOL nNewDelta = MAXCOL - nCol3; + SCSIZE nC, nR; + pSumExtraMatrix->GetDimensions( nC, nR); + nMaxCol = static_cast<SCCOL>(nC - 1); + nMaxRow = static_cast<SCROW>(nR - 1); + } + else + { + nMaxCol = MAXCOL; + nMaxRow = MAXROW; + } + if (nCol3 + nColDelta > nMaxCol) + { + SCCOL nNewDelta = nMaxCol - nCol3; nCol2 = nCol1 + nNewDelta; } - if (nRow3 + nRowDelta > MAXROW) + if (nRow3 + nRowDelta > nMaxRow) { - SCROW nNewDelta = MAXROW - nRow3; + SCROW nNewDelta = nMaxRow - nRow3; nRow2 = nRow1 + nNewDelta; } } @@ -4592,30 +4777,119 @@ void ScInterpreter::ScSumIf() rParam.nCol1 = nCol1; rParam.nCol2 = nCol2; rEntry.nField = nCol1; - SCCOL nColDiff = nCol3 - nCol1; - SCROW nRowDiff = nRow3 - nRow1; - ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE); - // Increment Entry.nField in iterator when switching to next column. - aCellIter.SetAdvanceQueryParamEntryField( TRUE ); - if ( aCellIter.GetFirst() ) + SCsCOL nColDiff = nCol3 - nCol1; + SCsROW nRowDiff = nRow3 - nRow1; + if (pQueryMatrix) { - do + // Never case-sensitive. + ScCompareOptions aOptions( pDok, rEntry, rParam.bRegExp); + ScMatrixRef pResultMatrix = QueryMat( pQueryMatrix, aOptions); + if (nGlobalError || !pResultMatrix) { - aAdr.SetCol( aCellIter.GetCol() + nColDiff); - aAdr.SetRow( aCellIter.GetRow() + nRowDiff); - ScBaseCell* pCell = GetCell( aAdr ); - if ( HasCellValueData(pCell) ) + PushIllegalParameter(); + return; + } + + if (pSumExtraMatrix) + { + for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) { - fVal = GetCellValue( aAdr, pCell ); - if ( bNull && fVal != 0.0 ) + for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow) { - bNull = FALSE; - fMem = fVal; + if (pResultMatrix->IsValue( nCol, nRow) && + pResultMatrix->GetDouble( nCol, nRow)) + { + SCSIZE nC = nCol + nColDiff; + SCSIZE nR = nRow + nRowDiff; + if (pSumExtraMatrix->IsValue( nC, nR)) + { + fVal = pSumExtraMatrix->GetDouble( nC, nR); + if ( bNull && fVal != 0.0 ) + { + bNull = FALSE; + fMem = fVal; + } + else + fSum += fVal; + } + } } - else - fSum += fVal; } - } while ( aCellIter.GetNext() ); + } + else + { + for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol) + { + for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow) + { + if (pResultMatrix->GetDouble( nCol, nRow)) + { + aAdr.SetCol( nCol + nColDiff); + aAdr.SetRow( nRow + nRowDiff); + ScBaseCell* pCell = GetCell( aAdr ); + if ( HasCellValueData(pCell) ) + { + fVal = GetCellValue( aAdr, pCell ); + if ( bNull && fVal != 0.0 ) + { + bNull = FALSE; + fMem = fVal; + } + else + fSum += fVal; + } + } + } + } + } + } + else + { + ScQueryCellIterator aCellIter(pDok, nTab1, rParam, FALSE); + // Increment Entry.nField in iterator when switching to next column. + aCellIter.SetAdvanceQueryParamEntryField( TRUE ); + if ( aCellIter.GetFirst() ) + { + if (pSumExtraMatrix) + { + do + { + SCSIZE nC = aCellIter.GetCol() + nColDiff; + SCSIZE nR = aCellIter.GetRow() + nRowDiff; + if (pSumExtraMatrix->IsValue( nC, nR)) + { + fVal = pSumExtraMatrix->GetDouble( nC, nR); + if ( bNull && fVal != 0.0 ) + { + bNull = FALSE; + fMem = fVal; + } + else + fSum += fVal; + } + } while ( aCellIter.GetNext() ); + } + else + { + do + { + aAdr.SetCol( aCellIter.GetCol() + nColDiff); + aAdr.SetRow( aCellIter.GetRow() + nRowDiff); + ScBaseCell* pCell = GetCell( aAdr ); + if ( HasCellValueData(pCell) ) + { + fVal = GetCellValue( aAdr, pCell ); + if ( bNull && fVal != 0.0 ) + { + bNull = FALSE; + fMem = fVal; + } + else + fSum += fVal; + } + } while ( aCellIter.GetNext() ); + } + } } } else @@ -5762,6 +6036,52 @@ void ScInterpreter::ScDBVarP() } +ScTokenArray* lcl_CreateExternalRefTokenArray( const ScAddress& rPos, ScDocument* pDoc, + const ScAddress::ExternalInfo& rExtInfo, const ScRefAddress& rRefAd1, + const ScRefAddress* pRefAd2 ) +{ + ScExternalRefManager* pRefMgr = pDoc->GetExternalRefManager(); + size_t nSheets = 1; + const String* pRealTab = pRefMgr->getRealTableName( rExtInfo.mnFileId, rExtInfo.maTabName); + ScTokenArray* pTokenArray = new ScTokenArray; + if (pRefAd2) + { + ScComplexRefData aRef; + aRef.InitRangeRel( ScRange( rRefAd1.GetAddress(), pRefAd2->GetAddress()), rPos); + aRef.Ref1.SetColRel( rRefAd1.IsRelCol()); + aRef.Ref1.SetRowRel( rRefAd1.IsRelRow()); + aRef.Ref1.SetTabRel( rRefAd1.IsRelTab()); + aRef.Ref1.SetFlag3D( true); + aRef.Ref2.SetColRel( pRefAd2->IsRelCol()); + aRef.Ref2.SetRowRel( pRefAd2->IsRelRow()); + aRef.Ref2.SetTabRel( pRefAd2->IsRelTab()); + nSheets = aRef.Ref2.nTab - aRef.Ref1.nTab + 1; + aRef.Ref2.SetFlag3D( nSheets > 1 ); + pTokenArray->AddExternalDoubleReference( rExtInfo.mnFileId, + (pRealTab ? *pRealTab : rExtInfo.maTabName), aRef); + } + else + { + ScSingleRefData aRef; + aRef.InitAddressRel( rRefAd1.GetAddress(), rPos); + aRef.SetColRel( rRefAd1.IsRelCol()); + aRef.SetRowRel( rRefAd1.IsRelRow()); + aRef.SetTabRel( rRefAd1.IsRelTab()); + aRef.SetFlag3D( true); + pTokenArray->AddExternalSingleReference( rExtInfo.mnFileId, + (pRealTab ? *pRealTab : rExtInfo.maTabName), aRef); + } + // The indirect usage of the external table can't be detected during the + // store-to-file cycle, mark it as permanently referenced so it gets stored + // even if not directly referenced anywhere. + pRefMgr->setCacheTableReferencedPermanently( rExtInfo.mnFileId, + rExtInfo.maTabName, nSheets); + ScCompiler aComp( pDoc, rPos, *pTokenArray); + aComp.CompileTokenArray(); + return pTokenArray; +} + + void ScInterpreter::ScIndirect() { RTL_LOGFILE_CONTEXT_AUTHOR( aLogger, "sc", "Eike.Rathke@sun.com", "ScInterpreter::ScIndirect" ); @@ -5780,15 +6100,46 @@ void ScInterpreter::ScIndirect() SCTAB nTab = aPos.Tab(); String sRefStr( GetString() ); ScRefAddress aRefAd, aRefAd2; - if ( ConvertDoubleRef( pDok, sRefStr, nTab, aRefAd, aRefAd2, aDetails) || + ScAddress::ExternalInfo aExtInfo; + if ( ConvertDoubleRef( pDok, sRefStr, nTab, aRefAd, aRefAd2, aDetails, &aExtInfo) || (bTryXlA1 && ConvertDoubleRef( pDok, sRefStr, nTab, aRefAd, - aRefAd2, aDetailsXlA1))) - PushDoubleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab(), - aRefAd2.Col(), aRefAd2.Row(), aRefAd2.Tab() ); - else if ( ConvertSingleRef ( pDok, sRefStr, nTab, aRefAd, aDetails) || + aRefAd2, aDetailsXlA1, &aExtInfo))) + { + if (aExtInfo.mbExternal) + { + /* TODO: future versions should implement a proper subroutine + * token. This procedure here is a minimally invasive fix for + * #i101645# in OOo3.1.1 */ + // Push a subroutine on the instruction code stack that + // resolves the external reference as the next instruction. + aCode.Push( lcl_CreateExternalRefTokenArray( aPos, pDok, + aExtInfo, aRefAd, &aRefAd2)); + // Signal subroutine call to interpreter. + PushTempToken( new FormulaUnknownToken( ocCall)); + } + else + PushDoubleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab(), + aRefAd2.Col(), aRefAd2.Row(), aRefAd2.Tab() ); + } + else if ( ConvertSingleRef ( pDok, sRefStr, nTab, aRefAd, aDetails, &aExtInfo) || (bTryXlA1 && ConvertSingleRef ( pDok, sRefStr, nTab, aRefAd, - aDetailsXlA1))) - PushSingleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab() ); + aDetailsXlA1, &aExtInfo))) + { + if (aExtInfo.mbExternal) + { + /* TODO: future versions should implement a proper subroutine + * token. This procedure here is a minimally invasive fix for + * #i101645# in OOo3.1.1 */ + // Push a subroutine on the instruction code stack that + // resolves the external reference as the next instruction. + aCode.Push( lcl_CreateExternalRefTokenArray( aPos, pDok, + aExtInfo, aRefAd, NULL)); + // Signal subroutine call to interpreter. + PushTempToken( new FormulaUnknownToken( ocCall)); + } + else + PushSingleRef( aRefAd.Col(), aRefAd.Row(), aRefAd.Tab() ); + } else { do diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx index 2722925fc56d..a73fe62998a6 100644 --- a/sc/source/core/tool/interpr4.cxx +++ b/sc/source/core/tool/interpr4.cxx @@ -3812,6 +3812,15 @@ StackVar ScInterpreter::Interpret() default : PushError( errUnknownOpCode); break; } + // If the function signalled that it pushed a subroutine on the + // instruction code stack instead of a result, continue with + // execution of the subroutine. + if (sp > nStackBase && pStack[sp-1]->GetOpCode() == ocCall) + { + Pop(); + continue; // while( ( pCur = aCode.Next() ) != NULL ... + } + // Remember result matrix in case it could be reused. if (pTokenMatrixMap && sp && GetStackType() == svMatrix) pTokenMatrixMap->insert( ScTokenMatrixMap::value_type( pCur, diff --git a/sc/source/core/tool/makefile.mk b/sc/source/core/tool/makefile.mk index 8a4b1b44fd12..ac0aa23fc044 100644 --- a/sc/source/core/tool/makefile.mk +++ b/sc/source/core/tool/makefile.mk @@ -1,7 +1,7 @@ #************************************************************************* # # 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 @@ -78,6 +78,7 @@ SLOFILES = \ $(SLO)$/docoptio.obj \ $(SLO)$/editutil.obj \ $(SLO)$/filtopt.obj \ + $(SLO)$/formulaparserpool.obj \ $(SLO)$/hints.obj \ $(SLO)$/indexmap.obj \ $(SLO)$/inputopt.obj \ @@ -122,6 +123,7 @@ EXCEPTIONSFILES= \ $(SLO)$/chartlock.obj \ $(SLO)$/chgtrack.obj \ $(SLO)$/compiler.obj \ + $(SLO)$/formulaparserpool.obj \ $(SLO)$/interpr1.obj \ $(SLO)$/interpr2.obj \ $(SLO)$/interpr3.obj \ diff --git a/sc/source/core/tool/progress.cxx b/sc/source/core/tool/progress.cxx index fc7a7088d2a9..450736997c2d 100644 --- a/sc/source/core/tool/progress.cxx +++ b/sc/source/core/tool/progress.cxx @@ -162,7 +162,7 @@ void ScProgress::CreateInterpretProgress( ScDocument* pDoc, BOOL bWait ) if ( !pGlobalProgress ) pInterpretProgress = new ScProgress( pDoc->GetDocumentShell(), ScGlobal::GetRscString( STR_PROGRESS_CALCULATING ), - pDoc->GetFormulaCodeInTree(), FALSE, bWait ); + pDoc->GetFormulaCodeInTree()/MIN_NO_CODES_PER_PROGRESS_UPDATE, FALSE, bWait ); pInterpretDoc = pDoc; } } diff --git a/sc/source/core/tool/rangenam.cxx b/sc/source/core/tool/rangenam.cxx index 704c3255486e..4a4683935e99 100644 --- a/sc/source/core/tool/rangenam.cxx +++ b/sc/source/core/tool/rangenam.cxx @@ -60,7 +60,7 @@ using namespace formula; // Interner ctor fuer das Suchen nach einem Index ScRangeData::ScRangeData( USHORT n ) - : pCode( NULL ), nIndex( n ), bModified( FALSE ) + : pCode( NULL ), nIndex( n ), bModified( FALSE ), mnMaxRow(-1), mnMaxCol(-1) {} ScRangeData::ScRangeData( ScDocument* pDok, @@ -76,7 +76,9 @@ ScRangeData::ScRangeData( ScDocument* pDok, eType ( nType ), pDoc ( pDok ), nIndex ( 0 ), - bModified ( FALSE ) + bModified ( FALSE ), + mnMaxRow (-1), + mnMaxCol (-1) { if (rSymbol.Len() > 0) { @@ -122,7 +124,9 @@ ScRangeData::ScRangeData( ScDocument* pDok, eType ( nType ), pDoc ( pDok ), nIndex ( 0 ), - bModified ( FALSE ) + bModified ( FALSE ), + mnMaxRow (-1), + mnMaxCol (-1) { if( !pCode->GetCodeError() ) { @@ -157,7 +161,9 @@ ScRangeData::ScRangeData( ScDocument* pDok, eType ( RT_NAME ), pDoc ( pDok ), nIndex ( 0 ), - bModified ( FALSE ) + bModified ( FALSE ), + mnMaxRow (-1), + mnMaxCol (-1) { ScSingleRefData aRefData; aRefData.InitAddress( rTarget ); @@ -179,7 +185,9 @@ ScRangeData::ScRangeData(const ScRangeData& rScRangeData) : eType (rScRangeData.eType), pDoc (rScRangeData.pDoc), nIndex (rScRangeData.nIndex), - bModified (rScRangeData.bModified) + bModified (rScRangeData.bModified), + mnMaxRow (rScRangeData.mnMaxRow), + mnMaxCol (rScRangeData.mnMaxCol) {} ScRangeData::~ScRangeData() @@ -247,7 +255,7 @@ void ScRangeData::UpdateSymbol( rtl::OUStringBuffer& rBuffer, const ScAddress& r ::std::auto_ptr<ScTokenArray> pTemp( pCode->Clone() ); ScCompiler aComp( pDoc, rPos, *pTemp.get()); aComp.SetGrammar(eGrammar); - aComp.MoveRelWrap(); + aComp.MoveRelWrap(GetMaxCol(), GetMaxRow()); aComp.CreateStringFromTokenArray( rBuffer ); } @@ -393,7 +401,7 @@ BOOL ScRangeData::IsReference( ScRange& rRange, const ScAddress& rPos ) const ::std::auto_ptr<ScTokenArray> pTemp( pCode->Clone() ); ScCompiler aComp( pDoc, rPos, *pTemp); aComp.SetGrammar(pDoc->GetGrammar()); - aComp.MoveRelWrap(); + aComp.MoveRelWrap(MAXCOL, MAXROW); return pTemp->IsReference( rRange ); } @@ -520,6 +528,26 @@ BOOL ScRangeData::IsNameValid( const String& rName, ScDocument* pDoc ) return TRUE; } +void ScRangeData::SetMaxRow(SCROW nRow) +{ + mnMaxRow = nRow; +} + +SCROW ScRangeData::GetMaxRow() const +{ + return mnMaxRow >= 0 ? mnMaxRow : MAXROW; +} + +void ScRangeData::SetMaxCol(SCCOL nCol) +{ + mnMaxCol = nCol; +} + +SCCOL ScRangeData::GetMaxCol() const +{ + return mnMaxCol >= 0 ? mnMaxCol : MAXCOL; +} + USHORT ScRangeData::GetErrCode() { diff --git a/sc/source/core/tool/reftokenhelper.cxx b/sc/source/core/tool/reftokenhelper.cxx index 42cf295390d6..e129abdcf97f 100644 --- a/sc/source/core/tool/reftokenhelper.cxx +++ b/sc/source/core/tool/reftokenhelper.cxx @@ -49,13 +49,14 @@ using ::std::auto_ptr; using ::rtl::OUString; void ScRefTokenHelper::compileRangeRepresentation( - vector<ScSharedTokenRef>& rRefTokens, const OUString& rRangeStr, ScDocument* pDoc) + vector<ScSharedTokenRef>& rRefTokens, const OUString& rRangeStr, ScDocument* pDoc, FormulaGrammar::Grammar eGrammar) { const sal_Unicode cSep = ';'; const sal_Unicode cQuote = '\''; + bool bFailure = false; sal_Int32 nOffset = 0; - while (nOffset >= 0) + while (nOffset >= 0 && !bFailure) { OUString aToken; ScRangeStringConverter::GetTokenByOffset(aToken, rRangeStr, nOffset, cSep, cQuote); @@ -63,17 +64,52 @@ void ScRefTokenHelper::compileRangeRepresentation( break; ScCompiler aCompiler(pDoc, ScAddress(0,0,0)); - aCompiler.SetGrammar(FormulaGrammar::GRAM_ENGLISH); + aCompiler.SetGrammar(eGrammar); auto_ptr<ScTokenArray> pArray(aCompiler.CompileString(aToken)); - // There should only be one reference per range token. - pArray->Reset(); - FormulaToken* p = pArray->GetNextReference(); - if (!p) - continue; + // There MUST be exactly one reference per range token and nothing + // else, and it MUST be a valid reference, not some #REF! + USHORT nLen = pArray->GetLen(); + if (!nLen) + continue; // Should a missing range really be allowed? + if (nLen != 1) + bFailure = true; + else + { + pArray->Reset(); + const FormulaToken* p = pArray->GetNextReference(); + if (!p) + bFailure = true; + else + { + const ScToken* pT = static_cast<const ScToken*>(p); + switch (pT->GetType()) + { + case svSingleRef: + if (!pT->GetSingleRef().Valid()) + bFailure = true; + break; + case svDoubleRef: + if (!pT->GetDoubleRef().Valid()) + bFailure = true; + break; + case svExternalSingleRef: + if (!pT->GetSingleRef().ValidExternal()) + bFailure = true; + break; + case svExternalDoubleRef: + if (!pT->GetDoubleRef().ValidExternal()) + bFailure = true; + break; + default: + ; + } + if (!bFailure) + rRefTokens.push_back( + ScSharedTokenRef(static_cast<ScToken*>(p->Clone()))); + } + } - rRefTokens.push_back( - ScSharedTokenRef(static_cast<ScToken*>(p->Clone()))); #if 0 switch (p->GetType()) { @@ -93,7 +129,10 @@ void ScRefTokenHelper::compileRangeRepresentation( ; } #endif + } + if (bFailure) + rRefTokens.clear(); } bool ScRefTokenHelper::getRangeFromToken(ScRange& rRange, const ScSharedTokenRef& pToken, bool bExternal) diff --git a/sc/source/core/tool/refupdat.cxx b/sc/source/core/tool/refupdat.cxx index d019a6082583..ddb5f3dc0a5c 100644 --- a/sc/source/core/tool/refupdat.cxx +++ b/sc/source/core/tool/refupdat.cxx @@ -821,27 +821,27 @@ ScRefUpdateRes ScRefUpdate::Move( ScDocument* pDoc, const ScAddress& rPos, } void ScRefUpdate::MoveRelWrap( ScDocument* pDoc, const ScAddress& rPos, - ScComplexRefData& rRef ) + SCCOL nMaxCol, SCROW nMaxRow, ScComplexRefData& rRef ) { if( rRef.Ref1.IsColRel() ) { rRef.Ref1.nCol = rRef.Ref1.nRelCol + rPos.Col(); - lcl_MoveItWrap( rRef.Ref1.nCol, static_cast<SCsCOL>(0), MAXCOL ); + lcl_MoveItWrap( rRef.Ref1.nCol, static_cast<SCsCOL>(0), nMaxCol ); } if( rRef.Ref2.IsColRel() ) { rRef.Ref2.nCol = rRef.Ref2.nRelCol + rPos.Col(); - lcl_MoveItWrap( rRef.Ref2.nCol, static_cast<SCsCOL>(0), MAXCOL ); + lcl_MoveItWrap( rRef.Ref2.nCol, static_cast<SCsCOL>(0), nMaxCol ); } if( rRef.Ref1.IsRowRel() ) { rRef.Ref1.nRow = rRef.Ref1.nRelRow + rPos.Row(); - lcl_MoveItWrap( rRef.Ref1.nRow, static_cast<SCsROW>(0), MAXROW ); + lcl_MoveItWrap( rRef.Ref1.nRow, static_cast<SCsROW>(0), nMaxRow ); } if( rRef.Ref2.IsRowRel() ) { rRef.Ref2.nRow = rRef.Ref2.nRelRow + rPos.Row(); - lcl_MoveItWrap( rRef.Ref2.nRow, static_cast<SCsROW>(0), MAXROW ); + lcl_MoveItWrap( rRef.Ref2.nRow, static_cast<SCsROW>(0), nMaxRow ); } SCsTAB nMaxTab = (SCsTAB) pDoc->GetTableCount() - 1; if( rRef.Ref1.IsTabRel() ) diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index e8a1dd90a403..0f03d31d3fc8 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -1821,8 +1821,11 @@ void ScTokenArray::ReadjustRelative3DReferences( const ScAddress& rOldPos, case svSingleRef : { ScSingleRefData& rRef1 = static_cast<ScToken*>(pCode[j])->GetSingleRef(); + if ( rRef1.IsFlag3D() ) + { rRef1.CalcAbsIfRel( rOldPos ); rRef1.CalcRelFromAbs( rNewPos ); + } } break; default: diff --git a/sc/source/filter/excel/biffdump.cxx b/sc/source/filter/excel/biffdump.cxx new file mode 100644 index 000000000000..c3478cf8cb50 --- /dev/null +++ b/sc/source/filter/excel/biffdump.cxx @@ -0,0 +1,9864 @@ +/************************************************************************* + * + * 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: biffdump.cxx,v $ + * $Revision: 1.91 $ + * + * 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 "biffdump.hxx" + +#if EXC_INCL_DUMPER +#include <tools/stream.hxx> +#include <sfx2/docfile.hxx> +#include <sfx2/objsh.hxx> +#include <sot/storinfo.hxx> + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> + +#include <rtl/math.hxx> +#include "document.hxx" +#include "global.hxx" +#include "fprogressbar.hxx" +#include "xlpivot.hxx" +#include "xicontent.hxx" +#include "imp_op.hxx" + +#define GETSTR(s) ByteString( s, RTL_TEXTENCODING_MS_1252 ) + +static const sal_Char* __pHexPrefix = "0x"; +static const sal_Char* __pBinPrefix = "0b"; +static const sal_Char* pU = "UNKNOWN "; + +const sal_Char* Biff8RecDumper::pLevelPreString = " "; +const sal_Char* Biff8RecDumper::pLevelPreStringNT = pLevelPreString + strlen( pLevelPreString ); +UINT32 Biff8RecDumper::nInstances = 0; +sal_Char* Biff8RecDumper::pBlankLine = NULL; +const UINT16 Biff8RecDumper::nLenBlankLine = 255; +const UINT16 Biff8RecDumper::nRecCnt = 0x2020; +UINT8* Biff8RecDumper::pCharType = NULL; +UINT8* Biff8RecDumper::pCharVal = NULL; + +static const UINT16 nLevelInc = 1; + +static UINT16 nXFCount = 0; + +static UINT16 nSXLISize[2] = {0, 0}; // array size for SXLI records [rows/cols] +static UINT16 nSXLIIndex = 0; // current index for SXLI records + +// ============================================================================ + +namespace { + +// decimal -------------------------------------------------------------------- + +inline void lclAppendDec( ByteString& rStr, sal_uInt8 nData ) +{ + rStr.Append( ByteString::CreateFromInt32( nData ) ); +} + +inline void lclAppendDec( ByteString& rStr, sal_Int8 nData ) +{ + rStr.Append( ByteString::CreateFromInt32( nData ) ); +} + +inline void lclAppendDec( ByteString& rStr, sal_uInt16 nData ) +{ + rStr.Append( ByteString::CreateFromInt32( nData ) ); +} + +inline void lclAppendDec( ByteString& rStr, sal_Int16 nData ) +{ + rStr.Append( ByteString::CreateFromInt32( nData ) ); +} + +inline void lclAppendDec( ByteString& rStr, sal_uInt32 nData ) +{ + rStr.Append( ByteString::CreateFromInt64( nData ) ); +} + +inline void lclAppendDec( ByteString& rStr, sal_Int32 nData ) +{ + rStr.Append( ByteString::CreateFromInt32( nData ) ); +} + +inline void lclAppendDec( ByteString& rStr, float fData ) +{ + rStr.Append( ByteString( ::rtl::math::doubleToString( fData, rtl_math_StringFormat_G, 15, '.', true ) ) ); +} + +inline void lclAppendDec( ByteString& rStr, double fData ) +{ + rStr.Append( ByteString( ::rtl::math::doubleToString( fData, rtl_math_StringFormat_G, 15, '.', true ) ) ); +} + +// hexadecimal ---------------------------------------------------------------- + +void lclAppendHex( ByteString& rStr, sal_uInt8 nData, bool bPrefix = true ) +{ + static const sal_Char spcHexDigits[] = "0123456789ABCDEF"; + static const ByteString saPrefix( "0x" ); + + if( bPrefix ) + rStr.Append( saPrefix ); + rStr.Append( spcHexDigits[ (nData >> 4) & 0x0F ] ).Append( spcHexDigits[ nData & 0x0F ] ); +} + +inline void lclAppendHex( ByteString& rStr, sal_Int8 nData, bool bPrefix = true ) +{ + lclAppendHex( rStr, static_cast< sal_uInt8 >( nData ), bPrefix ); +} + +void lclAppendHex( ByteString& rStr, sal_uInt16 nData, bool bPrefix = true ) +{ + lclAppendHex( rStr, static_cast< sal_uInt8 >( nData >> 8 ), bPrefix ); + lclAppendHex( rStr, static_cast< sal_uInt8 >( nData ), false ); +} + +inline void lclAppendHex( ByteString& rStr, sal_Int16 nData, bool bPrefix = true ) +{ + lclAppendHex( rStr, static_cast< sal_uInt16 >( nData ), bPrefix ); +} + +void lclAppendHex( ByteString& rStr, sal_uInt32 nData, bool bPrefix = true ) +{ + lclAppendHex( rStr, static_cast< sal_uInt16 >( nData >> 16 ), bPrefix ); + lclAppendHex( rStr, static_cast< sal_uInt16 >( nData ), false ); +} + +inline void lclAppendHex( ByteString& rStr, sal_Int32 nData, bool bPrefix = true ) +{ + lclAppendHex( rStr, static_cast< sal_uInt32 >( nData ), bPrefix ); +} + +inline void lclAppendHex( ByteString& rStr, double fData, bool bPrefix = true ) +{ + const sal_uInt32* pnData = reinterpret_cast< const sal_uInt32* >( &fData ); + lclAppendHex( rStr, pnData[ 0 ], bPrefix ); + lclAppendHex( rStr, pnData[ 1 ], false ); +} + +// others --------------------------------------------------------------------- + +void lclAppendGuid( ByteString& rStr, const XclGuid& rGuid ) +{ + lclAppendHex( rStr, SVBT32ToUInt32( rGuid.mpnData ), false ); + rStr.Append( '-' ); + lclAppendHex( rStr, SVBT16ToShort( rGuid.mpnData + 4 ), false ); + rStr.Append( '-' ); + lclAppendHex( rStr, SVBT16ToShort( rGuid.mpnData + 6 ), false ); + rStr.Append( '-' ); + lclAppendHex( rStr, rGuid.mpnData[ 8 ], false ); + lclAppendHex( rStr, rGuid.mpnData[ 9 ], false ); + rStr.Append( '-' ); + lclAppendHex( rStr, rGuid.mpnData[ 10 ], false ); + lclAppendHex( rStr, rGuid.mpnData[ 11 ], false ); + lclAppendHex( rStr, rGuid.mpnData[ 12 ], false ); + lclAppendHex( rStr, rGuid.mpnData[ 13 ], false ); + lclAppendHex( rStr, rGuid.mpnData[ 14 ], false ); + lclAppendHex( rStr, rGuid.mpnData[ 15 ], false ); +} + +} // namespace + +// ============================================================================ + +static void __AddHexNibble( ByteString& r, UINT8 nVal ) +{ + const sal_Char pH[] = "0123456789ABCDEF"; + + nVal &= 0x0F; + + r += pH[ nVal ]; +} + + +static void __AddPureHex( ByteString& r, UINT8 nVal ) +{ + __AddHexNibble( r, nVal >> 4 ); + __AddHexNibble( r, nVal ); +} + + +static void __AddHex( ByteString& r, UINT8 nVal ) +{ + r += __pHexPrefix; + __AddHexNibble( r, nVal >> 4 ); + __AddHexNibble( r, nVal ); +} + + +static void __AddPureHex( ByteString& r, UINT16 nVal ) +{ + __AddHexNibble( r, ( UINT8 ) ( nVal >> 12 ) ); + __AddHexNibble( r, ( UINT8 ) ( nVal >> 8 ) ); + __AddHexNibble( r, ( UINT8 ) ( nVal >> 4 ) ); + __AddHexNibble( r, ( UINT8 ) nVal ); +} + + +static void __AddHex( ByteString& r, UINT16 nVal ) +{ + r += __pHexPrefix; + __AddHexNibble( r, ( UINT8 ) ( nVal >> 12 ) ); + __AddHexNibble( r, ( UINT8 ) ( nVal >> 8 ) ); + __AddHexNibble( r, ( UINT8 ) ( nVal >> 4 ) ); + __AddHexNibble( r, ( UINT8 ) nVal ); +} + + +static void __AddPureHex( ByteString& r, UINT32 nVal ) +{ + __AddHexNibble( r, ( UINT8 ) ( nVal >> 28 ) ); + __AddHexNibble( r, ( UINT8 ) ( nVal >> 24 ) ); + __AddHexNibble( r, ( UINT8 ) ( nVal >> 20 ) ); + __AddHexNibble( r, ( UINT8 ) ( nVal >> 16 ) ); + __AddHexNibble( r, ( UINT8 ) ( nVal >> 12 ) ); + __AddHexNibble( r, ( UINT8 ) ( nVal >> 8 ) ); + __AddHexNibble( r, ( UINT8 ) ( nVal >> 4 ) ); + __AddHexNibble( r, ( UINT8 ) nVal ); +} + + +static void __AddHex( ByteString& r, UINT32 nVal ) +{ + r += __pHexPrefix; + __AddHexNibble( r, ( UINT8 ) ( nVal >> 28 ) ); + __AddHexNibble( r, ( UINT8 ) ( nVal >> 24 ) ); + __AddHexNibble( r, ( UINT8 ) ( nVal >> 20 ) ); + __AddHexNibble( r, ( UINT8 ) ( nVal >> 16 ) ); + __AddHexNibble( r, ( UINT8 ) ( nVal >> 12 ) ); + __AddHexNibble( r, ( UINT8 ) ( nVal >> 8 ) ); + __AddHexNibble( r, ( UINT8 ) ( nVal >> 4 ) ); + __AddHexNibble( r, ( UINT8 ) nVal ); +} + + +static void __AddHex( ByteString& r, INT32 nVal ) +{ + __AddHex( r, (UINT32) nVal ); +} + + +static void __AddPureBinNibble( ByteString& r, UINT8 nVal ) +{ + nVal <<= 4; + for( int n = 4 ; n ; n-- ) + { + r += ( nVal & 0x80 )? "1" : "0"; + nVal <<= 1; + } +} + + +static void __AddPureBin( ByteString& r, UINT8 nVal ) +{ + __AddPureBinNibble( r, nVal >> 4 ); + r += " "; + __AddPureBinNibble( r, nVal ); +} + + +static void __AddPureBin( ByteString& r, UINT16 nVal ) +{ + const sal_Char* pIn = " "; + __AddPureBin( r, ( UINT8 ) ( nVal >> 8 ) ); + r += pIn; + __AddPureBin( r, ( UINT8 ) nVal ); +} + + +static void __AddPureBin( ByteString& r, UINT32 nVal ) +{ + const sal_Char* pIn = " "; + __AddPureBin( r, ( UINT8 ) ( nVal >> 24 ) ); + r += pIn; + __AddPureBin( r, ( UINT8 ) ( nVal >> 16 ) ); + r += pIn; + __AddPureBin( r, ( UINT8 ) ( nVal >> 8 ) ); + r += pIn; + __AddPureBin( r, ( UINT8 ) nVal ); +} + + +inline static void __AddDec( ByteString& r, UINT32 n ) +{ + sal_Char p[ 32 ]; + sprintf( p, "%u", n ); // #100211# - checked + r += p; +} + + +inline static void __AddDec( ByteString& r, UINT16 n ) +{ + __AddDec( r, ( UINT32 ) n ); +} + + +inline static void __AddDec( ByteString& r, UINT8 n ) +{ + __AddDec( r, ( UINT32 ) n ); +} + + +inline static void __AddDec( ByteString& r, INT32 n ) +{ + sal_Char p[ 32 ]; + sprintf( p, "%d", n ); // #100211# - checked + r += p; +} + + +inline static void __AddDec( ByteString& r, INT16 n ) +{ + __AddDec( r, ( INT32 ) n ); +} + +inline static void __AddDec( ByteString& r, sal_Int8 n ) +{ + __AddDec( r, ( INT32 ) n ); +} + + +static void __AddDec( ByteString& r, UINT32 nVal, UINT16 nNumOfDig, sal_Char c = ' ' ) +{ + ByteString t; + ByteString aVal; + __AddDec( aVal, nVal ); + if( nNumOfDig > (UINT16) aVal.Len() ) + t.Fill( nNumOfDig - (UINT16) aVal.Len(), c ); + r += t; + r += aVal; +} + + +inline static void __AddDec1616( ByteString& r, UINT32 n ) +{ + __AddDec( r, (UINT16)(n >> 16) ); + r += '.'; + __AddDec( r, (UINT16)(n & 0xFFFF) ); +} + + +static void __AddDouble( ByteString& r, const double f ) +{ + r += ByteString( ::rtl::math::doubleToString( f, rtl_math_StringFormat_G, 15, '.', TRUE ) ); +} + + +static inline void __AddRK( ByteString& rString, sal_Int32 nRKValue ) +{ + __AddDouble( rString, XclTools::GetDoubleFromRK( nRKValue ) ); +} + + +inline static void __Add16p16( ByteString& r, UINT32 n ) +{ + __AddDouble( r, double(n) / 65536.0 ); +} + + +static void lcl_AddRef( ByteString& rStr, sal_uInt16 nCol, sal_uInt16 nRow ) +{ + ScAddress aRef( static_cast< SCCOL >( nCol ), static_cast< SCROW >( nRow ), 0 ); + rStr.Append( GETSTR( aRef.GetColRowString() ) ); +} + + +static void lcl_AddRangeRef( ByteString& rStr, sal_uInt16 nCol1, sal_uInt16 nRow1, sal_uInt16 nCol2, sal_uInt16 nRow2 ) +{ + lcl_AddRef( rStr, nCol1, nRow1 ); + if( (nCol1 != nCol2) || (nRow1 != nRow2) ) + { + rStr.Append( ':' ); + lcl_AddRef( rStr, nCol2, nRow2 ); + } +} + + +static void __AddCellHead( ByteString& r, const UINT16 nC, const UINT16 nR, const UINT16 nXF ) +{ + lcl_AddRef( r, (UINT8) nC, nR ); + r += " (XF="; + __AddDec( r, nXF ); + r += ')'; +} + + +inline static void lcl_AddFlag( + ByteString& rString, bool bFlag, const sal_Char* pcTrue = "true", const sal_Char* pcFalse = "false" ) +{ + rString += (bFlag ? pcTrue : pcFalse); +} + +inline static void lcl_AddOnOff( ByteString& rString, bool bFlag ) +{ + lcl_AddFlag( rString, bFlag, "on", "off" ); +} + + +static void lcl_AddEnum( + ByteString& rString, long nValue, const sal_Char* const ppcEnums[], long nSize, + const sal_Char* pcDefault = 0, long nOffset = 0 ) +{ + nValue -= nOffset; + const sal_Char* pcText = "!unknown!"; + if( (0 <= nValue) && (nValue < nSize) && ppcEnums[ nValue ] ) + pcText = ppcEnums[ nValue ]; + else if( pcDefault ) + pcText = pcDefault; + if( *pcText ) // nonempty string + rString.Append( " (" ).Append( pcText ).Append( ')' ); +} + + +namespace { + +void lclDumpString( SvStream& rOutStrm, const ByteString& rData ) +{ + ByteString aOutStr; + xub_StrLen nIdx = 0; + for( ; (nIdx < rData.Len()) && (aOutStr.Len() < 80); ++nIdx ) + { + sal_Char cChar = rData.GetChar( nIdx ); + if( 32 <= cChar ) + aOutStr.Append( cChar ); + else + { + aOutStr.Append( '<' ); + __AddHex( aOutStr, static_cast< sal_uInt8 >( cChar ) ); + aOutStr.Append( '>' ); + } + } + rOutStrm << aOutStr.GetBuffer(); + if( nIdx < rData.Len() ) + rOutStrm << "<...>"; +} + +void lclDumpStringValue( SvStream& rOutStrm, const ByteString& rName, const ByteString& rData ) +{ + rOutStrm << rName.GetBuffer() << "='"; + lclDumpString( rOutStrm, rData ); + rOutStrm << '\''; +} + +void lclDumpString( SvStream& rOutStrm, const String& rData ) +{ + ByteString aOutStr; + xub_StrLen nIdx = 0; + for( ; (nIdx < rData.Len()) && (aOutStr.Len() < 80); ++nIdx ) + { + sal_Unicode cChar = rData.GetChar( nIdx ); + if( (32 <= cChar) && (cChar <= 255) ) + aOutStr.Append( static_cast< sal_Char >( cChar ) ); + else + { + aOutStr.Append( '<' ); + if( cChar < 256 ) + __AddHex( aOutStr, static_cast< sal_uInt8 >( cChar ) ); + else + __AddHex( aOutStr, static_cast< sal_uInt16 >( cChar ) ); + aOutStr.Append( '>' ); + } + } + rOutStrm << aOutStr.GetBuffer(); + if( nIdx < rData.Len() ) + rOutStrm << "<...>"; +} + +void lclDumpStringValue( SvStream& rOutStrm, const ByteString& rName, const String& rData ) +{ + rOutStrm << rName.GetBuffer() << "='"; + lclDumpString( rOutStrm, rData ); + rOutStrm << '\''; +} + +} // namespace + + +IdRangeList::~IdRangeList() +{ + Clear(); +} + + +void IdRangeList::Clear( void ) +{ + IdRange* p = ( IdRange* ) First(); + + while( p ) + { + delete p; + p = ( IdRange* ) Next(); + } + + List::Clear(); +} + +// ============================================================================ +// +// H E L P E R O B J E C T S +// +// ============================================================================ + +namespace { + +// ---------------------------------------------------------------------------- + +class XclDumpStreamHeader +{ +public: + explicit XclDumpStreamHeader( SvStream& rInStrm, SvStream& rOutStrm, const String& rStrmName, const String& rStrmPath ); + ~XclDumpStreamHeader(); + inline ULONG GetStreamLen() const { return mnStrmLen; } + +private: + SvStream& mrOutStrm; + String maStrmName; + String maStrmPath; + ByteString maSeparator; + ULONG mnStrmLen; +}; + +XclDumpStreamHeader::XclDumpStreamHeader( SvStream& rInStrm, SvStream& rOutStrm, const String& rStrmName, const String& rStrmPath ) : + mrOutStrm( rOutStrm ), + maStrmName( rStrmName ), + maStrmPath( rStrmPath ), + mnStrmLen( 0 ) +{ + maSeparator.Assign( '+' ).Expand( 78, '-' ); + + rInStrm.Seek( STREAM_SEEK_TO_END ); + mnStrmLen = rInStrm.Tell(); + rInStrm.Seek( STREAM_SEEK_TO_BEGIN ); + + ByteString aLine; + lclAppendDec( aLine, mnStrmLen ); + + mrOutStrm << maSeparator.GetBuffer() << "\n"; + mrOutStrm << "| STREAM-BEGIN\n"; + mrOutStrm << "| "; + lclDumpStringValue( mrOutStrm, "stream-name", maStrmName ); + mrOutStrm << "\n| "; + lclDumpStringValue( mrOutStrm, "stream-path", maStrmPath ); + mrOutStrm << "\n| stream-len=" << aLine.GetBuffer() << "\n"; + mrOutStrm << "|\n\n"; +} + +XclDumpStreamHeader::~XclDumpStreamHeader() +{ + mrOutStrm << "|\n"; + mrOutStrm << "| "; + lclDumpStringValue( mrOutStrm, "stream-name", maStrmName ); + mrOutStrm << "\n| "; + lclDumpStringValue( mrOutStrm, "stream-path", maStrmPath ); + mrOutStrm << "\n"; + mrOutStrm << "| STREAM-END\n"; + mrOutStrm << maSeparator.GetBuffer() << "\n\n"; +} + +// ---------------------------------------------------------------------------- + +class XclDumpStorageHeader +{ +public: + explicit XclDumpStorageHeader( SotStorage& rInStrg, SvStream& rOutStrm, const String& rStrgPath ); + ~XclDumpStorageHeader(); + +private: + SvStream& mrOutStrm; + String maStrgName; + String maStrgPath; + ByteString maSeparator; +}; + +XclDumpStorageHeader::XclDumpStorageHeader( SotStorage& rInStrg, SvStream& rOutStrm, const String& rStrgPath ) : + mrOutStrm( rOutStrm ), + maStrgName( rInStrg.GetName() ), + maStrgPath( rStrgPath ) +{ + maSeparator.Assign( "++" ).Expand( 78, '=' ); + + mrOutStrm << maSeparator.GetBuffer() << "\n"; + mrOutStrm << "|| STORAGE-BEGIN\n"; + mrOutStrm << "|| "; + lclDumpStringValue( mrOutStrm, "storage-name", maStrgName ); + mrOutStrm << "\n|| "; + lclDumpStringValue( mrOutStrm, "storage-path", maStrgPath ); + mrOutStrm << "\n"; + + SvStorageInfoList aInfoList; + rInStrg.FillInfoList( &aInfoList ); + ByteString aLine; + lclAppendDec( aLine, aInfoList.Count() ); + mrOutStrm << "|| directory-size=" << aLine.GetBuffer() << "\n"; + + for( ULONG nInfo = 0; nInfo < aInfoList.Count(); ++nInfo ) + { + SvStorageInfo& rInfo = aInfoList.GetObject( nInfo ); + mrOutStrm << "|| type="; + if( rInfo.IsStream() ) + mrOutStrm << "stream "; + else if( rInfo.IsStorage() ) + mrOutStrm << "storage "; + else + mrOutStrm << "unknown "; + lclDumpStringValue( mrOutStrm, "name", rInfo.GetName() ); + mrOutStrm << "\n"; + } + + mrOutStrm << "||\n\n"; +} + +XclDumpStorageHeader::~XclDumpStorageHeader() +{ + mrOutStrm << "||\n"; + mrOutStrm << "|| "; + lclDumpStringValue( mrOutStrm, "storage-name", maStrgName ); + mrOutStrm << "\n|| "; + lclDumpStringValue( mrOutStrm, "storage-path", maStrgPath ); + mrOutStrm << "\n"; + mrOutStrm << "|| STORAGE-END\n"; + mrOutStrm << maSeparator.GetBuffer() << "\n\n"; +} + +// ---------------------------------------------------------------------------- + +} + +// ============================================================================ +// +// ============================================================================ + +void Biff8RecDumper::Print( const ByteString& r ) +{ + DBG_ASSERT( pDumpStream, "-Biff8RecDumper::Print(): Stream is wech!" ); + *pDumpStream << '\n' << pLevelPre; + pDumpStream->Write( r.GetBuffer(), r.Len() ); +} + + +void Biff8RecDumper::Print( const sal_Char* p ) +{ + DBG_ASSERT( pDumpStream, "-Biff8RecDumper::Print(): Stream is wech!" ); + DBG_ASSERT( p, "-Biff8RecDumper::Print(): ByteString is wech!" ); + + *pDumpStream << '\n' << pLevelPre << p; +} + + +static const sal_Char* GetSeriesType( const UINT16 n ) +{ + const sal_Char* p; + + switch( n ) + { + case 0: p = "(date) "; break; + case 1: p = "(numeric) "; break; + case 2: p = "(sequence)"; break; + case 3: p = "(text) "; break; + default: p = "(unknown) "; + } + + return p; +} + + +static const sal_Char* GetLineType( const UINT16 n ) +{ + const sal_Char* p; + + switch( n ) + { + case 0: p = "solid"; break; + case 1: p = "dash"; break; + case 2: p = "dot"; break; + case 3: p = "dash-dot"; break; + case 4: p = "dash-dot-dot"; break; + case 5: p = "none"; break; + case 6: p = "dark gray pattern"; break; + case 7: p = "medium gray pattern"; break; + case 8: p = "light gray pattern"; break; + default: p = pU; + } + + return p; +} + + +static ByteString GetRGB( const UINT32 n ) +{ + ByteString s; + + s += "R"; + __AddDec( s, ( UINT8 ) n ); + s += " G"; + __AddDec( s, ( UINT8 ) ( n >> 8 ) ); + s += " B"; + __AddDec( s, ( UINT8 ) ( n >> 16 ) ); + + return s; +} + + +static void AddRef( ByteString& t, UINT16 nRow, UINT16 nC, BOOL bName, UINT16 nTab = 0xFFFF ) +{ + BOOL bColRel = ( nC & 0x4000 ) != 0; + BOOL bRowRel = ( nC & 0x8000 ) != 0; + UINT8 nCol = (UINT8) nC; + INT8 nRelCol = (INT8) nCol; + INT16 nRelRow = (INT16) nRow; + + if( nTab < 0xFFFF ) + { + t += "XTI("; + __AddDec( t, nTab ); + t += ")!"; + } + + if( bName ) + { + // dump relative: [Column|Row] + // [C-1,R-1] = one column left, one row up + // [C+1,R+1] = one column right, one row down + // [C,R] = same column/row + // [C=B,R=2] = absolute column B/row 2 + t += "[C"; + if( bColRel ) + { + if( nRelCol > 0 ) + t += '+'; + if( nRelCol != 0 ) + __AddDec( t, (INT16)nRelCol ); + } + else + { + t += '='; + t += GETSTR( ::ScScColToAlpha( nCol ) ); + } + + t += ",R"; + if( bRowRel ) + { + if( nRelRow > 0 ) + t += "+"; + if( nRelRow != 0 ) + __AddDec( t, nRelRow ); + } + else + { + t += '='; + __AddDec( t, (INT32)nRow + 1 ); + } + t += ']'; + } + else + { + if( !bColRel ) + t += '$'; + t += GETSTR( ::ScColToAlpha( nCol ) ); + if( !bRowRel ) + t += '$'; + __AddDec( t, (UINT16)(nRow + 1) ); + } +} + +static void AddRangeRef( ByteString& t, UINT16 nRow1, UINT16 nC1, UINT16 nRow2, UINT16 nC2, BOOL bName, UINT16 nTab = 0xFFFF ) +{ + AddRef( t, nRow1, nC1, bName, nTab ); + if( (nRow1 != nRow2) || (nC1 != nC2) ) + { + t += ':'; + AddRef( t, nRow2, nC2, bName ); + } +} + + + +static BOOL AddUNICODEString( ByteString& rStr, XclImpStream& rStrm, const BOOL b16BitLen = TRUE, UINT16 nLen = 0, ByteString* pRawName = 0 ) +{ + BOOL bRet = TRUE; + + if( !nLen ) + nLen = b16BitLen ? rStrm.ReaduInt16() : rStrm.ReaduInt8(); + UINT8 nGrbit = rStrm.ReaduInt8(); + + UINT32 nExtLen; + UINT16 nCrun; + bool b16Bit, bFarEast, bRichString; + rStrm.ReadUniStringExtHeader( b16Bit, bRichString, bFarEast, nCrun, nExtLen, nGrbit ); + + rStr += "(l="; + __AddDec( rStr, nLen ); + rStr += " f="; + __AddHex( rStr, nGrbit ); + rStr += " "; + rStr += b16Bit ? "16-Bit" : "8-Bit"; + + if( bRichString && bFarEast ) + rStr += " rich far-east"; + else if( bRichString && !bFarEast ) + rStr += " rich"; + else if ( !bRichString && bFarEast ) + rStr += " far-east"; + rStr += ") '"; + + ByteString aData( rStrm.ReadRawUniString( nLen, b16Bit ), RTL_TEXTENCODING_MS_1252 ); + if( pRawName ) *pRawName = aData; + + xub_StrLen nIndex = 0; + while( (nIndex < aData.Len()) && (nIndex < 255) ) + { + UINT8 nChar = (UINT8)aData.GetChar( nIndex ); + if( nChar < ' ' ) + { + ByteString aIns( '<' ); + __AddHex( aIns, nChar ); + aIns += '>'; + aData.Erase( nIndex, 1 ).Insert( aIns, nIndex ); + nIndex += 5; + } + nIndex++; + } + + rStr += aData.Copy( 0, 255 ); + rStr += '\''; + if( aData.Len() > 255 ) + rStr += "..."; + + if( nCrun ) + { + rStr += " + "; + __AddDec( rStr, nCrun ); + rStr += " format blocks ("; + nCrun *= 4; + __AddDec( rStr, nCrun ); + rStr += " bytes)"; + rStrm.Ignore( nCrun ); + } + if( nExtLen ) + { + rStr += " + "; + __AddDec( rStr, nExtLen ); + rStr += " byte extended:"; + for( sal_uInt32 nIdx = 0; rStrm.IsValid() && (nIdx < nExtLen); ++nIdx ) + { + rStr.Append( ' ' ); + __AddPureHex( rStr, rStrm.ReaduInt8() ); + } + } + + return bRet; +} + + +DUMP_ERR::~DUMP_ERR() +{ + if( pHint ) + delete pHint; +} + + + + +#define Read1(rIn) (rIn).ReaduInt8() +#define Read2(rIn) (rIn).ReaduInt16() +#define Read4(rIn) (rIn).ReaduInt32() +#define Read8(rIn) (rIn).ReadDouble() +#define LINESTART() {t.Erase();t+=pPre;} +#define IGNORE(n) rIn.Ignore(n) +#define ADDBIN(n) __AddBin( t, Read##n( rIn ) ) +#define ADDHEX(n) __AddHex( t, Read##n( rIn ) ) +#define ADDDEC(n) __AddDec( t, Read##n( rIn ) ) +#define ADDDOUBLE() __AddDouble( t, rIn.ReadDouble() ) +#define ADD16P16() __Add16p16( t, Read4( rIn ) ) +#define ADDTEXT(T) t += T +#define PRINT() Print( t ) +#define PreDump(LEN) {rIn.PushPosition();ContDump(LEN);rIn.PopPosition();} +#define ADDCELLHEAD() {UINT16 nR,nC,nX;rIn>>nR>>nC>>nX;__AddCellHead(t,nC,nR,nX);} +#define STARTFLAG() {ADDTEXT( "flags=" ); __AddHex( t, __nFlags ); ADDTEXT( " " );} +#define ADDFLAG(mask,text) {if( __nFlags & mask ) t.Append( ' ' ).Append( text );} +#define ADDRESERVED(mask) ADDFLAG(mask,"!RESERVED!") + + +UINT16 Biff8RecDumper::DumpXF( XclImpStream& rStrm, const sal_Char* pPre ) +{ + ByteString t; // "t" needed by macros + + sal_uInt32 nBorder1, nBorder2; + sal_uInt16 nFont, nNumFmt, nTypeProt, nAlign, nMiscAttrib, nArea, __nFlags, nTmp; + rStrm >> nFont >> nNumFmt >> nTypeProt >> nAlign >> nMiscAttrib >> nBorder1 >> nBorder2 >> nArea; + bool bCell = !::get_flag( nTypeProt, EXC_XF_STYLE ); + + // XF type/parent + LINESTART(); + ::extract_value( nTmp, nTypeProt, 4, 12 ); + ADDTEXT( "index=#" ); __AddDec( t, nXFCount++ ); + ADDTEXT( " type=" ); lcl_AddFlag( t, bCell, "cell", "style" ); + ADDTEXT( " parent-xf=#" ); __AddDec( t, nTmp ); + PRINT(); + + // attribute used flags + LINESTART(); + ::extract_value( __nFlags, nMiscAttrib, 10, 6 ); + if( !bCell ) __nFlags ^= 0x3F; // in style XFs a 0 means used + ADDTEXT( "used " ); STARTFLAG(); + ADDFLAG( EXC_XF_DIFF_VALFMT, "numfmt" ); + ADDFLAG( EXC_XF_DIFF_FONT, "font" ); + ADDFLAG( EXC_XF_DIFF_ALIGN, "align" ); + ADDFLAG( EXC_XF_DIFF_BORDER, "border" ); + ADDFLAG( EXC_XF_DIFF_AREA, "area" ); + ADDFLAG( EXC_XF_DIFF_PROT, "prot" ); + PRINT(); + + // cell protection/font/number format + LINESTART(); + ADDTEXT( "cell-lock=" ); lcl_AddOnOff( t, ::get_flag( nTypeProt, EXC_XF_LOCKED ) ); + ADDTEXT( " hidden=" ); lcl_AddOnOff( t, ::get_flag( nTypeProt, EXC_XF_HIDDEN ) ); + ADDTEXT( " font=" ); __AddDec( t, nFont ); + ADDTEXT( " num-fmt=" ); __AddDec( t, nNumFmt ); + PRINT(); + + // alignment + LINESTART(); + ::extract_value( nTmp, nAlign, 0, 3 ); + ADDTEXT( "hor-align=" ); __AddDec( t, nTmp ); + ADDTEXT( " (" ); + switch( nTmp ) + { + case EXC_XF_HOR_GENERAL: ADDTEXT( "general" ); break; + case EXC_XF_HOR_LEFT: ADDTEXT( "left" ); break; + case EXC_XF_HOR_CENTER: ADDTEXT( "center" ); break; + case EXC_XF_HOR_RIGHT: ADDTEXT( "right" ); break; + case EXC_XF_HOR_FILL: ADDTEXT( "fill" ); break; + case EXC_XF_HOR_JUSTIFY: ADDTEXT( "justify" ); break; + case EXC_XF_HOR_CENTER_AS: ADDTEXT( "center-as" ); break; + case EXC_XF_HOR_DISTRIB: ADDTEXT( "distrib" ); break; + default: ADDTEXT( "!unknown!" ); + }; + ::extract_value( nTmp, nAlign, 4, 3 ); + ADDTEXT( ") ver-align=" ); __AddDec( t, nTmp ); + ADDTEXT( " (" ); + switch( nTmp ) + { + case EXC_XF_VER_TOP: ADDTEXT( "top" ); break; + case EXC_XF_VER_CENTER: ADDTEXT( "center" ); break; + case EXC_XF_VER_BOTTOM: ADDTEXT( "bottom" ); break; + case EXC_XF_VER_JUSTIFY: ADDTEXT( "justify" ); break; + case EXC_XF_VER_DISTRIB: ADDTEXT( "distrib" ); break; + default: ADDTEXT( "!unknown!" ); + }; + ADDTEXT( ") text-wrap=" ); lcl_AddOnOff( t, ::get_flag( nAlign, EXC_XF_LINEBREAK ) ); + PRINT(); + + LINESTART(); + ::extract_value( nTmp, nAlign, 8, 8 ); + ADDTEXT( "rotation=" ); __AddDec( t, nTmp ); + ADDTEXT( " (" ); + if( nTmp < 91 ) + { __AddDec( t, nTmp ); ADDTEXT( "\xB0" ); } + else if( nTmp < 181 ) + { __AddDec( t, static_cast< sal_Int32 >( 90 - nTmp ) ); ADDTEXT( "\xB0" ); } + else if( nTmp == EXC_ROT_STACKED ) + { ADDTEXT( "stacked" ); } + else + { ADDTEXT( "!unknown!" ); } + ::extract_value( nTmp, nMiscAttrib, 0, 4 ); + ADDTEXT( ") indent=" ); __AddDec( t, nTmp ); + ADDTEXT( " shrink=" ); lcl_AddOnOff( t, ::get_flag( nMiscAttrib, EXC_XF8_SHRINK ) ); + ::extract_value( nTmp, nMiscAttrib, 6, 2 ); + ADDTEXT( " text-dir=" ); __AddDec( t, nTmp ); + ADDTEXT( " (" ); + switch( nTmp ) + { + case EXC_XF_TEXTDIR_CONTEXT: ADDTEXT( "context" ); break; + case EXC_XF_TEXTDIR_LTR: ADDTEXT( "ltr" ); break; + case EXC_XF_TEXTDIR_RTL: ADDTEXT( "rtl" ); break; + default: ADDTEXT( "!unknown!" ); + }; + ADDTEXT( ")" ); + PRINT(); + + // border/area + LINESTART(); + ::extract_value( nTmp, nBorder1, 0, 4 ); + ADDTEXT( "left-line=" ); __AddDec( t, nTmp ); + ::extract_value( nTmp, nBorder1, 16, 7 ); + ADDTEXT( " color=" ); __AddDec( t, nTmp ); + ::extract_value( nTmp, nBorder1, 4, 4 ); + ADDTEXT( " right-line =" ); __AddDec( t, nTmp ); + ::extract_value( nTmp, nBorder1, 23, 7 ); + ADDTEXT( " color=" ); __AddDec( t, nTmp ); + PRINT(); + LINESTART(); + ::extract_value( nTmp, nBorder1, 8, 4 ); + ADDTEXT( "top-line =" ); __AddDec( t, nTmp ); + ::extract_value( nTmp, nBorder2, 0, 7 ); + ADDTEXT( " color=" ); __AddDec( t, nTmp ); + ::extract_value( nTmp, nBorder1, 12, 4 ); + ADDTEXT( " bottom-line=" ); __AddDec( t, nTmp ); + ::extract_value( nTmp, nBorder2, 7, 7 ); + ADDTEXT( " color=" ); __AddDec( t, nTmp ); + PRINT(); + LINESTART(); + ::extract_value( nTmp, nBorder2, 21, 4 ); + ADDTEXT( "diag-line=" ); __AddDec( t, nTmp ); + ::extract_value( nTmp, nBorder2, 14, 7 ); + ADDTEXT( " color=" ); __AddDec( t, nTmp ); + ADDTEXT( " diag-tl-to-br=" ); lcl_AddOnOff( t, ::get_flag( nBorder1, 0x40000000UL ) ); + ADDTEXT( " diag-bl-to-tr=" ); lcl_AddOnOff( t, ::get_flag( nBorder1, 0x80000000UL ) ); + PRINT(); + LINESTART(); + ::extract_value( nTmp, nBorder2, 26, 6 ); + ADDTEXT( "area-pattern=" ); __AddDec( t, nTmp ); + ::extract_value( nTmp, nArea, 0, 7 ); + ADDTEXT( " fore-color=" ); __AddDec( t, nTmp ); + ::extract_value( nTmp, nArea, 7, 7 ); + ADDTEXT( " back-color=" ); __AddDec( t, nTmp ); + PRINT(); + + return 0; +} + +void Biff8RecDumper::DumpValidPassword( XclImpStream& rIn, const sal_Char* pPre ) +{ + ByteString t; + UINT16 nHash; + rIn >> nHash; + LINESTART(); + ADDTEXT( "hash=" ); + __AddHex( t, nHash ); + if( nHash ) + { + ByteString sPasswd; + ByteString sDummy; + UINT16 nLen = 9; + UINT16 nDummy; + UINT16 nNewChar; + + nHash ^= 0xCE4B; + nDummy = nHash; + ADDTEXT( " without-mask=" ); + __AddHex( t, nHash ); + while( !(nDummy & 0x8000) && nLen ) + { + nLen--; + nDummy <<= 1; + } + if( !nLen ) nLen = 2; + if( (nLen ^ nHash) & 0x0001 ) nLen++; + if( nLen == 9 ) + { + nLen = 10; + nHash ^= 0x8001; + } + nHash ^= nLen; + if( nLen < 9 ) nHash <<= (8 - nLen); + for( UINT16 iChar = nLen; iChar > 0; iChar-- ) + { + switch( iChar ) + { + case 10: + nNewChar = (nHash & 0xC000) | 0x0400; + nHash ^= nNewChar; + nNewChar >>= 2; + break; + case 9: + nNewChar = 0x4200; + nHash ^= nNewChar; + nNewChar >>= 1; + break; + case 1: + nNewChar = nHash & 0xFF00; + break; + default: + nNewChar = (nHash & 0xE000) ^ 0x2000; + if( !nNewChar ) nNewChar = (nHash & 0xF000) ^ 0x1800; + if( nNewChar == 0x6000 ) nNewChar = 0x6100; + nHash ^= nNewChar; + nHash <<= 1; + break; + } + nNewChar >>= 8; + nNewChar &= 0x00FF; + sDummy = sPasswd; + sPasswd = (sal_Char) nNewChar; + sPasswd += sDummy; + } + ADDTEXT( " valid-password='" ); + t += sPasswd; + ADDTEXT( "'" ); + } + PRINT(); +} + + +void __AddGUID( ByteString& rStr, XclImpStream& rIn ) +{ + UINT16 nIndex; + __AddPureHex( rStr, Read4( rIn ) ); + rStr += "-"; + __AddPureHex( rStr, Read2( rIn ) ); + rStr += "-"; + __AddPureHex( rStr, Read2( rIn ) ); + rStr += "-"; + // last 2 parts byte for byte + for( nIndex = 0; nIndex < 2; nIndex++ ) + __AddPureHex( rStr, Read1( rIn ) ); + rStr += "-"; + for( nIndex = 0; nIndex < 6; nIndex++ ) + __AddPureHex( rStr, Read1( rIn ) ); +} + + +void Biff8RecDumper::PreDumpDecrypted( ULONG nL ) +{ + if( !nL ) return; + + ByteString t; + const sal_Char* pPre = (pLevelPre > pLevelPreString) ? pLevelPre - 1 : pLevelPre; + + LINESTART(); + ADDTEXT( "*** encrypted ***" ); + PRINT(); + pIn->DisableDecryption(); + pIn->Seek( EXC_REC_SEEK_TO_BEGIN ); + ContDump( nL ); + + if( pIn->HasValidDecrypter() ) + { + LINESTART(); + ADDTEXT( "*** decrypted ***" ); + PRINT(); + pIn->EnableDecryption(); + pIn->Seek( EXC_REC_SEEK_TO_BEGIN ); + ContDump( nL ); + } +} + + +void Biff8RecDumper::RecDump( BOOL bSubStream ) +{ + const sal_Char* p; + BOOL bDec = FALSE; + ByteString aTmp; + UINT16 __nFlags; + const UINT16 nR = pIn->GetRecId(); + const ByteString* pName = GetName( nR ); + + // set CONTINUE handling mode + switch( nR ) + { + case 0x000A: // EOF + case 0x003C: // CONT + case 0x005D: // OBJ + case 0x00EC: // MSODRAWING + case 0x01B6: // TXO + pIn->ResetRecord( false ); + break; + case 0x1066: // CHGELFRAME + pIn->ResetRecord( bReadContRecs, 0x1066 ); + break; + default: + pIn->ResetRecord( bReadContRecs ); + } + const ULONG nL = pIn->GetRecSize(); + + switch( nR ) + { + case 0x0009: + case 0x0209: + case 0x0409: + case 0x0809: + nLevelCnt = 0; + break; + case 0x1033: + if( pName ) + aTmp = *pName; + else + aTmp = "BEGIN "; + bDec = ( pLevelPre + nLevelInc ) >= pLevelPreString; + nLevelCnt++; + aTmp.Append( ByteString::CreateFromInt32( nLevelCnt ) ); + pName = &aTmp; + break; + case 0x1034: + if( pName ) + aTmp = *pName; + else + aTmp = "END "; + if( ( pLevelPre + nLevelInc ) <= pLevelPreStringNT ) + pLevelPre += nLevelInc; + if( nLevelCnt ) + { + aTmp.Append( ByteString::CreateFromInt32( nLevelCnt ) ); + nLevelCnt--; + } + else + aTmp += "#LEVEL ERROR#"; + pName = &aTmp; + break; + } + + ByteString aT; + ByteString& t = aT; + const sal_Char* pPre = (pLevelPre > pLevelPreString) ? pLevelPre - 1 : pLevelPre; + + if( nR || nL ) // skip dummy-zero DIMENSIONS at eof + { + if( bBlankLine ) + *pDumpStream << '\n'; + + aT += pLevelPre; + __AddHex( aT, nR ); + + if( pName ) + { + aT += " ("; + aT += *pName; + aT += ") ["; + } + else + aT += " ["; + + if( bReadContRecs ) + __AddHex( aT, nL ); + else + __AddHex( aT, (UINT16)nL ); + aT += "]"; + if( !bSkipOffset ) + { + aT += " :"; + __AddHex( aT, UINT32(pIn->GetSvStreamPos() - 2 * sizeof(UINT16)) ); + aT += ':'; + } + + Print( aT ); + } + + if( HasModeNameOnly( nR ) ) + ; + else if( HasModeHex( nR ) || !bBIFF8 ) + { + if( bEncrypted ) + PreDumpDecrypted( nL ); + else + ContDump( nL ); + } + else if( nMaxBodyLines && nL ) + { + XclImpStream& rIn = *pIn; + + if( bEncrypted ) + { + PreDumpDecrypted( nL ); + LINESTART(); + ADDTEXT( "*** contents ***" ); + PRINT(); + pIn->Seek( EXC_REC_SEEK_TO_BEGIN ); + } + + LINESTART(); + + switch( nR ) + { + case 0x0000: // DIMENSIONS - used area + case 0x0200: + { + LINESTART(); + UINT32 nR1, nR2; + UINT16 nC1, nC2; + rIn >> nR1 >> nR2 >> nC1 >> nC2; + ADDTEXT( "first row: " ); __AddHex( t, nR1 ); + ADDTEXT( " last row+1: " ); __AddHex( t, nR2 ); + ADDTEXT( " first col: " ); __AddHex( t, nC1 ); + ADDTEXT( " last col+1: " ); __AddHex( t, nC2 ); + ADDTEXT( " (" ); lcl_AddRangeRef( t, nC1, (UINT16)nR1, nC2-1, (UINT16)nR2-1 ); + ADDTEXT( ")" ); + PRINT(); + } + break; + case 0x06: + { + ADDCELLHEAD(); + PRINT(); + LINESTART(); + ADDTEXT( "val = " ); + ADDDOUBLE(); + rIn >> __nFlags; + if( __nFlags ) + { + ADDTEXT( " " ); + STARTFLAG(); + ADDFLAG( 0x01, "fAlwaysCalc" ); + ADDFLAG( 0x02, "fCalcOnLoad" ); + ADDFLAG( 0x08, "fShrFmla" ); + } + PRINT(); + LINESTART(); + UINT16 n; + ADDTEXT( "chn = " ); + ADDHEX( 4 ); + rIn >> n; + ADDTEXT( " cce = " ); + __AddDec( t, n ); + PRINT(); + FormulaDump( n, FT_CellFormula ); + if( rIn.GetRecLeft() > 0 ) + { + LINESTART(); + ADDTEXT( "additional formula data" ); + PRINT(); + ContDump( rIn.GetRecLeft() ); + } + } + break; + case 0x0013: // PASSWORD + DumpValidPassword( rIn, pPre ); + break; + case 0x0014: // HEADER + case 0x0015: // FOOTER + if( rIn.GetRecLeft() ) + AddUNICODEString( t, rIn ); + PRINT(); + break; + case 0x17: + { + if( mnSubstream == EXC_BOF_WORKSPACE ) + { + ADDTEXT( "filename=" ); + AddUNICODEString( t, rIn ); + PRINT(); + } + else + { + UINT16 n; + rIn >> n; + ADDTEXT( "# of XTI: " ); + __AddDec( t, n ); + PRINT(); + UINT16 nSB, nF, nL; + while( n && rIn.IsValid() ) + { + LINESTART(); + rIn >> nSB >> nF >> nL; + ADDTEXT( "Supbook = " ); + __AddDec( t, nSB ); + ADDTEXT( " Tab = " ); + __AddDec( t, nF ); + ADDTEXT( " ... " ); + __AddDec( t, nL ); + PRINT(); + n--; + } + } + } + break; + case 0x0018: + case 0x0218: // NAME + { + sal_uInt8 nKey, nNameLen, nMenuLen, nDescrLen, nHelpLen, nStatusLen; + sal_uInt16 nFmlaSize, nRes, nTab; + + rIn >> __nFlags >> nKey >> nNameLen >> nFmlaSize >> nRes >> nTab >> nMenuLen >> nDescrLen >> nHelpLen >> nStatusLen; + LINESTART(); + STARTFLAG(); + ADDFLAG( 0x0001, "fHidden" ); + ADDFLAG( 0x0002, "fFunc" ); + ADDFLAG( 0x0004, "fVBProc" ); + ADDFLAG( 0x0008, "fProc" ); + ADDFLAG( 0x0010, "fCalcExp" ); + ADDFLAG( 0x0020, "fBuiltIn" ); + ADDFLAG( 0x1000, "fBig" ); + ADDRESERVED( 0xE000 ); + ADDTEXT( " func-group-idx=" ); + __AddDec( t, (UINT16)((__nFlags & 0x0FC0) >> 6) ); + ADDTEXT( " shortcut=" ); __AddHex( t, nKey ); + PRINT(); + + LINESTART(); + ADDTEXT( "fmla-size=" ); __AddDec( t, nFmlaSize ); + ADDTEXT( " reserved=" ); __AddHex( t, nRes ); + ADDTEXT( " tab=" ); __AddDec( t, nTab ); + if( !nTab ) ADDTEXT( " (global)" ); + PRINT(); + + LINESTART(); + sal_uInt16 nBuiltIn = 0; + bool bBuiltIn = (nNameLen == 1) && (__nFlags & 0x0020); + if( bBuiltIn ) + { + rIn.PushPosition(); + sal_uInt8 nStrFlags; + rIn >> nStrFlags; + nBuiltIn = (nStrFlags & 1) ? rIn.ReaduInt16() : rIn.ReaduInt8(); + rIn.PopPosition(); + } + ADDTEXT( "name=" ); + ByteString aName; + AddUNICODEString( t, rIn, false, nNameLen, &aName ); + if( bBuiltIn ) + { + static const sal_Char* const ppcNames[] = { + "Consolidate_Area", "Auto_Open", "Auto_Close", "Extract", "Database", + "Criteria", "Print_Area", "Print_Titles", "Recorder", "Data_Form", + "Auto_Activate", "Auto_Deactivate", "Sheet_Title", "_FilterDatabase" }; + lcl_AddEnum( t, nBuiltIn, ppcNames, STATIC_TABLE_SIZE( ppcNames ) ); + if( (0 <= nBuiltIn) && (nBuiltIn < STATIC_TABLE_SIZE( ppcNames )) ) + aName.Assign( ppcNames[ nBuiltIn ] ); + } + maNames.push_back( aName ); + PRINT(); + + if( nFmlaSize && (rIn.GetRecLeft() > 0) ) + { + LINESTART(); + ADDTEXT( "name-definition=" ); + PRINT(); + FormulaDump( nFmlaSize, FT_RangeName ); + } + if( nMenuLen ) + { + LINESTART(); + ADDTEXT( "menu-text=" ); + AddUNICODEString( t, rIn, false, nMenuLen ); + PRINT(); + } + if( nDescrLen ) + { + LINESTART(); + ADDTEXT( "descr-text=" ); + AddUNICODEString( t, rIn, false, nDescrLen ); + PRINT(); + } + if( nHelpLen ) + { + LINESTART(); + ADDTEXT( "help-text=" ); + AddUNICODEString( t, rIn, false, nHelpLen ); + PRINT(); + } + if( nStatusLen ) + { + LINESTART(); + ADDTEXT( "status-text=" ); + AddUNICODEString( t, rIn, false, nStatusLen ); + PRINT(); + } + } + break; + case 0x001D: // SELECTION - list of selections + { + ADDTEXT( "pane: " ); ADDDEC( 1 ); + ADDTEXT( " active cell: " ); + UINT16 nR, nC; + rIn >> nR >> nC; + lcl_AddRef( t, nC, nR ); + ADDTEXT( " active index: " ); ADDDEC( 2 ); + ADDTEXT( " ref count: " ); + UINT16 nCount; + rIn >> nCount; + __AddDec( t, nCount ); + PRINT(); + for( UINT16 nIndex = 0; nIndex < nCount && rIn.IsValid(); nIndex++ ) + { + LINESTART(); + UINT16 nR1, nR2; + UINT8 nC1, nC2; + rIn >> nR1 >> nR2 >> nC1 >> nC2; + ADDTEXT( "ref#" ); __AddDec( t, nIndex, 3 ); + ADDTEXT( ": " ); lcl_AddRangeRef( t, nC1, nR1, nC2, nR2 ); + PRINT(); + } + } + break; + case 0x0023: // EXTERNNAME + { + PreDump( rIn.GetRecSize() ); + rIn >> __nFlags; + STARTFLAG(); + ADDFLAG( 0x0001, "builtin" ); + ADDFLAG( 0x0002, "automatic" ); + ADDFLAG( 0x0004, "wantcliprepr" ); + ADDFLAG( 0x0008, "DDEstddocname" ); + ADDFLAG( 0x0010, "OLE" ); + ADDRESERVED( 0x8000 ); + sal_uInt16 nClip = (__nFlags & 0x7FE0) >> 5; + ADDTEXT( " clip-format=" ); __AddHex( t, nClip ); + PRINT(); LINESTART(); + bool bFormula = false, bArray = false; + if( (__nFlags & 0x0001) || !(__nFlags & 0x7FFE) ) + { + ADDTEXT( "type=external name" ); + ADDTEXT( " table=" ); ADDDEC( 2 ); + ADDTEXT( " reserved=" ); ADDHEX( 2 ); + bFormula = true; + } + else if( __nFlags & 0x0010 ) + { + ADDTEXT( "type=OLE" ); + ADDTEXT( " stream-id=" ); ADDHEX( 4 ); + } + else + { + ADDTEXT( "type=DDE" ); + ADDTEXT( " reserved=" ); ADDHEX( 4 ); + bArray = true; + } + PRINT(); LINESTART(); + ADDTEXT( "name=" ); AddUNICODEString( t, rIn, FALSE ); + PRINT(); + if( rIn.GetRecLeft() > 0 ) + { + LINESTART(); + if( bFormula ) + { + sal_uInt16 nSize = rIn.ReaduInt16(); + ADDTEXT( "formula (size=" ); __AddDec( t, nSize ); + ADDTEXT( "):" ); + PRINT(); + FormulaDump( nSize, FT_RangeName ); + } + else if( bArray && (rIn.GetRecLeft() >= 3) ) + { + LINESTART(); + ADDTEXT( "constant array width=" ); ADDDEC( 1 ); + ADDTEXT( " height=" ); ADDDEC( 2 ); + PRINT(); + while( rIn.GetRecLeft() > 0 ) + { + sal_uInt8 nType = rIn.ReaduInt8(); + LINESTART(); + ADDTEXT( "type=" ); __AddHex( t, nType ); + ADDTEXT( " (" ); + switch( nType ) + { + case 0x00: + ADDTEXT( "empty) reserved=" ); ADDHEX( 4 ); + ADDTEXT( " " ); ADDHEX( 4 ); + break; + case 0x01: + ADDTEXT( "double) value=" ); ADDDOUBLE(); + break; + case 0x02: + ADDTEXT( "string) text=" ); AddUNICODEString( t, rIn ); + break; + case 0x04: + ADDTEXT( "bool) value=" ); lcl_AddFlag( t, rIn.ReaduInt8() ); + ADDTEXT( " reserved=" ); ADDHEX( 1 ); + ADDTEXT( " " ); ADDHEX( 2 ); + ADDTEXT( " " ); ADDHEX( 4 ); + break; + case 0x10: + ADDTEXT( "error) code=" ); ADDHEX( 1 ); + ADDTEXT( " reserved=" ); ADDHEX( 1 ); + ADDTEXT( " " ); ADDHEX( 2 ); + ADDTEXT( " " ); ADDHEX( 4 ); + break; + default: + ADDTEXT( "!unknown!)" ); + rIn.Ignore( 8 ); + } + PRINT(); + } + } + if( rIn.GetRecLeft() > 0 ) + { + LINESTART(); + ADDTEXT( "additional data:" ); + PRINT(); + ContDump( rIn.GetRecLeft() ); + } + } + } + break; + case 0x0026: + case 0x0027: + case 0x0028: + case 0x0029: + LINESTART(); + ADDDOUBLE(); + PRINT(); + break; + case 0x002F: // FILEPASS + { + LINESTART(); + sal_uInt16 nType; + rIn >> nType; + ADDTEXT( "encrypt-type=" ); __AddHex( t, nType ); + ADDTEXT( " (" ); + switch( nType ) + { + case 0x0000: + { + ADDTEXT( "BIFF2-BIFF7 XOR) key=" ); + ADDHEX( 2 ); + ADDTEXT( " hash=" ); + ADDHEX( 2 ); + PRINT(); + } + break; + + case 0x0001: + { + ADDTEXT( "BIFF8 standard/strong)" ); + PRINT(); + LINESTART(); + ADDTEXT( "reserved=" ); ADDHEX( 2 ); + sal_uInt16 nMode; + rIn >> nMode; + ADDTEXT( " mode=" ); __AddHex( t, nMode ); + ADDTEXT( " (" ); + switch( nMode ) + { + case 0x0001: + { + ADDTEXT( "BIFF8 standard)" ); + PRINT(); + LINESTART(); + ADDTEXT( "document-id=..." ); + PRINT(); + ContDump( 16 ); + LINESTART(); + ADDTEXT( "salt-data=..." ); + PRINT(); + ContDump( 16 ); + LINESTART(); + ADDTEXT( "salt-hash=..." ); + PRINT(); + ContDump( 16 ); + } + break; + case 0x0002: + { + ADDTEXT( "BIFF8X strong) flags=" ); + ADDHEX( 4 ); + PRINT(); + LINESTART(); + ADDTEXT( "info-size=" ); ADDHEX( 4 ); + ADDTEXT( " flags=" ); ADDHEX( 4 ); + ADDTEXT( " unknown=" ); ADDHEX( 4 ); + PRINT(); + LINESTART(); + ADDTEXT( "stream-crypt-id=" ); ADDHEX( 4 ); + ADDTEXT( " hash-algo-id=" ); ADDHEX( 4 ); + ADDTEXT( " hash-key-len=" ); ADDDEC( 4 ); + PRINT(); + LINESTART(); + ADDTEXT( "crypt-prov-type=" ); ADDHEX( 4 ); + ADDTEXT( " unknown=" ); ADDHEX( 4 ); + ADDTEXT( " unknown=" ); ADDHEX( 4 ); + PRINT(); + LINESTART(); + ADDTEXT( "crypt-provider-name='" ); + sal_uInt16 nChar; + do + { + rIn >> nChar; + if( nChar ) + t += (sal_Char)(((32 <= nChar) && (nChar <=127)) ? nChar : '.'); + } + while( nChar ); + ADDTEXT( "'" ); + PRINT(); + LINESTART(); + sal_uInt32 nLen; + rIn >> nLen; + ADDTEXT( "*** document-id *** len=" ); __AddHex( t, nLen ); + PRINT(); + ContDump( nLen ); + LINESTART(); + ADDTEXT( "*** salt-data *** len=" ); __AddHex( t, nLen ); + PRINT(); + ContDump( nLen ); + LINESTART(); + rIn >> nLen; + ADDTEXT( "*** salt-hash *** len=" ); __AddHex( t, nLen ); + PRINT(); + ContDump( nLen ); + } + break; + default: + { + ADDTEXT( "!unknown!)" ); + PRINT(); + ContDump( rIn.GetRecLeft() ); + } + } + } + break; + + default: + { + ADDTEXT( "!unknown!)" ); + PRINT(); + ContDump( rIn.GetRecLeft() ); + } + } + } + break; + case 0x0031: // FONT + case 0x0231: + { + LINESTART(); + ADDTEXT( "(index=" ); __AddDec( t, nFontIndex ); + ADDTEXT( ") " ); + nFontIndex++; if( nFontIndex == 4 ) nFontIndex++; + ADDTEXT( "height: " ); ADDDEC( 2 ); + ADDTEXT( "/20pt " ); + rIn >> __nFlags; + STARTFLAG(); + ADDFLAG( 0x0002, "fItalic" ); + ADDFLAG( 0x0008, "fStrikeout" ); + ADDFLAG( 0x0010, "fOutline" ); + ADDFLAG( 0x0020, "fShadow" ); + ADDRESERVED( 0xFFC5 ); + PRINT(); + LINESTART(); + ADDTEXT( "color: " ); ADDDEC( 2 ); + ADDTEXT( " boldness: " ); ADDDEC( 2 ); + ADDTEXT( " sub/sup: " ); ADDDEC( 2 ); + ADDTEXT( " underline: " ); ADDHEX( 1 ); + PRINT(); + LINESTART(); + ADDTEXT( "family: " ); ADDDEC( 1 ); + ADDTEXT( " charset: " ); ADDDEC( 1 ); +// ADDTEXT( " reserved: " ); ADDHEX( 1 ); + rIn.Ignore( 1 ); + ADDTEXT( " " ); + AddUNICODEString( t, rIn, FALSE ); + PRINT(); + } + break; + case 0x003D: // WINDOW1 + { + LINESTART(); + ADDTEXT( "pos-x=" ); ADDDEC( 2 ); + ADDTEXT( " pos-y=" ); ADDDEC( 2 ); + ADDTEXT( " width=" ); ADDDEC( 2 ); + ADDTEXT( " height=" ); ADDDEC( 2 ); + PRINT(); + LINESTART(); + rIn >> __nFlags; + STARTFLAG(); + ADDFLAG( 0x0001, "hide-window" ); + ADDFLAG( 0x0002, "min-window" ); + ADDFLAG( 0x0008, "show-hscroll" ); + ADDFLAG( 0x0010, "show-vscroll" ); + ADDFLAG( 0x0020, "show-tabbar" ); + ADDRESERVED( 0xFFC4 ); + PRINT(); + LINESTART(); + ADDTEXT( "active-tab=" ); ADDDEC( 2 ); + ADDTEXT( " first-vis-tab=" ); ADDDEC( 2 ); + ADDTEXT( " selected-tabs=" ); ADDDEC( 2 ); + ADDTEXT( " tabbar-width=" ); ADDDEC( 2 ); + PRINT(); + } + break; + case 0x0041: // PANE + { + LINESTART(); + ADDTEXT( "vert-split-pos=" ); ADDDEC( 2 ); + ADDTEXT( " hor-split-pos=" ); ADDDEC( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( "first-row=" ); ADDDEC( 2 ); + ADDTEXT( " first-col=" ); ADDDEC( 2 ); + ADDTEXT( " active-pane=" ); ADDDEC( 2 ); + PRINT(); + } + break; + case 0x0042: // CODEPAGE + { + LINESTART(); + sal_uInt16 nCodePage = rIn.ReaduInt16(); + ADDTEXT( "codepage=" ); __AddHex( t, nCodePage ); + ADDTEXT( " (" ); __AddDec( t, nCodePage ); + ADDTEXT( ")" ); + PRINT(); + } + break; + case 0x004D: // PLS + { + LINESTART(); + static const sal_Char* const ppcTypes[] = { "Win", "Mac" }; + sal_uInt16 nType = rIn.ReaduInt16(); + ADDTEXT( "environment=" ); + lcl_AddEnum( t, nType, ppcTypes, STATIC_TABLE_SIZE( ppcTypes ) ); + PRINT(); + if( nType == 0 ) + { + String aData; + sal_uInt32 __nFlags; + LINESTART(); + rIn.SetNulSubstChar( '\0' ); + aData = rIn.ReadRawUniString( 32, true ); + ADDTEXT( "device-name='" ); ADDTEXT( GETSTR( aData ) ); + ADDTEXT( "'" ); + PRINT(); LINESTART(); + ADDTEXT( "spec-version=" ); ADDDEC( 2 ); + ADDTEXT( " driver-version=" ); ADDDEC( 2 ); + sal_uInt16 nOwnSize, nPrvSize; + rIn >> nOwnSize >> nPrvSize; + ADDTEXT( " own-size=" ); __AddDec( t, nOwnSize ); + ADDTEXT( " prv-size=" ); __AddDec( t, nPrvSize ); + PRINT(); LINESTART(); + rIn >> __nFlags; + STARTFLAG(); + ADDFLAG( 0x00000001, "orient" ); + ADDFLAG( 0x00000002, "paper-size" ); + ADDFLAG( 0x00000004, "paper-height" ); + ADDFLAG( 0x00000008, "paper-width" ); + ADDFLAG( 0x00000010, "scale" ); + ADDFLAG( 0x00000100, "copies" ); + ADDRESERVED( 0xE0000080 ); + PRINT(); LINESTART(); + static const sal_Char* const ppcOrient[] = { 0, "portrait", "landsc" }; + sal_uInt16 nOrient = rIn.ReaduInt16(); + ADDTEXT( "orientation=" ); + lcl_AddEnum( t, nOrient, ppcOrient, STATIC_TABLE_SIZE( ppcOrient ) ); + ADDTEXT( " paper-size=" ); ADDDEC( 2 ); + ADDTEXT( " paper-width=" ); ADDDEC( 2 ); + ADDTEXT( " paper-height=" ); ADDDEC( 2 ); + PRINT(); LINESTART(); + ADDTEXT( "scale=" ); ADDDEC( 2 ); + ADDTEXT( " copies=" ); ADDDEC( 2 ); + PRINT(); + if( nOwnSize > 88 ) + { + LINESTART(); ADDTEXT( "additional data:" ); PRINT(); + ContDump( nOwnSize - 88 ); + } + if( nPrvSize > 0 ) + { + LINESTART(); ADDTEXT( "private data:" ); PRINT(); + ContDump( nPrvSize ); + } + } + if( rIn.GetRecLeft() > 0 ) + { + LINESTART(); ADDTEXT( "unknown data:" ); PRINT(); + ContDump( rIn.GetRecLeft() ); + } + } + break; + case 0x51: + { + UINT16 nR1, nR2; + UINT8 nC1, nC2; + rIn >> nR1 >> nR2 >> nC1 >> nC2; + lcl_AddRangeRef( t, nC1, nR1, nC2, nR2 ); + PRINT(); + LINESTART(); + ADDTEXT( "workbook: " ); + AddUNICODEString( t, rIn, TRUE ); + PRINT(); + } + break; + case 0x0052: // DCONNAME + { + ADDTEXT( "name=" ); + AddUNICODEString( t, rIn, TRUE ); + PRINT(); + LINESTART(); + ADDTEXT( "sheet=" ); + AddUNICODEString( t, rIn, TRUE ); + PRINT(); + } + break; + case 0x5B: // FILESHARING + { + PreDump( nL ); + rIn >> __nFlags; + if( __nFlags ) + { + LINESTART(); + STARTFLAG(); + ADDFLAG( 0x0001, "fReadOnlyRec" ); + PRINT(); + } + DumpValidPassword( rIn, pPre ); + } + break; + case 0x5D: + ObjDump( nL ); + break; + case 0x007D: // COLINFO - col range info + { + LINESTART(); + ADDTEXT( "col range: " ); + ADDDEC( 2 ); + ADDTEXT( "-" ); + ADDDEC( 2 ); + ADDTEXT( " width: " ); + ADDDEC( 2 ); + ADDTEXT( "/256 charwidth ix to XF: " ); + ADDDEC( 2 ); + PRINT(); + rIn >> __nFlags; + LINESTART(); + STARTFLAG(); + ADDFLAG( 0x0001, "fHidden" ); + ADDTEXT( " outlnlev=" ); + __AddDec( t, (UINT16)((__nFlags & 0x0700) >> 8) ); + ADDFLAG( 0x1000, "fCollapsed" ); + ADDRESERVED( 0xE8FE ); + PRINT(); + LINESTART(); + ADDTEXT( "reserved: " ); + ADDHEX( 1 ); + PRINT(); + } + break; + case 0x7E: + { +// LINESTART(); + ADDCELLHEAD(); + ADDTEXT( " val = " ); + __AddRK( t, rIn.ReadInt32() ); + PRINT(); + } + break; + case 0x0080: // GUTS - row & col gutters for outlines + { + LINESTART(); + ADDTEXT( "size row gutter: " ); + __AddDec( t, Read2( rIn ), 5 ); + ADDTEXT( " | size col gutter: " ); + __AddDec( t, Read2( rIn ), 5 ); + PRINT(); + LINESTART(); + ADDTEXT( "max outline lev: " ); + __AddDec( t, Read2( rIn ), 5 ); + ADDTEXT( " | max outline lev: " ); + __AddDec( t, Read2( rIn ), 5 ); + PRINT(); + } + break; + case 0x0081: // WSBOOL - additional workspace info + { + rIn >> __nFlags; + LINESTART(); + STARTFLAG(); + if( __nFlags & 0x00F1 ) + { + ADDFLAG( 0x0001, "fShowAutoBreaks" ); + ADDFLAG( 0x0010, "fDialog" ); + ADDFLAG( 0x0020, "fApplyStyles" ); + ADDFLAG( 0x0040, "fRowSumsBelow" ); + ADDFLAG( 0x0080, "fColSumsBelow" ); + PRINT(); + LINESTART(); + } + if( __nFlags & (0xCD00 | 0x320E) ) + { + ADDTEXT( " " ); + ADDFLAG( 0x0100, "fFitToPage" ); + ADDFLAG( 0x0400, "fDispRowGuts" ); + ADDFLAG( 0x0800, "fDispColGuts" ); + ADDFLAG( 0x4000, "fAee" ); + ADDFLAG( 0x8000, "fAfe" ); + ADDRESERVED( 0x320E ); + PRINT(); + } + if( !__nFlags ) + PRINT(); + } + break; + case 0x008C: // COUNTRY + { + LINESTART(); + ADDTEXT( "ui-country=" ); ADDDEC( 2 ); + ADDTEXT( " doc-country=" ); ADDDEC( 2 ); + PRINT(); + } + break; + case 0x92: // PALETTE + { + UINT16 nColCnt; + rIn >> nColCnt; + LINESTART(); + ADDTEXT( "count: " ); + __AddDec( t, nColCnt ); + PRINT(); + LINESTART(); + for( UINT16 nCol = 0; nCol < nColCnt; nCol++ ) + { + __AddDec( t, nCol, 2 ); + ADDTEXT( "=" ); + ADDHEX( 4 ); + ADDTEXT( " " ); + if( (nCol % 5 == 4) || (nCol == nColCnt - 1) ) + { + PRINT(); + LINESTART(); + } + } + } + break; + case 0x9D: // AUTOFILTERINFO -- count of drop-down arrows + { + LINESTART(); + ADDTEXT( "count of drop-down arrows: " ); + ADDDEC( 2 ); + PRINT(); + } + break; + case 0x9E: // AUTOFILTER -- autofilter settings + { + UINT8 nType; + UINT8 nCompare; + ByteString sTemp[ 2 ]; + UINT16 nLen[ 2 ] = { 0, 0 }; + UINT8 nF; + LINESTART(); + ADDTEXT( "count: " ); + ADDDEC( 2 ); + rIn >> __nFlags; + STARTFLAG(); + ADDFLAG( 0x0003, "fJoin" ); + ADDFLAG( 0x0004, "fSimpleEq1" ); + ADDFLAG( 0x0008, "fSimpleEq2" ); + ADDFLAG( 0x0010, "fTop10" ); + ADDFLAG( 0x0020, "fTop" ); + ADDFLAG( 0x0040, "fPercent" ); + PRINT(); + LINESTART(); + if( __nFlags & 0x0003 ) + ADDTEXT( "(custom conditions are OR-ed" ); + else + ADDTEXT( "(custom conditions are AND-ed" ); + if( __nFlags & 0x0010 ) + { + if( __nFlags & 0x0020 ) + ADDTEXT( "; show top " ); + else + ADDTEXT( "; show bottom " ); + __AddDec( t, (UINT16)(__nFlags >> 7) ); + if( __nFlags & 0x0040 ) + ADDTEXT( " percent" ); + else + ADDTEXT( " items" ); + } + ADDTEXT( ")" ); + PRINT(); + for( nF = 0; nF < 2; nF++ ) + { + LINESTART(); + __AddDec( t, (UINT16)(nF + 1) ); + ADDTEXT( ". Filter: " ); + rIn >> nType >> nCompare; + switch( nType ) + { + case 0x00: ADDTEXT( "not used " ); break; + case 0x02: ADDTEXT( "RK " ); break; + case 0x04: ADDTEXT( "double " ); break; + case 0x06: ADDTEXT( "string " ); break; + case 0x08: ADDTEXT( "bool/err " ); break; + case 0x0A: ADDTEXT( "show nothing " ); break; + case 0x0C: ADDTEXT( "all blanks " ); break; + case 0x0E: ADDTEXT( "all non-blanks " ); break; + default: + ADDTEXT( "unknown (" ); + __AddHex( t, nType ); + ADDTEXT( ") " ); + } + switch( nCompare ) + { + case 0x01: ADDTEXT( "< " ); break; + case 0x02: ADDTEXT( "= " ); break; + case 0x03: ADDTEXT( "<= " ); break; + case 0x04: ADDTEXT( "> " ); break; + case 0x05: ADDTEXT( "<> " ); break; + case 0x06: ADDTEXT( ">= " ); break; + default: if( nCompare ) __AddHex( t, nCompare ); + } + sTemp[ nF ] = t; + switch( nType ) + { + case 0x02: + __AddRK( sTemp[ nF ], rIn.ReadInt32() ); + IGNORE( 4 ); + break; + case 0x04: + __AddDouble( sTemp[ nF ], Read8( rIn ) ); + break; + case 0x06: + IGNORE( 4 ); + nLen[ nF ] = Read1( rIn ); + IGNORE( 3 ); + break; + case 0x08: + __AddHex( sTemp[ nF ], Read1( rIn ) ); + sTemp[ nF ] += " "; + __AddHex( sTemp[ nF ], Read1( rIn ) ); + IGNORE( 6 ); + break; + default: + IGNORE( 8 ); + } + } + for( nF = 0; nF < 2; nF++ ) + { + t = sTemp[ nF ]; + if( nLen[ nF ] ) + AddUNICODEString( t, rIn, TRUE, nLen[ nF ] ); + PRINT(); + } + } + break; + case 0xA0: + { + UINT16 nN, nD; + rIn >> nN >> nD; + LINESTART(); + ADDTEXT( "Window Zoom Magnification = " ); + __AddDec( t, nN ); + ADDTEXT( "/" ); + __AddDec( t, nD ); + PRINT(); + } + break; + case 0x00A1: // SETUP + { + LINESTART(); + ADDTEXT( "paper size: " ); ADDDEC( 2 ); + ADDTEXT( " scaling: " ); ADDDEC( 2 ); + ADDTEXT( " start page: " ); ADDDEC( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( "fit to width: " ); ADDDEC( 2 ); + ADDTEXT( " fit to height: " ); ADDDEC( 2 ); + PRINT(); + LINESTART(); + rIn >> __nFlags; + STARTFLAG(); + ADDFLAG( 0x0001, "fLeftRight" ); + ADDFLAG( 0x0002, "fPortrait" ); + ADDFLAG( 0x0004, "fNoPrintSettings" ); + ADDFLAG( 0x0008, "fMonochrom" ); + ADDFLAG( 0x0010, "fDraft" ); + ADDFLAG( 0x0020, "fNotes" ); + ADDFLAG( 0x0040, "fNoOrientation" ); + ADDFLAG( 0x0080, "fCustomNumber" ); + PRINT(); + LINESTART(); + ADDTEXT( "Print res: " ); ADDDEC( 2 ); + ADDTEXT( " vert print res: " ); ADDDEC( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( "header margin: " ); ADDDOUBLE(); + ADDTEXT( " footer margin: " ); ADDDOUBLE(); + ADDTEXT( " copies: " ); ADDDEC( 2 ); + PRINT(); + } + break; + case 0xAF: + { + UINT16 nCref; + UINT8 nLocked, nHidden, nName, nComment, nNameUser; + rIn >> nCref >> nLocked >> nHidden >> nName >> nComment >> nNameUser; + LINESTART(); + ADDTEXT( "Changing Cells = " ); + __AddDec( t, nCref ); + if( nLocked ) + ADDTEXT( " fLocked" ); + if( nHidden ) + ADDTEXT( " fHidden" ); + PRINT(); + LINESTART(); + ADDTEXT( "Name = " ); + __AddDec( t, nName ); + ADDTEXT( " Comment = " ); + __AddDec( t, nComment ); + ADDTEXT( " Name User = " ); + __AddDec( t, nNameUser ); + PRINT(); + ContDump( rIn.GetRecLeft() ); + } + break; + case 0xB0: // SXVIEW + { + UINT16 nColFirst, nColLast, nRowFirst, nRowLast; + rIn >> nRowFirst >> nRowLast >> nColFirst >> nColLast; + nSXLIIndex = 0; // new pivot table + LINESTART(); + ADDTEXT( "PivotTable: " ); __AddDec( t, nColFirst ); + ADDTEXT( " / " ); __AddDec( t, nRowFirst ); + ADDTEXT( " - " ); __AddDec( t, nColLast ); + ADDTEXT( " / " ); __AddDec( t, nRowLast ); + PRINT(); + LINESTART(); + ADDTEXT( "1st Head: " ); ADDDEC( 2 ); + rIn >> nRowFirst; + ADDTEXT( " First Data: " ); ADDDEC( 2 ); + ADDTEXT( " / " ); __AddDec( t, nRowFirst ); + PRINT(); + LINESTART(); + ADDTEXT( "Cache index: " ); ADDDEC( 2 ); + ADDTEXT( " reserved: " ); ADDHEX( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( "axis 4 data: " ); ADDDEC( 2 ); + ADDTEXT( " pos 4 Data: " ); ADDDEC( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( "num of fields: " ); ADDDEC( 2 ); + rIn >> nSXLISize[0] >> nSXLISize[1]; + ADDTEXT( " ...row fields: " ); __AddDec( t, nSXLISize[0] ); + ADDTEXT( " ...col fields: " ); __AddDec( t, nSXLISize[1] ); + PRINT(); + LINESTART(); + ADDTEXT( "num of page fields: " ); ADDDEC( 2 ); + ADDTEXT( " ...data fields: " ); ADDDEC( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( "data rows: " ); ADDDEC( 2 ); + ADDTEXT( " data cols: " ); ADDDEC( 2 ); + rIn >> __nFlags; + PRINT(); + if( __nFlags ) + { + LINESTART(); + STARTFLAG(); + ADDFLAG( 0x0001, "fRowGrand" ); + ADDFLAG( 0x0002, "fColGrand" ); + ADDFLAG( 0x0008, "fAutoFormat" ); + ADDFLAG( 0x0010, "fWidthHeightAuto" ); + ADDFLAG( 0x0020, "fFontAuto" ); + ADDFLAG( 0x0040, "fAlignAuto" ); + ADDFLAG( 0x0080, "fBorderAuto" ); + ADDFLAG( 0x0100, "fPatternAuto" ); + ADDFLAG( 0x0200, "fNumberAuto" ); + PRINT(); + } + LINESTART(); + ADDTEXT( "index 2 PivotTable autoform: " ); + ADDDEC( 2 ); + PRINT(); + LINESTART(); + UINT16 nTableLen = Read2( rIn ); + UINT16 nDataLen = Read2( rIn ); + ADDTEXT( "PivotTable name: " ); + if( nTableLen ) + AddUNICODEString( t, rIn, TRUE, nTableLen ); + else + ADDTEXT( "-/-" ); + PRINT(); + LINESTART(); + ADDTEXT( "data field name: " ); + if( nDataLen ) + AddUNICODEString( t, rIn, TRUE, nDataLen ); + else + ADDTEXT( "-/-" ); + PRINT(); + } + break; + case 0xB1: // SXVD + { + rIn >> __nFlags; + LINESTART(); + ADDTEXT( "Axis (" ); + __AddHex( t, __nFlags ); + ADDTEXT( "):" ); + if( __nFlags ) + { + ADDFLAG( 0x0001, "row" ); + ADDFLAG( 0x0002, "col" ); + ADDFLAG( 0x0004, "page" ); + ADDFLAG( 0x0008, "data" ); + } + else + ADDTEXT( " no axis" ); + ADDTEXT( " num of att. subtotals: " ); + ADDDEC( 2 ); + PRINT(); + rIn >> __nFlags; + LINESTART(); + ADDTEXT( "subtotal type(" ); + __AddHex( t, __nFlags ); + ADDTEXT( "):" ); + if( __nFlags ) + { + ADDFLAG( 0x0001, "Default" ); + ADDFLAG( 0x0002, "Sum" ); + ADDFLAG( 0x0004, "Counta" ); + ADDFLAG( 0x0008, "Average" ); + ADDFLAG( 0x0010, "Max" ); + ADDFLAG( 0x0020, "Min" ); + ADDFLAG( 0x0040, "Product" ); + ADDFLAG( 0x0080, "Count" ); + ADDFLAG( 0x0100, "Stdev" ); + ADDFLAG( 0x0200, "Stddevp" ); + ADDFLAG( 0x0400, "Var" ); + ADDFLAG( 0x0800, "Varp" ); + } + else + ADDTEXT( " none" ); + PRINT(); + LINESTART(); + ADDTEXT( "num of items: " ); + ADDDEC( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( "Name: " ); + UINT16 nLen = Read2( rIn ); + if( nLen == 0xFFFF ) + ADDTEXT( "<name in cache>" ); + else if( nLen ) + AddUNICODEString( t, rIn, TRUE, nLen ); + PRINT(); + } + break; + case 0xB2: // SXVI + { + UINT16 nType, nCache; + rIn >> nType >> __nFlags >> nCache; + LINESTART(); + switch( nType ) + { + case 0xFE: p = "Page"; break; + case 0xFF: p = "Null"; break; + case 0x00: p = "Data"; break; + case 0x01: p = "Default"; break; + case 0x02: p = "SUM"; break; + case 0x03: p = "COUNT"; break; + case 0x04: p = "AVERAGE"; break; + case 0x05: p = "MAX"; break; + case 0x06: p = "MIN"; break; + case 0x07: p = "PRODUCT"; break; + case 0x08: p = "COUNTA"; break; + case 0x09: p = "STDEV"; break; + case 0x0A: p = "STDEVP"; break; + case 0x0B: p = "VAR"; break; + case 0x0C: p = "VARP"; break; + case 0x0D: p = "Grand total"; break; + default: p = pU; + } + ADDTEXT( "Type (" ); + __AddHex( t, nType ); + ADDTEXT( "): " ); + ADDTEXT( p ); + ADDTEXT( " iCache: " ); + __AddDec( t, nCache ); + PRINT(); + if( __nFlags ) + { + LINESTART(); + STARTFLAG(); + ADDFLAG( 0x01, "fHidden" ); + ADDFLAG( 0x02, "fHideDetail" ); + ADDFLAG( 0x04, "fFormula" ); + ADDFLAG( 0x08, "fMissing" ); + PRINT(); + } + LINESTART(); + ADDTEXT( "Name: " ); + UINT16 nCch = Read2( rIn ); + if( nCch == 0xFFFF ) + ADDTEXT( "<name in cache>" ); + else if( nCch ) + AddUNICODEString( t, rIn, TRUE, nCch ); + else + ADDTEXT( "<empty string>" ); + PRINT(); + } + break; + case 0xB4: // SXIVD + { + const UINT16 nBrkNum = 5; + UINT16 nBrk = nBrkNum; + UINT16 nSize = (UINT16)(nL / 2); + LINESTART(); + for( UINT16 i = 0; i < nSize; i++ ) + { + ADDHEX( 2 ); + nBrk--; + if( nBrk ) + ADDTEXT( " " ); + else + { + PRINT(); + LINESTART(); + nBrk = nBrkNum; + } + } + if( nBrk < nBrkNum ) PRINT(); + } + break; + case 0xB5: // SXLI - pivot table line item array + { + UINT16 nIdent; + UINT16 nType; + UINT16 nMaxInd; + const sal_Char* pInd = " "; + const sal_Char* pType[] = { + "Data", "Default", "SUM", "COUNT","AVERAGE", + "MAX", "MIN", "PRODUCT", "COUNTA", "STDEV", + "STDEVP", "VAR", "VARP", "Grand total", + "Blank line" }; // undocumented + while( rIn.GetRecLeft() > 0 ) + { + rIn >> nIdent >> nType >> nMaxInd >> __nFlags; + LINESTART(); + ADDTEXT( "# of ident. items: " ); + __AddDec( t, nIdent ); + ADDTEXT( " Type (" ); + __AddHex( t, nType ); + ADDTEXT( "): " ); + if( nType > 0x0E ) + p = pU; + else + p = pType[ nType ]; + ADDTEXT( p ); + ADDTEXT( " relevant indexes: " ); + __AddDec( t, nMaxInd ); + PRINT(); + LINESTART(); + ADDTEXT( pInd ); + STARTFLAG(); + ADDFLAG( 0x0001, "fMultiDataName" ); + ADDFLAG( 0x0200, "fSub" ); + ADDFLAG( 0x0400, "fBlock" ); + ADDFLAG( 0x0800, "fGrand" ); + ADDFLAG( 0x1000, "fMultiDataOnAxis" ); + ADDFLAG( 0x2000, "fBlankLine" ); // undocumented + ADDFLAG( 0x4000, "fHideDetail" ); // undocumented + ADDRESERVED( 0x8000 ); + PRINT(); + LINESTART(); + ADDTEXT( pInd ); + ADDTEXT( "index to data field: " ); + __AddDec( t, (UINT16) ( (__nFlags & 0x01FE) >> 1 ) ); + PRINT(); + LINESTART(); + ADDTEXT( pInd ); + ADDTEXT( "array of " ); + __AddDec( t, nSXLISize[nSXLIIndex] ); + ADDTEXT( " indexes (^ are ident., * are irrelevant):" ); + PRINT(); + LINESTART(); + ADDTEXT( pInd ); + ADDTEXT( " " ); + const UINT16 nBrkNum = 5; + UINT16 nBrk = nBrkNum; + for( UINT16 i = 0; i < nSXLISize[nSXLIIndex]; i++ ) + { + __AddDec( t, Read2( rIn ), 7 ); + if( i < nIdent ) + ADDTEXT( "^" ); + else if( i < nMaxInd ) + ADDTEXT( " " ); + else + ADDTEXT( "*" ); + nBrk--; + if( !nBrk ) + { + PRINT(); + LINESTART(); + ADDTEXT( pInd ); + ADDTEXT( " " ); + nBrk = nBrkNum; + } + } + if( nBrk < nBrkNum ) + PRINT(); + } + nSXLIIndex = 1 - nSXLIIndex; + } + break; + case 0xB6: // SXPI - pivot table page item(s) + { + UINT16 nArrayCnt = (UINT16)(nL / 6); + LINESTART(); + __AddDec( t, nArrayCnt ); + ADDTEXT( " page items:" ); + PRINT(); + for( UINT16 iArray = 0; iArray < nArrayCnt; iArray++ ) + { + LINESTART(); + ADDTEXT( "index SXVD: " ); + __AddDec( t, Read2( rIn ), 3 ); + ADDTEXT( " index SXVI: " ); + UINT16 nSXVIInd; + rIn >> nSXVIInd; + __AddDec( t, nSXVIInd, 5 ); + if( nSXVIInd == 32765 ) + ADDTEXT( " (All items) Obj ID: " ); + else + ADDTEXT( " Obj ID: " ); + ADDHEX( 2 ); + PRINT(); + } + } + break; + case 0xBD: + { + UINT16 nC, nR, nXF; + INT32 nRK; + UINT16 n = (UINT16)((nL - 4) / 6); + + rIn >> nR >> nC; + while( n ) + { + rIn >> nXF >> nRK; + LINESTART(); + __AddCellHead( t, nC, nR, nXF ); + ADDTEXT( " val = " ); + __AddRK( t, nRK ); + PRINT(); + nC++; + n--; + } + } + break; + case 0xBE: + { + LINESTART(); + ADDCELLHEAD(); + PRINT(); + LINESTART(); + ADDTEXT( "next XFs: " ); + UINT16 n = (UINT16)((nL - 6) / 2); + while( n ) + { + __AddDec( t, Read2( rIn ) ); + n--; + if( n ) + ADDTEXT( ' ' ); + } + PRINT(); + } + break; + case 0x00C5: // SXDI + { + LINESTART(); + ADDTEXT( "Field: " ); + ADDDEC( 2 ); + UINT16 nFunc = Read2( rIn ); + ADDTEXT( " aggregation func (" ); + __AddHex( t, nFunc ); + ADDTEXT( "): " ); + const sal_Char* pFunc[] = { "Sum", "Count", "Average", "Max", "Min", + "Product", "Count Nums", "StdDev", "StdDevp", "Var", + "Varp" }; + p = (nFunc > 0x0A) ? pU : pFunc[ nFunc ]; + ADDTEXT( p ); + ADDTEXT( " display format (" ); + const sal_Char* pDispl[] = { + "Normal", "Difference", "Percentage of", "Percentage difference from", "Running total in", + "Percentage of row", "Percentage of column", "Percentage of total", "Index" }; + UINT16 nDispl = Read2( rIn ); + __AddHex( t, nDispl ); + ADDTEXT( "): " ); + p = (nDispl > 0x08) ? pU : pDispl[ nDispl ]; + ADDTEXT( p ); + PRINT(); + LINESTART(); + ADDTEXT( "ind. to SXVD: " ); ADDDEC( 2 ); + ADDTEXT( " ind. to SXVI: " ); ADDDEC( 2 ); + ADDTEXT( " num format: " ); ADDDEC( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( "name: " ); + UINT16 nCch = Read2( rIn ); + if( nCch == 0xFFFF ) + ADDTEXT( "<name in cache>" ); + else if( nCch ) + AddUNICODEString( t, rIn, TRUE, nCch ); + else + ADDTEXT( "<empty string>" ); + PRINT(); + } + break; + case 0x00C6: // SXDB - cache info + { + ADDTEXT( "number of recs: " ); ADDDEC( 4 ); + ADDTEXT( " stream id: " ); ADDHEX( 2 ); + ADDTEXT( " flags: " ); ADDHEX( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( "DB block recs: " ); ADDDEC( 2 ); + ADDTEXT( " base fields: " ); ADDDEC( 2 ); + ADDTEXT( " all fields: " ); ADDDEC( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( "reserved: " ); ADDHEX( 2 ); + ADDTEXT( " type: " ); ADDHEX( 2 ); + ADDTEXT( " changed by:" ); + PRINT(); + LINESTART(); + AddUNICODEString( t, rIn ); + PRINT(); + } + break; + case 0x00C7: // SXFIELD - Pivot Field + { + nItemCnt = 0; + + ADDTEXT( "#" ); + __AddDec( t, nFieldCnt, 3 ); + nFieldCnt++; + ADDTEXT( " (pivot field): " ); + if( rIn.GetRecLeft() < 14 ) + { + ADDTEXT( "<break in pivot field start>" ); + PRINT(); + } + else + { + PRINT(); + LINESTART(); + ADDTEXT( pPre ); + rIn >> __nFlags; + STARTFLAG(); + ADDFLAG( 0x0001, "fOrigItems" ); + ADDFLAG( 0x0002, "fPostponed" ); + ADDFLAG( 0x0004, "fCalculated" ); + ADDFLAG( 0x0008, "fGroupChild" ); + ADDFLAG( 0x0010, "fNumGroup" ); + ADDFLAG( 0x0200, "fLongIndex" ); + ADDFLAG( 0x1000, "f1000?" ); + ADDFLAG( 0x8000, "f8000?" ); + ADDRESERVED( 0x6000 ); + ADDTEXT( " data-type=" ); + __AddHex( t, static_cast< sal_uInt16 >( __nFlags & 0x0DE0 ) ); + ADDTEXT( "=" ); + switch( __nFlags & 0x0DE0 ) + { + case 0x0000: ADDTEXT( "spc" ); break; + case 0x0480: ADDTEXT( "str" ); break; + case 0x0520: ADDTEXT( "int[+dbl]" ); break; + case 0x0560: ADDTEXT( "dbl" ); break; + case 0x05A0: ADDTEXT( "str+int[+dbl]" ); break; + case 0x05E0: ADDTEXT( "str+dbl" ); break; + case 0x0900: ADDTEXT( "dat" ); break; + case 0x0D00: ADDTEXT( "dat+int/dbl" ); break; + case 0x0D80: ADDTEXT( "dat+str[+int/dbl]" ); break; + default: ADDTEXT( pU ); + } + PRINT(); + LINESTART(); + ADDTEXT( pPre ); + ADDTEXT( "group-subfield=" ); ADDDEC( 2 ); + ADDTEXT( " group-basefield=" ); ADDDEC( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( pPre ); + ADDTEXT( "item-count=" ); ADDDEC( 2 ); + ADDTEXT( " group-item-count=" ); ADDDEC( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( pPre ); + ADDTEXT( "base-item-count=" ); ADDDEC( 2 ); + ADDTEXT( " source-item-count=" ); ADDDEC( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( pPre ); + if( rIn.GetRecLeft() < 3 ) + { + ADDTEXT( "<break in pivot field name>" ); + PRINT(); + } + else + { + ADDTEXT( "name=" ); + AddUNICODEString( t, rIn ); + PRINT(); + } + } + } + break; + case 0x00C8: // SXINDEXLIST - indexes to source data + { + ADDTEXT( "#" ); + __AddDec( t, nTabIndexCnt, 3 ); + nTabIndexCnt++; + ADDTEXT( " (index list):" ); + for( UINT16 iIndex = 0; iIndex < rIn.GetRecSize(); iIndex++ ) + { + ADDTEXT( " " ); + ADDHEX( 1 ); + } + PRINT(); + } + break; + case 0x00C9: // SXDOUBLE - cache entry: double value + { + ADDTEXT( "#" ); + __AddDec( t, nItemCnt, 3 ); + ADDTEXT( " (double): " ); + nItemCnt++; + ADDTEXT( " " ); + ADDDOUBLE(); + PRINT(); + } + break; + case 0x00CA: // SXBOOLEAN - cache entry: boolean value + { + ADDTEXT( "#" ); + __AddDec( t, nItemCnt, 3 ); + ADDTEXT( " (boolean): " ); + nItemCnt++; + ADDTEXT( " " ); + lcl_AddFlag( t, rIn.ReaduInt16() != 0 ); + PRINT(); + } + break; + case 0x00CB: // SXERROR - cache entry: error code + { + ADDTEXT( "#" ); + __AddDec( t, nItemCnt, 3 ); + ADDTEXT( " (error): " ); + nItemCnt++; + ADDTEXT( " " ); + ADDHEX( 2 ); + PRINT(); + } + break; + case 0x00CC: // SXINTEGER - signed 16bit integer + { + ADDTEXT( "#" ); + __AddDec( t, nItemCnt, 3 ); + ADDTEXT( " (integer): " ); + nItemCnt++; + ADDTEXT( " " ); + ADDDEC( 2 ); + PRINT(); + } + break; + case 0x00CD: // SXSTRING - String + { + if( bSubStream ) + { + ADDTEXT( "#" ); + __AddDec( t, nItemCnt, 3 ); + ADDTEXT( " (string): " ); + nItemCnt++; + } + AddUNICODEString( t, rIn ); + PRINT(); + } + break; + case 0x00CE: // SXDATETIME - date & time special format + { + ADDTEXT( "#" ); + __AddDec( t, nItemCnt, 3 ); + ADDTEXT( " (date/time): " ); + nItemCnt++; + UINT8 nDay, nHour, nMin, nSec; + UINT16 nYear, nMonth; + rIn >> nYear >> nMonth >> nDay >> nHour >> nMin >> nSec; + if( nDay ) + { + __AddDec( t, nDay ); + ADDTEXT( "." ); + __AddDec( t, nMonth ); + ADDTEXT( "." ); + __AddDec( t, nYear ); + ADDTEXT( " " ); + } + __AddDec( t, nHour, 2, '0' ); + ADDTEXT( ":" ); + __AddDec( t, nMin, 2, '0' ); + ADDTEXT( ":" ); + __AddDec( t, nSec, 2, '0' ); + PRINT(); + } + break; + case 0x00CF: // SXEMPTY - cache entry: empty + { + ADDTEXT( "#" ); + __AddDec( t, nItemCnt, 3 ); + ADDTEXT( " (empty): " ); + nItemCnt++; + PRINT(); + } + break; + case 0x00D5: // SXIDSTM - pivot table cache stream id + { + LINESTART(); + UINT16 nStrId = Read2( rIn ); + ADDTEXT( "Stream ID: " ); + __AddHex( t, nStrId ); + PRINT(); + DumpRecordStream( OpenStorage( EXC_STORAGE_PTCACHE ), ScfTools::GetHexStr( nStrId ), EMPTY_STRING ); + } + break; + case 0x00D8: // SXNUMGROUP - numerical grouping in pivot cache field + { + LINESTART(); + rIn >> __nFlags; + STARTFLAG(); + ADDFLAG( 0x0001, "fAutoMin" ); + ADDFLAG( 0x0002, "fAutoMax" ); + ADDTEXT( " data-type=" ); + switch( (__nFlags & 0x003C) >> 2 ) + { + case 0x0001: ADDTEXT( "seconds" ); break; + case 0x0002: ADDTEXT( "minutes" ); break; + case 0x0003: ADDTEXT( "hours" ); break; + case 0x0004: ADDTEXT( "days" ); break; + case 0x0005: ADDTEXT( "months" ); break; + case 0x0006: ADDTEXT( "quarters" ); break; + case 0x0007: ADDTEXT( "years" ); break; + case 0x0008: ADDTEXT( "numeric" ); break; + default: ADDTEXT( pU ); + } + (__nFlags &= 0xFFC0) >>= 6; + ADDTEXT( " remaining=" ); __AddHex( t, __nFlags ); + ADDTEXT( "=" ); __AddDec( t, __nFlags ); + PRINT(); + } + break; + case 0xE0: + DumpXF( rIn, pPre ); + break; + case 0xE3: + { + LINESTART(); + ADDTEXT( "view source (" ); + UINT16 n = Read2( rIn ); + __AddHex( t, n ); + ADDTEXT( "): " ); + switch( n ) + { + case 0x01: p = "M$ Excel list or database"; break; + case 0x02: p = "external data source"; break; + case 0x04: p = "multiple consolidation ranges"; break; + case 0x08: p = "pivot table"; break; + case 0x10: p = "scenario manager summary report"; break; + default: p = pU; + } + ADDTEXT( p ); + PRINT(); + } + break; + case 0x00E5: // CELLMERGING + { + UINT16 nCount, nInd; + UINT16 nRow1, nRow2, nCol1, nCol2; + rIn >> nCount; + LINESTART(); + ADDTEXT( "Count: " ); + __AddDec( t, nCount ); + PRINT(); + LINESTART(); + for( nInd = 0; nInd < 3; nInd++ ) + ADDTEXT( " row - row / col-col | " ); + PRINT(); + LINESTART(); + if( (ULONG)(nCount * 8 + 2) == nL ) + { + for( nInd = 0; nInd < nCount; nInd++ ) + { + rIn >> nRow1 >> nRow2 >> nCol1 >> nCol2; + __AddDec( t, nRow1, 5 ); + ADDTEXT( "-" ); + __AddDec( t, nRow2, 5 ); + ADDTEXT( " / " ); + __AddDec( t, nCol1, 3 ); + ADDTEXT( "-" ); + __AddDec( t, nCol2, 3 ); + ADDTEXT( " | " ); + if( (nInd % 3 == 2) || (nInd == nCount - 1) ) + { + PRINT(); + LINESTART(); + } + } + } + else + { + LINESTART(); + ADDTEXT( "<Wrong record length!>" ); + PRINT(); + } + } + break; + case 0xEB: + case 0xEC: + case 0xED: + EscherDump( nL, true ); + break; + case 0x00F6: // SXNAME + { + LINESTART(); + rIn >> __nFlags; + STARTFLAG(); + ADDFLAG( 0x0002, "fNameErr" ); + ADDRESERVED( 0xFFFD ); + ADDTEXT( " field=" ); ADDDEC( 2 ); + PRINT(); + LINESTART(); + sal_Int16 nFunc; + rIn >> nFunc; + ADDTEXT( "function=" ); __AddHex( t, (INT32)nFunc ); + static const sal_Char* const ppcFuncs[] = { + "none", 0, "sum", "counta", "count", "average", "max", "min", + "product", "stdev", "stdevp", "var", "varp" }; + lcl_AddEnum( t, nFunc, ppcFuncs, STATIC_TABLE_SIZE( ppcFuncs ), 0, -1 ); + ADDTEXT( " SXPAIR-count=" ); ADDDEC( 2 ); + PRINT(); + } + break; + case 0x00F9: // SXFMLA + { + LINESTART(); + sal_uInt16 nSize; + rIn >> nSize; + ADDTEXT( "formula-size=" ); __AddDec( t, nSize ); + ADDTEXT( " SXNAME-count=" ); ADDDEC( 2 ); + PRINT(); + FormulaDump( nSize, FT_RangeName ); + } + break; + case 0xFC: + { + UINT16 nCnt = 0; + BOOL bOK = TRUE; + ContDump( 8 ); + + while( bOK && (rIn.GetRecLeft() > 0) ) + { + LINESTART(); + __AddDec( t, nCnt ); + ADDTEXT( ": " ); + bOK = AddUNICODEString( t, rIn ); + PRINT(); + nCnt++; + } + } + break; + case 0xFD: + { + LINESTART(); + ADDCELLHEAD(); + ADDTEXT( " sst = " ); + ADDDEC(4); + PRINT(); + } + break; + case 0x0100: // SXVDEX + { + LINESTART(); + sal_uInt32 __nFlags = Read4( rIn ); + STARTFLAG(); + if( __nFlags & 0x0000009F ) + { + ADDFLAG( 0x00000001, "fShowAllItems" ); + ADDFLAG( 0x00000002, "fDragToRow" ); + ADDFLAG( 0x00000004, "fDragToColumn" ); + ADDFLAG( 0x00000008, "fDragToPage" ); + ADDFLAG( 0x00000010, "fDragToHide" ); + ADDFLAG( 0x00000080, "fServerBased" ); + PRINT(); + LINESTART(); + } + if( __nFlags & 0x00007E00 ) + { + ADDTEXT( " " ); + ADDFLAG( 0x00000200, "fAutoSort" ); + ADDFLAG( 0x00000400, "fAscendSort" ); + ADDFLAG( 0x00000800, "fAutoShow" ); + ADDFLAG( 0x00001000, "fAscendShow" ); + ADDFLAG( 0x00002000, "fCalculatedField" ); + ADDFLAG( 0x00004000, "fLONewPage" ); // undocumented + PRINT(); + LINESTART(); + } + if( __nFlags & 0xFFE00000 ) + { + ADDTEXT( " " ); // Layout flags: + ADDFLAG( 0x00200000, "fLOReport" ); // undocumented + ADDFLAG( 0x00400000, "fLOBlankLine" ); // undocumented + ADDFLAG( 0x00800000, "fLOSubTotalTop" ); // undocumented + ADDTEXT( " show-items=" ); __AddDec( t, sal_uInt32( __nFlags >> 24 ) ); + PRINT(); + LINESTART(); + } + if( __nFlags & 0x001F8160 ) + { + ADDTEXT( " !RESERVED!" ); + PRINT(); + } + if( !__nFlags ) + PRINT(); + LINESTART(); + ADDTEXT( " sort-field=" ); + ADDDEC( 2 ); + ADDTEXT( " show-field=" ); + ADDDEC( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( "format=" ); + UINT16 n = Read2( rIn ); + if( n ) + __AddDec( t, n ); + else + ADDTEXT( "none" ); + PRINT(); + } + break; + case 0x0122: // SXDBEX - ext. cache info + { + ADDTEXT( "last changed: " ); ADDDOUBLE(); + ADDTEXT( " SXFORMULA recs: " ); ADDDEC( 4 ); + PRINT(); + } + break; + case 0x0138: // CHTRINFO - change tracking info + { + rIn.DisableDecryption(); + ADDTEXT( "14 bytes of unknown data..." ); + PRINT(); + ContDump( 14 ); + LINESTART(); + ADDTEXT( "16 bytes unknown identification:" ); + PRINT(); + ContDump( 16 ); + LINESTART(); + ADDTEXT( "unknown: " ); ADDHEX( 2 ); + ADDTEXT( " user: " ); + if( rIn.GetRecLeft() > 3 ) + AddUNICODEString( t, rIn ); + PRINT(); + LINESTART(); + __AddDec( t, (UINT16)(rIn.GetRecLeft() - 10) ); + ADDTEXT( " bytes of unknown data..." ); + PRINT(); + ContDump( rIn.GetRecLeft() - 10 ); + LINESTART(); + ADDTEXT( "date/time: " ); ADDDEC( 2 ); + ADDTEXT( "-" ); ADDDEC( 1 ); + ADDTEXT( "-" ); ADDDEC( 1 ); + ADDTEXT( " " ); ADDDEC( 1 ); + ADDTEXT( ":" ); ADDDEC( 1 ); + ADDTEXT( ":" ); ADDDEC( 1 ); + ADDTEXT( " unknown: " ); ADDHEX( 1 ); + ADDTEXT( " " ); ADDHEX( 2 ); + PRINT(); + } + break; + case 0x0137: // CHTRINSERT - change tracking: insert/remove + { + ADDTEXT( "len: " ); ADDDEC( 4 ); + ADDTEXT( " index: " ); ADDDEC( 4 ); + ADDTEXT( " op: " ); + UINT16 nOp; + rIn >> nOp; + switch( nOp ) + { + case 0x0000: ADDTEXT( "insert row" ); break; + case 0x0001: ADDTEXT( "insert column" ); break; + case 0x0002: ADDTEXT( "delete row" ); break; + case 0x0003: ADDTEXT( "delete column" ); break; + default: + __AddHex( t, nOp ); + ADDTEXT( " *UNKNOWN*" ); + } + ADDTEXT( " accept: " ); ADDHEX( 2 ); + ADDTEXT( " tab: " ); ADDDEC( 2 ); + PRINT(); + LINESTART(); + UINT16 __nFlags = Read2( rIn ); + STARTFLAG(); + ADDFLAG( 0x0001, "fAuto" ); + ADDRESERVED( 0xFFFE ); + UINT16 nCol1, nRow1, nCol2, nRow2; + rIn >> nRow1 >> nRow2 >> nCol1 >> nCol2; + ADDTEXT( " range: " ); lcl_AddRangeRef( t, nCol1, nRow1, nCol2, nRow2 ); + ADDTEXT( " unknown: " ); ADDHEX( 4 ); + PRINT(); + } + break; + case 0x013B: // CHTRCELLCONTENT: change tracking: changed cell + { + PreDump( nL ); + ADDTEXT( "len: " ); ADDDEC( 4 ); + ADDTEXT( " index: " ); ADDDEC( 4 ); + ADDTEXT( " opcode: " ); ADDHEX( 2 ); + ADDTEXT( " accept: " ); ADDHEX( 2 ); + ADDTEXT( " tab: " ); ADDDEC( 2 ); + PRINT(); + LINESTART(); + UINT16 nChg, nOldType, nNewType; + rIn >> nChg; + nOldType = (nChg & 0x0038) >> 3; + nNewType = nChg & 0x0007; + ADDTEXT( "change (" ); __AddHex( t, nChg ); + ADDTEXT( "): " ); + switch( nOldType ) + { + case 0x0000: ADDTEXT( "empty->" ); break; + case 0x0001: ADDTEXT( "RK->" ); break; + case 0x0002: ADDTEXT( "double->" ); break; + case 0x0003: ADDTEXT( "string->" ); break; + case 0x0004: ADDTEXT( "bool->" ); break; + case 0x0005: ADDTEXT( "formula->" ); break; + default: ADDTEXT( "*UNKNOWN*->" ); + } + switch( nNewType ) + { + case 0x0000: ADDTEXT( "empty" ); break; + case 0x0001: ADDTEXT( "RK" ); break; + case 0x0002: ADDTEXT( "double" ); break; + case 0x0003: ADDTEXT( "string" ); break; + case 0x0004: ADDTEXT( "bool" ); break; + case 0x0005: ADDTEXT( "formula" ); break; + default: ADDTEXT( "*UNKNOWN*" ); + } + UINT16 nFormatData = (nChg & 0xFF00); + if( (nFormatData == 0x1100) || (nFormatData == 0x1300) ) + ADDTEXT( "; contains add. data" ); + ADDTEXT( " format: " ); ADDHEX( 2 ); + UINT16 nCol, nRow; + rIn >> nRow >> nCol; + ADDTEXT( " address: " ); lcl_AddRef( t, nCol, nRow ); + PRINT(); + LINESTART(); + UINT16 nOldLen; + rIn >> nOldLen; + ADDTEXT( "old value len: " ); __AddHex( t, nOldLen ); + if( nOldType == 0x0003 ) + nOldLen >>= 1; + ADDTEXT( " unknown: " ); ADDHEX( 4 ); + PRINT(); + UINT16 nCount = 0; + switch( nFormatData ) + { + case 0x1100: nCount = 8; break; + case 0x1300: nCount = 4; break; + } + if( nCount ) + { + LINESTART(); + ADDTEXT( "additional format data:" ); + for( UINT16 nIndex = 0; nIndex < nCount; nIndex ++ ) + { + ADDTEXT( " " ); + ADDHEX( 2 ); + } + PRINT(); + } + if( nOldType ) + { + LINESTART(); + ADDTEXT( "old value: " ); + switch( nOldType ) + { + case 0x0001: + __AddRK( t, rIn.ReadInt32() ); + PRINT(); + break; + case 0x0002: + ADDDOUBLE(); + PRINT(); + break; + case 0x0003: + AddUNICODEString( t, rIn ); + PRINT(); + break; + case 0x0004: + if( Read2( rIn ) ) + ADDTEXT( "true" ); + else + ADDTEXT( "false" ); + PRINT(); + break; + case 0x0005: + { + PRINT(); + UINT16 nLen; + rIn >> nLen; + FormulaDump( nLen, FT_CellFormula ); + IGNORE( 1 ); + } + break; + } + } + if( nNewType ) + { + LINESTART(); + ADDTEXT( "new value: " ); + switch( nNewType ) + { + case 0x0001: + __AddRK( t, rIn.ReadInt32() ); + PRINT(); + break; + case 0x0002: + ADDDOUBLE(); + PRINT(); + break; + case 0x0003: + AddUNICODEString( t, rIn ); + PRINT(); + break; + case 0x0004: + if( Read2( rIn ) ) + ADDTEXT( "true" ); + else + ADDTEXT( "false" ); + PRINT(); + break; + case 0x0005: + { + PRINT(); + UINT16 nLen; + rIn >> nLen; + FormulaDump( nLen, FT_CellFormula ); + IGNORE( 1 ); + } + break; + } + } + if( rIn.GetRecLeft() > 0 ) + { + LINESTART(); + ADDTEXT( "*UNKNOWN* data:" ); + PRINT(); + PreDump( rIn.GetRecLeft() ); + } + } + break; + case 0x013D: // TABID + { + ADDTEXT( "tab ids:" ); + while( rIn.GetRecLeft() ) + { + ADDTEXT( " " ); + ADDDEC( 2 ); + } + PRINT(); + } + break; + case 0x0140: // CHTRMOVE - change tracking: moved range + { + ADDTEXT( "len: " ); ADDDEC( 4 ); + ADDTEXT( " index: " ); ADDDEC( 4 ); + ADDTEXT( " opcode: " ); ADDHEX( 2 ); + ADDTEXT( " accept: " ); ADDHEX( 2 ); + PRINT(); + UINT16 nTab1, nTab2; + UINT16 nCol11, nCol12, nCol21, nCol22; + UINT16 nRow11, nRow12, nRow21, nRow22; + rIn >> nTab2 >> nRow11 >> nRow12 >> nCol11 >> nCol12 >> nRow21 >> nRow22 >> nCol21 >> nCol22 >> nTab1; + LINESTART(); + ADDTEXT( "move range from: tab=" ); __AddDec( t, nTab1 ); + ADDTEXT( " " ); lcl_AddRangeRef( t, nCol11, nRow11, nCol12, nRow12 ); + ADDTEXT( " to: tab=" ); __AddDec( t, nTab2 ); + ADDTEXT( " " ); lcl_AddRangeRef( t, nCol21, nRow21, nCol22, nRow22 ); + ADDTEXT( " unknown: " ); ADDHEX( 4 ); + PRINT(); + } + break; + case 0x014D: // CHTRINSERTTAB - change tracking: insert tab + { + ADDTEXT( "len: " ); ADDDEC( 4 ); + ADDTEXT( " index: " ); ADDDEC( 4 ); + ADDTEXT( " opcode: " ); ADDHEX( 2 ); + ADDTEXT( " accept: " ); ADDHEX( 2 ); + ADDTEXT( " tab: " ); ADDDEC( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( "unknown: " ); ADDHEX( 4 ); + ADDTEXT( " table name: " ); + AddUNICODEString( t, rIn ); + PRINT(); + LINESTART(); + __AddDec( t, (sal_uInt32)rIn.GetRecLeft() ); + ADDTEXT( " bytes of unknown data:" ); + PRINT(); + ContDump( rIn.GetRecLeft() ); + } + break; + case 0x015F: // LABELRANGES + { + UINT16 nCnt, nR1, nR2, nC1, nC2; + rIn >> nCnt; + ADDTEXT( "row headers: " ); __AddDec( t, nCnt ); + PRINT(); + while( nCnt-- ) + { + rIn >> nR1 >> nR2 >> nC1 >> nC2; + LINESTART(); + AddRangeRef( t, nR1, nC1 | 0xC000, nR2, nC2 | 0xC000, FALSE ); + PRINT(); + } + rIn >> nCnt; + LINESTART(); + ADDTEXT( "column headers: " ); __AddDec( t, nCnt ); + PRINT(); + while( nCnt-- ) + { + rIn >> nR1 >> nR2 >> nC1 >> nC2; + LINESTART(); + AddRangeRef( t, nR1, nC1 | 0xC000, nR2, nC2 | 0xC000, FALSE ); + PRINT(); + } + } + break; + case 0x0193: + { + ADDTEXT( "unknown: " ); ADDHEX( 4 ); + PRINT(); + LINESTART(); + ADDTEXT( "16 bytes unknown identification:" ); + PRINT(); + ContDump( 16 ); + LINESTART(); + ADDTEXT( "date/time: " ); ADDDEC( 2 ); + ADDTEXT( "-" ); ADDDEC( 1 ); + ADDTEXT( "-" ); ADDDEC( 1 ); + ADDTEXT( " " ); ADDDEC( 1 ); + ADDTEXT( ":" ); ADDDEC( 1 ); + ADDTEXT( ":" ); ADDDEC( 1 ); + ADDTEXT( " unknown: " ); ADDHEX( 1 ); + PRINT(); + LINESTART(); + ADDTEXT( "user: " ); + if( rIn.GetRecLeft() > 3 ) + AddUNICODEString( t, rIn ); + PRINT(); + } + break; + case 0x0194: + { + rIn.DisableDecryption(); + ADDTEXT( "unknown: " ); ADDHEX( 4 ); + ADDTEXT( " date/time: " ); ADDDEC( 2 ); + ADDTEXT( "-" ); ADDDEC( 1 ); + ADDTEXT( "-" ); ADDDEC( 1 ); + ADDTEXT( " " ); ADDDEC( 1 ); + ADDTEXT( ":" ); ADDDEC( 1 ); + ADDTEXT( ":" ); ADDDEC( 1 ); + ADDTEXT( " unknown: " ); ADDHEX( 1 ); + PRINT(); + LINESTART(); + ADDTEXT( "user: " ); + if( rIn.GetRecLeft() > 3 ) + AddUNICODEString( t, rIn ); + PRINT(); + LINESTART(); + __AddDec( t, (sal_uInt32)rIn.GetRecLeft() ); + ADDTEXT( " bytes of unknown data:" ); + PRINT(); + ContDump( rIn.GetRecLeft() ); + } + break; + case 0x0195: + rIn.DisableDecryption(); + ContDump( nL ); + break; + case 0x0196: + { + rIn.DisableDecryption(); + ADDTEXT( "unknown: " ); ADDHEX( 2 ); + ADDTEXT( " " ); ADDHEX( 2 ); + ADDTEXT( " " ); ADDHEX( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( "16 bytes unknown identification:" ); + PRINT(); + ContDump( 16 ); + LINESTART(); + ADDTEXT( "16 bytes unknown identification:" ); + PRINT(); + ContDump( 16 ); + LINESTART(); + ADDTEXT( "count of changes: " ); ADDDEC( 2 ); + ADDTEXT( " " ); + __AddDec( t, (sal_uInt32)rIn.GetRecLeft() ); + ADDTEXT( " bytes of unknown data:" ); + PRINT(); + ContDump( rIn.GetRecLeft() ); + } + break; + case 0x01A9: // USERBVIEW + { + LINESTART(); + ADDTEXT( "view id: " ); ADDHEX( 4 ); + ADDTEXT( " tab id: " ); ADDDEC( 4 ); + ADDTEXT( " guid: " ); __AddGUID( t, rIn ); + PRINT(); + LINESTART(); + ADDTEXT( "window x: " ); ADDDEC( 4 ); + ADDTEXT( " y: " ); ADDDEC( 4 ); + ADDTEXT( " width: " ); ADDDEC( 4 ); + ADDTEXT( " height: " ); ADDDEC( 4 ); + ADDTEXT( " ratio: " ); ADDDEC( 2 ); + PRINT(); + LINESTART(); + UINT16 __nFlags = Read2( rIn ); + STARTFLAG(); + ADDFLAG( 0x0001, "fDsplFormulaBar" ); + ADDFLAG( 0x0002, "fDsplStatus" ); + ADDFLAG( 0x0004, "fNoteOff" ); + ADDFLAG( 0x0008, "fDsplHScroll" ); + ADDFLAG( 0x0010, "fDsplVScroll" ); + ADDFLAG( 0x0020, "fBotAdornment" ); + ADDFLAG( 0x0040, "fZoom" ); + ADDFLAG( 0x0080, "fShowPlaceHld" ); + ADDFLAG( 0x0100, "fHideAll" ); + if( !(__nFlags & 0x0180) ) + ADDTEXT( " fShowAll" ); + PRINT(); + LINESTART(); + ADDTEXT( "flags2: " ); ADDHEX( 2 ); + ADDTEXT( " merge int: " ); ADDDEC( 2 ); + ADDTEXT( " reserved: " ); ADDHEX( 2 ); + PRINT(); + if( rIn.GetRecLeft() > 3 ) + { + LINESTART(); + ADDTEXT( "name: " ); + AddUNICODEString( t, rIn ); + PRINT(); + } + } + break; + case 0x01AA: // USERSVIEWBEGIN + { + LINESTART(); + ADDTEXT( "guid: " ); __AddGUID( t, rIn ); + ADDTEXT( " tab id: " ); ADDDEC( 4 ); + PRINT(); + LINESTART(); + ADDTEXT( "wscale: " ); ADDDEC( 4 ); + ADDTEXT( " icolor: " ); ADDDEC( 4 ); + ADDTEXT( " pane: " ); ADDDEC( 4 ); + PRINT(); + LINESTART(); + UINT32 __nFlags = Read4( rIn ); + STARTFLAG(); + if( __nFlags & 0x000000FF ) + { + ADDFLAG( 0x00000001, "fShowPgBrk" ); + ADDFLAG( 0x00000002, "fDsplForml" ); + ADDFLAG( 0x00000004, "fDsplGrid" ); + ADDFLAG( 0x00000008, "fDsplRCHead" ); + ADDFLAG( 0x00000010, "fDsplGuts" ); + ADDFLAG( 0x00000020, "fDsplZeros" ); + ADDFLAG( 0x00000040, "fPrintHorC" ); + ADDFLAG( 0x00000080, "fPrintVerC" ); + PRINT(); + LINESTART(); + } + if( __nFlags & 0x00007F00 ) + { + ADDTEXT( " " ); + ADDFLAG( 0x00000100, "fPrintRCHead" ); + ADDFLAG( 0x00000200, "fPrintGrid" ); + ADDFLAG( 0x00000400, "fFitToPage" ); + ADDFLAG( 0x00000800, "fPrintArea" ); + ADDFLAG( 0x00001000, "fOnePrintArea" ); + ADDFLAG( 0x00002000, "fFilter" ); + ADDFLAG( 0x00004000, "fAutoFilter" ); + PRINT(); + LINESTART(); + } + if( __nFlags & 0xFFF80000 ) + { + ADDTEXT( " " ); + ADDFLAG( 0x00020000, "fSplitV" ); + ADDFLAG( 0x00040000, "fSplitH" ); + ADDFLAG( 0x00180000, "fHiddenRow" ); + ADDFLAG( 0x00200000, "fHiddenCol" ); + ADDFLAG( 0x01000000, "fChartSize" ); + ADDFLAG( 0x02000000, "fFilterUnique" ); + ADDFLAG( 0x04000000, "fLayoutView" ); + ADDRESERVED( 0xF8C18000 ); + PRINT(); + LINESTART(); + } + if( !__nFlags ) + PRINT(); + ADDTEXT( "visible: " ); ADDHEX( 2 ); + ADDTEXT( " " ); ADDHEX( 2 ); + ADDTEXT( " " ); ADDHEX( 2 ); + ADDTEXT( " " ); ADDHEX( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( "pane pos vert: " ); ADDDOUBLE(); + ADDTEXT( " hor: " ); ADDDOUBLE(); + ADDTEXT( " 1st vis right: " ); ADDDEC( 2 ); + ADDTEXT( " bott: " ); ADDDEC( 2 ); + PRINT(); + } + break; + case 0x01AB: // USERSVIEWEND + { + LINESTART(); + ADDTEXT( "settings are valid: " ); ADDHEX( 2 ); + PRINT(); + } + break; + case 0x01AD: // QSI - web query range + { + LINESTART(); + rIn >> __nFlags; + STARTFLAG(); + ADDFLAG( 0x0001, "fTitles" ); + ADDFLAG( 0x0002, "fRowNums" ); + ADDFLAG( 0x0004, "fDisRefr" ); + ADDFLAG( 0x0080, "fFill" ); + ADDFLAG( 0x0100, "fAutoFmt" ); + ADDFLAG( 0x0400, "fDisEdit" ); + ADDRESERVED( 0xFA78 ); + PRINT(); + LINESTART(); + ADDTEXT( "AutoFmt: " ); ADDDEC( 2 ); + ADDTEXT( " AutoFmtAttr: " ); ADDHEX( 2 ); + ADDTEXT( " reserved: " ); ADDHEX( 4 ); + PRINT(); + LINESTART(); + ADDTEXT( "name: " ); + AddUNICODEString( t, rIn ); + PRINT(); + } + break; + case 0x01AE: + { + LINESTART(); + ADDTEXT( "# of tabs: " ); + UINT16 nTabs; + rIn >> nTabs; + __AddDec( t, nTabs ); + rIn.PushPosition(); + PRINT(); + LINESTART(); + if( nL <= (ULONG)(2 + 2 * nTabs) ) + { + ADDTEXT( "----- shortened record -----" ); + PRINT(); + + rIn.PopPosition(); + ContDump( nL - 2 ); + } + else + { + rIn.RejectPosition(); + ADDTEXT( "file name: " ); + AddUNICODEString( t, rIn ); + PRINT(); + while( nTabs ) + { + LINESTART(); + ADDTEXT( " " ); + AddUNICODEString( t, rIn ); + PRINT(); + nTabs--; + } + } + + } + break; + case 0x01B0: // CONDFMT + { + LINESTART(); + ADDTEXT( "cf-count=" ); ADDDEC( 2 ); + rIn >> __nFlags; + ADDTEXT( " " ); + STARTFLAG(); + ADDFLAG( 0x0001, "tough-recalc" ); + ADDRESERVED( 0xFFFE ); + PRINT(); + LINESTART(); + sal_uInt16 nR1, nR2, nC1, nC2, nCount; + rIn >> nR1 >> nR2 >> nC1 >> nC2 >> nCount; + ADDTEXT( "max-range=" ); lcl_AddRangeRef( t, nC1, nR1, nC2, nR2 ); + ADDTEXT( " range-count=" ); __AddDec( t, nCount ); + PRINT(); + + for( sal_uInt16 nRange = 0; rIn.IsValid() && (nRange < nCount); ++nRange ) + { + if( !(nRange % 4) ) + { + LINESTART(); + ADDTEXT( pPre ); + } + rIn >> nR1 >> nR2 >> nC1 >> nC2; + ByteString aRef; + lcl_AddRangeRef( aRef, nC1, nR1, nC2, nR2 ); + aRef.Expand( 16, ' ' ); + ADDTEXT( aRef ); + if( (nRange % 4 == 3) || (nRange + 1 == nCount) ) + PRINT(); + } + } + break; + case 0x01B1: // CF - conditional format + { + sal_uInt8 nType, nOp; + sal_uInt16 nSize1, nSize2; + sal_uInt32 nFlags; + rIn >> nType >> nOp >> nSize1 >> nSize2 >> nFlags; + LINESTART(); + ADDTEXT( "type=" ); __AddHex( t, nType ); + ADDTEXT( " (" ); + switch( nType ) + { + case 0x01: ADDTEXT( "compare" ); break; + case 0x02: ADDTEXT( "formula" ); break; + default: ADDTEXT( "!unknown!" ); + } + ADDTEXT( ") operator=" ); __AddHex( t, nOp ); + ADDTEXT( " (" ); + switch( nOp ) + { + case 0x00: ADDTEXT( "none" ); break; + case 0x01: ADDTEXT( "between" ); break; + case 0x02: ADDTEXT( "not-between" ); break; + case 0x03: ADDTEXT( "equal" ); break; + case 0x04: ADDTEXT( "not-equal" ); break; + case 0x05: ADDTEXT( "greater" ); break; + case 0x06: ADDTEXT( "less" ); break; + case 0x07: ADDTEXT( "greater-eq" ); break; + case 0x08: ADDTEXT( "less-eq" ); break; + default: ADDTEXT( "!unknown!" ); + } + ADDTEXT( ")" ); + PRINT(); + LINESTART(); + ADDTEXT( "formula-size-1=" ); __AddDec( t, nSize1 ); + ADDTEXT( " formula-size-2=" ); __AddDec( t, nSize2 ); + PRINT(); + LINESTART(); + sal_uInt32 __nFlags = nFlags; + STARTFLAG(); + __nFlags = ~__nFlags; + ADDFLAG( 0x00000400, "bord-lft" ); + ADDFLAG( 0x00000800, "bord-rgt" ); + ADDFLAG( 0x00001000, "bord-top" ); + ADDFLAG( 0x00002000, "bord-bot" ); + ADDFLAG( 0x00010000, "patt-style" ); + ADDFLAG( 0x00020000, "patt-fgcol" ); + ADDFLAG( 0x00040000, "patt-bgcol" ); + __nFlags = ~__nFlags; + ADDFLAG( 0x04000000, "font" ); + ADDFLAG( 0x10000000, "bord" ); + ADDFLAG( 0x20000000, "patt" ); + ADDRESERVED( 0xCBC00000 ); + PRINT(); + LINESTART(); + ADDTEXT( "unknown=" ); ADDHEX( 2 ); + PRINT(); + if( nFlags & 0x04000000 ) + { + LINESTART(); ADDTEXT( "*** FONT ***" ); PRINT(); + ContDump( 64 ); + LINESTART(); + ADDTEXT( "height=" ); ADDHEX( 4 ); + rIn >> __nFlags; + ADDTEXT( " style-" ); + STARTFLAG(); + ADDFLAG( 0x00000002, "italic" ); + ADDFLAG( 0x00000080, "strikeout" ); + ADDRESERVED( 0xFFFFFF7D ); + ADDTEXT( " weight=" ); ADDDEC( 2 ); + PRINT(); + LINESTART(); + sal_uInt16 nEsc; + rIn >> nEsc; + ADDTEXT( "escapement=" ); __AddDec( t, nEsc ); + ADDTEXT( " (" ); + switch( nEsc ) + { + case 0x0000: ADDTEXT( "none" ); break; + case 0x0001: ADDTEXT( "super" ); break; + case 0x0002: ADDTEXT( "sub" ); break; + default: ADDTEXT( "!unknown!" ); + } + sal_uInt8 nUnd; + rIn >> nUnd; + ADDTEXT( ") underline=" ); __AddDec( t, nUnd ); + ADDTEXT( " (" ); + switch( nUnd ) + { + case 0x00: ADDTEXT( "none" ); break; + case 0x01: ADDTEXT( "single" ); break; + case 0x02: ADDTEXT( "double" ); break; + default: ADDTEXT( "!unknown!" ); + } + ADDTEXT( ") unknown=" ); ADDHEX( 1 ); + ADDTEXT( " " ); ADDHEX( 1 ); + ADDTEXT( " " ); ADDHEX( 1 ); + PRINT(); + LINESTART(); + ADDTEXT( "color=" ); ADDHEX( 4 ); + ADDTEXT( " unknown=" ); ADDHEX( 4 ); + rIn >> __nFlags; + ADDTEXT( " used-" ); + STARTFLAG(); + __nFlags = ~__nFlags; + ADDFLAG( 0x00000002, "italic" ); + ADDFLAG( 0x00000080, "strikeout" ); + __nFlags = ~__nFlags; + ADDRESERVED( 0xFFFFFF65 ); + PRINT(); + LINESTART(); + ADDTEXT( "escape-def=" ); ADDHEX( 4 ); + ADDTEXT( " underl-def=" ); ADDHEX( 4 ); + PRINT(); + ContDump( 18 ); + } + if( nFlags & 0x10000000 ) + { + LINESTART(); ADDTEXT( "*** BORDER ***" ); PRINT(); + sal_uInt16 nLine; + sal_uInt32 nColor; + rIn >> nLine >> nColor; + LINESTART(); + ADDTEXT( "line-style=" ); __AddHex( t, nLine ); + ADDTEXT( " (lft=" ); __AddDec( t, (sal_uInt16)(nLine & 0x000F) ); + ADDTEXT( " rgt=" ); __AddDec( t, (sal_uInt16)((nLine & 0x00F0) >> 4) ); + ADDTEXT( " top=" ); __AddDec( t, (sal_uInt16)((nLine & 0x0F00) >> 8) ); + ADDTEXT( " bot=" ); __AddDec( t, (sal_uInt16)((nLine & 0xF000) >> 12) ); + ADDTEXT( ")" ); + PRINT(); + LINESTART(); + ADDTEXT( "line-color=" ); __AddHex( t, nColor ); + ADDTEXT( " (lft=" ); __AddDec( t, (sal_uInt16)(nColor & 0x0000007F) ); + ADDTEXT( " rgt=" ); __AddDec( t, (sal_uInt16)((nColor & 0x00003F80) >> 7) ); + ADDTEXT( " top=" ); __AddDec( t, (sal_uInt16)((nColor & 0x007F0000) >> 16) ); + ADDTEXT( " bot=" ); __AddDec( t, (sal_uInt16)((nColor & 0x3F800000) >> 23) ); + ADDTEXT( ") unknown=" ); ADDHEX( 2 ); + PRINT(); + } + if( nFlags & 0x20000000 ) + { + LINESTART(); ADDTEXT( "*** AREA ***" ); PRINT(); + sal_uInt16 nPatt, nColor; + rIn >> nPatt >> nColor; + LINESTART(); + ADDTEXT( "pattern=" ); __AddHex( t, nPatt ); + ADDTEXT( " (" ); __AddDec( t, (sal_uInt16)((nPatt & 0xFC00) >> 10) ); + ADDTEXT( ") color=" ); __AddHex( t, nColor ); + ADDTEXT( " (fg=" ); __AddDec( t, (sal_uInt16)(nColor & 0x007F) ); + ADDTEXT( " bg=" ); __AddDec( t, (sal_uInt16)((nColor & 0x3F80) >> 7) ); + ADDTEXT( ")" ); + PRINT(); + } + if( rIn.IsValid() && nSize1 && (rIn.GetRecLeft() >= nSize1) ) + { + LINESTART(); ADDTEXT( "*** FORMULA 1 ***" ); PRINT(); + FormulaDump( nSize1, FT_RangeName ); + } + if( rIn.IsValid() && nSize2 && (rIn.GetRecLeft() >= nSize2) ) + { + LINESTART(); ADDTEXT( "*** FORMULA 2 ***" ); PRINT(); + FormulaDump( nSize2, FT_RangeName ); + } + } + break; + case 0x01B2: // DVAL - header of DV recs + { + rIn >> __nFlags; + LINESTART(); + STARTFLAG(); + ADDTEXT( " (" ); + __AddPureBin( t, __nFlags ); + ADDTEXT( ")" ); + ADDTEXT( "):" ); + ADDFLAG( 0x0001, "fWnClosed" ); + ADDFLAG( 0x0002, "fWnPinned" ); + ADDFLAG( 0x0004, "fCached" ); + PRINT(); + LINESTART(); + ADDTEXT( "input window: " ); + ADDHEX( 4 ); + ADDTEXT( " / " ); + ADDHEX( 4 ); + PRINT(); + LINESTART(); + ADDTEXT( "object id: " ); + ADDHEX( 4 ); + PRINT(); + LINESTART(); + ADDTEXT( "num of DV recs: " ); + ADDDEC( 4 ); + PRINT(); + } + break; + case 0x01B6: // TXO - text box + { + LINESTART(); + rIn >> __nFlags; + STARTFLAG(); + switch( __nFlags & 0x000E ) + { + case 0x0002: ADDTEXT( " h-left" ); break; + case 0x0004: ADDTEXT( " h-center" ); break; + case 0x0006: ADDTEXT( " h-right" ); break; + case 0x0008: ADDTEXT( " h-block" ); break; + default: ADDTEXT( " *h-unknown*" ); + } + switch( __nFlags & 0x0070 ) + { + case 0x0010: ADDTEXT( " v-top" ); break; + case 0x0020: ADDTEXT( " v-center" ); break; + case 0x0030: ADDTEXT( " v-bottom" ); break; + case 0x0040: ADDTEXT( " v-block" ); break; + default: ADDTEXT( " *v-unknown*" ); + } + ADDFLAG( 0x0200, "lock-text" ); + ADDRESERVED( 0xFD81 ); + ADDTEXT( " orient=" ); + sal_uInt16 nOrient = rIn.ReaduInt16(); + __AddDec( t, nOrient ); + ADDTEXT( " (" ); + switch( nOrient ) + { + case 0: ADDTEXT( "no-rot" ); break; + case 1: ADDTEXT( "stacked" ); break; + case 2: ADDTEXT( "90\xB0 ccw" ); break; + case 3: ADDTEXT( "90\xB0 cw" ); break; + default: ADDTEXT( "!unknown!" ); + } + ADDTEXT( ")" ); + PRINT(); + LINESTART(); + ADDTEXT( "reserved=" ); + ADDHEX( 2 ); ADDTEXT( " " ); ADDHEX( 2 ); ADDTEXT( " " ); ADDHEX( 2 ); + ADDTEXT( " text-len=" ); ADDDEC( 2 ); + ADDTEXT( " format-size=" ); ADDDEC( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( "reserved=" ); ADDHEX( 2 ); + sal_uInt16 nLinkSize = rIn.ReaduInt16(); + ADDTEXT( " link-size=" ); __AddDec( t, nLinkSize ); + PRINT(); + if( nLinkSize > 0 ) + { + LINESTART(); + sal_uInt16 nFmlaSize = rIn.ReaduInt16(); + ADDTEXT( "fmla-size=" ); __AddDec( t, nFmlaSize ); + ADDTEXT( " reserved=" ); ADDHEX( 4 ); + PRINT(); + FormulaDump( nFmlaSize, FT_CellFormula ); + } + } + break; + case 0x01BE: // DV - data validation record + { + UINT32 __nFlags; + rIn >> __nFlags; + LINESTART(); + STARTFLAG(); + ADDTEXT( " (" ); + __AddPureBin( t, __nFlags ); + ADDTEXT( ")" ); + PRINT(); + LINESTART(); + if( __nFlags ) + { + ADDTEXT( " " ); + ADDFLAG( 0x00000080, "fStrLookup" ); + ADDFLAG( 0x00000100, "fAllowBlank" ); + ADDFLAG( 0x00000200, "fSuppressCombo" ); + ADDFLAG( 0x00040000, "fShowInputMsg" ); + ADDFLAG( 0x00080000, "fShowErrorMsg" ); + } + PRINT(); + LINESTART(); + ADDTEXT( "error style: " ); + const char* pErrStyle[] = { "stop", "warning", "info", "4" }; + ADDTEXT( pErrStyle[ ( __nFlags >> 4 ) & 0x03 ] ); + PRINT(); + LINESTART(); + const char* pValType[] = + { + "all", "integer", "decimal", "list", "date", "time", "text len", "user", + "8", "9", "A", "B", "C", "D", "E", "F" + }; + LINESTART(); + ADDTEXT( "validation type: " ); + ADDTEXT( pValType[ __nFlags & 0x0000000F ] ); + PRINT(); + + const char* pOpType[] = + { + "between", "not between", "equal", "not equal", + "greater", "less", "greater or equal", "less or equal", + "8", "9", "A", "B", "C", "D", "E", "F" + }; + LINESTART(); + ADDTEXT( "operator type: " ); + ADDTEXT( pOpType[ ( __nFlags >> 20 ) & 0x0000000F ] ); + PRINT(); + + LINESTART(); + ADDTEXT( "Prompt Title: " ); + AddUNICODEString( t, rIn ); + PRINT(); + LINESTART(); + ADDTEXT( "Error Title: " ); + AddUNICODEString( t, rIn ); + PRINT(); + LINESTART(); + ADDTEXT( "Prompt Message: " ); + AddUNICODEString( t, rIn ); + PRINT(); + LINESTART(); + ADDTEXT( "Error Message: " ); + AddUNICODEString( t, rIn ); + PRINT(); + if( rIn.GetRecLeft() > 8 ) + { + UINT16 nLen; + rIn >> nLen; + LINESTART(); + ADDTEXT( "Len1: " ); + __AddDec( t, nLen ); + ADDTEXT( " (unknown1: " ); + ADDHEX( 2 ); + ADDTEXT( ")" ); + PRINT(); + FormulaDump( nLen, FT_RangeName ); + + rIn >> nLen; + LINESTART(); + ADDTEXT( "Len2: " ); + __AddDec( t, nLen ); + ADDTEXT( " (unknown2: " ); + ADDHEX( 2 ); + ADDTEXT( ")" ); + PRINT(); + FormulaDump( nLen, FT_RangeName ); + + LINESTART(); + ADDTEXT( "range count: " ); + ADDHEX( 2 ); + PRINT(); + } + + while( rIn.GetRecLeft() >= 8 ) + { + // Row-Row / Col-Col + UINT16 nR1, nR2, nC1, nC2; + rIn >> nR1 >> nR2 >> nC1 >> nC2; + LINESTART(); + AddRangeRef( t, nR1, nC1 | 0xC000, nR2, nC2 | 0xC000, FALSE ); + PRINT(); + } + } + break; + case 0x01B8: // HLINK + { + PreDump( nL ); + + UINT32 n1, n2; + LINESTART(); + PRINT(); + UINT16 nR1, nR2, nC1, nC2; + rIn >> nR1 >> nR2 >> nC1 >> nC2; + ADDTEXT( "Cellrange=" ); + lcl_AddRangeRef( t, nC1, nR1, nC2, nR2 ); + PRINT(); + LINESTART(); + ADDTEXT( "GUID StdLink=" ); __AddGUID( t, rIn ); + PRINT(); + LINESTART(); + ADDTEXT( " must=79EAC9D0-BAF9-11CE-8C82-00AA004BA90B" ); + PRINT(); + LINESTART(); + ADDTEXT( "unknown=" ); ADDHEX( 4 ); + PRINT(); + UINT32 __nFlags = Read4( rIn ); + LINESTART(); + STARTFLAG(); + ADDFLAG( 0x00000001, "fBody" ); + ADDFLAG( 0x00000002, "fAbs" ); + ADDFLAG( 0x00000014, "fDescr" ); + ADDFLAG( 0x00000008, "fMark" ); + ADDFLAG( 0x00000080, "fFrame" ); + ADDFLAG( 0x00000100, "fUNC" ); + ADDRESERVED( 0xFFFFFE60 ); + PRINT(); + + //description + String aData; + if( __nFlags & 0x00000014 ) + { + LINESTART(); + rIn >> n1; + ADDTEXT( "## Description ## [l=" ); + __AddDec( t, n1 ); + ADDTEXT( "]: '" ); + aData = rIn.ReadRawUniString( (USHORT)(n1 - 1), TRUE ); + t += GETSTR( aData ); + ADDTEXT( "<" ); ADDHEX( 2 ); ADDTEXT( ">'" ); // trailing zero + PRINT(); + } + + // frame name + if( __nFlags & 0x00000080 ) + { + LINESTART(); + rIn >> n1; + ADDTEXT( "## Frame ## [l=" ); + __AddDec( t, n1 ); + ADDTEXT( "]: '" ); + aData = rIn.ReadRawUniString( (USHORT)(n1 - 1), TRUE ); + t += GETSTR( aData ); + ADDTEXT( "<" ); ADDHEX( 2 ); ADDTEXT( ">'" ); // trailing zero + PRINT(); + } + + // network path + if( __nFlags & 0x00000100 ) + { + LINESTART(); + rIn >> n1; + ADDTEXT( "## UNC ## [l=" ); + __AddDec( t, n1 ); + ADDTEXT( "]: '" ); + aData = rIn.ReadRawUniString( (USHORT)(n1 - 1), TRUE ); + t += GETSTR( aData ); + ADDTEXT( "<" ); ADDHEX( 2 ); ADDTEXT( ">'" ); // trailing zero + PRINT(); + } + + // file link or URL + else if( __nFlags & 0x00000001 ) + { + rIn.PushPosition(); + rIn >> n1; + rIn.PopPosition(); + LINESTART(); + ADDTEXT( "## Content GUID ## " ); + __AddGUID( t, rIn ); + switch( n1 ) + { + case 0x00000303: // file + { + ADDTEXT( " File Moniker" ); + PRINT(); + LINESTART(); + ADDTEXT( " must=00000303-0000-0000-C000-000000000046" ); + PRINT(); + LINESTART(); + ADDTEXT( "## File link ## up level=" ); + ADDDEC( 2 ); + rIn >> n2; + ADDTEXT( " [l=" ); __AddDec( t, n2 ); + ADDTEXT( ", 8-Bit]: '" ); + aData = rIn.ReadRawByteString( (USHORT)(n2 - 1) ); + t += GETSTR( aData ); + ADDTEXT( "<" ); ADDHEX( 1 ); ADDTEXT( ">'" ); // trailing zero + PRINT(); + ContDump( 24 ); + rIn >> n2; + LINESTART(); + ADDTEXT( "bytes left=" ); __AddDec( t, n2 ); + if( n2 ) + { + rIn >> n2; + LINESTART(); + ADDTEXT( " string byte count=" ); + __AddDec( t, n2 ); + ADDTEXT( " unknown=" ); + ADDHEX( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( "[l=" ); + __AddDec( t, n2 / 2 ); + ADDTEXT( "]: '" ); + aData = rIn.ReadRawUniString( (USHORT)n2, TRUE ); + t += GETSTR( aData ); + ADDTEXT( "'" ); + } + PRINT(); + } + break; + case 0x79EAC9E0: // URL + { + ADDTEXT( " URL Moniker" ); + PRINT(); + LINESTART(); + ADDTEXT( " must=79EAC9E0-BAF9-11CE-8C82-00AA004BA90B" ); + PRINT(); + rIn >> n2; + LINESTART(); + ADDTEXT( "## URL ## string byte count=" ); + __AddDec( t, n2 ); + PRINT(); + LINESTART(); + ADDTEXT( "[l=" ); + __AddDec( t, n2 / 2 ); + ADDTEXT( "]: '" ); + aData = rIn.ReadRawUniString( (USHORT)(n2 / 2 - 1), TRUE ); + t += GETSTR( aData ); + ADDTEXT( "<" ); ADDHEX( 2 ); ADDTEXT( ">'" ); // trailing zero + PRINT(); + } + break; + default: + { + ADDTEXT( " (!!UNKNOWN!!)" ); + PRINT(); + } + break; + } + } + + // text mark + if( __nFlags & 0x00000008 ) + { + LINESTART(); + rIn >> n1; + ADDTEXT( "## Text mark ## [l=" ); + __AddDec( t, n1 ); + ADDTEXT( "]: '" ); + aData = rIn.ReadRawUniString( (USHORT)(n1 - 1), TRUE ); + t += GETSTR( aData ); + ADDTEXT( "<" ); ADDHEX( 2 ); ADDTEXT( ">'" ); // trailing zero + PRINT(); + } + } + break; + case 0x01BB: // SXFDBTYPE - SQL data type + { + ADDTEXT( "SQL data type: " ); ADDHEX( 2 ); + PRINT(); + } + break; + case 0x0201: + { + LINESTART(); + ADDCELLHEAD(); + PRINT(); + } + break; + case 0x0203: + { + LINESTART(); + ADDCELLHEAD(); + ADDTEXT( " val = " ); + ADDDOUBLE(); + PRINT(); + } + break; + case 0x0205: + { + LINESTART(); + ADDCELLHEAD(); + ADDTEXT( " val = " ); ADDHEX( 1 ); + ADDTEXT( " type = " ); ADDDEC( 1 ); + PRINT(); + } + break; + case 0x0208: // ROW - row info + { + LINESTART(); + ADDTEXT( "row #: " ); ADDDEC( 2 ); + ADDTEXT( " def. cols: " ); ADDDEC( 2 ); + ADDTEXT( "-" ); ADDDEC( 2 ); + ADDTEXT( " ht: " ); ADDDEC( 2 ); + ADDTEXT( " reserved: " ); ADDHEX( 4 ); + PRINT(); + rIn >> __nFlags; + LINESTART(); + STARTFLAG(); + ADDTEXT( " outlnlev=" ); + __AddDec( t, (UINT16)(__nFlags & 0x0007) ); + ADDFLAG( 0x0010, "fCollapsed" ); + ADDFLAG( 0x0020, "fRowHeightZero" ); + ADDFLAG( 0x0040, "fUnsynced" ); + ADDFLAG( 0x0080, "fGhostDirty" ); + ADDRESERVED( 0xFF08 ); + PRINT(); + UINT16 nXF; + rIn >> nXF; + LINESTART(); + ADDTEXT( "ix to XF: " ); __AddDec( t, (UINT16)(nXF & 0x0FFF) ); + ADDTEXT( " add. flags(" ); __AddHex( t, nXF ); + ADDTEXT( "):" ); + ADDFLAG( 0x1000, "fExAsc" ); + ADDFLAG( 0x2000, "fExDsc" ); + ADDRESERVED( 0xC000 ); + PRINT(); + } + break; + case 0x0021: // ARRAY + case 0x0221: + { + UINT16 nR1, nR2; + UINT8 nC1, nC2; + rIn >> nR1 >> nR2 >> nC1 >> nC2 >> __nFlags; + LINESTART(); + ADDTEXT( "range: " ); + lcl_AddRangeRef( t, nC1, nR1, nC2, nR2 ); + PRINT(); + LINESTART(); + STARTFLAG(); + ADDFLAG( 0x0001, "fAlwaysCalc" ); + ADDFLAG( 0x0002, "fCalcOnLoad" ); + ADDRESERVED( 0xFFFC ); + PRINT(); + LINESTART(); + ADDTEXT( "chn = " ); + ADDHEX( 4 ); + UINT16 n; + rIn >> n; + ADDTEXT( " cce = " ); + __AddDec( t, n ); + PRINT(); + FormulaDump( n, FT_SharedFormula ); + } + break; + case 0x0225: // DEFAULTROWHEIGHT - height & flags + { + rIn >> __nFlags; + LINESTART(); + ADDTEXT( "default row " ); + STARTFLAG(); + ADDFLAG( 0x0001, "fUnsynced" ); + ADDFLAG( 0x0002, "fRowHtZero" ); + ADDFLAG( 0x0004, "fExAsc" ); + ADDFLAG( 0x0008, "fExDsc" ); + ADDRESERVED( 0xFFF0 ); + PRINT(); + LINESTART(); + ADDTEXT( "default row height: " ); + ADDDEC( 2 ); + PRINT(); + } + break; + case 0x023E: // WINDOW2 + { + LINESTART(); + rIn >> __nFlags; + STARTFLAG(); + ADDFLAG( 0x0001, "show-formulas" ); + ADDFLAG( 0x0002, "show-grid" ); + ADDFLAG( 0x0004, "show-headers" ); + ADDFLAG( 0x0008, "frozen" ); + ADDFLAG( 0x0010, "show-zero" ); + ADDFLAG( 0x0020, "auto-grid-color" ); + ADDFLAG( 0x0040, "right-to-left" ); + ADDFLAG( 0x0080, "show-outline" ); + ADDFLAG( 0x0100, "remove-splits" ); + ADDFLAG( 0x0200, "sheet-selected" ); + ADDFLAG( 0x0400, "sheet-visible" ); + ADDFLAG( 0x0800, "show-pagebreak" ); + ADDRESERVED( 0xF000 ); + PRINT(); + LINESTART(); + ADDTEXT( "first-row=" ); ADDDEC( 2 ); + ADDTEXT( " first-col=" ); ADDDEC( 2 ); + ADDTEXT( " grid-color=" ); ADDDEC( 2 ); + ADDTEXT( " reserved=" ); ADDHEX( 2 ); + PRINT(); + // reallife: WINDOW2 in charts do not have teh following fields + if( rIn.GetRecLeft() >= 8 ) + { + LINESTART(); + ADDTEXT( "pagebreak-zoom=" ); ADDDEC( 2 ); + ADDTEXT( "% view-zoom=" ); ADDDEC( 2 ); + ADDTEXT( "% reserved=" ); ADDHEX( 4 ); + PRINT(); + } + } + break; + case 0x027E: + { + ADDCELLHEAD(); + ADDTEXT( " val = " ); + __AddRK( t, rIn.ReadInt32() ); + PRINT(); + } + break; + case 0x0293: // STYLE + { + LINESTART(); + sal_uInt16 nXF; + rIn >> nXF; + ADDTEXT( "xf-ref=" ); __AddHex( t, nXF ); + ADDTEXT( " (xf=#" ); __AddDec( t, static_cast< sal_uInt16 >( nXF & EXC_STYLE_XFMASK ) ); + if( ::get_flag( nXF, EXC_STYLE_BUILTIN ) ) + { + sal_uInt8 nStyleId, nLevel; + rIn >> nStyleId >> nLevel; + ADDTEXT( " builtin) style-id=" ); __AddDec( t, nStyleId ); + ADDTEXT( " (" ); + static const sal_Char* ppcStyles[] = { + "Normal", "RowLevel", "ColLevel", "Comma", "Currency", + "Percent", "Comma_0", "Currency_0", + "Hyperlink", "Followed_Hyperlink" }; + if( nStyleId < STATIC_TABLE_SIZE( ppcStyles ) ) + ADDTEXT( ppcStyles[ nStyleId ] ); + else + ADDTEXT( "!unknown!" ); + ADDTEXT( ") outline-level=" ); __AddDec( t, nLevel ); + } + else + { + ADDTEXT( ") name=" ); + AddUNICODEString( t, rIn ); + } + PRINT(); + } + break; + case 0x041E: + { + LINESTART(); + ADDTEXT( "Index: " ); ADDHEX( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( "Format: " ); AddUNICODEString( t, rIn ); + PRINT(); + } + break; + case 0x04BC: + { + UINT16 nR1, nR2; + UINT8 nC1, nC2; + LINESTART(); + rIn >> nR1 >> nR2 >> nC1 >> nC2; + lcl_AddRangeRef( t, nC1, nR1, nC2, nR2 ); + PRINT(); + LINESTART(); + ADDTEXT( "reserved = " ); + __AddPureHex( t, Read2( rIn ) ); + UINT16 n; + rIn >> n; + ADDTEXT( " cce = " ); + __AddDec( t, n ); + PRINT(); + FormulaDump( n, FT_SharedFormula ); + } + break; + case 0x0803: // WEBQRYSETTINGS - web query: options + { + UINT16 nCnt; + LINESTART(); + ADDTEXT( "repeated recnum: " ); + ADDHEX( 2 ); + ADDTEXT( " unknown:" ); + for( nCnt = 0; nCnt < 3; nCnt++ ) + { + ADDTEXT( " " ); + ADDHEX( 2 ); + } + PRINT(); + LINESTART(); + rIn >> __nFlags; + STARTFLAG(); + ADDFLAG( 0x0001, "fImportPRE" ); + ADDFLAG( 0x0002, "fIgnoreSep" ); + ADDFLAG( 0x0004, "fUseSetting" ); + ADDFLAG( 0x0010, "fIgnoreDate" ); + ADDFLAG( 0x0020, "fWhatIsIt?" ); + ADDRESERVED( 0xFFC8 ); + PRINT(); + LINESTART(); + rIn >> __nFlags; + STARTFLAG(); + ADDFLAG( 0x0002, "fTables" ); + ADDRESERVED( 0xFFFD ); + PRINT(); + LINESTART(); + ADDTEXT( "unknown: " ); ADDHEX( 2 ); + ADDTEXT( " " ); ADDHEX( 2 ); + ADDTEXT( " " ); ADDHEX( 2 ); + ADDTEXT( " " ); ADDHEX( 2 ); + ADDTEXT( " " ); ADDHEX( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( "refresh: " ); ADDDEC( 2 ); + ADDTEXT( " unknown: " ); ADDHEX( 2 ); + ADDTEXT( " " ); ADDHEX( 2 ); + PRINT(); + } + break; + case 0x0804: // WEBQRYTABLES - web query: selected tables + { + LINESTART(); + ADDTEXT( "repeated recnum: " ); ADDHEX( 2 ); + ADDTEXT( " unknown: " ); ADDHEX( 2 ); + PRINT(); + if( nL > 6 ) + { + LINESTART(); + ADDTEXT( "text: " ); + AddUNICODEString( t, rIn ); + PRINT(); + } + } + break; + case 0x0809: // BOF + { + rIn.DisableDecryption(); + LINESTART(); + ADDTEXT( "version number: " ); + ADDHEX( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( "substream type: " ); + rIn >> mnSubstream; + __AddHex( t, mnSubstream ); + ADDTEXT( " (" ); + switch( mnSubstream ) + { + case 0x0005: p = "Workbook globals"; break; + case 0x0006: p = "Visual Basic module"; break; + case 0x0010: p = "Worksheet or dialog sheet"; break; + case 0x0020: p = "Chart"; break; + case 0x0040: p = "MS 4.0 Macro"; break; + case 0x0100: p = "Workspace file"; break; + default: p = pU; + } + ADDTEXT( p ); + ADDTEXT( ")" ); + PRINT(); + LINESTART(); + UINT16 n; + rIn >> n; + ADDTEXT( "build identifier: "); + __AddHex( t, n ); + ADDTEXT( " (=" ); + __AddDec( t, n ); + ADDTEXT( ")" ); + PRINT(); + + LINESTART(); + rIn >> n; + ADDTEXT( "build year: "); + __AddHex( t, n ); + ADDTEXT( " (=" ); + __AddDec( t, n ); + ADDTEXT( ")" ); + PRINT(); + + UINT32 __nFlags; + rIn >> __nFlags; + LINESTART(); + ADDTEXT( "file history " ); + STARTFLAG(); + if( __nFlags ) + { + ADDFLAG( 0x00000001, "fWin" ); + ADDFLAG( 0x00000002, "fRisc" ); + ADDFLAG( 0x00000004, "fBeta" ); + ADDFLAG( 0x00000008, "fWinAny" ); + ADDFLAG( 0x00000010, "fMacAny" ); + ADDFLAG( 0x00000020, "fBetaAny" ); + ADDFLAG( 0x00000100, "fRiscAny" ); + ADDRESERVED( 0xFFFFE0C0 ); + } + PRINT(); + + LINESTART(); + ADDTEXT( "lowest BIFF version: "); + ADDHEX( 4 ); + PRINT(); + } + break; + case 0x1002: // ChartChart + { + LINESTART(); + ADDTEXT( "Pos = " ); + ADD16P16(); + ADDTEXT( " / " ); + ADD16P16(); + ADDTEXT( " Size = " ); + ADD16P16(); + ADDTEXT( " / " ); + ADD16P16(); + PRINT(); + } + break; + case 0x1003: // ChartSeries + { + sal_uInt16 nCatType, nValType, nCatCnt, nValCnt, nBubType, nBubCnt; + rIn >> nCatType >> nValType >> nCatCnt >> nValCnt >> nBubType >> nBubCnt; + LINESTART(); + ADDTEXT( "category-type=" ); __AddDec( t, nCatType ); + ADDTEXT( " " ); ADDTEXT( GetSeriesType( nCatType ) ); + ADDTEXT( " count=" ); __AddDec( t, nCatCnt ); + PRINT(); + LINESTART(); + ADDTEXT( " value-type=" ); __AddDec( t, nValType ); + ADDTEXT( " " ); ADDTEXT( GetSeriesType( nValType ) ); + ADDTEXT( " count=" ); __AddDec( t, nValCnt ); + PRINT(); + LINESTART(); + ADDTEXT( " bubble-type=" ); __AddDec( t, nBubType ); + ADDTEXT( " " ); ADDTEXT( GetSeriesType( nBubType ) ); + ADDTEXT( " count=" ); __AddDec( t, nBubCnt ); + PRINT(); + } + break; + case 0x1006: // ChartDataformat + { + INT16 n; + LINESTART(); + rIn >> n; + ADDTEXT( "Point number = " ); + __AddDec( t, n ); + if( n == -1 ) + ADDTEXT( " (entire series)" ); + PRINT(); + LINESTART(); + ADDTEXT( "Series index = " ); + ADDDEC( 2 ); + ADDTEXT( " Series number = " ); + ADDDEC( 2 ); + if( Read2( rIn ) & 0x01 ) + ADDTEXT( " (fXL4iss)" ); + PRINT(); + } + break; + case 0x1007: // ChartLineform + { + LINESTART(); + ADDTEXT( "Color = " ); + ADDTEXT( GetRGB( Read4( rIn ) ) ); + ADDTEXT( " Pattern : " ); + ADDTEXT( GetLineType( Read2( rIn ) ) ); + switch( ( INT16 ) Read2( rIn ) ) + { + case -1: p = "hairline"; break; + case 0: p = "narrow (single)"; break; + case 1: p = "medium (double)"; break; + case 2: p = "wide (triple)"; break; + default: p = pU; + } + ADDTEXT( ", " ); + ADDTEXT( p ); + PRINT(); + rIn >> __nFlags; + if( __nFlags ) + { + LINESTART(); + STARTFLAG(); + ADDFLAG( 0x0001, "fAuto" ); + ADDFLAG( 0x0004, "fDrawTick" ); + PRINT(); + } + LINESTART(); + ADDTEXT( "color index = " ); + ADDDEC( 2 ); + PRINT(); + } + break; + case 0x1009: // ChartMarkerformat + { + UINT16 n; + LINESTART(); + ADDTEXT( "Fore = " ); + ADDTEXT( GetRGB( Read4( rIn ) ) ); + ADDTEXT( " Back = " ); + ADDTEXT( GetRGB( Read4( rIn ) ) ); + rIn >> n; + switch( n ) + { + case 0: p = "no marker"; break; + case 1: p = "square"; break; + case 2: p = "diamond"; break; + case 3: p = "triangle"; break; + case 4: p = "X"; break; + case 5: p = "star"; break; + case 6: p = "Dow-Jones"; break; + case 7: p = "std deviation"; break; + case 8: p = "circle"; break; + case 9: p = "plus sign"; break; + default: p = pU; + } + ADDTEXT( " Type = " ); + ADDTEXT( p ); + PRINT(); + rIn >> __nFlags; + if( __nFlags ) + { + LINESTART(); + STARTFLAG(); + ADDFLAG( 0x0001, "fAuto" ); + ADDFLAG( 0x0010, "fNoBackg" ); + ADDFLAG( 0x0020, "fNoFore" ); + ADDRESERVED( 0xFFCE ); + PRINT(); + } + LINESTART(); + ADDTEXT( "border color = " ); + ADDDEC( 2 ); + ADDTEXT( " fill color = " ); + ADDDEC( 2 ); + ADDTEXT( " size = " ); + ADDDEC(4); + PRINT(); + } + break; + case 0x100A: // ChartAreaformat + { + LINESTART(); + ADDTEXT( "Fore = " ); + ADDTEXT( GetRGB( Read4( rIn ) ) ); + ADDTEXT( " Back = " ); + ADDTEXT( GetRGB( Read4( rIn ) ) ); + ADDTEXT( " Pattern = " ); + UINT16 n; + rIn >> n >> __nFlags; + __AddDec( t, n ); + ADDTEXT( " (" ); + __AddHex( t, n ); + ADDTEXT( ")" ); + PRINT(); + if( __nFlags ) + { + LINESTART(); + STARTFLAG(); + ADDFLAG( 0x01, "fAuto" ); + ADDFLAG( 0x02, "fInvertNeg" ); + PRINT(); + } + } + LINESTART(); + ADDTEXT( "color index fore = " ); + ADDDEC( 2 ); + ADDTEXT( ", back = " ); + ADDDEC( 2 ); + PRINT(); + break; + case 0x100B: // ChartPieformat + LINESTART(); + ADDDEC( 2 ); + ADDTEXT( "%" ); + PRINT(); + break; + case 0x100C: // ChartAttachedlabel + ContDump( nL ); + break; + case 0x100D: // ChartSeriestext + ContDump( nL ); + break; + case 0x1014: // ChartChartformat + { + ContDump( 16 ); + LINESTART(); + rIn >> __nFlags; + if( __nFlags ) + { + LINESTART(); + STARTFLAG(); + ADDFLAG( 0x0001, "fVaried" ); + PRINT(); + } + LINESTART(); + ADDTEXT( "drawing order = " ); + ADDDEC( 2 ); + PRINT(); + } + break; + case 0x1015: // ChartLegend + { + UINT32 nX, nY, nDx, nDy; + UINT8 nWType, nWSpacing; + rIn >> nX >> nY >> nDx >> nDy >> nWType >> nWSpacing >> __nFlags; + LINESTART(); + __AddDec( t, nX ); + ADDTEXT( " / " ); + __AddDec( t, nY ); + ADDTEXT( " [" ); + __AddDec( t, nDx ); + ADDTEXT( " / " ); + __AddDec( t, nDy ); + ADDTEXT( "]" ); + PRINT(); + LINESTART(); + ADDTEXT( " Type: " ); + switch( nWType ) + { + case 0: p = "bottom"; break; + case 1: p = "corner"; break; + case 2: p = "top"; break; + case 3: p = "right"; break; + case 4: p = "left"; break; + case 7: p = "not docked or inside the plot area"; break; + default: p = pU; + } + ADDTEXT( p ); + ADDTEXT( " Spacing: " ); + switch( nWSpacing ) + { + case 0: p = "close"; break; + case 1: p = "medium"; break; + case 2: p = "open"; break; + default: p = pU; + } + ADDTEXT( p ); + PRINT(); + if( __nFlags ) + { + LINESTART(); + STARTFLAG(); + ADDFLAG( 0x01, "fAutoPosition" ); + ADDFLAG( 0x02, "fAutoSeries" ); + ADDFLAG( 0x04, "fAutoPosX" ); + ADDFLAG( 0x08, "fAutoPosY" ); + ADDFLAG( 0x10, "fVert" ); + ADDFLAG( 0x20, "fWasDataTable" ); + PRINT(); + } + } + break; + case 0x1016: // ChartSerieslist + ContDump( nL ); + break; + case 0x1017: // ChartBar + { + LINESTART(); + ADDTEXT( "space betw. bars = " ); + ADDDEC( 2 ); + ADDTEXT( " space betw. cat = " ); + ADDDEC( 2 ); + PRINT(); + rIn >> __nFlags; + if( __nFlags ) + { + LINESTART(); + STARTFLAG(); + ADDFLAG( 0x0001, "fTranspose" ); + ADDFLAG( 0x0002, "fStacked" ); + ADDFLAG( 0x0004, "f100" ); + ADDFLAG( 0x0008, "fHasShadow" ); + PRINT(); + } + } + break; + case 0x1018: // ChartLine + ContDump( nL ); + break; + case 0x1019: // ChartPie + ContDump( nL ); + break; + case 0x101A: // ChartArea + ContDump( nL ); + break; + case 0x101C: // ChartLine + ContDump( nL ); + break; + case 0x101D: // ChartAxis + { + static const sal_Char* const ppcIds[] = { "x-axis", "y-axis", "z-axis" }; + LINESTART(); + sal_uInt16 nAxisId = rIn.ReaduInt16(); + ADDTEXT( "axis-id=" ); __AddDec( t, nAxisId ); + lcl_AddEnum( t, nAxisId, ppcIds, STATIC_TABLE_SIZE( ppcIds ) ); + PRINT(); + ContDump( 16 ); + } + break; + case 0x101E: // CHTICK + { + static const sal_Char* const ppcTickMode[] = { "off", "inside", "outside", "cross" }; + static const sal_Char* const ppcTickPos[] = { "off", "low", "high", "next-to-axis" }; + static const sal_Char* const ppcText[] = { "transparent", "opaque" }; + LINESTART(); + sal_uInt8 nMajor, nMinor, nPos, nText; + rIn >> nMajor >> nMinor >> nPos >> nText; + ADDTEXT( "major=" ); __AddDec( t, nMajor ); + lcl_AddEnum( t, nMajor, ppcTickMode, STATIC_TABLE_SIZE( ppcTickMode ) ); + ADDTEXT( " minor=" ); __AddDec( t, nMinor ); + lcl_AddEnum( t, nMinor, ppcTickMode, STATIC_TABLE_SIZE( ppcTickMode ) ); + PRINT(); + LINESTART(); + ADDTEXT( "position=" ); __AddDec( t, nPos ); + lcl_AddEnum( t, nPos, ppcTickPos, STATIC_TABLE_SIZE( ppcTickPos ) ); + ADDTEXT( " text-mode=" ); __AddDec( t, nText ); + lcl_AddEnum( t, nText, ppcText, STATIC_TABLE_SIZE( ppcText ) ); + ADDTEXT( " text-color=" ); + ADDTEXT( GetRGB( Read4( rIn ) ) ); + PRINT(); + LINESTART(); + ADDTEXT( "reserved=" ); ADDHEX( 4 ); + ADDTEXT( "," ); ADDHEX( 4 ); + ADDTEXT( "," ); ADDHEX( 4 ); + ADDTEXT( "," ); ADDHEX( 4 ); + PRINT(); + rIn >> __nFlags; + LINESTART(); + STARTFLAG(); + ADDFLAG( 0x0001, "fAutoCol" ); + ADDFLAG( 0x0002, "fAutoBack" ); + ADDFLAG( 0x0020, "fAutoRot" ); + ADDRESERVED( 0xFFDC ); + PRINT(); + LINESTART(); + ADDTEXT( "color=" ); ADDDEC( 2 ); + ADDTEXT( " rotation=" ); ADDDEC( 2 ); + PRINT(); + } + break; + case 0x101F: // CHVALUERANGE + { + LINESTART(); + ADDTEXT( "min=" ); ADDDOUBLE(); + ADDTEXT( " max=" ); ADDDOUBLE(); + ADDTEXT( " major=" ); ADDDOUBLE(); + ADDTEXT( " minor=" ); ADDDOUBLE(); + ADDTEXT( " axis-cross=" ); ADDDOUBLE(); + PRINT(); + rIn >> __nFlags; + LINESTART(); + STARTFLAG(); + ADDFLAG( 0x0001, "fAutoMin" ); + ADDFLAG( 0x0002, "fAutoMax" ); + ADDFLAG( 0x0004, "fAutoMajor" ); + ADDFLAG( 0x0008, "fAutoMinor" ); + ADDFLAG( 0x0010, "fAutoCross" ); + ADDFLAG( 0x0020, "fLogScale" ); + ADDFLAG( 0x0040, "fReverse" ); + ADDFLAG( 0x0080, "fMaxCross" ); + ADDRESERVED( 0xFF00 ); + PRINT(); + } + break; + case 0x1020: // CHEXTRANGE + { + LINESTART(); + ADDTEXT( "axis-cross=" ); ADDDEC( 2 ); + ADDTEXT( " label-freq=" ); ADDDEC( 2 ); + ADDTEXT( " mark-freq=" ); ADDDEC( 2 ); + PRINT(); + rIn >> __nFlags; + LINESTART(); + STARTFLAG(); + ADDFLAG( 0x0001, "fBetween" ); + ADDFLAG( 0x0002, "fMaxCross" ); + ADDFLAG( 0x0004, "fReverse" ); + ADDRESERVED( 0xFFF8 ); + PRINT(); + } + break; + case 0x1021: // ChartAxislineformat + { + LINESTART(); + switch( Read2( rIn ) ) + { + case 0: p = "axis line itself"; break; + case 1: p = "major grid line"; break; + case 2: p = "minor grid line"; break; + case 3: p = "walls or floor"; break; + default: p = pU; + } + ADDTEXT( p ); + PRINT(); + } + break; + case 0x1022: // CHARTFORMATLINK + ContDump( nL ); + break; + case 0x1024: // ChartDefaulttext + ContDump( nL ); + break; + case 0x1025: // ChartText + { + LINESTART(); + UINT8 nAt, nVat; + UINT16 nBkgMode; + INT32 nX, nY, nDx, nDy; + UINT16 nGrbit2, nIcvText; + INT16 nTrot; + rIn >> nAt >> nVat >> nBkgMode; + ADDTEXT( "h = " ); + switch( nAt ) + { + case 1: p = "left"; break; + case 2: p = "center"; break; + case 3: p = "right"; break; + case 4: p = "justify"; break; + case 5: p = "distribute"; break; + default: p = pU; + } + ADDTEXT( p ); + ADDTEXT( " v = " ); + switch( nVat ) + { + case 1: p = "top"; break; + case 2: p = "center"; break; + case 3: p = "bottom"; break; + case 4: p = "justify"; break; + case 5: p = "distribute"; break; + default: p = pU; + } + ADDTEXT( p ); + ADDTEXT( " mode = " ); + if( nBkgMode == 1 ) + ADDTEXT( "transparent" ); + else if( nBkgMode == 2 ) + ADDTEXT( "opaque" ); + else + ADDTEXT( pU ); + PRINT(); + LINESTART(); + ADDTEXT( "color = " ); + ADDTEXT( GetRGB( Read4( rIn ) ) ); + rIn >> nX >> nY >> nDx >> nDy >> __nFlags >> nIcvText >> nGrbit2 >> nTrot; + ADDTEXT( " pos[size] = " ); + __AddDec( t, nX ); + ADDTEXT( " / " ); + __AddDec( t, nY ); + ADDTEXT( " [" ); + __AddDec( t, nDx ); + ADDTEXT( " / " ); + __AddDec( t, nDy ); + ADDTEXT( "]" ); + PRINT(); + LINESTART(); + ADDTEXT( " (pos[size] = " ); + __AddHex( t, nX ); + ADDTEXT( " / " ); + __AddHex( t, nY ); + ADDTEXT( " [" ); + __AddHex( t, nDx ); + ADDTEXT( " / " ); + __AddHex( t, nDy ); + ADDTEXT( "])" ); + PRINT(); + if( __nFlags ) + { + LINESTART(); + STARTFLAG(); + ADDFLAG( 0x0001, "fAutoColor" ); + ADDFLAG( 0x0002, "fShowKey" ); + ADDFLAG( 0x0004, "fShowValue" ); + ADDFLAG( 0x0008, "fVert" ); + ADDFLAG( 0x0010, "fAutoText" ); + ADDFLAG( 0x0020, "fGenerated" ); + ADDFLAG( 0x0040, "fDeleted" ); + ADDFLAG( 0x0080, "fAutoMode" ); + ADDFLAG( 0x0800, "fShLabPct" ); + ADDFLAG( 0x1000, "fShowPct" ); + ADDFLAG( 0x2000, "fShowBubbleSizes" ); + ADDFLAG( 0x4000, "fShowLabel" ); + PRINT(); + } + LINESTART(); + ADDTEXT( "rot = " ); + switch( __nFlags & 0x0700 ) + { + case 0x0000: p = "no rotation"; break; + case 0x0100: p = "top to bottom, upright"; break; + case 0x0200: p = "90 deg counterclockwise"; break; + case 0x0300: p = "90 deg clockwise"; break; + default: p = pU; + } + ADDTEXT( p ); + ADDTEXT( " trot = " ); + __AddDec( t, nTrot ); + PRINT(); + LINESTART(); + ADDTEXT( "text color = " ); + __AddDec( t, nIcvText ); + PRINT(); + LINESTART(); + ADDTEXT( "placement: " ); + switch( nGrbit2 & 0x000F ) + { + case 0: p = "0 default"; break; + case 1: p = "outside"; break; + case 2: p = "inside"; break; + case 3: p = "center"; break; + case 4: p = "axis"; break; + case 5: p = "above"; break; + case 6: p = "below"; break; + case 7: p = "left"; break; + case 8: p = "right"; break; + case 9: p = "auto"; break; + case 10: p = "moved"; break; + default: p = pU; + } + ADDTEXT( p ); + PRINT(); + } + break; + case 0x1026: // ChartFontx + ContDump( nL ); + break; + case 0x1027: // CHOBJECTLINK + { + static const sal_Char* const ppcObjLink[] = { 0, "title", "y-axis", "x-axis", "data", "legend", "none", "z-axis" }; + LINESTART(); + sal_uInt16 nObjLink; + rIn >> nObjLink; + ADDTEXT( "link=" ); __AddDec( t, nObjLink ); + lcl_AddEnum( t, nObjLink, ppcObjLink, STATIC_TABLE_SIZE( ppcObjLink ) ); + ADDTEXT( " series=" ); ADDDEC( 2 ); + ADDTEXT( " point=" ); ADDDEC( 2 ); + PRINT(); + } + break; + case 0x1032: // ChartFrame + { + LINESTART(); + switch( Read2( rIn ) ) + { + case 0: p = "no border"; break; + case 1: + case 2: + case 3: p = "reserved"; break; + case 4: p = "with shadow"; break; + default: p = pU; + } + ADDTEXT( "Frame type: " ); + ADDTEXT( p ); + PRINT(); + rIn >> __nFlags; + if( __nFlags ) + { + LINESTART(); + STARTFLAG(); + ADDFLAG( 0x01, "fAutoSize" ); + ADDFLAG( 0x02, "fAutoPosition" ); + PRINT(); + } + } + break; + case 0x1035: // ChartPlotarea + ContDump( nL ); + break; + case 0x103A: // Chart3D + ContDump( nL ); + break; + case 0x103C: // ChartPicf + LINESTART(); + ADDTEXT( "bmp-mode=" ); ADDDEC( 2 ); + ADDTEXT( " format=" ); ADDDEC( 2 ); + ADDTEXT( " flags=" ); ADDHEX( 2 ); + ADDTEXT( " scale=" ); ADDDOUBLE(); + PRINT(); + break; + case 0x103D: // ChartDropbar + ContDump( nL ); + break; + case 0x103E: // ChartRadar + ContDump( nL ); + break; + case 0x103F: // ChartSurface + ContDump( nL ); + break; + case 0x1040: // ChartRadararea + ContDump( nL ); + break; + case 0x1041: // ChartAxisparent + { + LINESTART(); + switch( Read2( rIn ) ) + { + case 0: p = "main"; break; + case 1: p = "secondary"; break; + default: p = pU; + } + ADDTEXT( "Index: " ); + ADDTEXT( p ); + ADDTEXT( " " ); + ADDDEC(4); + ADDTEXT( '/' ); + ADDDEC(4); + ADDTEXT( " [" ); + ADDDEC(4); + ADDTEXT( '/' ); + ADDDEC(4); + ADDTEXT( ']' ); + PRINT(); + } + break; + case 0x1043: // ChartLegendxn + ContDump( nL ); + break; + case 0x1044: // ChartShtprops + ContDump( nL ); + break; + case 0x1045: // ChartSertocrt + ContDump( nL ); + break; + case 0x1046: // ChartAxesused + { + LINESTART(); + ADDTEXT( "Used : " ); + ADDDEC( 2 ); + PRINT(); + } + break; + case 0x1048: // ChartSbaseref + ContDump( nL ); + break; + case 0x104A: // CHSERPARENT + LINESTART(); + ADDTEXT( "parent-index=" ); ADDDEC( 2 ); + ADDTEXT( " (one-based)" ); + PRINT(); + break; + case 0x104B: // CHSERTRENDLINE + { + static const sal_Char* const ppcType[] = + { "poynomial", "exponential", "logarithmic", "power", "moving-avg" }; + sal_uInt8 nType; + rIn >> nType; + LINESTART(); + ADDTEXT( "line-type=" ); __AddDec( t, nType ); + lcl_AddEnum( t, nType, ppcType, STATIC_TABLE_SIZE( ppcType ) ); + ADDTEXT( " order=" ); ADDDEC( 1 ); + ADDTEXT( " intercept=" ); ADDDOUBLE(); + PRINT(); + LINESTART(); + ADDTEXT( "show-equation=" ); ADDDEC( 1 ); + ADDTEXT( " show-r-sqr=" ); ADDDEC( 1 ); + PRINT(); + LINESTART(); + ADDTEXT( "forecast-for=" ); ADDDOUBLE(); + ADDTEXT( " forecast-back=" ); ADDDOUBLE(); + PRINT(); + } + break; + case 0x104E: // ChartIfmt + ContDump( nL ); + break; + case 0x104F: // ChartPos + { + LINESTART(); + UINT16 nMdTopLt, nMdBotRt; + INT32 nX, nY, nDx, nDy; + rIn >> nMdTopLt >> nMdBotRt >> nX >> nY >> nDx >> nDy; + ADDTEXT( "TopLr = " ); + __AddDec( t, nMdTopLt ); + ADDTEXT( " BotRt = " ); + __AddDec( t, nMdBotRt ); + PRINT(); + LINESTART(); + __AddDec( t, nX ); + ADDTEXT( " / " ); + __AddDec( t, nY ); + ADDTEXT( " [" ); + __AddDec( t, nDx ); + ADDTEXT( " / " ); + __AddDec( t, nDy ); + ADDTEXT( "]" ); + PRINT(); + } + break; + case 0x1050: // ChartAlruns + ContDump( nL ); + break; + case 0x1051: // AI + { + LINESTART(); + UINT8 n8 = Read1( rIn ); + switch( n8 ) + { + case 0: p = "title or text"; break; + case 1: p = "values"; break; + case 2: p = "categories"; break; + case 3: p = "bubble sizes"; break; + default: p = pU; + } + ADDTEXT( "Link index identifier: " ); + ADDTEXT( p ); + if ( p == pU ) + __AddHex( t, n8 ); + PRINT(); + LINESTART(); + switch( Read1( rIn ) ) + { + case 0: p = "default categories"; break; + case 1: p = "text or value"; break; + case 2: p = "linked to worksheet"; break; + case 3: p = "not used (HaHaHa...)"; break; + case 4: p = "error reported"; break; + default: p = pU; + } + ADDTEXT( "Refernce type: " ); + ADDTEXT( p ); + PRINT(); + rIn >> __nFlags; + if( __nFlags ) + { + LINESTART(); + STARTFLAG(); + ADDFLAG( 0x01, "fCustomIfmt" ); + PRINT(); + } + LINESTART(); + ADDTEXT( "Numberformat = " ); + ADDDEC( 2 ); + PRINT(); + LINESTART(); + UINT16 n; + rIn >> n; + ADDTEXT( "Formula [" ); + __AddDec( t, n ); + ADDTEXT( "]: ---------------- " ); + PRINT(); + FormulaDump( n, FT_CellFormula ); + } + break; + case 0x105B: // CHSERERRORBAR + { + static const sal_Char* const ppcType[] = { 0, "x-plus", "x-minus", "y-plus", "y-minus" }; + static const sal_Char* const ppcSource[] = { 0, "percent", "fixed", "std-dev", "custom", "std-error" }; + static const sal_Char* const ppcLineEnd[] = { "blank", "t-shape" }; + sal_uInt8 nType, nSource, nLineEnd; + rIn >> nType >> nSource >> nLineEnd; + LINESTART(); + ADDTEXT( "bar-type=" ); __AddDec( t, nType ); + lcl_AddEnum( t, nType, ppcType, STATIC_TABLE_SIZE( ppcType ) ); + ADDTEXT( " value-source=" ); __AddDec( t, nSource ); + lcl_AddEnum( t, nSource, ppcSource, STATIC_TABLE_SIZE( ppcSource ) ); + ADDTEXT( " line-end=" ); __AddDec( t, nLineEnd ); + lcl_AddEnum( t, nLineEnd, ppcLineEnd, STATIC_TABLE_SIZE( ppcLineEnd ) ); + PRINT(); + LINESTART(); + ADDTEXT( "reserved=" ); ADDHEX( 1 ); + ADDTEXT( " value=" ); ADDDOUBLE(); + ADDTEXT( " ref-count=" ); ADDDEC( 2 ); + PRINT(); + } + break; + case 0x105D: // ChartSerfmt + ContDump( nL ); + break; + case 0x105F: // Chart3DDataForm + { + UINT8 nGround, nTop; + nGround = Read1( rIn ); + nTop = Read1( rIn ); + UINT16 nStyle = ((UINT16)nGround << 8) | nTop; + LINESTART(); + ADDTEXT( "3D - format (" ); + __AddHex( t, nGround ); + ADDTEXT( " " ); + __AddHex( t, nTop ); + ADDTEXT( "): " ); + switch( nStyle ) + { + case 0x0000: ADDTEXT( "bar" ); break; + case 0x0001: ADDTEXT( "pyramid" ); break; + case 0x0002: ADDTEXT( "pyramid, cut" ); break; + case 0x0100: ADDTEXT( "cylinder" ); break; + case 0x0101: ADDTEXT( "cone" ); break; + case 0x0102: ADDTEXT( "cone, cut" ); break; + default: ADDTEXT( pU ); + } + PRINT(); + } + break; + case 0x1060: // ChartFbi + { + LINESTART(); + ADDTEXT( "dmixBasis = " ); + ADDDEC( 2 ); + ADDTEXT( " dmiyBasis = " ); + ADDDEC( 2 ); + ADDTEXT( " twpHeightBasis = " ); + ADDDEC( 2 ); + ADDTEXT( " scab = " ); + ADDDEC( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( "ifnt = " ); + ADDDEC( 2 ); + PRINT(); + } + break; + case 0x1061: // ChartBoppop + ContDump( nL ); + break; + case 0x1062: // ChartAxcext + { + LINESTART(); + ADDTEXT( "cat on axis: " ); + ADDDEC( 2 ); + ADDTEXT( " ... " ); + ADDDEC( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( "major unit: val = " ); + ADDDEC( 2 ); + ADDTEXT( " units = " ); + ADDDEC( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( "minor unit: val = " ); + ADDDEC( 2 ); + ADDTEXT( " units = " ); + ADDDEC( 2 ); + PRINT(); + LINESTART(); + ADDTEXT( "base unit = " ); + ADDDEC( 2 ); + ADDTEXT( " crossing point of val axis = " ); + ADDDEC( 2 ); + PRINT(); + rIn >> __nFlags; + if( __nFlags ) + { + LINESTART(); + STARTFLAG(); + ADDFLAG( 0x0001, "fAutoMin" ); + ADDFLAG( 0x0002, "fAutoMax" ); + ADDFLAG( 0x0004, "fAutoMajor" ); + ADDFLAG( 0x0008, "fAutoMinor" ); + ADDFLAG( 0x0010, "fDateAxis" ); + ADDFLAG( 0x0020, "fAutoBase" ); + ADDFLAG( 0x0040, "fAutoCross" ); + ADDFLAG( 0x0080, "fAutoDate" ); + PRINT(); + } + } + break; + case 0x1063: // ChartDat + ContDump( nL ); + break; + case 0x1064: // ChartPlotgrowth + { + UINT32 nDx, nDy; + rIn >> nDx >> nDy; + LINESTART(); + ADDTEXT( "dxPlotGrowth = " ); + __Add16p16( t, nDx ); + ADDTEXT( " (" ); + __AddHex( t, nDx ); + ADDTEXT( ") dyPlotGrowth = " ); + __Add16p16( t, nDy ); + ADDTEXT( " (" ); + __AddHex( t, nDy ); + ADDTEXT( ")" ); + PRINT(); + } + break; + case 0x1065: // ChartSiindex + ContDump( nL ); + break; + case 0x1066: // ChartGelframe + EscherDump( nL, false ); + break; + case 0x1067: // ChartBoppcustom + ContDump( nL ); + break; + default: + if( !bEncrypted ) + ContDump( nL ); + } + + } + + if( nR == EXC_ID_FILEPASS ) + { + bEncrypted = true; + pIn->Seek( EXC_REC_SEEK_TO_BEGIN ); + bool bValid = (XclImpDecryptHelper::ReadFilepass( *pIn ) == ERRCODE_NONE); + LINESTART(); + ADDTEXT( "decrypter=" ); lcl_AddOnOff( t, bValid ); + PRINT(); + bBIFF8 = bBIFF8 && bValid; // dump BIFF8 hex only on invalid decrypter + } + + if( bDec ) + pLevelPre -= nLevelInc; +} + + +static const sal_Char* GetBlipType( UINT8 n ) +{ + switch ( n ) + { + case 0 : + return " ERROR"; + break; + case 1 : + return " UNKNOWN"; + break; + case 2 : + return " EMF"; + break; + case 3 : + return " WMF"; + break; + case 4 : + return " PICT"; + break; + case 5 : + return " JPEG"; + break; + case 6 : + return " PNG"; + break; + case 7 : + return " DIB"; + break; + default: + if ( n < 32 ) + return " NotKnown"; + else + return " Client"; + } +} + +void Biff8RecDumper::EscherDump( const ULONG nMaxLen, bool bDumpOffset ) +{ + ULONG n = nMaxLen; + UINT16 nPre, nR; + UINT32 nL; + const sal_Char* p; + ByteString aT; + UINT16 nDumpSize; + + aT += pLevelPre; + + ULONG nStartPos = pIn->GetSvStreamPos(); + while( pIn->IsValid() && (n > 0) ) + { + ULONG nCurrPos = pIn->GetSvStreamPos(); + *pIn >> nPre >> nR >> nL; + n -= sizeof( nPre ) + sizeof( nR ) + sizeof( nL ); + + switch( nR ) + { + case 0xF000: p = "MsofbtDggContainer"; break; + case 0xF006: p = "MsofbtDgg"; break; + case 0xF016: p = "MsofbtCLSID"; break; + case 0xF00B: p = "MsofbtOPT"; break; + case 0xF11A: p = "MsofbtColorMRU"; break; + case 0xF11E: p = "MsofbtSplitMenuColors"; break; + case 0xF001: p = "MsofbtBstoreContainer"; break; + case 0xF007: p = "MsofbtBSE"; break; + case 0xF002: p = "MsofbtDgContainer"; break; + case 0xF008: p = "MsofbtDg"; break; + case 0xF118: p = "MsofbtRegroupItem"; break; + case 0xF120: p = "MsofbtColorScheme"; break; + case 0xF003: p = "MsofbtSpgrContainer"; break; + case 0xF004: p = "MsofbtSpContainer"; break; + case 0xF009: p = "MsofbtSpgr"; break; + case 0xF00A: p = "MsofbtSp"; break; + case 0xF00C: p = "MsofbtTextbox"; break; + case 0xF00D: p = "MsofbtClientTextbox"; break; + case 0xF00E: p = "MsofbtAnchor"; break; + case 0xF00F: p = "MsofbtChildAnchor"; break; + case 0xF010: p = "MsofbtClientAnchor"; break; + case 0xF011: p = "MsofbtClientData"; break; + case 0xF11F: p = "MsofbtOleObject"; break; + case 0xF11D: p = "MsofbtDeletedPspl"; break; + case 0xF005: p = "MsofbtSolverContainer"; break; + case 0xF012: p = "MsofbtConnectorRule"; break; + case 0xF013: p = "MsofbtAlignRule"; break; + case 0xF014: p = "MsofbtArcRule"; break; + case 0xF015: p = "MsofbtClientRule"; break; + case 0xF017: p = "MsofbtCalloutRule"; break; + case 0xF119: p = "MsofbtSelection"; break; + case 0xF122: p = "MsofbtUDefProp"; break; + default: + if( nR >= 0xF018 && nR <= 0xF117 ) + p = "MsofbtBLIP"; + else if ( ( nPre & 0x000F ) == 0x000F ) + p = "UNKNOWN container"; + else + p = "UNKNOWN ID"; + } + + aT += " "; + __AddHex( aT, nR ); + ((aT += " ") += p) += " ["; + __AddHex( aT, nPre ); + aT += ','; + __AddHex( aT, nL ); + aT += "] instance: "; + __AddDec( aT, (UINT16)(nPre >> 4) ); + if( bDumpOffset ) + { + aT.Append( " pos=" ); + __AddHex( aT, static_cast< sal_uInt32 >( mnEscherPos + nCurrPos - nStartPos ) ); + } + Print( aT ); + + if ( nR == 0xF007 && 36 <= n && 36 <= nL ) + { // BSE, FBSE + ULONG nP = pIn->GetRecPos(); + UINT8 n8; + UINT16 n16; + UINT32 n32; + + aT = " btWin32: "; + *pIn >> n8; + __AddHex( aT, n8 ); + aT += GetBlipType( n8 ); + aT += " btMacOS: "; + *pIn >> n8; + __AddHex( aT, n8 ); + aT += GetBlipType( n8 ); + Print( aT ); + + aT = " rgbUid:"; + Print( aT ); + ContDump( 16 ); + + aT = " tag: "; + *pIn >> n16; + __AddHex( aT, n16 ); + Print( aT ); + + aT = " size: "; + *pIn >> n32; + __AddHex( aT, n32 ); + Print( aT ); + + aT = " cRef: "; + *pIn >> n32; + __AddHex( aT, n32 ); + Print( aT ); + + aT = " offs: "; + *pIn >> n32; + __AddHex( aT, n32 ); + Print( aT ); + + aT = " usage: "; + *pIn >> n8; + __AddHex( aT, n8 ); + aT += " cbName: "; + *pIn >> n8; + __AddHex( aT, n8 ); + aT += " unused2: "; + *pIn >> n8; + __AddHex( aT, n8 ); + aT += " unused3: "; + *pIn >> n8; + __AddHex( aT, n8 ); + Print( aT ); + + n -= pIn->GetRecPos() - nP; + nL = 0; // loop to MsofbtBLIP + } + else if ( nR == 0xF00F && 0x10 <= n && 0x10 <= nL ) + { // ChildAnchor + ULONG nP = pIn->GetRecPos(); + sal_Int32 n32; + + aT.Assign( " pos1=" ); + *pIn >> n32; lclAppendDec( aT, n32 ); + aT.Append( " pos2=" ); + *pIn >> n32; lclAppendDec( aT, n32 ); + aT.Append( " pos3=" ); + *pIn >> n32; lclAppendDec( aT, n32 ); + aT.Append( " pos4=" ); + *pIn >> n32; lclAppendDec( aT, n32 ); + Print( aT ); + + ULONG nC = pIn->GetRecPos() - nP; + n -= nC; + nL -= nC; + } + else if ( nR == 0xF010 && 0x12 <= n && 0x12 <= nL ) + { // ClientAnchor + ULONG nP = pIn->GetRecPos(); + UINT16 n16; + + aT = " Flag: "; + *pIn >> n16; + __AddHex( aT, n16 ); + if( n16 & 0x0001 ) aT += " -fixedpos"; + if( n16 & 0x0002 ) aT += " -fixedsize"; + Print( aT ); + + aT = " Col1: "; + *pIn >> n16; + __AddHex( aT, n16 ); + aT += " dX1: "; + *pIn >> n16; + __AddHex( aT, n16 ); + aT += " Row1: "; + *pIn >> n16; + __AddHex( aT, n16 ); + aT += " dY1: "; + *pIn >> n16; + __AddHex( aT, n16 ); + Print( aT ); + + aT = " Col2: "; + *pIn >> n16; + __AddHex( aT, n16 ); + aT += " dX2: "; + *pIn >> n16; + __AddHex( aT, n16 ); + aT += " Row2: "; + *pIn >> n16; + __AddHex( aT, n16 ); + aT += " dY2: "; + *pIn >> n16; + __AddHex( aT, n16 ); + Print( aT ); + + ULONG nC = pIn->GetRecPos() - nP; + n -= nC; + nL -= nC; + } + else if ( nR == 0xF00A ) + { + sal_uInt32 nId, nFlags; + *pIn >> nId >> nFlags; + aT.Assign( " shape-id=" ); + __AddHex( aT, nId ); + aT.Append( " flags=" ); + __AddHex( aT, nFlags ); + Print( aT ); + nL -= 8; n -= 8; + } + else if ( nR == 0xF00B || nR == 0xF122 ) + { // OPT + sal_uInt32 nComplex = 0; + while ( nL >= 6 + nComplex && n >= 6 + nComplex ) + { + UINT16 n16; + UINT32 n32; + *pIn >> n16 >> n32; + nL -= 6; n -= 6; + aT = " "; + __AddHex( aT, n16 ); + aT += " ("; + __AddDec( aT, n16 & 0x3FFF, 5 ); + if ( (n16 & 0x8000) == 0 ) + { + if ( n16 & 0x4000 ) + aT += ", fBlipID"; + aT += ") "; + __AddHex( aT, n32 ); + if ( (n16 & 0x4000) == 0 ) + { + aT += " ("; + __AddDec1616( aT, n32 ); + aT += ')'; + } + Print( aT ); + } + else + { + aT += ", fComplex) "; + __AddHex( aT, n32 ); + Print( aT ); + nComplex += n32; + } + } + // complex property data + while ( nComplex && n > 0 ) + { + sal_uInt32 nDumpSize = (nComplex > n) ? n : nComplex; + ContDump( nDumpSize ); + nComplex -= nDumpSize; + nL -= nDumpSize; + n -= nDumpSize; + } + } + else if ( nR == 0xF012 ) + { + aT = " Connector rule: "; __AddDec( aT, pIn->ReaduInt32() ); + aT += " ShapeID A: "; __AddHex( aT, pIn->ReaduInt32() ); + aT += " ShapeID B: "; __AddHex( aT, pIn->ReaduInt32() ); + Print( aT ); + aT = " ShapeID connector: "; __AddHex( aT, pIn->ReaduInt32() ); + aT += " Connect pt A: "; __AddHex( aT, pIn->ReaduInt32() ); + aT += " Connect pt B: "; __AddHex( aT, pIn->ReaduInt32() ); + Print( aT ); + nL -= 24; n -= 24; + } + + if( ( nPre & 0x000F ) == 0x000F ) + { // Container + if ( nL <= (UINT32) n ) + Print( " completed within" ); + else + Print( " continued elsewhere" ); + } + else + // -> 0x0000 ... 0x0FFF + { + nDumpSize = ( ( UINT32 ) nL > ( UINT32 ) n )? ( UINT16 ) n : ( UINT16 ) nL; + + if( nDumpSize ) + { + ContDump( nDumpSize ); + n -= nDumpSize; + } + } + + aT.Erase(); + } + if( bDumpOffset ) + mnEscherPos += nMaxLen; +} + + +void Biff8RecDumper::ObjDump( const ULONG nMaxLen ) +{ +#if 0 +// if an entire hex block is needed + pIn->PushPosition(); + ContDump( nMaxLen ); + pIn->PopPosition(); +#endif + + ULONG n = nMaxLen; + UINT16 nR, nL; + const sal_Char* p; + ByteString t; + XclImpStream& rIn = *pIn; + UINT16 nDumpSize; + sal_uInt16 nObjFlags = 0; + + t += pLevelPre; + + while( n > 0 ) + { + rIn >> nR >> nL; + n -= sizeof( nR ) + sizeof( nL ); + + BOOL bDetails = FALSE; + switch( nR ) + { + case 0x0000: p = "ftEnd"; break; + case 0x0001: p = "(Reserved)"; break; + case 0x0002: p = "(Reserved)"; break; + case 0x0003: p = "(Reserved)"; break; + case 0x0004: p = "ftMacro"; break; + case 0x0005: p = "ftButton"; break; + case 0x0006: p = "ftGmo"; break; + case 0x0007: p = "ftCf"; break; + case 0x0008: p = "ftPioGrbit"; bDetails = TRUE; break; + case 0x0009: p = "ftPictFmla"; bDetails = TRUE; break; + case 0x000A: p = "ftCbls"; break; + case 0x000B: p = "ftRbo"; break; + case 0x000C: p = "ftSbs"; break; + case 0x000D: p = "ftNts"; break; + case 0x000E: p = "ftSbsFmla"; break; + case 0x000F: p = "ftGboData"; break; + case 0x0010: p = "ftEdoData"; break; + case 0x0011: p = "ftRboData"; break; + case 0x0012: p = "ftCblsData"; break; + case 0x0013: p = "ftLbsData"; break; + case 0x0014: p = "ftCblsFmla"; break; + case 0x0015: p = "ftCmo"; bDetails = TRUE; break; + default: + p = "UNKNOWN ID"; + } + + t += " "; + __AddHex( t, nR ); + t += " ["; + __AddHex( t, nL ); + (t += "] ") += p; + Print( t ); + + nDumpSize = ( ( UINT32 ) nL > ( UINT32 ) n )? ( UINT16 ) n : ( UINT16 ) nL; + + if( nDumpSize ) + { + ULONG nPos1 = (bDetails ? rIn.GetRecPos() : 0); + ContDump( nDumpSize ); + n -= nDumpSize; + if ( bDetails ) + { + ULONG nPos2 = rIn.GetRecPos(); + rIn.Seek( nPos1 ); + t.Erase(); + switch ( nR ) + { + case 0x0008 : // ftPioGrbit + { + rIn >> nObjFlags; + UINT16 __nFlags = nObjFlags; + if ( __nFlags ) + { + ADDTEXT( " " ); + STARTFLAG(); + ADDFLAG( 0x0001, "man-size" ); + ADDFLAG( 0x0002, "linked" ); + ADDFLAG( 0x0008, "symbol" ); + ADDFLAG( 0x0010, "control" ); + ADDFLAG( 0x0020, "ctls-stream" ); + ADDFLAG( 0x0200, "autoload" ); + ADDRESERVED( 0xFDC4 ); + } + } + break; + case 0x0009 : // ftPictFmla + { + ADDTEXT( " Document type " ); + UINT16 nFmlaLen; + rIn >> nFmlaLen; + if( nObjFlags & 0x0002 ) + { + ADDTEXT( "linked\n OLE stream: LNK??? (from EXTERNNAME) " ); + rIn >> nFmlaLen; + ADDTEXT( " unknown=" ); ADDHEX( 4 ); + PRINT(); + t.Erase(); + FormulaDump( nFmlaLen, FT_CellFormula ); + } + else + { + ADDTEXT( "embedded " ); + const UINT16 nStringOffset = 14; // MAY be right + rIn.Seek( nPos1 + nStringOffset ); + INT32 nBytesLeft = nL - nStringOffset; + UINT16 nStrLen = rIn.ReaduInt16(); + ULONG nPos3 = rIn.GetRecPos(); + if( nStrLen ) + AddUNICODEString( t, rIn, TRUE, nStrLen ); + nBytesLeft -= (rIn.GetRecPos() - nPos3); + ADDTEXT( '\n' ); + if ( nBytesLeft < 4 ) + ADDTEXT( " >> ByteString OVERRUN <<\n" ); + + rIn.Seek( nPos1 + sizeof(nFmlaLen) + nFmlaLen ); + if( nObjFlags & 0x0020 ) + { + sal_uInt32 nStrmStart, nStrmLen; + rIn >> nStrmStart >> nStrmLen; + ADDTEXT( " 'Ctls' stream start=" ); + __AddHex( t, nStrmStart ); + ADDTEXT( " size=" ); + __AddHex( t, nStrmLen ); + maCtlsPosMap[ nStrmStart ] = nStrmLen; + } + else + { + ADDTEXT( " OLE storage name: MBD" ); + __AddPureHex( t, rIn.ReaduInt32() ); + } + } + } + break; + case 0x0015 : // ftCmo + { + UINT16 nType, nId; + rIn >> nType >> nId; + ADDTEXT( " Object ID " ); + __AddHex( t, nId ); + switch ( nType ) + { + case 0x0000 : p = "Group"; break; + case 0x0001 : p = "Line"; break; + case 0x0002 : p = "Rectangle"; break; + case 0x0003 : p = "Oval"; break; + case 0x0004 : p = "Arc"; break; + case 0x0005 : p = "Chart"; break; + case 0x0006 : p = "Text"; break; + case 0x0007 : p = "Button"; break; + case 0x0008 : p = "Picture"; break; + case 0x0009 : p = "Polygon"; break; + case 0x000a : p = "(Reserved)"; break; + case 0x000b : p = "Check box"; break; + case 0x000c : p = "Option button";break; + case 0x000d : p = "Edit box"; break; + case 0x000e : p = "Label"; break; + case 0x000f : p = "Dialog box"; break; + case 0x0010 : p = "Spinner"; break; + case 0x0011 : p = "Scroll bar"; break; + case 0x0012 : p = "List box"; break; + case 0x0013 : p = "Group box"; break; + case 0x0014 : p = "Combo box"; break; + case 0x0015 : p = "(Reserved)"; break; + case 0x0016 : p = "(Reserved)"; break; + case 0x0017 : p = "(Reserved)"; break; + case 0x0018 : p = "(Reserved)"; break; + case 0x0019 : p = "Comment"; break; + case 0x001a : p = "(Reserved)"; break; + case 0x001b : p = "(Reserved)"; break; + case 0x001c : p = "(Reserved)"; break; + case 0x001d : p = "(Reserved)"; break; + case 0x001e : p = "Microsoft Office drawing"; break; + default: + p = "UNKNOWN"; + } + ADDTEXT( ", type " ); + __AddHex( t, nType ); + ADDTEXT( ' ' ); + ADDTEXT( p ); + } + break; + } + if ( t.Len() ) + PRINT(); + rIn.Seek( nPos2 ); + } + } + + t.Erase(); + } +} + + +#undef LINESTART +#undef IGNORE +#undef ADDHEX +#undef ADDDEC +#undef PRINT +#undef PreDump +#undef ADDCELLHEAD + +void Biff8RecDumper::ContDump( const ULONG nL ) +{ + UINT32 nC = nMaxBodyLines; + UINT32 n = nL; + UINT32 nInL, nTmp; + UINT8* pB = new UINT8[ nL ]; + UINT8* p; + const UINT16 nLineLen = 16; + UINT16 nCharCnt; + BOOL bPart; + ByteString aT; + + aT += pLevelPre; + + while( n && nC ) + { + bPart = n < nLineLen; + nInL = bPart? n : nLineLen; + n -= nInL; + + pIn->Read( pB, nInL ); + + // als Hex-Codes + nTmp = nInL; + p = pB; + nCharCnt = 0; + while( nTmp ) + { + if( nCharCnt == nLineLen / 2 ) + aT += ' '; + + nCharCnt++; + + aT += ' '; + __AddPureHex( aT, *p ); + p++; + + nTmp--; + } + + if( bPart ) + aT += GetBlanks( ( UINT16 ) ( ( nLineLen - nInL ) * 3 ) ); + + // als chars + + aT += " "; + if( nInL < 9 ) + aT += ' '; + + nTmp = nInL; + p = pB; + nCharCnt = 0; + while( nTmp ) + { + if( nCharCnt == nLineLen / 2 ) + aT += ' '; + + nCharCnt++; + + if( IsPrintable( *p ) ) + aT += static_cast< sal_Char >( *p ); + else + aT += '.'; + + p++; + + nTmp--; + } + + Print( aT ); + aT.Erase(); + aT += pLevelPre; + + nC--; + } + + delete[] pB; +} + + +// Formula dumper ============================================================= + +/** Name and parameter count of an Excel function. */ +struct XclDumpFunc +{ + const sal_Char* pName; /// Name of the function. + sal_uInt16 nParam; /// Parameter count for fixed functions. +}; + +static const XclDumpFunc pFuncData[] = +{ +/* 0*/ { "COUNT", 0 }, + { "IF", 0 }, + { "ISNA", 1 }, + { "ISERROR", 1 }, + { "SUM", 0 }, +/* 5*/ { "AVERAGE", 0 }, + { "MIN", 0 }, + { "MAX", 0 }, + { "ROW", 0 }, + { "COLUMN", 0 }, +/* 10*/ { "NA", 0 }, + { "NPV", 0 }, + { "STDEV", 0 }, + { "DOLLAR", 0 }, + { "FIXED", 0 }, +/* 15*/ { "SIN", 1 }, + { "COS", 1 }, + { "TAN", 1 }, + { "ATAN", 1 }, + { "PI", 0 }, +/* 20*/ { "SQRT", 1 }, + { "EXP", 1 }, + { "LN", 1 }, + { "LOG10", 1 }, + { "ABS", 1 }, +/* 25*/ { "INT", 1 }, + { "SIGN", 1 }, + { "ROUND", 2 }, + { "LOOKUP", 0 }, + { "INDEX", 0 }, +/* 30*/ { "REPT", 2 }, + { "MID", 3 }, + { "LEN", 1 }, + { "VALUE", 1 }, + { "TRUE", 0 }, +/* 35*/ { "FALSE", 0 }, + { "AND", 0 }, + { "OR", 0 }, + { "NOT", 1 }, + { "MOD", 2 }, +/* 40*/ { "DCOUNT", 3 }, + { "DSUM", 3 }, + { "DAVERAGE", 3 }, + { "DMIN", 3 }, + { "DMAX", 3 }, +/* 45*/ { "DSTDEV", 3 }, + { "VAR", 0 }, + { "DVAR", 3 }, + { "TEXT", 2 }, + { "LINEST", 0 }, +/* 50*/ { "TREND", 0 }, + { "LOGEST", 0 }, + { "GROWTH", 0 }, + { "GOTO" }, // macro/internal + { "HALT" }, // macro/internal +/* 55*/ { "RETURN" }, // macro/internal + { "PV", 0 }, + { "FV", 0 }, + { "NPER", 0 }, + { "PMT", 0 }, +/* 60*/ { "RATE", 0 }, + { "MIRR", 3 }, + { "IRR", 0 }, + { "RAND", 0 }, + { "MATCH", 0 }, +/* 65*/ { "DATE", 3 }, + { "TIME", 3 }, + { "DAY", 1 }, + { "MONTH", 1 }, + { "YEAR", 1 }, +/* 70*/ { "WEEKDAY", 0 }, + { "HOUR", 1 }, + { "MINUTE", 1 }, + { "SECOND", 1 }, + { "NOW", 0 }, +/* 75*/ { "AREAS", 1 }, + { "ROWS", 1 }, + { "COLUMNS", 1 }, + { "OFFSET", 0 }, + { "ABSREF" }, // macro/internal +/* 80*/ { "RELREF" }, // macro/internal + { "ARGUMENT" }, // macro/internal + { "SEARCH", 0 }, + { "TRANSPOSE", 1 }, + { "ERROR" }, // macro/internal +/* 85*/ { "STEP" }, // macro/internal + { "TYPE", 1 }, + { "ECHO" }, // macro/internal + { "SET.NAME" }, // macro/internal + { "CALLER" }, // macro/internal +/* 90*/ { "DEREF" }, // macro/internal + { "WINDOWS" }, // macro/internal + { "SERIES" }, // macro/internal + { "DOCUMENTS" }, // macro/internal + { "ACTIVE.CELL" }, // macro/internal +/* 95*/ { "SELECTION" }, // macro/internal + { "RESULT" }, // macro/internal + { "ATAN2", 2 }, + { "ASIN", 1 }, + { "ACOS", 1 }, +/*100*/ { "CHOOSE", 0 }, + { "HLOOKUP", 0 }, + { "VLOOKUP", 0 }, + { "LINKS" }, // macro/internal + { "INPUT" }, // macro/internal +/*105*/ { "ISREF", 1 }, + { "GET.FORMULA" }, // macro/internal + { "GET.NAME" }, // macro/internal + { "SET.VALUE", 2 }, // macro/internal + { "LOG", 0 }, +/*110*/ { "EXEC" }, // macro/internal + { "CHAR", 1 }, + { "LOWER", 1 }, + { "UPPER", 1 }, + { "PROPER", 1 }, +/*115*/ { "LEFT", 0 }, + { "RIGHT", 0 }, + { "EXACT", 2 }, + { "TRIM", 1 }, + { "REPLACE", 4 }, +/*120*/ { "SUBSTITUTE", 0 }, + { "CODE", 1 }, + { "NAMES" }, // macro/internal + { "DIRECTORY" }, // macro/internal + { "FIND", 0 }, +/*125*/ { "CELL", 0 }, + { "ISERR", 1 }, + { "ISTEXT", 1 }, + { "ISNUMBER", 1 }, + { "ISBLANK", 1 }, +/*130*/ { "T", 1 }, + { "N", 1 }, + { "FOPEN" }, // macro/internal + { "FCLOSE" }, // macro/internal + { "FSIZE" }, // macro/internal +/*135*/ { "FREADLN" }, // macro/internal + { "FREAD" }, // macro/internal + { "FWRITELN" }, // macro/internal + { "FWRITE" }, // macro/internal + { "FPOS" }, // macro/internal +/*140*/ { "DATEVALUE", 1 }, + { "TIMEVALUE", 1 }, + { "SLN", 3 }, + { "SYD", 4 }, + { "DDB", 0 }, +/*145*/ { "GET.DEF" }, // macro/internal + { "REFTEXT" }, // macro/internal + { "TEXTREF" }, // macro/internal + { "INDIRECT", 0 }, + { "REGISTER" }, // macro/internal +/*150*/ { "CALL" }, + { "ADD.BAR" }, // macro/internal + { "ADD.MENU" }, // macro/internal + { "ADD.COMMAND" }, // macro/internal + { "ENABLE.COMMAND" }, // macro/internal +/*155*/ { "CHECK.COMMAND" }, // macro/internal + { "RENAME.COMMAND" }, // macro/internal + { "SHOW.BAR" }, // macro/internal + { "DELETE.MENU" }, // macro/internal + { "DELETE.COMMAND" }, // macro/internal +/*160*/ { "GET.CHART.ITEM" }, // macro/internal + { "DIALOG.BOX" }, // macro/internal + { "CLEAN", 1 }, + { "MDETERM", 1 }, + { "MINVERSE", 1 }, +/*165*/ { "MMULT", 2 }, + { "FILES" }, // macro/internal + { "IPMT", 0 }, + { "PPMT", 0 }, + { "COUNTA", 0 }, +/*170*/ { "CANCEL.KEY" }, // macro/internal + { "FOR" }, // macro/internal + { "WHILE" }, // macro/internal + { "BREAK" }, // macro/internal + { "NEXT" }, // macro/internal +/*175*/ { "INITIATE" }, // macro/internal + { "REQUEST" }, // macro/internal + { "POKE" }, // macro/internal + { "EXECUTE" }, // macro/internal + { "TERMINATE" }, // macro/internal +/*180*/ { "RESTART" }, // macro/internal + { "HELP" }, // macro/internal + { "GET.BAR" }, // macro/internal + { "PRODUCT", 0 }, + { "FACT", 1 }, +/*185*/ { "GET.CELL" }, // macro/internal + { "GET.WORKSPACE" }, // macro/internal + { "GET.WINDOW" }, // macro/internal + { "GET.DOCUMENT" }, // macro/internal + { "DPRODUCT", 3 }, +/*190*/ { "ISNONTEXT", 1 }, + { "GET.NOTE" }, // macro/internal + { "NOTE" }, // macro/internal + { "STDEVP", 0 }, + { "VARP", 0 }, +/*195*/ { "DSTDDEVP", 3 }, + { "DVARP", 3 }, + { "TRUNC", 0 }, + { "ISLOGICAL", 1 }, + { "DBCOUNTA", 3 }, +/*200*/ { "DELETE.BAR" }, // macro/internal + { "UNREGISTER" }, // macro/internal + { "202" }, // not used + { "203" }, // not used + { "USDOLLAR" }, +/*205*/ { "FINDB" }, + { "SEARCHB" }, + { "REPLACEB", 4 }, + { "LEFTB" }, + { "RIGHTB" }, +/*210*/ { "MIDB", 3 }, + { "LENB", 1 }, + { "ROUNDUP", 2 }, + { "ROUNDDOWN", 2 }, + { "ASC", 1 }, +/*215*/ { "DBSC", 1 }, + { "RANK", 0 }, + { "217" }, // not used + { "218" }, // not used + { "ADDRESS", 0 }, +/*220*/ { "DAYS360", 0 }, + { "TODAY", 0 }, + { "VDB", 0 }, + { "ELSE" }, // macro/internal + { "ELSE.IF" }, // macro/internal +/*225*/ { "END.IF" }, // macro/internal + { "FOR.CELL" }, // macro/internal + { "MEDIAN", 0 }, + { "SUMPRODUCT", 0 }, + { "SINH", 1 }, +/*230*/ { "COSH", 1 }, + { "TANH", 1 }, + { "ASINH", 1 }, + { "ACOSH", 1 }, + { "ATANH", 1 }, +/*235*/ { "DGET", 3 }, + { "CREATE.OBJECT" }, // macro/internal + { "VOLATILE" }, // macro/internal + { "LAST.ERROR" }, // macro/internal + { "CUSTOM.UNDO" }, // macro/internal +/*240*/ { "CUSTOM.REPEAT" }, // macro/internal + { "FORMULA.CONVERT" }, // macro/internal + { "GET.LINK.INFO" }, // macro/internal + { "TEXT.BOX" }, // macro/internal + { "INFO", 1 }, +/*245*/ { "GROUP" }, // macro/internal + { "GET.OBJECT" }, // macro/internal + { "DB", 0 }, + { "PAUSE" }, // macro/internal + { "249" }, // not used +/*250*/ { "250" }, // not used + { "RESUME" }, // macro/internal + { "FREQUENCY", 2 }, + { "ADD.TOOLBAR" }, // macro/internal + { "DELETE.TOOLBAR" }, // macro/internal +/*255*/ { "EXTERN.CALL" }, // macro/internal + { "RESET.TOOLBAR" }, // macro/internal + { "EVALUATE" }, // macro/internal + { "GET.TOOLBAR" }, // macro/internal + { "GET.TOOL" }, // macro/internal +/*260*/ { "SPELLING.CHECK" }, // macro/internal + { "ERROR.TYPE", 1 }, + { "APP.TITLE" }, // macro/internal + { "WINDOW.TITLE" }, // macro/internal + { "SAVE.TOOLBAR" }, // macro/internal +/*265*/ { "ENABLE.TOOL" }, // macro/internal + { "PRESS.TOOL" }, // macro/internal + { "REGISTER.ID" }, // macro/internal + { "GET.WORKBOOK" }, // macro/internal + { "AVEDEV", 0 }, +/*270*/ { "BETADIST", 0 }, + { "GAMMALN", 1 }, + { "BETAINV", 0 }, + { "BINOMDIST", 4 }, + { "CHIDIST", 2 }, +/*275*/ { "CHIINV", 2 }, + { "COMBIN", 2 }, + { "CONFIDENCE", 3 }, + { "CRITBINOM", 3 }, + { "EVEN", 1 }, +/*280*/ { "EXPONDIST", 3 }, + { "FDIST", 3 }, + { "FINV", 3 }, + { "FISHER", 1 }, + { "FISHERINV", 1 }, +/*285*/ { "FLOOR", 2 }, + { "GAMMADIST", 4 }, + { "GAMMAINV", 3 }, + { "CEILING", 2 }, + { "HYPGEOMDIST", 4 }, +/*290*/ { "LOGNORMDIST", 3 }, + { "LOGINV", 3 }, + { "NEGBINOMDIST", 3 }, + { "NORMDIST", 4 }, + { "NORMSDIST", 1 }, +/*295*/ { "NORMINV", 3 }, + { "NORMSINV", 1 }, + { "STANDARDIZE", 3 }, + { "ODD", 1 }, + { "PERMUT", 2 }, +/*300*/ { "POISSON", 3 }, + { "TDIST", 3 }, + { "WEIBULL", 4 }, + { "SUMXMY2", 2 }, + { "SUMX2MY2", 2 }, +/*305*/ { "SUMX2PY2", 2 }, + { "CHITEST", 2 }, + { "CORREL", 2 }, + { "COVAR", 2 }, + { "FORECAST", 3 }, +/*310*/ { "FTEST", 2 }, + { "INTERCEPT", 2 }, + { "PEARSON", 2 }, + { "RSQ", 2 }, + { "STEYX", 2 }, +/*315*/ { "SLOPE", 2 }, + { "TTEST", 4 }, + { "PROB", 0 }, + { "DEVSQ", 0 }, + { "GEOMEAN", 0 }, +/*320*/ { "HARMEAN", 0 }, + { "SUMSQ", 0 }, + { "KURT", 0 }, + { "SKEW", 0 }, + { "ZTEST", 0 }, +/*325*/ { "LARGE", 2 }, + { "SMALL", 2 }, + { "QUARTILE", 2 }, + { "PERCENTILE", 2 }, + { "PERCENTRANK", 0 }, +/*330*/ { "MODE", 0 }, + { "TRIMMEAN", 2 }, + { "TINV", 2 }, + { "333" }, // not used + { "MOVIE.COMMAND" }, // macro/internal +/*335*/ { "GET.MOVIE" }, // macro/internal + { "CONCATENATE", 0 }, + { "POWER", 2 }, + { "PIVOT.ADD.DATA" }, // macro/internal + { "GET.PIVOT.TABLE" }, // macro/internal +/*340*/ { "GET.PIVOT.FIELD" }, // macro/internal + { "GET.PIVOT.ITEM" }, // macro/internal + { "RADIANS", 1 }, + { "DEGREES", 1 }, + { "SUBTOTAL", 0 }, +/*345*/ { "SUMIF", 0 }, + { "COUNTIF", 2 }, + { "COUNTBLANK", 1 }, + { "SCENARIO.GET" }, // macro/internal + { "OPTIONS.LISTS.GET" }, // macro/internal +/*350*/ { "ISPMT", 4 }, + { "DATEDIF", 3 }, + { "DATESTRING", 1 }, + { "NUMBERSTRING", 2 }, + { "ROMAN", 0 }, +/*355*/ { "OPEN.DIALOG" }, // macro/internal + { "SAVE.DIALOG" }, // macro/internal + { "VIEW.GET" }, // macro/internal + { "GETPIVOTDATA", 0 }, + { "HYPERLINK", 2 }, +/*360*/ { "PHONETIC", 1 }, + { "AVERAGEA", 0 }, + { "MAXA", 0 }, + { "MINA", 0 }, + { "STDEVPA", 0 }, +/*365*/ { "VARPA", 0 }, + { "STDEVA", 0 }, + { "VARA", 0 }, + { "BAHTTEXT", 1 }, + { "THAIDAYOFWEEK", 1 }, +/*370*/ { "THAIDIGIT", 1 }, + { "THAIMONTHOFYEAR", 1 }, + { "THAINUMSOUND", 1 }, + { "THAINUMSTRING", 1 }, + { "THAISTRINGLENGTH", 1 }, +/*375*/ { "ISTHAIDIGIT", 1 }, + { "ROUNDBAHTDOWN", 1 }, + { "ROUNDBAHTUP", 1 }, + { "THAIYEAR", 1 }, + { "RTD" }, +/*380*/ { "ISHYPERLINK", 1 } +}; + +const XclDumpFunc* lcl_GetFuncData( sal_uInt16 nIndex ) +{ + return (nIndex < STATIC_TABLE_SIZE( pFuncData )) ? (pFuncData + nIndex) : NULL; +} + +// ---------------------------------------------------------------------------- + +/** Stack helper to create a human readable formula string from UPN. */ +class XclDumpFormulaStackImpl : private ScfDelStack< ByteString > +{ +public: + void PushOperand( const ByteString& rOperand ); + void PushUnary( const ByteString& rOperator, bool bInFront ); + void PushBinary( const ByteString& rOperator ); + void PushFunction( const ByteString& rFuncName, sal_uInt16 nParamCount ); + inline ByteString GetString() const { return Top() ? *Top() : ByteString(); } +}; + +void XclDumpFormulaStackImpl::PushOperand( const ByteString& rOperand ) +{ + Push( new ByteString( rOperand ) ); +} + +void XclDumpFormulaStackImpl::PushUnary( const ByteString& rOperator, bool bInFront ) +{ + if( !Count() ) return; + ByteString* pOp = Top(); + pOp->Insert( rOperator, bInFront ? 0 : pOp->Len() ); +} + +void XclDumpFormulaStackImpl::PushBinary( const ByteString& rOperator ) +{ + if( Count() < 2 ) return; + // second operand is on top + ByteString* pSecond = Pop(); + ByteString* pFirst = Top(); + *pFirst += rOperator; + *pFirst += *pSecond; + delete pSecond; +} + +void XclDumpFormulaStackImpl::PushFunction( const ByteString& rFuncName, sal_uInt16 nParamCount ) +{ + if( Count() < nParamCount ) return; + ByteString* pNew = new ByteString( ')' ); + for( sal_uInt16 nIndex = 0; nIndex < nParamCount; ++nIndex ) + { + if( nIndex ) pNew->Insert( ';', 0 ); + ByteString* pOp = Pop(); + pNew->Insert( *pOp, 0 ); + delete pOp; + } + pNew->Insert( '(', 0 ); + pNew->Insert( rFuncName, 0 ); + Push( pNew ); +} + +// ---------------------------------------------------------------------------- + +/** Stack to create a human readable formula and token class overview from UPN. */ +class XclDumpFormulaStack +{ +public: + void PushOperand( const ByteString& rOperand, sal_uInt8 nToken ); + inline void PushOperand( const sal_Char* pcOperand, sal_uInt8 nToken ) + { PushOperand( ByteString( pcOperand ), nToken ); } + + void PushUnary( const ByteString& rOperator, bool bInFront = true ); + inline void PushUnary( const sal_Char* pcOperator, bool bInFront = true ) + { PushUnary( ByteString( pcOperator ), bInFront ); } + + void PushBinary( const ByteString& rOperator ); + inline void PushBinary( const sal_Char* pcOperator ) + { PushBinary( ByteString( pcOperator ) ); } + + void PushFunction( const ByteString& rFuncName, sal_uInt16 nParamCount, sal_uInt8 nToken ); + inline void PushFunction( const sal_Char* pcFuncName, sal_uInt16 nParamCount, sal_uInt8 nToken ) + { PushFunction( ByteString( pcFuncName ), nParamCount, nToken ); } + + inline ByteString GetFormula() const { return maFmla.GetString(); } + inline ByteString GetTokenClasses() const { return maClass.GetString(); } + + static ByteString GetTokenClass( sal_uInt8 nToken ); + +private: + void PushTokenClass( sal_uInt8 nToken ); + + XclDumpFormulaStackImpl maFmla; + XclDumpFormulaStackImpl maClass; +}; + +void XclDumpFormulaStack::PushOperand( const ByteString& rOperand, sal_uInt8 nToken ) +{ + maFmla.PushOperand( rOperand ); + maClass.PushOperand( GetTokenClass( nToken ) ); +} + +void XclDumpFormulaStack::PushUnary( const ByteString& rOperator, bool bInFront ) +{ + maFmla.PushUnary( rOperator, bInFront ); + maClass.PushUnary( rOperator, bInFront ); +} + +void XclDumpFormulaStack::PushBinary( const ByteString& rOperator ) +{ + maFmla.PushBinary( rOperator ); + maClass.PushBinary( rOperator ); +} + +void XclDumpFormulaStack::PushFunction( const ByteString& rFuncName, sal_uInt16 nParamCount, sal_uInt8 nToken ) +{ + maFmla.PushFunction( rFuncName, nParamCount ); + maClass.PushFunction( GetTokenClass( nToken ), nParamCount ); +} + +ByteString XclDumpFormulaStack::GetTokenClass( sal_uInt8 nToken ) +{ + sal_Char cClass = 'B'; + switch( nToken & 0xE0 ) + { + case 0x20: cClass = 'R'; break; + case 0x40: cClass = 'V'; break; + case 0x60: cClass = 'A'; break; + } + return ByteString( cClass ); +} + +// ---------------------------------------------------------------------------- + +const sal_Char* lcl_GetErrorString( sal_uInt8 nErr ) +{ + switch( nErr ) + { + case 0x00: return "#NULL!"; + case 0x07: return "#DIV/0!"; + case 0x0F: return "#VALUE!"; + case 0x17: return "#REF!"; + case 0x1D: return "#NAME?"; + case 0x24: return "#NUM!"; + case 0x2A: return "#N/A!"; + } + return "!unknown!"; +} + + + +void lcl_StartToken( ByteString& rString, sal_uInt16 nPos, sal_uInt8 nToken, const sal_Char* pTokenName ) +{ + rString.Erase(); + rString.Append( " " ); + __AddHex( rString, nPos ); + rString.Append( " " ); + __AddHex( rString, nToken ); + rString.Append( " t" ).Append( pTokenName ).Expand( 33, ' ' ); +} + +void lcl_StartTokenClass( ByteString& rString, sal_uInt16 nPos, sal_uInt8 nToken, const sal_Char* pTokenName ) +{ + ByteString aToken( pTokenName ); + aToken.Append( XclDumpFormulaStack::GetTokenClass( nToken ) ); + lcl_StartToken( rString, nPos, nToken, aToken.GetBuffer() ); +} + +void Biff8RecDumper::FormulaDump( const UINT16 nL, const FORMULA_TYPE eFT ) +{ + if( !nL ) + return; + + sal_uInt32 nStartPos = pIn->GetRecPos(); + const sal_uInt32 nAfterPos = nStartPos + nL; + + BYTE nOp; + ByteString t, aOperand; + BOOL bError = FALSE; + const BOOL bRangeName = eFT == FT_RangeName; + const BOOL bSharedFormula = eFT == FT_SharedFormula; + const BOOL bRNorSF = bRangeName || bSharedFormula; + + XclDumpFormulaStack aStack; + sal_Bool bPrinted = sal_True; + +#define PRINTTOKEN() { if( !bPrinted ) Print( t ); bPrinted = sal_True; } +#define STARTTOKEN( name ) lcl_StartToken( t, static_cast< sal_uInt16 >( pIn->GetRecPos() - nStartPos - 1 ), nOp, name ) +#define STARTTOKENCLASS( name ) lcl_StartTokenClass( t, static_cast< sal_uInt16 >( pIn->GetRecPos() - nStartPos - 1 ), nOp, name ) + + while( pIn->IsValid() && ( pIn->GetRecPos() < nAfterPos ) && !bError ) + { + *pIn >> nOp; + bPrinted = sal_False; + aOperand.Erase(); + + switch( nOp ) // Buch Seite: + { // SDK4 SDK5 + case 0x01: // Array Formula [325 ] + { + STARTTOKEN( "Exp" ); + sal_uInt16 nRow, nCol; + *pIn >> nRow >> nCol; + t += "array formula or shared formula, base-address="; + lcl_AddRef( t, nCol, nRow ); + aStack.PushFunction( "ARRAY", 0, nOp ); + } + break; + case 0x02: // Data Table [325 277] + { + STARTTOKEN( "Tbl" ); + sal_uInt16 nRow, nCol; + *pIn >> nRow >> nCol; + t += "multiple operation, base-address="; + lcl_AddRef( t, nCol, nRow ); + aStack.PushFunction( "MULTIPLE.OPERATIONS", 0, nOp ); + } + break; + case 0x03: // Addition [312 264] + STARTTOKEN( "Add" ); + aStack.PushBinary( "+" ); + break; + case 0x04: // Subtraction [313 264] + STARTTOKEN( "Sub" ); + aStack.PushBinary( "-" ); + break; + case 0x05: // Multiplication [313 264] + STARTTOKEN( "Mul" ); + aStack.PushBinary( "*" ); + break; + case 0x06: // Division [313 264] + STARTTOKEN( "Div" ); + aStack.PushBinary( "/" ); + break; + case 0x07: // Exponetiation [313 265] + STARTTOKEN( "Power" ); + aStack.PushBinary( "^" ); + break; + case 0x08: // Concatenation [313 265] + STARTTOKEN( "Concat" ); + aStack.PushBinary( "&" ); + break; + case 0x09: // Less Than [313 265] + STARTTOKEN( "LT" ); + aStack.PushBinary( "<" ); + break; + case 0x0A: // Less Than or Equal [313 265] + STARTTOKEN( "LE" ); + aStack.PushBinary( "<=" ); + break; + case 0x0B: // Equal [313 265] + STARTTOKEN( "EQ" ); + aStack.PushBinary( "=" ); + break; + case 0x0C: // Greater Than or Equal [313 265] + STARTTOKEN( "GE" ); + aStack.PushBinary( ">=" ); + break; + case 0x0D: // Greater Than [313 265] + STARTTOKEN( "GT" ); + aStack.PushBinary( ">" ); + break; + case 0x0E: // Not Equal [313 265] + STARTTOKEN( "NE" ); + aStack.PushBinary( "<>" ); + break; + case 0x0F: // Intersection [314 265] + STARTTOKEN( "Isect" ); + aStack.PushBinary( " " ); + break; + case 0x10: // List [314 265] + STARTTOKEN( "List" ); + aStack.PushBinary( ";" ); + break; + case 0x11: // Range [314 265] + STARTTOKEN( "Range" ); + aStack.PushBinary( ":" ); + break; + case 0x12: // Unary Plus [312 264] + STARTTOKEN( "Uplus" ); + aStack.PushUnary( "+" ); + break; + case 0x13: // Unary Minus [312 264] + STARTTOKEN( "Uminus" ); + aStack.PushUnary( "-" ); + break; + case 0x14: // Percent Sign [312 264] + STARTTOKEN( "Percent" ); + aStack.PushUnary( "%", false ); + break; + case 0x15: // Parenthesis [326 278] + STARTTOKEN( "Paren" ); + // simulate two unary operators to enclose operand + aStack.PushUnary( "(" ); + aStack.PushUnary( ")", false ); + break; + case 0x16: // Missing Argument [314 266] + STARTTOKEN( "MissArg" ); + aStack.PushOperand( "~", nOp ); + break; + case 0x17: // ByteString Constant [314 266] + { + STARTTOKEN( "Str" ); + + UINT8 nLen; + *pIn >> nLen; + + t += "string [len="; + __AddDec( t, nLen ); + t += "] "; + + aOperand += '"'; + if( nLen ) + aOperand += GETSTR( pIn->ReadUniString( nLen ) ); + else + pIn->Ignore( 1 ); + aOperand += '"'; + t += aOperand; + aStack.PushOperand( aOperand, nOp ); + } + break; + case 0x18: + { + STARTTOKEN( "Extended" ); + UINT8 nEptg; + *pIn >> nEptg; + +#define D(name,size,ext,type) {t+="eptg ";__AddDec(t,(UINT16)nEptg);t+=": "; \ + t+=name;t+=" [";__AddDec(t,(UINT16)size);t+="] ";t+=type; \ + if(ext)t+=" + ext";PRINTTOKEN();ContDump(size);aStack.PushOperand(name,nOp);} + switch( nEptg ) + { // name size ext type + case 0x00: // res + D( "res", 0, 0, "" ); + break; + case 0x01: // Lel 4 - err + D( "Lel", 4, 0, "err" ); + break; + case 0x02: // Rw 4 - ref + D( "Rw", 4, 0, "ref" ); + break; + case 0x03: // Col 4 - ref + D( "Col", 4, 0, "ref" ); + break; + case 0x04: // res + case 0x05: // res + D( "res", 0, 0, "" ); + break; + case 0x06: // RwV 4 - val + D( "RwV", 4, 0, "val" ); + break; + case 0x07: // ColV 4 - val + D( "ColV", 4, 0, "val" ); + break; + case 0x08: // res + case 0x09: // res + D( "res", 0, 0, "" ); + break; + case 0x0A: // Radical 13 - ref + D( "Radical", 13, 0, "ref" ); + break; + case 0x0B: // RadicalS 13 x ref + D( "RadicalS", 13, 1, "ref" ); + break; + case 0x0C: // RwS 4 x ref + D( "RwS", 4, 1, "ref" ); + break; + case 0x0D: // ColS 4 x ref + D( "ColS", 4, 1, "ref" ); + break; + case 0x0E: // RwSV 4 x val + D( "RwSV", 4, 1, "val" ); + break; + case 0x0F: // ColSV 4 x val + D( "ColSV", 4, 1, "val" ); + break; + case 0x10: // RadicalLel 4 - err + D( "RadicalLel", 4, 0, "err" ); + break; + case 0x11: // res + case 0x12: // res + case 0x13: // res + case 0x14: // res + case 0x15: // res + case 0x16: // res + case 0x17: // res + case 0x18: // res + D( "res", 0, 0, "" ); + break; + case 0x19: // invalid values + case 0x1A: // invalid values + D( "invalid vals", 0, 0, "" ); + break; + case 0x1B: // res + case 0x1C: // res + D( "res", 0, 0, "" ); + break; + case 0x1D: // SxName 4 - val + D( "SxName", 4, 0, "val" ); + break; + case 0x1E: // res + D( "res", 0, 0, "" ); + break; + default: + D( "!unknown!", 0, 0, "" ); + } +#undef D + } + break; + case 0x19: // Special Attribute [327 279] + { + STARTTOKEN( "Attr" ); + UINT16 nData, nFakt; + BYTE nOpt; + + *pIn >> nOpt >> nData; + nFakt = 2; + + t += "flags="; __AddHex( t, nOpt ); + + if( nOpt & 0x01 ) t += " volatile"; + if( nOpt & 0x02 ) t += " if"; + if( nOpt & 0x04 ) t += " choose"; + if( nOpt & 0x08 ) t += " skip"; + if( nOpt & 0x10 ) t += " sum"; + if( nOpt & 0x20 ) t += " assignment"; + if( nOpt & 0x40 ) t += " space"; + if( nOpt & 0x80 ) t += " unknown"; + + if( nOpt & 0x02 ) + { + t += " skip-to-false="; + __AddHex( t, nData ); + } + if( nOpt & 0x04 ) + { + t += " count="; + __AddDec( t, nData ); + t += " skip="; + for( sal_uInt16 nIdx = 0; nIdx <= nData; ++nIdx ) + { + if( nIdx ) t += ','; + __AddDec( t, pIn->ReaduInt16() ); + } + } + if( nOpt & 0x08 ) + { + t += " skip="; + __AddHex( t, nData ); + t += " ("; + __AddDec( t, sal_uInt8( nData + 1 ) ); + t += " bytes)"; + } + if( nOpt & 0x10 ) + aStack.PushFunction( "ATTRSUM", 1, nOp ); + if( nOpt & 0x40 ) + { + t += " type="; + __AddDec( t, static_cast< sal_uInt8 >( nData ) ); + t += " count="; + __AddDec( t, static_cast< sal_uInt8 >( nData >> 8 ) ); + } + } + break; + case 0x1C: // Error Value [314 266] + { + STARTTOKEN( "Err" ); + sal_uInt8 nErr = pIn->ReaduInt8(); + t += "error value ("; __AddHex( t, nErr ); + t += ") "; + t += lcl_GetErrorString( nErr ); + aStack.PushOperand( lcl_GetErrorString( nErr ), nOp ); + } + break; + case 0x1D: // Boolean [315 266] + STARTTOKEN( "Bool" ); + aOperand += pIn->ReaduInt8() ? "TRUE" : "FALSE"; + t += aOperand; + aStack.PushOperand( aOperand, nOp ); + break; + case 0x1E: // Integer [315 266] + STARTTOKEN( "Int" ); + __AddDec( aOperand, pIn->ReaduInt16() ); + t += aOperand; + aStack.PushOperand( aOperand, nOp ); + break; + case 0x1F: // Number [315 266] + STARTTOKEN( "Num" ); + __AddDouble( aOperand, pIn->ReadDouble() ); + t += aOperand; + aStack.PushOperand( aOperand, nOp ); + break; + case 0x20: // Array Constant [317 268] + case 0x40: + case 0x60: + STARTTOKENCLASS( "Array" ); + pIn->Ignore( 7 ); + aStack.PushOperand( "{ConstArray}", nOp ); + break; + case 0x21: // Function, Fixed Number of Arguments [333 282] + case 0x41: + case 0x61: + { + STARTTOKENCLASS( "Func" ); + UINT16 nInd = pIn->ReaduInt16(); + const XclDumpFunc* pFunc = lcl_GetFuncData( nInd ); + aOperand += pFunc ? pFunc->pName : "!unknown!"; + + t += "fix function: index="; __AddHex( t, nInd ); + t += " ("; t += aOperand; + t += ')'; + aStack.PushFunction( aOperand, pFunc ? pFunc->nParam : 0, nOp ); + } + break; + case 0x22: // Function, Variable Number of Arg. [333 283] + case 0x42: + case 0x62: + { + STARTTOKENCLASS( "FuncVar" ); + BYTE nAnz; + UINT16 nInd; + *pIn >> nAnz >> nInd; + const XclDumpFunc* pFunc = lcl_GetFuncData( nInd & 0x7FFF ); + aOperand += pFunc ? pFunc->pName : "!unknown!"; + + t += "var function: index="; __AddHex( t, nInd ); + t += " ("; t += aOperand; + t += ") param count="; __AddHex( t, nAnz ); + t += " ("; __AddDec( t, (UINT8)(nAnz & 0x7F) ); + t += ')'; + if( nAnz & 0x8000 ) + t += " cmd-equiv."; + aStack.PushFunction( aOperand, nAnz & 0x7F, nOp ); + } + break; + case 0x23: // Name [318 269] + case 0x43: + case 0x63: + { + STARTTOKENCLASS( "Name" ); + sal_uInt16 nNameIdx = pIn->ReaduInt16(); + __AddDec( aOperand, nNameIdx ); + t += "internal name: index="; + t += aOperand; + pIn->Ignore( 2 ); + if( (0 < nNameIdx) && (nNameIdx <= maNames.size()) ) + aOperand = maNames[ nNameIdx - 1 ]; + else + aOperand.Insert( "NAME(", 0 ).Append( ')' ); + aStack.PushOperand( aOperand, nOp ); + } + break; + case 0x24: // Cell Reference [319 270] + case 0x44: + case 0x64: + case 0x2A: // Deleted Cell Reference [323 273] + case 0x4A: + case 0x6A: + { + if( (nOp & 0x1F) == 0x04 ) + STARTTOKENCLASS( "Ref" ); + else + STARTTOKENCLASS( "RefErr" ); + + UINT16 nCol, nRow; + *pIn >> nRow >> nCol; + AddRef( aOperand, nRow, nCol, bRangeName ); + t += "2D cell ref C/R="; __AddHex( t, nCol ); + t += '/'; __AddHex( t, nRow ); + t += ' '; t += aOperand; + aStack.PushOperand( aOperand, nOp ); + } + break; + case 0x25: // Area Reference [320 270] + case 0x45: + case 0x65: + case 0x2B: // Deleted Area Refernce [323 273] + case 0x4B: + case 0x6B: + { + if( (nOp & 0x1F) == 0x05 ) + STARTTOKENCLASS( "Area" ); + else + STARTTOKENCLASS( "AreaErr" ); + + UINT16 nRowFirst, nRowLast, nColFirst, nColLast; + *pIn >> nRowFirst >> nRowLast >> nColFirst >> nColLast; + AddRangeRef( aOperand, nRowFirst, nColFirst, nRowLast, nColLast, bRangeName ); + t += "2D area ref C/R:C/R="; __AddHex( t, nColFirst ); + t += '/'; __AddHex( t, nRowFirst ); + t += ':'; __AddHex( t, nColLast ); + t += '/'; __AddHex( t, nRowLast ); + t += ' '; t += aOperand; + aStack.PushOperand( aOperand, nOp ); + } + break; + case 0x26: // Constant Reference Subexpression [321 271] + case 0x46: + case 0x66: + { + STARTTOKENCLASS( "MemArea" ); + sal_uInt32 nRes; + sal_uInt16 nSize; + *pIn >> nRes >> nSize; + t += "reserved="; __AddHex( t, nRes ); + t += " size="; __AddDec( t, nSize ); + } + break; + case 0x27: // Erroneous Constant Reference Subexpr. [322 272] + case 0x47: + case 0x67: + { + STARTTOKENCLASS( "MemErr" ); + sal_uInt32 nRes; + sal_uInt16 nSize; + *pIn >> nRes >> nSize; + t += "reserved="; __AddHex( t, nRes ); + t += " size="; __AddDec( t, nSize ); + } + break; + case 0x28: // Incomplete Constant Reference Subexpr.[331 281] + case 0x48: + case 0x68: + { + STARTTOKENCLASS( "MemNoMem" ); + sal_uInt32 nRes; + sal_uInt16 nSize; + *pIn >> nRes >> nSize; + t += "reserved="; __AddHex( t, nRes ); + t += " size="; __AddDec( t, nSize ); + } + break; + case 0x29: // Variable Reference Subexpression [331 281] + case 0x49: + case 0x69: + { + STARTTOKENCLASS( "MemFunc" ); + sal_uInt16 nSize; + *pIn >> nSize; + t += "size="; __AddDec( t, nSize ); + } + break; + case 0x2C: // Cell Reference Within a Name/ShrdFmla [323 273] + case 0x4C: + case 0x6C: + { + STARTTOKENCLASS( "RefN" ); + UINT16 nRow, nCol; + *pIn >> nRow >> nCol; + AddRef( aOperand, nRow, nCol, bRNorSF ); + t += "2D cell ref in name C/R="; __AddHex( t, nCol ); + t += '/'; __AddHex( t, nRow ); + t += ' '; t += aOperand; + aStack.PushOperand( aOperand, nOp ); + } + break; + case 0x2D: // Area Reference Within a Name/ShrdFmla [324 274] + case 0x4D: + case 0x6D: + { + STARTTOKENCLASS( "AreaN" ); + UINT16 nRowFirst, nRowLast, nColFirst, nColLast; + *pIn >> nRowFirst >> nRowLast >> nColFirst >> nColLast; + AddRangeRef( aOperand, nRowFirst, nColFirst, nRowLast, nColLast, bRNorSF ); + t += "2D area ref in name C/R:C/R"; __AddHex( t, nColFirst ); + t += '/'; __AddHex( t, nRowFirst ); + t += ':'; __AddHex( t, nColLast ); + t += '/'; __AddHex( t, nRowLast ); + t += ' '; t += aOperand; + aStack.PushOperand( aOperand, nOp ); + } + break; + case 0x2E: // Reference Subexpression Within a Name [332 282] + case 0x4E: + case 0x6E: + { + STARTTOKENCLASS( "MemAreaN" ); + sal_uInt16 nSize; + *pIn >> nSize; + t += "size="; __AddDec( t, nSize ); + } + break; + case 0x2F: // Incomplete Reference Subexpression... [332 282] + case 0x4F: + case 0x6F: + { + STARTTOKENCLASS( "MemNoMemN" ); + sal_uInt16 nSize; + *pIn >> nSize; + t += "size="; __AddDec( t, nSize ); + } + break; + case 0x39: // Name or External Name [ 275] + case 0x59: + case 0x79: + { + STARTTOKENCLASS( "NameX" ); + UINT16 nXti, nName; + *pIn >> nXti >> nName; + pIn->Ignore( 2 ); + t += "external name: XTI="; __AddDec( t, nXti ); + t += " name index="; __AddDec( t, nName ); + aOperand += "EXTNAME(XTI("; + __AddDec( aOperand, nXti ); + aOperand += "),"; + __AddDec( aOperand, nName ); + aOperand += ')'; + aStack.PushOperand( aOperand, nOp ); + } + break; + case 0x3A: // 3-D Cell Reference [ 275] + case 0x5A: + case 0x7A: + case 0x3C: // Deleted 3-D Cell Reference [ 277] + case 0x5C: + case 0x7C: + { + if( (nOp & 0x1F) == 0x1A ) + STARTTOKENCLASS( "Ref3d" ); + else + STARTTOKENCLASS( "Ref3dErr" ); + + UINT16 nXti, nRow, nCol; + *pIn >> nXti >> nRow >> nCol; + AddRef( aOperand, nRow, nCol, bRangeName, nXti ); + t += "3D cell ref Xti!C/R="; __AddHex( t, nXti ); + t += '!'; __AddHex( t, nCol ); + t += '/'; __AddHex( t, nRow ); + t += ' '; t += aOperand; + aStack.PushOperand( aOperand, nOp ); + } + break; + case 0x3B: // 3-D Area Reference [ 276] + case 0x5B: + case 0x7B: + case 0x3D: // Deleted 3-D Area Reference [ 277] + case 0x5D: + case 0x7D: + { + if( (nOp & 0x1F) == 0x1B ) + STARTTOKENCLASS( "Area3d" ); + else + STARTTOKENCLASS( "Area3dErr" ); + + UINT16 nXti, nRow1, nCol1, nRow2, nCol2; + *pIn >> nXti >> nRow1 >> nRow2 >> nCol1 >> nCol2; + AddRangeRef( aOperand, nRow1, nCol1, nRow2, nCol2, bRangeName, nXti ); + t += "3D area ref Xti!C/R:C/R="; __AddHex( t, nXti ); + t += '!'; __AddHex( t, nCol1 ); + t += '/'; __AddHex( t, nRow1 ); + t += ':'; __AddHex( t, nCol2 ); + t += '/'; __AddHex( t, nRow2 ); + t += ' '; t += aOperand; + aStack.PushOperand( aOperand, nOp ); + } + break; + default: + STARTTOKEN( "unknown" ); + bError = TRUE; + } + PRINTTOKEN(); + } + t.Assign( " Formula = " ); + if( aStack.GetFormula().Len() ) t += aStack.GetFormula(); else t += "ERROR IN STACK"; + Print( t ); + t.Assign( " Tokencl = " ).Append( aStack.GetTokenClasses() ); + Print( t ); + pIn->Seek( nAfterPos ); +} + + +// ============================================================================ +// +// S T R E A M C O N T E N T S +// +// ============================================================================ + +void Biff8RecDumper::DumpBinary( SvStream& rInStrm, ULONG nSize ) +{ + ULONG nStrmPos = rInStrm.Tell(); + rInStrm.Seek( STREAM_SEEK_TO_END ); + ULONG nStrmLen = rInStrm.Tell(); + rInStrm.Seek( nStrmPos ); + ULONG nDumpEnd = (nSize == STREAM_SEEK_TO_END) ? nStrmLen : ::std::min( nStrmPos + nSize, nStrmLen ); + + const ULONG LINE_SIZE = 16; + sal_uInt8 pnData[ LINE_SIZE ]; + + while( rInStrm.Tell() < nDumpEnd ) + { + ByteString aBinLine; + ByteString aTextLine; + + ULONG nLineLen = ::std::min( nDumpEnd - rInStrm.Tell(), LINE_SIZE ); + rInStrm.Read( pnData, nLineLen ); + + for( sal_uInt8 *pnByte = pnData, *pnEnd = pnData + nLineLen; pnByte != pnEnd; ++pnByte ) + { + if( pnByte - pnData == LINE_SIZE / 2 ) + { + aBinLine.Append( ' ' ); + aTextLine.Append( ' ' ); + } + __AddPureHex( aBinLine, *pnByte ); + aBinLine.Append( ' ' ); + aTextLine.Append( static_cast< sal_Char >( IsPrintable( *pnByte ) ? *pnByte : '.' ) ); + } + + aBinLine.Expand( LINE_SIZE * 3 + 3, ' ' ); + (*pDumpStream) << aBinLine.GetBuffer() << aTextLine.GetBuffer() << "\n"; + } +} + +// ============================================================================ +// +// F O R M C O N T R O L S +// +// ============================================================================ + +namespace { + +// little helpers ------------------------------------------------------------- + +/** Import from bytestream. */ +SvStream& operator>>( SvStream& rStrm, XclGuid& rGuid ) +{ + rStrm.Read( rGuid.mpnData, 16 ); + return rStrm; +} + +/** Output guid into text stream. */ +SvStream& operator<<( SvStream& rStrm, const XclGuid& rGuid ) +{ + ByteString aOut; + lclAppendGuid( aOut, rGuid ); + return rStrm << aOut.GetBuffer(); +} + +void lclAlignStream( SvStream& rInStrm, ULONG nStartPos, ULONG nDataWidth ) +{ + rInStrm.SeekRel( nDataWidth - 1 - (rInStrm.Tell() - nStartPos + nDataWidth - 1) % nDataWidth ); +} + +// control types -------------------------------------------------------------- + +const sal_uInt16 EXC_CTRL_PAGE = 0x0007; +const sal_uInt16 EXC_CTRL_IMAGE = 0x000C; +const sal_uInt16 EXC_CTRL_FRAME = 0x000E; +const sal_uInt16 EXC_CTRL_SPINBUTTON = 0x0010; +const sal_uInt16 EXC_CTRL_PUSHBUTTON = 0x0011; +const sal_uInt16 EXC_CTRL_TABSTRIP = 0x0012; +const sal_uInt16 EXC_CTRL_LABEL = 0x0015; +const sal_uInt16 EXC_CTRL_TEXTBOX = 0x0017; +const sal_uInt16 EXC_CTRL_LISTBOX = 0x0018; +const sal_uInt16 EXC_CTRL_COMBOBOX = 0x0019; +const sal_uInt16 EXC_CTRL_CHECKBOX = 0x001A; +const sal_uInt16 EXC_CTRL_OPTIONBUTTON = 0x001B; +const sal_uInt16 EXC_CTRL_TOGGLEBUTTON = 0x001C; +const sal_uInt16 EXC_CTRL_SCROLLBAR = 0x002F; +const sal_uInt16 EXC_CTRL_MULTIPAGE = 0x0039; +const sal_uInt16 EXC_CTRL_REFEDIT = 0x8000; +const sal_uInt16 EXC_CTRL_FONTDATA = 0xFFF0; // internal use only +const sal_uInt16 EXC_CTRL_USERFORM = 0xFFF1; // internal use only +const sal_uInt16 EXC_CTRL_ADDDATA = 0xFFF2; // internal use only +const sal_uInt16 EXC_CTRL_FRAMECHILD = 0xFFF3; // internal use only +const sal_uInt16 EXC_CTRL_PROGRESSBAR = 0xFFF4; // internal use only +const sal_uInt16 EXC_CTRL_UNKNOWN = 0xFFFF; // internal use only + +const sal_uInt16 EXC_CTRL_RECORD_ID = 0x0000; +const sal_uInt16 EXC_CTRL_CLIENT_ID = 0x0200; +const sal_uInt16 EXC_CTRL_CONTAINER_ID = 0x0400; + +// control names -------------------------------------------------------------- + +struct XclDumpControlInfo +{ + sal_uInt16 mnType; + const sal_Char* mpcName; + sal_uInt16 mnId; +}; + +static const XclDumpControlInfo spControlInfos[] = +{ + { EXC_CTRL_PAGE, "Page", EXC_CTRL_CONTAINER_ID }, + { EXC_CTRL_IMAGE, "Image", EXC_CTRL_CLIENT_ID }, + { EXC_CTRL_FRAME, "Frame", EXC_CTRL_CLIENT_ID }, + { EXC_CTRL_SPINBUTTON, "Spin", EXC_CTRL_CLIENT_ID }, + { EXC_CTRL_PUSHBUTTON, "PushButton", EXC_CTRL_CLIENT_ID }, + { EXC_CTRL_TABSTRIP, "TabStrip", EXC_CTRL_CLIENT_ID }, + { EXC_CTRL_LABEL, "Label", EXC_CTRL_CLIENT_ID }, + { EXC_CTRL_TEXTBOX, "TextBox", EXC_CTRL_CLIENT_ID }, + { EXC_CTRL_LISTBOX, "ListBox", EXC_CTRL_CLIENT_ID }, + { EXC_CTRL_COMBOBOX, "ComboBox", EXC_CTRL_CLIENT_ID }, + { EXC_CTRL_CHECKBOX, "CheckBox", EXC_CTRL_CLIENT_ID }, + { EXC_CTRL_OPTIONBUTTON, "OptionButton", EXC_CTRL_CLIENT_ID }, + { EXC_CTRL_TOGGLEBUTTON, "ToggleButton", EXC_CTRL_CLIENT_ID }, + { EXC_CTRL_SCROLLBAR, "ScrollBar", EXC_CTRL_CLIENT_ID }, + { EXC_CTRL_MULTIPAGE, "MultiPage", EXC_CTRL_CLIENT_ID }, + { EXC_CTRL_REFEDIT, "RefEdit", EXC_CTRL_CLIENT_ID }, + { EXC_CTRL_FONTDATA, "FontData", EXC_CTRL_CLIENT_ID }, + { EXC_CTRL_USERFORM, "UserForm", EXC_CTRL_CONTAINER_ID }, + { EXC_CTRL_ADDDATA, "AddData", EXC_CTRL_RECORD_ID }, + { EXC_CTRL_FRAMECHILD, "FrameChild", EXC_CTRL_RECORD_ID }, + { EXC_CTRL_PROGRESSBAR, "ProgressBar", EXC_CTRL_RECORD_ID } +}; + +typedef ::std::map< sal_uInt16, const XclDumpControlInfo* > XclDumpControlInfoMap; +typedef ScfRef< XclDumpControlInfoMap > XclDumpControlInfoMapRef; + +XclDumpControlInfoMapRef lclCreateControlInfoMap() +{ + XclDumpControlInfoMapRef xMap( new XclDumpControlInfoMap ); + for( const XclDumpControlInfo *pIt = spControlInfos, *pEnd = STATIC_TABLE_END( spControlInfos ); pIt != pEnd; ++pIt ) + (*xMap)[ pIt->mnType ] = pIt; + return xMap; +} + +const XclDumpControlInfoMap& lclGetControlInfoMap() +{ + static const XclDumpControlInfoMapRef sxMap = lclCreateControlInfoMap(); + return *sxMap; +} + +void lclAppendControlType( ByteString& rStr, sal_uInt16 nCtrlType ) +{ + const XclDumpControlInfoMap& rMap = lclGetControlInfoMap(); + XclDumpControlInfoMap::const_iterator aIt = rMap.find( nCtrlType ); + rStr.Append( (aIt == rMap.end()) ? "*UNKNOWN*" : aIt->second->mpcName ); +} + +void lclDumpControlType( SvStream& rOutStrm, sal_uInt16 nCtrlType ) +{ + ByteString aTitle( "type=" ); + lclAppendHex( aTitle, nCtrlType ); + aTitle.Append( " (" ); + lclAppendControlType( aTitle, nCtrlType ); + aTitle.Append( ')' ); + rOutStrm << aTitle.GetBuffer(); +} + +sal_uInt16 lclDumpControlHeader( SvStream& rInStrm, SvStream& rOutStrm, sal_uInt16 nCtrlType ) +{ + lclDumpControlType( rOutStrm, nCtrlType ); + sal_uInt16 nId, nSize; + rInStrm >> nId >> nSize; + ByteString aLine( " id=" ); lclAppendHex( aLine, nId ); + const XclDumpControlInfoMap& rMap = lclGetControlInfoMap(); + XclDumpControlInfoMap::const_iterator aIt = rMap.find( nCtrlType ); + bool bValid = (aIt != rMap.end()) && (aIt->second->mnId == nId); + aLine.Append( bValid ? " (valid)" : " (invalid)" ); + aLine.Append( " size=" ); lclAppendHex( aLine, nSize ); + rOutStrm << aLine.GetBuffer() << "\n"; + return nSize; +} + +// control GUIDs -------------------------------------------------------------- + +struct XclDumpControlGuid +{ + sal_uInt16 mnType; + sal_uInt32 mnGuidData1; + sal_uInt16 mnGuidData2; + sal_uInt16 mnGuidData3; + sal_uInt8 mnGuidData41; + sal_uInt8 mnGuidData42; + sal_uInt8 mnGuidData43; + sal_uInt8 mnGuidData44; + sal_uInt8 mnGuidData45; + sal_uInt8 mnGuidData46; + sal_uInt8 mnGuidData47; + sal_uInt8 mnGuidData48; +}; + +static const XclDumpControlGuid spControlGuids[] = +{ + { EXC_CTRL_PUSHBUTTON, 0xD7053240, 0xCE69, 0x11CD, 0xA7, 0x77, 0x00, 0xDD, 0x01, 0x14, 0x3C, 0x57 }, + { EXC_CTRL_TOGGLEBUTTON, 0x8BD21D60, 0xEC42, 0x11CE, 0x9E, 0x0D, 0x00, 0xAA, 0x00, 0x60, 0x02, 0xF3 }, + { EXC_CTRL_CHECKBOX, 0x8BD21D40, 0xEC42, 0x11CE, 0x9E, 0x0D, 0x00, 0xAA, 0x00, 0x60, 0x02, 0xF3 }, + { EXC_CTRL_OPTIONBUTTON, 0x8BD21D50, 0xEC42, 0x11CE, 0x9E, 0x0D, 0x00, 0xAA, 0x00, 0x60, 0x02, 0xF3 }, + { EXC_CTRL_LABEL, 0x978C9E23, 0xD4B0, 0x11CE, 0xBF, 0x2D, 0x00, 0xAA, 0x00, 0x3F, 0x40, 0xD0 }, + { EXC_CTRL_TEXTBOX, 0x8BD21D10, 0xEC42, 0x11CE, 0x9E, 0x0D, 0x00, 0xAA, 0x00, 0x60, 0x02, 0xF3 }, + { EXC_CTRL_LISTBOX, 0x8BD21D20, 0xEC42, 0x11CE, 0x9E, 0x0D, 0x00, 0xAA, 0x00, 0x60, 0x02, 0xF3 }, + { EXC_CTRL_COMBOBOX, 0x8BD21D30, 0xEC42, 0x11CE, 0x9E, 0x0D, 0x00, 0xAA, 0x00, 0x60, 0x02, 0xF3 }, + { EXC_CTRL_SPINBUTTON, 0x79176FB0, 0xB7F2, 0x11CE, 0x97, 0xEF, 0x00, 0xAA, 0x00, 0x6D, 0x27, 0x76 }, + { EXC_CTRL_SCROLLBAR, 0xDFD181E0, 0x5E2F, 0x11CE, 0xA4, 0x49, 0x00, 0xAA, 0x00, 0x4A, 0x80, 0x3D }, + { EXC_CTRL_IMAGE, 0x4C599241, 0x6926, 0x101B, 0x99, 0x92, 0x00, 0x00, 0x0B, 0x65, 0xC6, 0xF9 }, + { EXC_CTRL_PROGRESSBAR, 0x35053A22, 0x8589, 0x11D1, 0xB1, 0x6A, 0x00, 0xC0, 0xF0, 0x28, 0x36, 0x28 } +}; + +typedef ::std::map< XclGuid, sal_uInt16 > XclDumpControlGuidMap; +typedef ScfRef< XclDumpControlGuidMap > XclDumpControlGuidMapRef; + +XclDumpControlGuidMapRef lclCreateControlGuidMap() +{ + XclDumpControlGuidMapRef xMap( new XclDumpControlGuidMap ); + for( const XclDumpControlGuid *pIt = spControlGuids, *pEnd = STATIC_TABLE_END( spControlGuids ); pIt != pEnd; ++pIt ) + { + XclGuid aGuid( pIt->mnGuidData1, pIt->mnGuidData2, pIt->mnGuidData3, + pIt->mnGuidData41, pIt->mnGuidData42, pIt->mnGuidData43, pIt->mnGuidData44, + pIt->mnGuidData45, pIt->mnGuidData46, pIt->mnGuidData47, pIt->mnGuidData48 ); + (*xMap)[ aGuid ] = pIt->mnType; + } + return xMap; +} + +const XclDumpControlGuidMap& lclGetControlGuidMap() +{ + static const XclDumpControlGuidMapRef sxMap = lclCreateControlGuidMap(); + return *sxMap; +} + +sal_uInt16 lclDumpControlGuid( SvStream& rInStrm, SvStream& rOutStrm ) +{ + XclGuid aGuid; + rInStrm >> aGuid; + const XclDumpControlGuidMap& rMap = lclGetControlGuidMap(); + XclDumpControlGuidMap::const_iterator aIt = rMap.find( aGuid ); + sal_uInt16 nCtrlType = (aIt == rMap.end()) ? EXC_CTRL_UNKNOWN : aIt->second; + rOutStrm << "guid=" << aGuid; + return nCtrlType; +}; + +// other guids ---------------------------------------------------------------- + +static const XclGuid saStdFontGuid( 0x0BE35203, 0x8F91, 0x11CE, 0x9D, 0xE3, 0x00, 0xAA, 0x00, 0x4B, 0xB8, 0x51 ); +static const XclGuid saStdPicGuid( 0x0BE35204, 0x8F91, 0x11CE, 0x9D, 0xE3, 0x00, 0xAA, 0x00, 0x4B, 0xB8, 0x51 );\ + +// ---------------------------------------------------------------------------- + +} // namespace + +// *** yet some other ugly macros for the specials of form control dumping *** + +// align the instream +#define EXC_CTRLDUMP_ALIGN_INSTRM( val ) lclAlignStream( rInStrm, nStartPos, val ) +// push the string to outstream +#define EXC_CTRLDUMP_PRINT() { if( t.Len() ) { rOutStrm << t.GetBuffer() << '\n'; t.Erase(); } } + +// implementation, don't use +#define IMPL_EXC_CTRLDUMP_PLAIN_VALUE( type, func, text ) { type n; rInStrm >> n; t.Append( " " text "=" ); func( t, n ); EXC_CTRLDUMP_PRINT(); } +#define IMPL_EXC_CTRLDUMP_VALUE( type, func, text ) { EXC_CTRLDUMP_ALIGN_INSTRM( sizeof( type ) ); IMPL_EXC_CTRLDUMP_PLAIN_VALUE( type, func, text ); } +#define IMPL_EXC_CTRLDUMP_PLAIN_VAR( var, mask, func, text ) { rInStrm >> var; var &= (mask); t.Append( " " text "=" ); func( t, var ); EXC_CTRLDUMP_PRINT(); } +#define IMPL_EXC_CTRLDUMP_VAR( var, mask, func, text ) { EXC_CTRLDUMP_ALIGN_INSTRM( sizeof( var ) ); IMPL_EXC_CTRLDUMP_PLAIN_VAR( var, mask, func, text ); } + +// read a value from stream (no stream alignment) +#define EXC_CTRLDUMP_PLAIN_HEX4( text ) IMPL_EXC_CTRLDUMP_PLAIN_VALUE( sal_uInt32, lclAppendHex, text ) +#define EXC_CTRLDUMP_PLAIN_DEC4( text ) IMPL_EXC_CTRLDUMP_PLAIN_VALUE( sal_Int32, lclAppendDec, text ) +#define EXC_CTRLDUMP_PLAIN_HEX2( text ) IMPL_EXC_CTRLDUMP_PLAIN_VALUE( sal_uInt16, lclAppendHex, text ) +#define EXC_CTRLDUMP_PLAIN_DEC2( text ) IMPL_EXC_CTRLDUMP_PLAIN_VALUE( sal_Int16, lclAppendDec, text ) +#define EXC_CTRLDUMP_PLAIN_HEX1( text ) IMPL_EXC_CTRLDUMP_PLAIN_VALUE( sal_uInt8, lclAppendHex, text ) +#define EXC_CTRLDUMP_PLAIN_DEC1( text ) IMPL_EXC_CTRLDUMP_PLAIN_VALUE( sal_Int8, lclAppendDec, text ) +#define EXC_CTRLDUMP_PLAIN_DECF( text ) IMPL_EXC_CTRLDUMP_PLAIN_VALUE( float, lclAppendDec, text ) +// read a value from stream (with stream alignment) +#define EXC_CTRLDUMP_HEX4( text ) IMPL_EXC_CTRLDUMP_VALUE( sal_uInt32, lclAppendHex, text ) +#define EXC_CTRLDUMP_DEC4( text ) IMPL_EXC_CTRLDUMP_VALUE( sal_Int32, lclAppendDec, text ) +#define EXC_CTRLDUMP_HEX2( text ) IMPL_EXC_CTRLDUMP_VALUE( sal_uInt16, lclAppendHex, text ) +#define EXC_CTRLDUMP_DEC2( text ) IMPL_EXC_CTRLDUMP_VALUE( sal_Int16, lclAppendDec, text ) +#define EXC_CTRLDUMP_HEX1( text ) IMPL_EXC_CTRLDUMP_VALUE( sal_uInt8, lclAppendHex, text ) +#define EXC_CTRLDUMP_DEC1( text ) IMPL_EXC_CTRLDUMP_VALUE( sal_Int8, lclAppendDec, text ) +// read a value from stream into existing variable (no stream alignment) +#define EXC_CTRLDUMP_PLAIN_HEXVAR( var, text ) IMPL_EXC_CTRLDUMP_PLAIN_VAR( var, ~0, lclAppendHex, text ) +#define EXC_CTRLDUMP_PLAIN_DECVAR( var, text ) IMPL_EXC_CTRLDUMP_PLAIN_VAR( var, ~0, lclAppendDec, text ) +#define EXC_CTRLDUMP_PLAIN_HEXVARMASK( var, mask, text ) IMPL_EXC_CTRLDUMP_PLAIN_VAR( var, mask, lclAppendHex, text ) +#define EXC_CTRLDUMP_PLAIN_DECVARMASK( var, mask, text ) IMPL_EXC_CTRLDUMP_PLAIN_VAR( var, mask, lclAppendDec, text ) +// read a value from stream into existing variable (with stream alignment) +#define EXC_CTRLDUMP_HEXVAR( var, text ) IMPL_EXC_CTRLDUMP_VAR( var, ~0, lclAppendHex, text ) +#define EXC_CTRLDUMP_DECVAR( var, text ) IMPL_EXC_CTRLDUMP_VAR( var, ~0, lclAppendDec, text ) +#define EXC_CTRLDUMP_HEXVARMASK( var, mask, text ) IMPL_EXC_CTRLDUMP_VAR( var, mask, lclAppendHex, text ) +#define EXC_CTRLDUMP_DECVARMASK( var, mask, text ) IMPL_EXC_CTRLDUMP_VAR( var, mask, lclAppendDec, text ) +// read flag fields +#define EXC_CTRLDUMP_PLAIN_STARTOPTFLAG( text, doread, defaults )\ +{ \ + nFlags = defaults; \ + t.Append( " " text ); \ + if( doread ) \ + rInStrm >> nFlags; \ + else \ + t.Append( "-defaulted" ); \ + t.Append( '=' ); \ + lclAppendHex( t, nFlags ); \ +} +#define EXC_CTRLDUMP_STARTOPTFLAG( text, doread, defaults ) { if( doread ) { EXC_CTRLDUMP_ALIGN_INSTRM( sizeof( nFlags ) ); } EXC_CTRLDUMP_PLAIN_STARTOPTFLAG( text, doread, defaults ) } +#define EXC_CTRLDUMP_PLAIN_STARTFLAG( text ) EXC_CTRLDUMP_PLAIN_STARTOPTFLAG( text, true, 0 ) +#define EXC_CTRLDUMP_STARTFLAG( text ) EXC_CTRLDUMP_STARTOPTFLAG( text, true, 0 ) +#define EXC_CTRLDUMP_ADDFLAG( flag, text ) { if( nFlags & (flag) ) t.Append( " " text ); } +#define EXC_CTRLDUMP_ADDFLAGVALUE( start, width, text ) { sal_uInt32 nValue; ::extract_value( nValue, nFlags, start, width ); t.Append( " " text "=" ); lclAppendDec( t, nValue ); } +#define EXC_CTRLDUMP_ENDFLAG( reserved ) { if( nFlags & (reserved) ) { t.Append( " ?" ); lclAppendHex( t, static_cast< sal_uInt32 >( nFlags & (reserved) ) ); } EXC_CTRLDUMP_PRINT(); } +// read coordinates +#define EXC_CTRLDUMP_COORD2( text ) { EXC_CTRLDUMP_ALIGN_INSTRM( 4 ); EXC_CTRLDUMP_DEC2( text "-x" ); EXC_CTRLDUMP_DEC2( text "-y" ); } +#define EXC_CTRLDUMP_COORD4( text ) { EXC_CTRLDUMP_DEC4( text "-x" ); EXC_CTRLDUMP_DEC4( text "-y" ); } +#define EXC_CTRLDUMP_SIZE4( text ) { EXC_CTRLDUMP_DEC4( text "-width" ); EXC_CTRLDUMP_DEC4( text "-height" ); } +// read guid +#define EXC_CTRLDUMP_PLAIN_GUID( text ) IMPL_EXC_CTRLDUMP_PLAIN_VALUE( XclGuid, lclAppendGuid, text ) +#define EXC_CTRLDUMP_GUID( text ) { EXC_CTRLDUMP_ALIGN_INSTRM( 4 ); EXC_CTRLDUMP_PLAIN_GUID( text ); } +// read control type +#define EXC_CTRLDUMP_CTRLTYPE( var, text ) \ +{ \ + EXC_CTRLDUMP_ALIGN_INSTRM( 2 ); \ + rInStrm >> var; \ + t.Assign( " " text "=" ); lclAppendHex( t, var ); \ + t.Append( " (" ); lclAppendControlType( t, var ); \ + t.Append( ')' ); \ + EXC_CTRLDUMP_PRINT(); \ +} +// read character array, add to string, but do not print +#define EXC_CTRLDUMP_RAWSTRING( var ) \ +{ \ + t.Append( "='" ); \ + if( var ) \ + { \ + EXC_CTRLDUMP_ALIGN_INSTRM( 4 ); \ + ULONG nNextPos = rInStrm.Tell() + (var); \ + if( var > 128 ) var = 128; \ + sal_Char pc[ 129 ]; \ + rInStrm.Read( pc, var ); pc[ var ] = '\0'; \ + t.Append( pc ); \ + rInStrm.Seek( nNextPos ); \ + } \ + t.Append( '\'' ); \ +} +// read a string +#define EXC_CTRLDUMP_STRING( var, text ) \ +{ \ + t.Append( " " text ); \ + EXC_CTRLDUMP_RAWSTRING( var ); \ + EXC_CTRLDUMP_PRINT(); \ +} +// read an array of strings +#define EXC_CTRLDUMP_STRINGARRAY( total, count, text ) \ +{ \ + ULONG nNextPos = rInStrm.Tell() + (total); \ + for( sal_uInt32 nIdx = 0; (nIdx < (count)) && (rInStrm.Tell() < nNextPos); ++nIdx )\ + { \ + EXC_CTRLDUMP_ALIGN_INSTRM( 4 ); \ + sal_uInt32 nLen; \ + rInStrm >> nLen; \ + nLen &= 0x7FFFFFFF; \ + t.Append( " " text "[" ); \ + lclAppendDec( t, nIdx + 1 ); \ + t.Append( ']' ); \ + EXC_CTRLDUMP_RAWSTRING( nLen ); \ + } \ + EXC_CTRLDUMP_PRINT(); \ + rInStrm.Seek( nNextPos ); \ +} +// read embedded font data +#define EXC_CTRLDUMP_FONT( var, text ) \ +if( var ) \ +{ \ + EXC_CTRLDUMP_PRINT(); \ + XclGuid aGuid; rInStrm >> aGuid; \ + rOutStrm << "embedded-font-guid=" << aGuid; \ + if( aGuid == saStdFontGuid ) \ + { \ + rOutStrm << " (StdFont)\n"; \ + EXC_CTRLDUMP_PLAIN_HEX1( "unknown1" ); \ + EXC_CTRLDUMP_PLAIN_DEC1( "script-type" ); \ + EXC_CTRLDUMP_PLAIN_HEX1( "unknown2" ); \ + sal_uInt8 nFlags; \ + EXC_CTRLDUMP_PLAIN_STARTFLAG( "font-style-flags" ); \ + EXC_CTRLDUMP_ADDFLAG( 0x02, "italic" ); \ + EXC_CTRLDUMP_ADDFLAG( 0x04, "underline" ); \ + EXC_CTRLDUMP_ADDFLAG( 0x08, "strikeout" ); \ + EXC_CTRLDUMP_ENDFLAG( 0xF1 ); \ + EXC_CTRLDUMP_PLAIN_DEC2( "font-weight" ); \ + EXC_CTRLDUMP_PLAIN_DEC4( "font-size" ); \ +/* font-size := pt*10000 + (1-((pt+1)%3))*2500 */ \ + sal_uInt8 nLen; \ + EXC_CTRLDUMP_PLAIN_DECVAR( nLen, "font-name-len" ); \ + sal_Char* p = new sal_Char[ nLen + 1 ]; \ + rInStrm.Read( p, nLen ); p[ nLen ] = '\0'; \ + t.Append( " font-name='" ).Append( p ).Append( '\'' );\ + delete [] p; \ + EXC_CTRLDUMP_PRINT(); \ + } \ + else \ + rOutStrm << " (*UNKNOWN*)\n"; \ +} +// read image data +#define EXC_CTRLDUMP_IMAGE( var, text ) \ +if( var ) \ +{ \ + EXC_CTRLDUMP_PRINT(); \ + XclGuid aGuid; rInStrm >> aGuid; \ + rOutStrm << "embedded-" text "-guid=" << aGuid; \ + if( aGuid == saStdPicGuid ) \ + { \ + rOutStrm << " (StdPict)\n"; \ + EXC_CTRLDUMP_PLAIN_HEX2( "u1" ); \ + EXC_CTRLDUMP_PLAIN_HEX2( "u2" ); \ + sal_uInt32 nLen; \ + EXC_CTRLDUMP_PLAIN_DECVAR( nLen, text "-len" ); \ + rInStrm.SeekRel( nLen ); \ + } \ + else \ + rOutStrm << " (*UNKNOWN*)\n"; \ +} +// hex dump remaining or unknown data +#define EXC_CTRLDUMP_REMAINING( nextpos ) \ +{ \ + EXC_CTRLDUMP_ALIGN_INSTRM( 4 ); \ + if( rInStrm.Tell() < (nextpos) ) \ + { \ + rOutStrm << " unknown-data=\n"; \ + DumpBinary( rInStrm, ::std::min< ULONG >( (nextpos) - rInStrm.Tell(), 1024 ) );\ + } \ + rInStrm.Seek( nextpos ); \ +} + +// *** macros end *** + +void Biff8RecDumper::DumpControlContents( SvStream& rInStrm, sal_uInt16 nCtrlType ) +{ + SvStream& rOutStrm = *pDumpStream; + + if( nCtrlType == EXC_CTRL_PROGRESSBAR ) + { + lclDumpControlType( rOutStrm, nCtrlType ); + rOutStrm << '\n'; + + ByteString t; // "t" needed for macros + sal_uInt32 nFlags = 0; // "nFlags" needed for macros + + EXC_CTRLDUMP_PLAIN_HEX4( "unknown" ); + EXC_CTRLDUMP_PLAIN_HEX4( "unknown" ); + EXC_CTRLDUMP_PLAIN_DEC4( "width" ); + EXC_CTRLDUMP_PLAIN_DEC4( "height" ); + EXC_CTRLDUMP_PLAIN_HEX4( "unknown" ); + EXC_CTRLDUMP_PLAIN_HEX4( "unknown" ); + EXC_CTRLDUMP_PLAIN_HEX4( "unknown" ); + EXC_CTRLDUMP_PLAIN_DECF( "min" ); + EXC_CTRLDUMP_PLAIN_DECF( "max" ); + EXC_CTRLDUMP_PLAIN_STARTFLAG( "flags1" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000001, "vertical" ); + EXC_CTRLDUMP_ADDFLAG( 0x00010000, "smooth-scroll" ); + EXC_CTRLDUMP_ENDFLAG( 0xFFFEFFFE ); + EXC_CTRLDUMP_PLAIN_HEX4( "unknown" ); + EXC_CTRLDUMP_PLAIN_HEX4( "unknown" ); + EXC_CTRLDUMP_PLAIN_HEX4( "unknown" ); + EXC_CTRLDUMP_PLAIN_STARTFLAG( "flags2" ); + EXC_CTRLDUMP_ADDFLAG( 0x0001, "border-single" ); + EXC_CTRLDUMP_ADDFLAG( 0x0002, "enabled" ); + EXC_CTRLDUMP_ADDFLAG( 0x0004, "3d-style" ); + EXC_CTRLDUMP_ADDFLAGVALUE( 3, 8, "mouse-icon" ); + EXC_CTRLDUMP_ADDFLAG( 0x2000, "ole-drop-manual" ); + EXC_CTRLDUMP_ENDFLAG( 0xFFFFD800 ); + return; + } + + sal_uInt16 nSize = lclDumpControlHeader( rInStrm, rOutStrm, nCtrlType ); + if( nSize > 0 ) + { + ULONG nStartPos = rInStrm.Tell(); // for stream alignment macro + ByteString t; // "t" needed for macros + sal_uInt32 nFlags = 0; // "nFlags" needed for macros + + bool bHasFontData = false; + sal_uInt32 nNameLen = 0; + sal_uInt32 nCaptionLen = 0; + sal_uInt32 nValueLen = 0; + sal_uInt32 nGroupNameLen = 0; + sal_uInt32 nTagLen = 0; + sal_uInt32 nTipLen = 0; + sal_uInt32 nCtrlIdLen = 0; + sal_uInt32 nCtrlSrcLen = 0; + sal_uInt32 nRowSrcLen = 0; + sal_uInt16 nPic = 0; + sal_uInt16 nIcon = 0; + sal_uInt16 nFont = 0; + + switch( nCtrlType ) + { + case EXC_CTRL_PUSHBUTTON: + { + EXC_CTRLDUMP_STARTFLAG( "content-flags" ); + EXC_CTRLDUMP_ADDFLAG( 0x0001, "forecolor" ); + EXC_CTRLDUMP_ADDFLAG( 0x0002, "backcolor" ); + EXC_CTRLDUMP_ADDFLAG( 0x0004, "option" ); + EXC_CTRLDUMP_ADDFLAG( 0x0008, "caption" ); + EXC_CTRLDUMP_ADDFLAG( 0x0010, "picpos" ); + EXC_CTRLDUMP_ADDFLAG( 0x0020, "size" ); + EXC_CTRLDUMP_ADDFLAG( 0x0040, "mouseptr" ); + EXC_CTRLDUMP_ADDFLAG( 0x0080, "pic" ); + EXC_CTRLDUMP_ADDFLAG( 0x0100, "accel" ); + EXC_CTRLDUMP_ADDFLAG( 0x0200, "notakefocus" ); + EXC_CTRLDUMP_ADDFLAG( 0x0400, "icon" ); + EXC_CTRLDUMP_ENDFLAG( 0xFFFFF800 ); + sal_uInt32 nCtrlFlags = nFlags; + + if( nCtrlFlags & 0x0001 ) EXC_CTRLDUMP_HEX4( "forecolor" ); + if( nCtrlFlags & 0x0002 ) EXC_CTRLDUMP_HEX4( "backcolor" ); + + EXC_CTRLDUMP_STARTOPTFLAG( "option-flags", nCtrlFlags & 0x0004, 0x0000001B ); + EXC_CTRLDUMP_ADDFLAG( 0x00000002, "enabled" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000004, "locked" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000008, "opaque" ); + EXC_CTRLDUMP_ADDFLAG( 0x00800000, "wordwrap" ); + EXC_CTRLDUMP_ADDFLAG( 0x10000000, "autosize" ); + EXC_CTRLDUMP_ENDFLAG( 0xEF7FFFF1 ); + + if( nCtrlFlags & 0x0008 ) EXC_CTRLDUMP_DECVARMASK( nCaptionLen, 0x7FFFFFFF, "caption-len" ); + if( nCtrlFlags & 0x0010 ) EXC_CTRLDUMP_COORD2( "picpos" ); + if( nCtrlFlags & 0x0040 ) EXC_CTRLDUMP_DEC1( "mouseptr" ); + if( nCtrlFlags & 0x0080 ) EXC_CTRLDUMP_HEXVAR( nPic, "pic" ); + if( nCtrlFlags & 0x0100 ) EXC_CTRLDUMP_HEX2( "accel" ); + if( nCtrlFlags & 0x0400 ) EXC_CTRLDUMP_HEXVAR( nIcon, "icon" ); + + if( nCtrlFlags & 0x0008 ) EXC_CTRLDUMP_STRING( nCaptionLen, "caption" ); + if( nCtrlFlags & 0x0020 ) EXC_CTRLDUMP_SIZE4( "size" ); + EXC_CTRLDUMP_REMAINING( nStartPos + nSize ); + + EXC_CTRLDUMP_IMAGE( nPic, "pic" ); + EXC_CTRLDUMP_IMAGE( nIcon, "icon" ); + bHasFontData = true; + } + break; + + case EXC_CTRL_TOGGLEBUTTON: + case EXC_CTRL_CHECKBOX: + case EXC_CTRL_OPTIONBUTTON: + case EXC_CTRL_TEXTBOX: + case EXC_CTRL_LISTBOX: + case EXC_CTRL_COMBOBOX: + case EXC_CTRL_REFEDIT: + { + EXC_CTRLDUMP_STARTFLAG( "content-flags" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000001, "option" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000002, "backcolor" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000004, "forecolor" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000008, "maxlen" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000010, "borderstyle" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000020, "scrollbars" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000040, "style" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000080, "mouseptr" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000100, "size" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000200, "passwordchar" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000400, "listwidth" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000800, "boundcol" ); + EXC_CTRLDUMP_ADDFLAG( 0x00001000, "textcol" ); + EXC_CTRLDUMP_ADDFLAG( 0x00002000, "colcount" ); + EXC_CTRLDUMP_ADDFLAG( 0x00004000, "listrows" ); + EXC_CTRLDUMP_ADDFLAG( 0x00008000, "colwidth?" ); + EXC_CTRLDUMP_ADDFLAG( 0x00010000, "matchentry" ); + EXC_CTRLDUMP_ADDFLAG( 0x00020000, "liststyle" ); + EXC_CTRLDUMP_ADDFLAG( 0x00040000, "showdropbtn" ); + EXC_CTRLDUMP_ADDFLAG( 0x00100000, "dropbtnstyle" ); + EXC_CTRLDUMP_ADDFLAG( 0x00200000, "multistate" ); + EXC_CTRLDUMP_ADDFLAG( 0x00400000, "value" ); + EXC_CTRLDUMP_ADDFLAG( 0x00800000, "caption" ); + EXC_CTRLDUMP_ADDFLAG( 0x01000000, "picpos" ); + EXC_CTRLDUMP_ADDFLAG( 0x02000000, "bordercolor" ); + EXC_CTRLDUMP_ADDFLAG( 0x04000000, "specialeff" ); + EXC_CTRLDUMP_ADDFLAG( 0x08000000, "icon" ); + EXC_CTRLDUMP_ADDFLAG( 0x10000000, "pic" ); + EXC_CTRLDUMP_ADDFLAG( 0x20000000, "accel" ); + EXC_CTRLDUMP_ENDFLAG( 0x40080000 ); // 0x80000000 always set? + sal_uInt32 nCtrlFlags = nFlags; + + EXC_CTRLDUMP_STARTFLAG( "2nd-content-flags" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000001, "groupname" ); + EXC_CTRLDUMP_ENDFLAG( 0xFFFFFFFE ); + sal_uInt32 nCtrlFlags2 = nFlags; + + EXC_CTRLDUMP_STARTOPTFLAG( "option-flags", nCtrlFlags & 0x00000001, 0x2C80081B ); + EXC_CTRLDUMP_ADDFLAG( 0x00000002, "enabled" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000004, "locked" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000008, "opaque" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000400, "colheads" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000800, "intheight" ); + EXC_CTRLDUMP_ADDFLAG( 0x00001000, "matchreq" ); + EXC_CTRLDUMP_ADDFLAG( 0x00002000, "align" ); + EXC_CTRLDUMP_ADDFLAGVALUE( 15, 4, "ime-mode" ); + EXC_CTRLDUMP_ADDFLAG( 0x00080000, "dragbehav" ); + EXC_CTRLDUMP_ADDFLAG( 0x00100000, "enterkeybehav" ); + EXC_CTRLDUMP_ADDFLAG( 0x00200000, "enterfieldbehav" ); + EXC_CTRLDUMP_ADDFLAG( 0x00400000, "tabkeybehav" ); + EXC_CTRLDUMP_ADDFLAG( 0x00800000, "wordwrap" ); + EXC_CTRLDUMP_ADDFLAG( 0x04000000, "selmargin" ); + EXC_CTRLDUMP_ADDFLAG( 0x08000000, "autowordsel" ); + EXC_CTRLDUMP_ADDFLAG( 0x10000000, "autosize" ); + EXC_CTRLDUMP_ADDFLAG( 0x20000000, "hidesel" ); + EXC_CTRLDUMP_ADDFLAG( 0x40000000, "autotab" ); + EXC_CTRLDUMP_ADDFLAG( 0x80000000, "multiline" ); + EXC_CTRLDUMP_ENDFLAG( 0x030043F1 ); + + if( nCtrlFlags & 0x00000002 ) EXC_CTRLDUMP_HEX4( "backcolor" ); + if( nCtrlFlags & 0x00000004 ) EXC_CTRLDUMP_HEX4( "forecolor" ); + if( nCtrlFlags & 0x00000008 ) EXC_CTRLDUMP_DEC4( "maxlen" ); + if( nCtrlFlags & 0x00000010 ) EXC_CTRLDUMP_DEC1( "borderstyle" ); + if( nCtrlFlags & 0x00000020 ) EXC_CTRLDUMP_DEC1( "scrollbars" ); + if( nCtrlFlags & 0x00000040 ) EXC_CTRLDUMP_DEC1( "style" ); + if( nCtrlFlags & 0x00000080 ) EXC_CTRLDUMP_DEC1( "mouseptr" ); + if( nCtrlFlags & 0x00000200 ) EXC_CTRLDUMP_HEX2( "passwordchar" ); + if( nCtrlFlags & 0x00000400 ) EXC_CTRLDUMP_DEC4( "listwidth" ); + if( nCtrlFlags & 0x00000800 ) EXC_CTRLDUMP_DEC2( "boundcol" ); + if( nCtrlFlags & 0x00001000 ) EXC_CTRLDUMP_DEC2( "textcol" ); + if( nCtrlFlags & 0x00002000 ) EXC_CTRLDUMP_DEC2( "colcount" ); + if( nCtrlFlags & 0x00004000 ) EXC_CTRLDUMP_DEC2( "listrows" ); + if( nCtrlFlags & 0x00008000 ) EXC_CTRLDUMP_DEC2( "colwidth?" ); + if( nCtrlFlags & 0x00010000 ) EXC_CTRLDUMP_DEC1( "matchentry" ); + if( nCtrlFlags & 0x00020000 ) EXC_CTRLDUMP_DEC1( "liststyle" ); + if( nCtrlFlags & 0x00040000 ) EXC_CTRLDUMP_DEC1( "showdropbtn" ); + if( nCtrlFlags & 0x00100000 ) EXC_CTRLDUMP_DEC1( "dropbtnstyle" ); + if( nCtrlFlags & 0x00200000 ) EXC_CTRLDUMP_DEC1( "multistate" ); + if( nCtrlFlags & 0x00400000 ) EXC_CTRLDUMP_DECVARMASK( nValueLen, 0x7FFFFFFF, "value-len" ); + if( nCtrlFlags & 0x00800000 ) EXC_CTRLDUMP_DECVARMASK( nCaptionLen, 0x7FFFFFFF, "caption-len" ); + if( nCtrlFlags & 0x01000000 ) EXC_CTRLDUMP_COORD2( "picpos" ); + if( nCtrlFlags & 0x02000000 ) EXC_CTRLDUMP_HEX4( "bordercolor" ); + if( nCtrlFlags & 0x04000000 ) EXC_CTRLDUMP_DEC4( "specialeff" ); + if( nCtrlFlags & 0x08000000 ) EXC_CTRLDUMP_HEXVAR( nIcon, "icon" ); + if( nCtrlFlags & 0x10000000 ) EXC_CTRLDUMP_HEXVAR( nPic, "pic" ); + if( nCtrlFlags & 0x20000000 ) EXC_CTRLDUMP_HEX1( "accel" ); + if( nCtrlFlags2 & 0x00000001 ) EXC_CTRLDUMP_DECVARMASK( nGroupNameLen, 0x7FFFFFFF, "groupname-len" ); + + if( nCtrlFlags & 0x00000100 ) EXC_CTRLDUMP_SIZE4( "size" ); + if( nCtrlFlags & 0x00400000 ) EXC_CTRLDUMP_STRING( nValueLen, "value" ); + if( nCtrlFlags & 0x00800000 ) EXC_CTRLDUMP_STRING( nCaptionLen, "caption" ); + if( nCtrlFlags2 & 0x00000001 ) EXC_CTRLDUMP_STRING( nGroupNameLen, "groupname" ); + EXC_CTRLDUMP_REMAINING( nStartPos + nSize ); + + EXC_CTRLDUMP_IMAGE( nIcon, "icon" ); + EXC_CTRLDUMP_IMAGE( nPic, "pic" ); + bHasFontData = true; + } + break; + + case EXC_CTRL_LABEL: + { + EXC_CTRLDUMP_STARTFLAG( "content-flags" ); + EXC_CTRLDUMP_ADDFLAG( 0x0001, "forecolor" ); + EXC_CTRLDUMP_ADDFLAG( 0x0002, "backcolor" ); + EXC_CTRLDUMP_ADDFLAG( 0x0004, "option" ); + EXC_CTRLDUMP_ADDFLAG( 0x0008, "caption" ); + EXC_CTRLDUMP_ADDFLAG( 0x0010, "picpos" ); + EXC_CTRLDUMP_ADDFLAG( 0x0020, "size" ); + EXC_CTRLDUMP_ADDFLAG( 0x0040, "mouseptr" ); + EXC_CTRLDUMP_ADDFLAG( 0x0080, "bordercolor" ); + EXC_CTRLDUMP_ADDFLAG( 0x0100, "borderstyle" ); + EXC_CTRLDUMP_ADDFLAG( 0x0200, "specialeff" ); + EXC_CTRLDUMP_ADDFLAG( 0x0400, "pic" ); + EXC_CTRLDUMP_ADDFLAG( 0x0800, "accel" ); + EXC_CTRLDUMP_ADDFLAG( 0x1000, "icon" ); + EXC_CTRLDUMP_ENDFLAG( 0xFFFFE000 ); + sal_uInt32 nCtrlFlags = nFlags; + + if( nCtrlFlags & 0x0001 ) EXC_CTRLDUMP_HEX4( "forecolor" ); + if( nCtrlFlags & 0x0002 ) EXC_CTRLDUMP_HEX4( "backcolor" ); + + EXC_CTRLDUMP_STARTOPTFLAG( "option-flags", nCtrlFlags & 0x0004, 0x0080001B ); + EXC_CTRLDUMP_ADDFLAG( 0x00000002, "enabled" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000004, "locked" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000008, "opaque" ); + EXC_CTRLDUMP_ADDFLAG( 0x00800000, "wordwrap" ); + EXC_CTRLDUMP_ADDFLAG( 0x10000000, "autosize" ); + EXC_CTRLDUMP_ENDFLAG( 0xEF7FFFF0 ); // 0x00000001 always set? + + if( nCtrlFlags & 0x0008 ) EXC_CTRLDUMP_DECVARMASK( nCaptionLen, 0x7FFFFFFF, "caption-len" ); + if( nCtrlFlags & 0x0010 ) EXC_CTRLDUMP_COORD2( "picpos" ); + if( nCtrlFlags & 0x0040 ) EXC_CTRLDUMP_DEC1( "mouseptr" ); + if( nCtrlFlags & 0x0080 ) EXC_CTRLDUMP_HEX4( "bordercolor" ); + if( nCtrlFlags & 0x0100 ) EXC_CTRLDUMP_HEX2( "borderstyle" ); + if( nCtrlFlags & 0x0200 ) EXC_CTRLDUMP_HEX2( "specialeff" ); + if( nCtrlFlags & 0x0400 ) EXC_CTRLDUMP_HEXVAR( nPic, "pic" ); + if( nCtrlFlags & 0x0800 ) EXC_CTRLDUMP_HEX2( "accel" ); + if( nCtrlFlags & 0x1000 ) EXC_CTRLDUMP_HEXVAR( nIcon, "icon" ); + + if( nCtrlFlags & 0x0008 ) EXC_CTRLDUMP_STRING( nCaptionLen, "caption" ); + if( nCtrlFlags & 0x0020 ) EXC_CTRLDUMP_SIZE4( "size" ); + EXC_CTRLDUMP_REMAINING( nStartPos + nSize ); + + EXC_CTRLDUMP_IMAGE( nPic, "pic" ); + EXC_CTRLDUMP_IMAGE( nIcon, "icon" ); + bHasFontData = true; + } + break; + + case EXC_CTRL_SPINBUTTON: + case EXC_CTRL_SCROLLBAR: + { + EXC_CTRLDUMP_STARTFLAG( "content-flags" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000001, "forecolor" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000002, "backcolor" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000004, "option" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000008, "size" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000010, "mouseptr" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000100, "unknown1" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000200, "unknown2" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000400, "unknown3" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000020, "min" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000040, "max" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000080, "value" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000800, "step" ); + EXC_CTRLDUMP_ADDFLAG( 0x00001000, "page-step" ); + EXC_CTRLDUMP_ADDFLAG( 0x00002000, "orient" ); + EXC_CTRLDUMP_ADDFLAG( 0x00004000, "prop-thumb" ); + EXC_CTRLDUMP_ADDFLAG( 0x00008000, "delay" ); + EXC_CTRLDUMP_ADDFLAG( 0x00010000, "icon" ); + EXC_CTRLDUMP_ENDFLAG( 0xFFFE0000 ); + sal_uInt32 nCtrlFlags = nFlags; + + if( nCtrlFlags & 0x00000001 ) EXC_CTRLDUMP_HEX4( "forecolor" ); + if( nCtrlFlags & 0x00000002 ) EXC_CTRLDUMP_HEX4( "backcolor" ); + + EXC_CTRLDUMP_STARTOPTFLAG( "option-flags", nCtrlFlags & 0x00000004, 0x0000001B ); + EXC_CTRLDUMP_ADDFLAG( 0x00000002, "enabled" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000004, "locked" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000008, "opaque" ); + EXC_CTRLDUMP_ADDFLAG( 0x10000000, "autosize" ); + EXC_CTRLDUMP_ENDFLAG( 0xEFFFFFF1 ); + + if( nCtrlFlags & 0x00000010 ) EXC_CTRLDUMP_DEC1( "mouseptr" ); + if( nCtrlFlags & 0x00000020 ) EXC_CTRLDUMP_DEC4( "min" ); + if( nCtrlFlags & 0x00000040 ) EXC_CTRLDUMP_DEC4( "max" ); + if( nCtrlFlags & 0x00000080 ) EXC_CTRLDUMP_DEC4( "value" ); + if( nCtrlFlags & 0x00000100 ) EXC_CTRLDUMP_HEX4( "unknown1" ); + if( nCtrlFlags & 0x00000200 ) EXC_CTRLDUMP_HEX4( "unknown2" ); + if( nCtrlFlags & 0x00000400 ) EXC_CTRLDUMP_HEX4( "unknown3" ); + if( nCtrlFlags & 0x00000800 ) EXC_CTRLDUMP_DEC4( "step" ); + if( nCtrlFlags & 0x00001000 ) EXC_CTRLDUMP_DEC4( "page-step" ); + if( nCtrlFlags & 0x00002000 ) EXC_CTRLDUMP_DEC4( "orient" ); + if( nCtrlFlags & 0x00004000 ) EXC_CTRLDUMP_DEC4( "prop-thumb" ); + if( nCtrlFlags & 0x00008000 ) EXC_CTRLDUMP_DEC4( "delay" ); + if( nCtrlFlags & 0x00010000 ) EXC_CTRLDUMP_HEXVAR( nIcon, "icon" ); + + if( nCtrlFlags & 0x00000008 ) EXC_CTRLDUMP_SIZE4( "size" ); + EXC_CTRLDUMP_REMAINING( nStartPos + nSize ); + + EXC_CTRLDUMP_IMAGE( nIcon, "icon" ); + } + break; + + case EXC_CTRL_IMAGE: + { + EXC_CTRLDUMP_STARTFLAG( "content-flags" ); + EXC_CTRLDUMP_ADDFLAG( 0x0004, "autosize" ); + EXC_CTRLDUMP_ADDFLAG( 0x0008, "bordercolor" ); + EXC_CTRLDUMP_ADDFLAG( 0x0010, "backcolor" ); + EXC_CTRLDUMP_ADDFLAG( 0x0020, "borderstyle" ); + EXC_CTRLDUMP_ADDFLAG( 0x0040, "mouseptr" ); + EXC_CTRLDUMP_ADDFLAG( 0x0080, "picsizemode" ); + EXC_CTRLDUMP_ADDFLAG( 0x0100, "speceffect" ); + EXC_CTRLDUMP_ADDFLAG( 0x0200, "size" ); + EXC_CTRLDUMP_ADDFLAG( 0x0400, "pic" ); + EXC_CTRLDUMP_ADDFLAG( 0x0800, "picalign" ); + EXC_CTRLDUMP_ADDFLAG( 0x1000, "pictiling" ); + EXC_CTRLDUMP_ADDFLAG( 0x2000, "option" ); + EXC_CTRLDUMP_ADDFLAG( 0x4000, "icon" ); + EXC_CTRLDUMP_ENDFLAG( 0xFFFF8003 ); + sal_uInt32 nCtrlFlags = nFlags; + + if( nCtrlFlags & 0x0008 ) EXC_CTRLDUMP_HEX4( "bordercolor" ); + if( nCtrlFlags & 0x0010 ) EXC_CTRLDUMP_HEX4( "backcolor" ); + if( nCtrlFlags & 0x0020 ) EXC_CTRLDUMP_HEX1( "borderstyle" ); + if( nCtrlFlags & 0x0040 ) EXC_CTRLDUMP_DEC1( "mouseptr" ); + if( nCtrlFlags & 0x0080 ) EXC_CTRLDUMP_DEC1( "picsizemode" ); + if( nCtrlFlags & 0x0100 ) EXC_CTRLDUMP_HEX1( "speceffect" ); + if( nCtrlFlags & 0x0400 ) EXC_CTRLDUMP_HEXVAR( nPic, "pic" ); + if( nCtrlFlags & 0x0800 ) EXC_CTRLDUMP_HEX1( "picalign" ); + + EXC_CTRLDUMP_STARTOPTFLAG( "option-flags", nCtrlFlags & 0x2000, 0x0000001B ); + EXC_CTRLDUMP_ADDFLAG( 0x00000002, "enabled" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000008, "opaque" ); + EXC_CTRLDUMP_ENDFLAG( 0xFFFFFFF5 ); + + if( nCtrlFlags & 0x4000 ) EXC_CTRLDUMP_HEXVAR( nIcon, "icon" ); + + if( nCtrlFlags & 0x0200 ) EXC_CTRLDUMP_SIZE4( "size" ); + EXC_CTRLDUMP_REMAINING( nStartPos + nSize ); + + EXC_CTRLDUMP_IMAGE( nPic, "pic" ); + EXC_CTRLDUMP_IMAGE( nIcon, "icon" ); + } + break; + + case EXC_CTRL_TABSTRIP: + { + EXC_CTRLDUMP_STARTFLAG( "content-flags" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000001, "selected-tab" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000002, "backcolor" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000004, "forecolor" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000010, "size" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000020, "caption-arr-len" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000040, "mouseptr" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000100, "taborientation" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000200, "tabstyle" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000400, "multirow" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000800, "fixed-width" ); + EXC_CTRLDUMP_ADDFLAG( 0x00001000, "fixed-height" ); + EXC_CTRLDUMP_ADDFLAG( 0x00008000, "infotip-arr-len" ); + EXC_CTRLDUMP_ADDFLAG( 0x00020000, "id-arr-len" ); + EXC_CTRLDUMP_ADDFLAG( 0x00040000, "option" ); + EXC_CTRLDUMP_ADDFLAG( 0x00080000, "last-id" ); + EXC_CTRLDUMP_ADDFLAG( 0x00200000, "unknown-arr-len" ); + EXC_CTRLDUMP_ADDFLAG( 0x00400000, "tab-count" ); + EXC_CTRLDUMP_ADDFLAG( 0x00800000, "shortcut-arr-len" ); + EXC_CTRLDUMP_ADDFLAG( 0x01000000, "icon" ); + EXC_CTRLDUMP_ENDFLAG( 0xFE116088 ); + sal_uInt32 nCtrlFlags = nFlags; + + sal_uInt32 nTabCount = 0; + sal_uInt32 nIdArrLen = 0; + sal_uInt32 nUnknownArrLen = 0; + sal_uInt32 nShortArrLen = 0; + + if( nCtrlFlags & 0x00000001 ) EXC_CTRLDUMP_DEC4( "selected-tab" ); // size ok? + if( nCtrlFlags & 0x00000002 ) EXC_CTRLDUMP_HEX4( "backcolor" ); + if( nCtrlFlags & 0x00000004 ) EXC_CTRLDUMP_HEX4( "forecolor" ); + if( nCtrlFlags & 0x00000020 ) EXC_CTRLDUMP_HEXVAR( nCaptionLen, "caption-arr-len" ); + if( nCtrlFlags & 0x00000040 ) EXC_CTRLDUMP_DEC1( "mouseptr" ); // size ok? + if( nCtrlFlags & 0x00000100 ) EXC_CTRLDUMP_DEC4( "taborientation" ); // size ok? + if( nCtrlFlags & 0x00000200 ) EXC_CTRLDUMP_DEC4( "tabstyle" ); // size ok? + if( nCtrlFlags & 0x00000800 ) EXC_CTRLDUMP_DEC4( "fixed-width" ); + if( nCtrlFlags & 0x00001000 ) EXC_CTRLDUMP_DEC4( "fixed-height" ); + if( nCtrlFlags & 0x00008000 ) EXC_CTRLDUMP_HEXVAR( nTipLen, "infotip-arr-len" ); + if( nCtrlFlags & 0x00020000 ) EXC_CTRLDUMP_HEXVAR( nIdArrLen, "id-arr-len" ); + + EXC_CTRLDUMP_STARTOPTFLAG( "option-flags", nCtrlFlags & 0x00040000, 0x0000001B ); + EXC_CTRLDUMP_ADDFLAG( 0x00000002, "enabled" ); + EXC_CTRLDUMP_ENDFLAG( 0xFFFFFFFD ); + + if( nCtrlFlags & 0x00080000 ) EXC_CTRLDUMP_DEC4( "last-id" ); + if( nCtrlFlags & 0x00200000 ) EXC_CTRLDUMP_HEXVAR( nUnknownArrLen, "unknown-arr-len" ); + if( nCtrlFlags & 0x00400000 ) EXC_CTRLDUMP_DECVAR( nTabCount, "tab-count" ); + if( nCtrlFlags & 0x00800000 ) EXC_CTRLDUMP_HEXVAR( nShortArrLen, "shortcut-arr-len" ); + if( nCtrlFlags & 0x01000000 ) EXC_CTRLDUMP_HEXVAR( nIcon, "icon" ); + + if( nCtrlFlags & 0x00000010 ) EXC_CTRLDUMP_SIZE4( "size" ); + if( nCtrlFlags & 0x00000020 ) EXC_CTRLDUMP_STRINGARRAY( nCaptionLen, nTabCount, "caption" ); + if( nCtrlFlags & 0x00008000 ) EXC_CTRLDUMP_STRINGARRAY( nTipLen, nTabCount, "infotip" ); + if( nCtrlFlags & 0x00020000 ) EXC_CTRLDUMP_STRINGARRAY( nIdArrLen, nTabCount, "id" ); + if( nCtrlFlags & 0x00200000 ) EXC_CTRLDUMP_STRINGARRAY( nUnknownArrLen, nTabCount, "unknown" ); + if( nCtrlFlags & 0x00800000 ) EXC_CTRLDUMP_STRINGARRAY( nShortArrLen, nTabCount, "shortcut" ); + EXC_CTRLDUMP_REMAINING( nStartPos + nSize ); + + EXC_CTRLDUMP_IMAGE( nIcon, "icon" ); + bHasFontData = true; + } + break; + + case EXC_CTRL_USERFORM: + case EXC_CTRL_FRAME: + case EXC_CTRL_MULTIPAGE: + case EXC_CTRL_PAGE: + { + EXC_CTRLDUMP_STARTFLAG( "content-flags" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000002, "backcolor" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000004, "forecolor" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000008, "last-id" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000040, "option" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000080, "borderstyle" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000100, "mouseptr" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000200, "scrollbars" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000400, "size" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000800, "scrollsize" ); + EXC_CTRLDUMP_ADDFLAG( 0x00001000, "scrollpos" ); + EXC_CTRLDUMP_ADDFLAG( 0x00008000, "icon" ); + EXC_CTRLDUMP_ADDFLAG( 0x00010000, "cycle" ); + EXC_CTRLDUMP_ADDFLAG( 0x00020000, "speceffect" ); + EXC_CTRLDUMP_ADDFLAG( 0x00040000, "bordercolor" ); + EXC_CTRLDUMP_ADDFLAG( 0x00080000, "caption" ); + EXC_CTRLDUMP_ADDFLAG( 0x00100000, "font" ); + EXC_CTRLDUMP_ADDFLAG( 0x00200000, "pic" ); + EXC_CTRLDUMP_ADDFLAG( 0x00400000, "zoom" ); + EXC_CTRLDUMP_ADDFLAG( 0x00800000, "picalign" ); + EXC_CTRLDUMP_ADDFLAG( 0x01000000, "pictiling" ); + EXC_CTRLDUMP_ADDFLAG( 0x02000000, "picsizemode" ); + EXC_CTRLDUMP_ADDFLAG( 0x04000000, "typeinfover" ); + EXC_CTRLDUMP_ADDFLAG( 0x08000000, "drawbuffer" ); + EXC_CTRLDUMP_ENDFLAG( 0xF0006031 ); + sal_uInt32 nCtrlFlags = nFlags; + + if( nCtrlFlags & 0x00000002 ) EXC_CTRLDUMP_HEX4( "backcolor" ); + if( nCtrlFlags & 0x00000004 ) EXC_CTRLDUMP_HEX4( "forecolor" ); + if( nCtrlFlags & 0x00000008 ) EXC_CTRLDUMP_DEC4( "last-id" ); + + EXC_CTRLDUMP_STARTOPTFLAG( "option-flags", nCtrlFlags & 0x00000040, 0x00000002 ); + EXC_CTRLDUMP_ADDFLAG( 0x00000002, "enabled" ); + EXC_CTRLDUMP_ENDFLAG( 0xFFFFFFFD ); + + if( nCtrlFlags & 0x00000080 ) EXC_CTRLDUMP_HEX1( "borderstyle" ); + if( nCtrlFlags & 0x00000100 ) EXC_CTRLDUMP_DEC1( "mouseptr" ); + if( nCtrlFlags & 0x00000200 ) EXC_CTRLDUMP_HEX1( "scrollbars" ); + if( nCtrlFlags & 0x00008000 ) EXC_CTRLDUMP_HEXVAR( nIcon, "icon" ); + if( nCtrlFlags & 0x00010000 ) EXC_CTRLDUMP_DEC1( "cycle" ); + if( nCtrlFlags & 0x00020000 ) EXC_CTRLDUMP_HEX1( "speceffect" ); + if( nCtrlFlags & 0x00040000 ) EXC_CTRLDUMP_HEX4( "bordercolor" ); + if( nCtrlFlags & 0x00080000 ) EXC_CTRLDUMP_DECVARMASK( nCaptionLen, 0x7FFFFFFF, "caption-len" ); + if( nCtrlFlags & 0x00100000 ) EXC_CTRLDUMP_HEXVAR( nFont, "font" ); + if( nCtrlFlags & 0x00200000 ) EXC_CTRLDUMP_HEXVAR( nPic, "pic" ); + if( nCtrlFlags & 0x00400000 ) EXC_CTRLDUMP_DEC4( "zoom" ); + if( nCtrlFlags & 0x00800000 ) EXC_CTRLDUMP_HEX1( "picalign" ); + if( nCtrlFlags & 0x02000000 ) EXC_CTRLDUMP_DEC1( "picsizemode" ); + if( nCtrlFlags & 0x04000000 ) EXC_CTRLDUMP_DEC4( "typeinfover" ); + if( nCtrlFlags & 0x08000000 ) EXC_CTRLDUMP_DEC4( "drawbuffer" ); + + if( nCtrlFlags & 0x00000400 ) EXC_CTRLDUMP_SIZE4( "size" ); + if( nCtrlFlags & 0x00000800 ) EXC_CTRLDUMP_SIZE4( "scrollsize" ); + if( nCtrlFlags & 0x00001000 ) EXC_CTRLDUMP_COORD4( "scrollpos" ); + if( nCtrlFlags & 0x00080000 ) EXC_CTRLDUMP_STRING( nCaptionLen, "caption" ); + EXC_CTRLDUMP_REMAINING( nStartPos + nSize ); + + EXC_CTRLDUMP_FONT( nFont, "font" ); + EXC_CTRLDUMP_IMAGE( nIcon, "icon" ); + EXC_CTRLDUMP_IMAGE( nPic, "pic" ); + } + break; + + case EXC_CTRL_FONTDATA: + { + EXC_CTRLDUMP_STARTFLAG( "content-flags" ); + EXC_CTRLDUMP_ADDFLAG( 0x01, "font-name" ); + EXC_CTRLDUMP_ADDFLAG( 0x02, "font-style" ); + EXC_CTRLDUMP_ADDFLAG( 0x04, "font-size" ); + EXC_CTRLDUMP_ADDFLAG( 0x10, "language-id" ); + EXC_CTRLDUMP_ADDFLAG( 0x40, "align" ); + EXC_CTRLDUMP_ADDFLAG( 0x80, "font-weight" ); + EXC_CTRLDUMP_ENDFLAG( 0xFFFFFF08 ); // 0x20 always set? + sal_uInt32 nCtrlFlags = nFlags; + + if( nCtrlFlags & 0x0001 ) EXC_CTRLDUMP_DECVARMASK( nNameLen, 0x7FFFFFFF, "font-name-len" ); + + EXC_CTRLDUMP_STARTOPTFLAG( "font-style-flags", nCtrlFlags & 0x0002, 0x40000000 ); + EXC_CTRLDUMP_ADDFLAG( 0x0001, "bold" ); + EXC_CTRLDUMP_ADDFLAG( 0x0002, "italic" ); + EXC_CTRLDUMP_ADDFLAG( 0x0004, "underline" ); + EXC_CTRLDUMP_ADDFLAG( 0x0008, "strikeout" ); + EXC_CTRLDUMP_ADDFLAG( 0x2000, "sunken" ); + EXC_CTRLDUMP_ENDFLAG( 0xBFFFDFF0 ); // 0x40000000 always set? + + if( nCtrlFlags & 0x0004 ) EXC_CTRLDUMP_DEC4( "font-size" ); + if( nCtrlFlags & 0x0010 ) EXC_CTRLDUMP_HEX2( "language-id" ); + if( nCtrlFlags & 0x0040 ) + { + EXC_CTRLDUMP_ALIGN_INSTRM( 2 ); + sal_uInt16 nAlign; rInStrm >> nAlign; + t += " align="; lclAppendDec( t, nAlign ); + switch( nAlign ) + { + case 1: t += "=left"; break; + case 2: t += "=right"; break; + case 3: t += "=center"; break; + default: t += "=!unknown!"; + } + EXC_CTRLDUMP_PRINT(); + } + if( nCtrlFlags & 0x0080 ) EXC_CTRLDUMP_DEC2( "font-weight" ); + + if( nCtrlFlags & 0x0001 ) EXC_CTRLDUMP_STRING( nNameLen, "font-name" ); + EXC_CTRLDUMP_REMAINING( nStartPos + nSize ); + } + break; + + case EXC_CTRL_ADDDATA: + { + EXC_CTRLDUMP_STARTFLAG( "content-flags" ); + EXC_CTRLDUMP_ADDFLAG( 0x0001, "guid1" ); + EXC_CTRLDUMP_ADDFLAG( 0x0002, "guid2" ); + EXC_CTRLDUMP_ADDFLAG( 0x0008, "guid4" ); + EXC_CTRLDUMP_ADDFLAG( 0x0040, "unknown1" ); + EXC_CTRLDUMP_ENDFLAG( 0xFFFFFFB4 ); + sal_uInt32 nCtrlFlags = nFlags; + + if( nCtrlFlags & 0x0040 ) EXC_CTRLDUMP_HEX4( "unknown1" ); + + if( nCtrlFlags & 0x0001 ) EXC_CTRLDUMP_GUID( "guid1" ); + if( nCtrlFlags & 0x0002 ) EXC_CTRLDUMP_GUID( "guid2" ); + if( nCtrlFlags & 0x0008 ) EXC_CTRLDUMP_GUID( "guid4" ); + EXC_CTRLDUMP_REMAINING( nStartPos + nSize ); + } + break; + + case EXC_CTRL_FRAMECHILD: + { + EXC_CTRLDUMP_STARTFLAG( "content-flags" ); + EXC_CTRLDUMP_ADDFLAG( 0x0001, "name-len" ); + EXC_CTRLDUMP_ADDFLAG( 0x0002, "tag-len" ); + EXC_CTRLDUMP_ADDFLAG( 0x0004, "storage-id" ); + EXC_CTRLDUMP_ADDFLAG( 0x0008, "helpcontext-id" ); + EXC_CTRLDUMP_ADDFLAG( 0x0010, "option" ); + EXC_CTRLDUMP_ADDFLAG( 0x0020, "substream-len" ); + EXC_CTRLDUMP_ADDFLAG( 0x0040, "tabpos" ); + EXC_CTRLDUMP_ADDFLAG( 0x0080, "type" ); + EXC_CTRLDUMP_ADDFLAG( 0x0100, "pos" ); + EXC_CTRLDUMP_ADDFLAG( 0x0800, "tiptext" ); + EXC_CTRLDUMP_ADDFLAG( 0x1000, "ctrl-id" ); + EXC_CTRLDUMP_ADDFLAG( 0x2000, "ctrl-source" ); + EXC_CTRLDUMP_ADDFLAG( 0x4000, "row-source" ); + EXC_CTRLDUMP_ENDFLAG( 0xFFFF8600 ); + sal_uInt32 nCtrlFlags = nFlags; + + sal_uInt32 nStorageId = 0; + sal_uInt32 nSubStrmLen = 0; + sal_uInt16 nChildType = EXC_CTRL_UNKNOWN; + + if( nCtrlFlags & 0x0001 ) EXC_CTRLDUMP_DECVARMASK( nNameLen, 0x7FFFFFFF, "name-len" ); + if( nCtrlFlags & 0x0002 ) EXC_CTRLDUMP_DECVARMASK( nTagLen, 0x7FFFFFFF, "tag-len" ); + if( nCtrlFlags & 0x0004 ) EXC_CTRLDUMP_PLAIN_DECVAR( nStorageId, "storage-id" ); + if( nCtrlFlags & 0x0008 ) EXC_CTRLDUMP_PLAIN_DEC4( "helpcontext-id" ); + + EXC_CTRLDUMP_STARTOPTFLAG( "option-flags", nCtrlFlags & 0x0010, 0x00000033 ); + EXC_CTRLDUMP_ADDFLAG( 0x00000001, "tabstop" ); + EXC_CTRLDUMP_ADDFLAG( 0x00000002, "visible" ); + EXC_CTRLDUMP_ADDFLAG( 0x00040000, "container" ); + EXC_CTRLDUMP_ENDFLAG( 0xFFFBFFFC ); + + if( nCtrlFlags & 0x0020 ) EXC_CTRLDUMP_HEXVAR( nSubStrmLen, "substream-len" ); + if( nCtrlFlags & 0x0040 ) EXC_CTRLDUMP_DEC2( "tabpos" ); + if( nCtrlFlags & 0x0080 ) EXC_CTRLDUMP_CTRLTYPE( nChildType, "type" ); + if( nCtrlFlags & 0x0800 ) EXC_CTRLDUMP_DECVARMASK( nTipLen, 0x7FFFFFFF, "infotip-len" ); + if( nCtrlFlags & 0x1000 ) EXC_CTRLDUMP_DECVARMASK( nCtrlIdLen, 0x7FFFFFFF, "ctrl-id-len" ); + if( nCtrlFlags & 0x2000 ) EXC_CTRLDUMP_DECVARMASK( nCtrlSrcLen, 0x7FFFFFFF, "ctrl-source-len" ); + if( nCtrlFlags & 0x4000 ) EXC_CTRLDUMP_DECVARMASK( nRowSrcLen, 0x7FFFFFFF, "row-source-len" ); + + if( nCtrlFlags & 0x0001 ) EXC_CTRLDUMP_STRING( nNameLen, "name" ); + if( nCtrlFlags & 0x0002 ) EXC_CTRLDUMP_STRING( nTagLen, "tag" ); + if( nCtrlFlags & 0x0100 ) EXC_CTRLDUMP_COORD4( "pos" ); + if( nCtrlFlags & 0x0800 ) EXC_CTRLDUMP_STRING( nTipLen, "infotip" ); + if( nCtrlFlags & 0x1000 ) EXC_CTRLDUMP_STRING( nCtrlIdLen, "ctrl-id" ); + if( nCtrlFlags & 0x2000 ) EXC_CTRLDUMP_STRING( nCtrlSrcLen, "ctrl-source" ); + if( nCtrlFlags & 0x4000 ) EXC_CTRLDUMP_STRING( nRowSrcLen, "row-source" ); + EXC_CTRLDUMP_REMAINING( nStartPos + nSize ); + + if( (nCtrlFlags & 0x0080) && (nChildType != EXC_CTRL_UNKNOWN) ) + { + if( (nFlags & 0x00040000) && (nStorageId > 0) ) + maCtrlStorages.push_back( XclDumpCtrlPortion( nStorageId, nChildType ) ); + if( (nCtrlFlags & 0x0020) && (nSubStrmLen > 0) ) + maCtrlPortions.push_back( XclDumpCtrlPortion( nSubStrmLen, nChildType ) ); + } + } + break; + + default: + EXC_CTRLDUMP_REMAINING( nStartPos + nSize ); + } + + // font data + if( bHasFontData ) + DumpControlContents( rInStrm, EXC_CTRL_FONTDATA ); + } +} + +// ============================================================================ +// +// S T R E A M S +// +// ============================================================================ + +void Biff8RecDumper::DumpBinaryStream( SotStorageRef xStrg, const String& rStrmName, const String& rStrgPath ) +{ + SotStorageStreamRef xInStrm = OpenStream( xStrg, rStrmName ); + if( !xInStrm || !pDumpStream ) return; + + XclDumpStreamHeader aStrmHeader( *xInStrm, *pDumpStream, rStrmName, rStrgPath ); + DumpBinary( *xInStrm ); + (*pDumpStream) << "\n"; +} + +void Biff8RecDumper::DumpTextStream( SotStorageRef xStrg, const String& rStrmName, const String& rStrgPath ) +{ + SotStorageStreamRef xInStrm = OpenStream( xStrg, rStrmName ); + if( !xInStrm || !pDumpStream ) return; + + XclDumpStreamHeader aStrmHeader( *xInStrm, *pDumpStream, rStrmName, rStrgPath ); + while( xInStrm->Tell() < aStrmHeader.GetStreamLen() ) + { + ByteString aLine; + xInStrm->ReadLine( aLine ); + lclDumpString( *pDumpStream, aLine ); + (*pDumpStream) << "\n"; + } + (*pDumpStream) << "\n"; +} + +void Biff8RecDumper::DumpRecordStream( SotStorageRef xStrg, const String& rStrmName, const String& rStrgPath ) +{ + SotStorageStreamRef xInStrm = OpenStream( xStrg, rStrmName ); + if( !xInStrm || !pDumpStream ) return; + + XclDumpStreamHeader aStrmHeader( *xInStrm, *pDumpStream, rStrmName, rStrgPath ); + + XclImpStream* pOldStream = pIn; + pIn = new XclImpStream( *xInStrm, GetRoot() ); + XclImpStream& rIn = *pIn; + if( pOldStream ) + rIn.CopyDecrypterFrom( *pOldStream ); + + // -- dump from here -- + UINT16 nId; + BOOL bLoop = TRUE; + + while( bLoop && rIn.StartNextRecord() ) + { + nId = rIn.GetRecId(); + if( HasModeDump( nId ) ) + RecDump( TRUE ); + + bLoop = (nId != 0x000A); + } + + delete pIn; + pIn = pOldStream; +} + +void Biff8RecDumper::DumpCtlsStream() +{ + SotStorageStreamRef xInStrm = OpenStream( EXC_STREAM_CTLS ); + if( !xInStrm || !pDumpStream ) return; + + SvStream& rInStrm = *xInStrm; + SvStream& rOutStrm = *pDumpStream; + XclDumpStreamHeader aStrmHeader( rInStrm, rOutStrm, EXC_STREAM_CTLS, EMPTY_STRING ); + + for( StrmPortionMap::const_iterator aIt = maCtlsPosMap.begin(), aEnd = maCtlsPosMap.end(); aIt != aEnd; ++aIt ) + { + ULONG nCtrlPos = static_cast< ULONG >( aIt->first ); + ULONG nCtrlEnd = nCtrlPos + static_cast< ULONG >( aIt->second ); + if( nCtrlEnd <= aStrmHeader.GetStreamLen() ) + { + // stream position + ULONG nStartPos = nCtrlPos; // for stream alignment macro + rInStrm.Seek( nStartPos ); + + ByteString t( "\npos=" ); __AddHex( t, aIt->first ); + t.Append( " len=" ); __AddHex( t, aIt->second ); + rOutStrm << t.GetBuffer() << " "; + + // control type + sal_uInt16 nCtrlType = lclDumpControlGuid( rInStrm, rOutStrm ); + rOutStrm << "\n"; + + // control contents + if( nCtrlType != EXC_CTRL_UNKNOWN ) + DumpControlContents( rInStrm, nCtrlType ); + + // remaining unknown data + EXC_CTRLDUMP_REMAINING( nCtrlEnd ); + rOutStrm << "\n"; + } + } +} + +void Biff8RecDumper::DumpControlFrameStream( SotStorageRef xInStrg, sal_uInt16 nCtrlType, const String& rStrgPath ) +{ + static const String saStrmName( sal_Unicode( 'f' ) ); + + SotStorageStreamRef xInStrm = OpenStream( xInStrg, saStrmName ); + if( !xInStrm || !pDumpStream ) return; + + SvStream& rInStrm = *xInStrm; + SvStream& rOutStrm = *pDumpStream; + XclDumpStreamHeader aStrmHeader( rInStrm, rOutStrm, saStrmName, rStrgPath ); + + if( aStrmHeader.GetStreamLen() > 0 ) + { + ByteString t; // "t" needed for macros + + rOutStrm << "header-record\n"; + DumpControlContents( rInStrm, nCtrlType ); + rOutStrm << "\n"; + + if( nCtrlType == EXC_CTRL_USERFORM ) + { + rOutStrm << "add-records\n"; + sal_uInt16 nAddCount; + EXC_CTRLDUMP_PLAIN_DECVAR( nAddCount, "count" ); + EXC_CTRLDUMP_PRINT(); + rOutStrm << "\n"; + + for( sal_uInt16 nAdd = 0; (nAdd < nAddCount) && (rInStrm.Tell() < aStrmHeader.GetStreamLen()); ++nAdd ) + { + DumpControlContents( rInStrm, EXC_CTRL_ADDDATA ); + rOutStrm << "\n"; + } + } + + rOutStrm << "children-records\n"; + sal_uInt32 nRecCount, nTotalSize; + EXC_CTRLDUMP_PLAIN_DECVAR( nRecCount, "count" ); + EXC_CTRLDUMP_PLAIN_HEXVAR( nTotalSize, "total-size" ); + if( nTotalSize > 0 ) + { + EXC_CTRLDUMP_PLAIN_HEX4( "header-unknown" ); + rOutStrm << "\n"; + + for( sal_uInt32 nRec = 0; (nRec < nRecCount) && (rInStrm.Tell() < aStrmHeader.GetStreamLen()); ++nRec ) + { + DumpControlContents( rInStrm, EXC_CTRL_FRAMECHILD ); + rOutStrm << "\n"; + } + } + else + rOutStrm << "\n"; + + if( rInStrm.Tell() < aStrmHeader.GetStreamLen() ) + { + rOutStrm << "remaining=\n"; + DumpBinary( rInStrm ); + rOutStrm << "\n"; + } + } +} + +void Biff8RecDumper::DumpControlObjectsStream( SotStorageRef xInStrg, const String& rStrgPath ) +{ + static const String saStrmName( sal_Unicode( 'o' ) ); + + SotStorageStreamRef xInStrm = OpenStream( xInStrg, saStrmName ); + if( !xInStrm || !pDumpStream ) return; + + SvStream& rInStrm = *xInStrm; + SvStream& rOutStrm = *pDumpStream; + XclDumpStreamHeader aStrmHeader( rInStrm, rOutStrm, saStrmName, rStrgPath ); + + if( aStrmHeader.GetStreamLen() > 0 ) + { + ULONG nStrmPos = 0; + for( XclDumpCtrlPortionVec::const_iterator aIt = maCtrlPortions.begin(), aEnd = maCtrlPortions.end(); aIt != aEnd; ++aIt ) + { + rInStrm.Seek( nStrmPos ); + DumpControlContents( rInStrm, aIt->second ); + rOutStrm << "\n"; + nStrmPos += aIt->first; + } + + if( rInStrm.Tell() < aStrmHeader.GetStreamLen() ) + { + rOutStrm << "remaining=\n"; + DumpBinary( rInStrm ); + rOutStrm << "\n"; + } + } +} + +// ============================================================================ +// +// S T O R A G E S +// +// ============================================================================ + +void Biff8RecDumper::DumpAnyStorage( SotStorageRef xParentStrg, const String& rStrgName, const String& rStrgPath ) +{ + SotStorageRef xInStrg = OpenStorage( xParentStrg, rStrgName ); + if( !xInStrg || !pDumpStream ) return; + + XclDumpStorageHeader aStrgHeader( *xInStrg, *pDumpStream, rStrgPath ); +} + +void Biff8RecDumper::DumpUserFormStorage( SotStorageRef xParentStrg, const String& rStrgName, sal_uInt16 nCtrlType, const String& rStrgPath ) +{ + SotStorageRef xInStrg = OpenStorage( xParentStrg, rStrgName ); + if( !xInStrg || !pDumpStream ) return; + + XclDumpStorageHeader aStrgHeader( *xInStrg, *pDumpStream, rStrgPath ); + + // streams + maCtrlStorages.clear(); + maCtrlPortions.clear(); + DumpControlFrameStream( xInStrg, nCtrlType, rStrgPath ); + DumpControlObjectsStream( xInStrg, rStrgPath ); + DumpTextStream( xInStrg, CREATE_STRING( "\003VBFrame" ), rStrgPath ); + + // frame substorages + XclDumpCtrlPortionVec aCtrlStorages( maCtrlStorages ); // make local copy, maCtrlStorages is reused in loop + for( XclDumpCtrlPortionVec::const_iterator aIt = aCtrlStorages.begin(), aEnd = aCtrlStorages.end(); aIt != aEnd; ++aIt ) + { + sal_uInt32 nStorageId = aIt->first; + String aSubName( sal_Unicode( 'i' ) ); + if( nStorageId < 10 ) + aSubName.Append( sal_Unicode( '0' ) ); + aSubName.Append( String::CreateFromInt32( static_cast< sal_Int32 >( nStorageId ) ) ); + + String aPath( rStrgPath ); + aPath.Append( sal_Unicode( '/' ) ).Append( rStrgName ); + + DumpUserFormStorage( xInStrg, aSubName, aIt->second, aPath ); + } +} + +void Biff8RecDumper::DumpVbaProjectStorage() +{ + SotStorageRef xInStrg = OpenStorage( EXC_STORAGE_VBA_PROJECT ); + if( !xInStrg || !pDumpStream ) return; + + XclDumpStorageHeader aStrgHeader( *xInStrg, *pDumpStream, EMPTY_STRING ); + // PROJECT substream + DumpTextStream( xInStrg, CREATE_STRING( "PROJECT" ), EXC_STORAGE_VBA_PROJECT ); + // VBA storage + DumpAnyStorage( xInStrg, EXC_STORAGE_VBA, EXC_STORAGE_VBA_PROJECT ); + // user forms + SvStorageInfoList aInfoList; + xInStrg->FillInfoList( &aInfoList ); + for( ULONG nInfo = 0; nInfo < aInfoList.Count(); ++nInfo ) + { + SvStorageInfo& rInfo = aInfoList.GetObject( nInfo ); + if( rInfo.IsStorage() && (rInfo.GetName() != EXC_STORAGE_VBA) ) + DumpUserFormStorage( xInStrg, rInfo.GetName(), EXC_CTRL_USERFORM, EXC_STORAGE_VBA_PROJECT ); + } +} + +// ============================================================================ +// +// ============================================================================ + +const sal_Char* Biff8RecDumper::GetBlanks( const UINT16 nNumOfBlanks ) +{ + DBG_ASSERT( pBlankLine, "-Biff8RecDumper::GetBlanks(): nicht so schnell mein Freund!" ); + DBG_ASSERT( nNumOfBlanks <= nLenBlankLine, + "+Biff8RecDumper::GetBlanks(): So viel kannst Du nicht von mir verlangen!" ); + + return pBlankLine + ( ( nNumOfBlanks <= nLenBlankLine )? ( nLenBlankLine - nNumOfBlanks ) : 0 ); +} + + +BOOL Biff8RecDumper::IsLineEnd( const sal_Char c, sal_Char& rNext, SvStream& rIn, INT32& rLeft ) +{ + static const sal_Char cNL = '\n'; + static const sal_Char cRET = '\r'; + + if( IsEndOfLine( c ) ) + { + sal_Char cDouble = ( c == cNL )? cRET : cNL; + + if( rNext == cDouble ) + { + rIn >> rNext; + rLeft--; + } + + return TRUE; + } + else + return FALSE; +} + + +_KEYWORD Biff8RecDumper::GetKeyType( const ByteString& r ) +{ + ByteString t( r ); + _KEYWORD e; + + t.ToUpperAscii(); + + if( t == "SKIPDUMP" ) + e = Skipdump; + else if( t == "SKIPOFFSET" ) + e = SkipOffset; + else if( t == "READCONTRECS" ) + e = ReadContRecs; + else if( t == "NOWARNINGS" ) + e = NoWarnings; + else if( t == "CONTLOAD" ) + e = Contload; + else if( t == "BLANKLINE" ) + e = BlankLine; + else if( t == "EXPORTBOOKSTREAM" ) + e = ExportBookStream; + else if( t == "PARSEP" ) + e = Parsep; + else if( t == "MAXBODYLINES" ) + e = Maxbodylines; + else if( t == "INCLUDE" || t == "+" ) + e = Include; + else if( t == "EXCLUDE" || t == "-" ) + e = Exclude; + else if( t == "HEX" || t == "H" ) + e = Hex; + else if( t == "BODY" || t == "B" ) + e = Body; + else if( t == "NAMEONLY" || t =="N" ) + e = NameOnly; + else if( t == "COMMENT" ) + e = Comment; + else if( t == "OUTPUT" ) + e = Output; + else if( t == "TITLE" ) + e = Title; + else if( t == "CLEARFILE" ) + e = ClearFile; + else + e = KW_Unknown; + + return e; +} + + +void Biff8RecDumper::Init( void ) +{ + bClearFile = FALSE; + + if( pDumpModes || ppRecNames ) + return; + + const sal_Char* pDefName = "biffrecdumper.ini"; + const sal_Char* pIniKey = "BIFFRECDUMPERINI"; + const sal_Char pPathSep[] = { SAL_PATHDELIMITER, '\0' }; + ByteString aIniName; + + SvFileStream* pIn = NULL; + + // first try: search for biffrecdumper.ini in dir, specified in %HOME% + const sal_Char* pHome = getenv( "HOME" ); + if( pHome ) + { + aIniName = pHome; + aIniName.EraseTrailingChars( *pPathSep ); + aIniName += pPathSep; + aIniName += pDefName; + + pIn = CreateInStream( aIniName.GetBuffer() ); + } + + if( !pIn ) + { // %HOME% not set or %HOME%\biffrecdumper.ini could not be opened + const sal_Char* pIni = getenv( pIniKey ); + if( pIni ) + { + pIn = CreateInStream( pIni ); + if( !pIn ) + { + AddError( 0, "Could not open ini file", ByteString( pIni ) ); + bEndLoading = TRUE; // zur Sicherheit.... + } + } + } + + if( pIn ) + { + pIn->Seek( STREAM_SEEK_TO_END ); + + const UINT32 nStreamLen = pIn->Tell(); + + if( nStreamLen <= 1 ) + { + pIn->Close(); + delete pIn; + return; + } + + pIn->Seek( STREAM_SEEK_TO_BEGIN ); + + pDumpModes = new UINT16[ nRecCnt ]; + ppRecNames = new ByteString*[ nRecCnt ]; + + memset( pDumpModes, 0x00, sizeof( UINT16 ) * nRecCnt ); + memset( ppRecNames, 0x00, sizeof( ByteString* )* nRecCnt ); + + enum STATE { PreLine, InCommand, PostCommand, InId, PostEqu, + InVal, InName, InInExClude, InBodyMode, PostSepIEC, + PostSepBM, InComment }; + + STATE eAct = PreLine; + sal_Char c; + sal_Char cNext; + INT32 n = ( INT32 ) nStreamLen; + ByteString aCommand; + ByteString aVal; + ByteString aInExClude; + ByteString aHexBody; + UINT32 nLine = 1; + BOOL bCommand = FALSE; + + *pIn >> c >> cNext; + + while( n > 0 ) + { + n--; + + switch( eAct ) + { + case PreLine: + if( IsAlphaNum( c ) ) + { + if( IsNum( c ) ) + { + eAct = InId; + bCommand = FALSE; + } + else + { + eAct = InCommand; + bCommand = TRUE; + } + aCommand.Erase(); + aCommand += c; + } + else if( c == cComm1 && cNext == cComm2 ) + eAct = InComment; + else if( IsLineEnd( c, cNext, *pIn, n ) ) + nLine++; + else if( !IsBlank( c ) ) + { + AddError( nLine, "Unexpected command or id" ); + n = 0; + } + break; + case InCommand: + if( c == '=' ) + { + eAct = PostEqu; + aVal.Erase(); + } + else if( IsAlpha( c ) ) + aCommand += c; + else if( IsBlank( c ) ) + eAct = PostCommand; + else if( IsLineEnd( c, cNext, *pIn, n ) ) + { + if( ExecCommand( nLine, aCommand ) ) + { + eAct = PreLine; + nLine++; + } + else + n = 0; + } + else if( c == cComm1 && cNext == cComm2 ) + { + if( ExecCommand( nLine, aCommand ) ) + eAct = InComment; + else + { + AddError( nLine, "Invalid command before comment", aCommand ); + n = 0; + } + } + else + { + aCommand += '>'; + aCommand += c; + aCommand += '<'; + AddError( nLine, "Invalid character in command or id", aCommand ); + n = 0; + } + break; + case PostCommand: + if( c == '=' ) + { + eAct = PostEqu; + aVal.Erase(); + } + else if( IsLineEnd( c, cNext, *pIn, n ) ) + { + if( ExecCommand( nLine, aCommand ) ) + { + eAct = PreLine; + nLine++; + } + else + n = 0; + } + else if( c == cComm1 && cNext == cComm2 ) + { + if( ExecCommand( nLine, aCommand ) ) + eAct = InComment; + else + { + AddError( nLine, "Invalid command before comment", aCommand ); + n = 0; + } + } + else if( !IsBlank( c ) ) + { + AddError( nLine, "Expecting blank or \'=\' following the command", aCommand ); + n = 0; + } + break; + case InId: + if( c == '=' ) + { + eAct = PostEqu; + aVal.Erase(); + } + else if( IsAlphaNum( c ) ) + aCommand += c; + else if( IsBlank( c ) ) + eAct = PostCommand; + else if( ( c == cComm1 && cNext == cComm2 ) || IsLineEnd( c, cNext, *pIn, n ) ) + { + AddError( nLine, "Unexpected end of record id", aCommand ); + eAct = InComment; + } + else + { + AddError( nLine, "Unexpected sal_Char in record id", aCommand ); + n = 0; + } + break; + case PostEqu: + if( bCommand ) + { // Command + if( c == cComm1 && cNext == cComm2 ) + { + if( ExecCommand( nLine, aCommand ) ) + eAct = InComment; + else + { + AddError( nLine, "Unknown command", aCommand ); + n = 0; + } + } + else if( IsLineEnd( c, cNext, *pIn, n ) ) + { + if( ExecCommand( nLine, aCommand ) ) + { + eAct = PreLine; + nLine++; + } + else + { + AddError( nLine, "Unknown command", aCommand ); + n = 0; + } + } + else if( !bCommand && c == cParSep ) + eAct = PostSepIEC; + else if( !IsBlank( c ) ) + { + aVal.Erase(); + aVal += c; + eAct = InVal; + } + } + else + { // Set + if( ( c == cComm1 && cNext == cComm2 ) || IsLineEnd( c, cNext, *pIn, n ) ) + { + AddError( nLine, "No mode set for record", aCommand ); + n = 0; + } + else if( !bCommand && c == cParSep ) + eAct = PostSepIEC; + else + { + aVal.Erase(); + aVal += c; + eAct = InName; + aInExClude.Erase(); + aHexBody.Erase(); + } + } + break; + case InVal: + if( c == cComm1 && cNext == cComm2 ) + { + if( ExecCommand( nLine, aCommand, &aVal ) ) + eAct = InComment; + else + { + AddError( nLine, "Unknown command", aCommand ); + n = 0; + } + } + else if( IsLineEnd( c, cNext, *pIn, n ) ) + { + if( ExecCommand( nLine, aCommand, &aVal ) ) + { + eAct = PreLine; + nLine++; + } + else + { + AddError( nLine, "Unknown command", aCommand ); + n = 0; + } + } + else + aVal += c; + break; + case InName: + if( c == cParSep ) + eAct = PostSepIEC; + else if( c == cComm1 && cNext == cComm2 ) + { + if( ExecSetVal( nLine, aCommand, &aVal, NULL, NULL ) ) + eAct = InComment; + else + n = 0; + } + else if( IsLineEnd( c, cNext, *pIn, n ) ) + { + if( ExecSetVal( nLine, aCommand, &aVal, NULL, NULL ) ) + { + eAct = PreLine; + nLine++; + } + else + n = 0; + } + else + aVal += c; + break; + case InInExClude: + if( c == cParSep ) + eAct = PostSepBM; + else if( c == cComm1 && cNext == cComm2 ) + { + if( ExecSetVal( nLine, aCommand, &aVal, &aInExClude, NULL ) ) + eAct = InComment; + else + n = 0; + } + else if( IsLineEnd( c, cNext, *pIn, n ) ) + { + if( ExecSetVal( nLine, aCommand, &aVal, &aInExClude, NULL ) ) + { + eAct = PreLine; + nLine++; + } + else + n = 0; + } + else + aInExClude += c; + break; + case InBodyMode: + if( c == cParSep ) + { + AddError( nLine, "Only 3 parameter possible" ); + n = 0; + } + else if( c == cComm1 && cNext == cComm2 ) + { + if( ExecSetVal( nLine, aCommand, &aVal, &aInExClude, &aHexBody ) ) + eAct = InComment; + else + n = 0; + } + else if( IsLineEnd( c, cNext, *pIn, n ) ) + { + if( ExecSetVal( nLine, aCommand, &aVal, &aInExClude, &aHexBody ) ) + { + eAct = PreLine; + nLine++; + } + else + n = 0; + } + else + aInExClude += c; + break; + case PostSepIEC: + if( c == cParSep ) + eAct = PostSepBM; + else if( c == cComm1 && cNext == cComm2 ) + { + if( ExecSetVal( nLine, aCommand, &aVal, NULL, NULL ) ) + eAct = InComment; + else + n = 0; + } + else if( IsLineEnd( c, cNext, *pIn, n ) ) + { + if( ExecSetVal( nLine, aCommand, &aVal, NULL, NULL ) ) + { + eAct = PreLine; + nLine++; + } + else + n = 0; + } + else if( !IsBlank( c ) ) + { + aInExClude += c; + eAct = InInExClude; + } + break; + case PostSepBM: + if( c == cParSep ) + eAct = PostSepBM; + else if( c == cComm1 && cNext == cComm2 ) + { + if( ExecSetVal( nLine, aCommand, &aVal, &aInExClude, NULL ) ) + eAct = InComment; + else + n = 0; + } + else if( IsLineEnd( c, cNext, *pIn, n ) ) + { + if( ExecSetVal( nLine, aCommand, &aVal, &aInExClude, NULL ) ) + { + eAct = PreLine; + nLine++; + } + else + n = 0; + } + else if( !IsBlank( c ) ) + { + aHexBody += c; + eAct = InBodyMode; + } + break; + case InComment: + if( IsLineEnd( c, cNext, *pIn, n ) ) + { + eAct = PreLine; + nLine++; + } + break; + default: + n = 0; + } + + c = cNext; + *pIn >> cNext; + } + + pIn->Close(); + delete pIn; + } +} + + +BOOL Biff8RecDumper::ExecCommand( const UINT32 nL, const ByteString& r, const ByteString* pVal ) +{ + _KEYWORD e = GetKeyType( r ); + BOOL b = TRUE; + const UINT32 nValLen = ( pVal )? pVal->Len() : 0; + BOOL bSet; + UINT16 nMode; + + switch( e ) + { + case Skipdump: bSkip = TRUE; break; + case SkipOffset: bSkipOffset = TRUE; break; + case ReadContRecs: bReadContRecs = TRUE; break; + case NoWarnings: bWarnings = FALSE; break; + case Contload: bEndLoading = TRUE; break; + case BlankLine: bBlankLine = TRUE; break; + case ExportBookStream: bExportBookStream = TRUE; break; + case Parsep: + if( nValLen == 0 ) + { + AddError( nL, "No separator found" ); + b = FALSE; + } + else if( nValLen == 1 ) + cParSep = *( pVal->GetBuffer() ); + else + { + AddError( nL, "More than 1 sal_Char is not valid for separator", *pVal ); + b = FALSE; + } + break; + case Maxbodylines: + if( nValLen ) + { + UINT32 n = GetVal( *pVal ); + + if( n == 0xFFFFFFFF ) + { + AddError( nL, "Syntax error in value of body lines" ); + b = FALSE; + } + else + nMaxBodyLines = n; + } + else + { + AddError( nL, "No value specified for number of body lines" ); + b = FALSE; + } + break; + case Include: + bSet = FALSE; + nMode = MODE_SKIP; + goto _common; + case Exclude: + bSet = TRUE; + nMode = MODE_SKIP; + goto _common; + case Hex: + bSet = TRUE; + nMode = MODE_HEX; + goto _common; + case Body: + bSet = FALSE; + nMode = MODE_HEX; + goto _common; + case NameOnly: + bSet = TRUE; + nMode = MODE_NAMEONLY; + goto _common; +_common: + if( pVal ) + { + IdRangeList aRL; + if( FillIdRangeList( nL, aRL, *pVal ) ) + { + const IdRange* p = aRL.First(); + if( bSet ) + { + while( p ) + { SetFlag( p->nFirst, p->nLast, nMode ); p = aRL.Next(); } + } + else + { + while( p ) + { ClrFlag( p->nFirst, p->nLast, nMode ); p = aRL.Next(); } + } + } + else + b = FALSE; + } + break; + case Comment: + if( pVal && pVal->Len() >= 2 ) + { + cComm1 = pVal->GetChar( 0 ); + cComm2 = pVal->GetChar( 1 ); + } + break; + case Output: + CopyStrpOnStrp( pOutName, pVal ); + if( pOutName ) + { + if( *pOutName == "*" ) + { + ByteString aDefault( "DefaultDumpName.txt" ); + SfxObjectShell* pShell = GetDocShell(); + if( pShell ) + { + SfxMedium* pMedium = pShell->GetMedium(); + if( pMedium ) + { + const ByteString aTextExtension( ".txt" ); + aDefault = GETSTR( pMedium->GetPhysicalName() ); + xub_StrLen nStrLen = aDefault.Len(); + if( nStrLen >= 4 ) + { + ByteString aTmp( aDefault ); + aTmp.ToLowerAscii(); + if( aTmp.Copy( nStrLen -4 ) == ".xls" ) + aDefault.Replace( nStrLen - 4, aTextExtension.Len(), aTextExtension ); + else + aDefault += aTextExtension; + } + else + aDefault += aTextExtension; + } + } + + *pOutName = aDefault; + } + CreateOutStream(); + } + else if( pDumpStream ) + { + pDumpStream->Close(); + DELANDNULL( pDumpStream ); + } + break; + case Title: + CopyStrpOnStrp( pTitle, pVal ); + break; + case ClearFile: + bClearFile = TRUE; + break; + default: + AddError( nL, "Unknown command", r ); + b = FALSE; + } + + return b; +} + + +BOOL Biff8RecDumper::ExecSetVal( const UINT32 nL, const ByteString& rId, const ByteString* pName, + const ByteString* pIEC, const ByteString* pHB ) +{ + UINT32 _nId = GetVal( rId ); + + if( _nId == 0xFFFFFFFF ) + { + AddError( nL, "Syntax error in record id", rId ); + return FALSE; + } + else if( _nId >= ( UINT32 ) nRecCnt ) + { + AddError( nL, "Record id to high", rId ); + return FALSE; + } + + UINT16 nId = ( UINT16 ) _nId; + + if( pName && pName->Len() ) + SetName( nId, *pName ); + + _KEYWORD e; + UINT16 n = GetMode( nId ); + + if( pIEC && pIEC->Len() ) + { + e = GetKeyType( *pIEC ); + + if( e == Include ) + n &= ~MODE_SKIP; + else if( e == Exclude ) + n |= MODE_SKIP; + else + { + AddError( nL, "Invalid key for in-/exclude", *pIEC ); + return FALSE; + } + } + + if( pHB && pHB->Len() ) + { + e = GetKeyType( *pHB ); + + if( e == NameOnly ) + n |= MODE_NAMEONLY; + else + { + n &= ~MODE_NAMEONLY; + if( e == Hex ) + n |= MODE_HEX; + else if( e == Body ) + n &= ~MODE_HEX; + else + { + AddError( nL, "Invalid key for hex/body/name only", *pIEC ); + return FALSE; + } + } + } + + SetMode( nId, n ); + return TRUE; +} + + +void Biff8RecDumper::SetFlag( const UINT16 nF, const UINT16 nL, const UINT16 nFl ) +{ + UINT16 n = ( nF < nL )? nF : nL; + UINT16 nLast = ( nF < nL )? nL : nF; + + if( nLast >= nRecCnt ) + nLast = nRecCnt - 1; + + while( n <= nLast ) + { + pDumpModes[ n ] |= nFl; + n++; + } +} + + +void Biff8RecDumper::ClrFlag( const UINT16 nF, const UINT16 nL, const UINT16 nFlags ) +{ + UINT16 n = ( nF < nL )? nF : nL; + UINT16 nLast = ( nF < nL )? nL : nF; + UINT16 nFl = ~nFlags; + + if( nLast >= nRecCnt ) + nLast = nRecCnt - 1; + + while( n <= nLast ) + { + pDumpModes[ n ] &= nFl; + n++; + } +} + + +void Biff8RecDumper::SetName( const UINT16 n, ByteString* p ) +{ + if( n < nRecCnt ) + CopyStrpOnStrp( ppRecNames[ n ], p ); +} + + +UINT32 Biff8RecDumper::GetVal( const ByteString& r ) +{ + const sal_Char* p = r.GetBuffer(); + sal_Char c = *p; + UINT32 n = 0; + const UINT32 nLimitDec = 0xFFFFFFFF / 10; + const UINT32 nLimitHex = 0xFFFFFFFF / 16; + BOOL bError = FALSE; + + enum STATE { First, Dec, MaybeHex, Hex }; + + STATE e = First; + + while( c ) + { + switch( e ) + { + case First: + if( IsNum( c ) ) + { + if( c == '0' ) + e = MaybeHex; + else + { + e = Dec; + n = GetVal( c ); + } + } + else + bError = TRUE; + break; + case Dec: + if( n < nLimitDec && IsNum( c ) ) + { + n *= 10; + n += GetVal( c ); + } + else + bError = TRUE; + break; + case MaybeHex: + if( c == 'x' || c == 'X' ) + { + e = Hex; + n = 0; + } + else if( IsNum( c ) ) + { + n = GetVal( c ); + e = Dec; + } + else + bError = TRUE; + break; + case Hex: + if( n < nLimitHex && IsHex( c ) ) + { + n *= 16; + n += GetVal( c ); + } + else + bError = TRUE; + break; + } + + if( bError ) + c = 0x00; + else + { + p++; + c = *p; + } + } + + if( bError ) + return 0xFFFFFFFF; + else + return n; +} + + +BOOL Biff8RecDumper::FillIdRangeList( const UINT32 nL, IdRangeList& rRL, const ByteString& rV ) +{ + rRL.Clear(); + + const sal_Char* pSyntErr = "Syntax error in number (list)"; + +#define SYNTERR(ch) AddError( ((UINT32)(b=FALSE))+nL, pSyntErr, ch? ((((t+=">")+=ByteString::CreateFromInt32(ch))+="<")) : t ) +#define NEWVAL(_n) _n=(n>=(UINT32)nRecCnt)?nRecCnt-1:(UINT16)n +#define ORDERN() {if(n1>n2){UINT16 nT=n1;n1=n2;n2=nT;}} + + const sal_Char* p = rV.GetBuffer(); + sal_Char c = *p; + const sal_Char cSep = cParSep; + const sal_Char cCont = '.'; + const sal_Char cAll = '*'; + ByteString t; + UINT16 n1 = 0, n2 = 0; + UINT32 n; + BOOL b = TRUE; + BOOL bExp2 = FALSE; + + enum STATE { PreFirst, InFirst, PostFirst, InCont, PreLast, InLast, PostLast }; + STATE e = PreFirst; + + while( c ) + { + switch( e ) + { + case PreFirst: + if( IsAlphaNum( c ) ) + { + t += c; + e = InFirst; + } + else if( c == cAll ) + { + rRL.Append( 0, nRecCnt - 1 ); + e = PostLast; + } + else if( !IsBlank( c ) ) + SYNTERR( c ); + break; + case InFirst: + if( c == cSep || c == cCont || IsBlank( c ) ) + { + n = GetVal( t ); + if( n == 0xFFFFFFFF ) + SYNTERR( 0 ); + else + NEWVAL( n1 ); + + t.Erase(); + + if( c == cSep ) + { + rRL.Append( n1, n1 ); + e = PreFirst; + } + else if( c == cCont ) + { + bExp2 = TRUE; + e = InCont; + } + else + e = PostFirst; + } + else if( IsAlphaNum( c ) ) + t += c; + else + SYNTERR( c ); + break; + case PostFirst: + if( c == cCont ) + { + e = InCont; + bExp2 = TRUE; + } + else if( c == cSep ) + { + n = GetVal( t ); + if( n == 0xFFFFFFFF ) + SYNTERR( 0 ); + else + NEWVAL( n1 ); + + e = PreFirst; + } + else if( !IsBlank( c ) ) + SYNTERR( c ); + break; + case InCont: + if( IsAlphaNum( c ) ) + { + t += c; + e = InLast; + } + else if( IsBlank( c ) ) + e = PreLast; + else if( c == cSep || c == cAll ) + { + rRL.Append( n1, nRecCnt - 1 ); + bExp2 = FALSE; + e = PreFirst; + } + else if( c != cCont ) + SYNTERR( c ); + break; + case PreLast: + if( IsAlphaNum( c ) ) + { + t += c; + e = InLast; + } + else if( !IsBlank( c ) ) + SYNTERR( c ); + break; + break; + case InLast: + if( c == cSep || IsBlank( c ) ) + { + n = GetVal( t ); + if( n == 0xFFFFFFFF ) + SYNTERR( 0 ); + else + NEWVAL( n2 ); + + t.Erase(); + ORDERN(); + rRL.Append( n1, n2 ); + bExp2 = FALSE; + e = ( c == cSep )? PreFirst : PostLast; + } + else if( IsAlphaNum( c ) ) + t += c; + else + SYNTERR( c ); + break; + case PostLast: + if( c == cSep ) + { + e = PreFirst; + bExp2 = FALSE; + } + else if( !IsBlank( c ) ) + SYNTERR( c ); + break; + } + + if( b ) + { + p++; + c = *p; + } + else + c = 0x00; + } + + if( bExp2 ) + { + if( t.Len() ) + { + n = GetVal( t ); + if( n == 0xFFFFFFFF ) + SYNTERR( 0 ); + else + NEWVAL( n2 ); + ORDERN(); + } + else + n2 = nRecCnt - 1; + + if( b ) + rRL.Append( n1, n2 ); + } + +#undef SYNTERR +#undef NEWVAL +#undef ORDERN + + return b; +} + + +BOOL Biff8RecDumper::CreateOutStream() +{ + if( pDumpStream ) + { + pDumpStream->Close(); + DELANDNULL( pDumpStream ); + } + + if( !bSkip && pOutName ) + { + pOutName->EraseLeadingChars( ' ' ); + pOutName->EraseTrailingChars( ' ' ); + pOutName->EraseLeadingChars( '\t' ); + pOutName->EraseTrailingChars( '\t' ); + + pDumpStream = new SvFileStream( String::CreateFromAscii( pOutName->GetBuffer() ), STREAM_WRITE|STREAM_SHARE_DENYWRITE|(bClearFile?STREAM_TRUNC:0) ); + + if( pDumpStream->IsOpen() ) + { + pDumpStream->Seek( bClearFile? STREAM_SEEK_TO_BEGIN : STREAM_SEEK_TO_END ); + return TRUE; + } + else + { + DELANDNULL( pDumpStream ); + } + } + + return FALSE; +} + + +SvFileStream* Biff8RecDumper::CreateInStream( const sal_Char* pN ) +{ + SvFileStream* p = new SvFileStream( String::CreateFromAscii( pN ), STREAM_READ|STREAM_SHARE_DENYWRITE ); + + if( p->IsOpen() ) + return p; + else + { + delete p; + return NULL; + } +} + + +SvFileStream* Biff8RecDumper::CreateInStream( const sal_Char* pP, const sal_Char* pN ) +{ + ByteString t( pP ); + const sal_Char c = t.GetChar( t.Len() - 1 ); + + if( c != '\\' ) + t += '\\'; + else if( c != '/' ) + t += '/'; + + t += pN; + + return CreateInStream( t.GetBuffer() ); +} + + +void Biff8RecDumper::AddError( const UINT32 n, const ByteString& rT, const ByteString& rH ) +{ + DUMP_ERR* p = new DUMP_ERR( n, rT, rH ); + + if( pFirst ) + pLast->pNext = p; + else + pFirst = p; + + pLast = p; +} + + +Biff8RecDumper::Biff8RecDumper( const XclImpRoot& rRoot, BOOL _bBIFF8 ) : + XclImpRoot( rRoot ), + bBIFF8( _bBIFF8 ), + bEncrypted( false ), + mnEscherPos( 0 ) +{ + nXFCount = 0; + nFontIndex = 0; + nInstances++; + mnSubstream = EXC_BOF_UNKNOWN; + + if( !pCharType ) + { + pCharType = new UINT8[ 256 ]; + memset( pCharType, 0x00, 256 ); + + pCharVal = new UINT8[ 256 ]; + memset( pCharVal, 0x00, 256 ); + + sal_Char c; + UINT8 n; + +#define __TYPE(n) pCharType[(UINT8)n] +#define __VAL(n) pCharVal[(UINT8)n] + + __TYPE( '\n' ) = CT_EOL; + __TYPE( '\r' ) = CT_EOL; + + __TYPE( ' ' ) = CT_BLANK; + __TYPE( '\t' ) = CT_BLANK; + + for( c = '0', n = 0 ; c <= '9' ; c++, n++ ) + { + __TYPE( c ) = CT_NUM|CT_HEX|CT_ALPHANUM; + __VAL( c ) = n; + } + for( c = 'a', n = 10 ; c <= 'f' ; c++, n++ ) + { + __TYPE( c ) = CT_HEX|CT_ALPHA|CT_ALPHANUM|CT_LOWERALPHA; + __VAL( c ) = n; + } + for( c = 'g' ; c <= 'z' ; c++ ) + __TYPE( c ) = CT_ALPHA|CT_ALPHANUM|CT_LOWERALPHA; + for( c = 'A', n = 10 ; c <= 'F' ; c++, n++ ) + { + __TYPE( c ) = CT_HEX|CT_ALPHA|CT_ALPHANUM|CT_UPPERALPHA; + __VAL( c ) = n; + } + for( c = 'G' ; c <= 'Z' ; c++ ) + __TYPE( c ) = CT_ALPHA|CT_ALPHANUM|CT_UPPERALPHA; + +#undef __TYPE +#undef __VAL + } + + pDumpStream = NULL; + + if( !pBlankLine ) + { + pBlankLine = new sal_Char[ nLenBlankLine + 1 ]; + memset( pBlankLine, ' ', nLenBlankLine ); + pBlankLine[ nLenBlankLine ] = 0x00; + } + + pTitle = NULL; + pOutName = NULL; + pLevelPre = pLevelPreStringNT; + + nMaxBodyLines = 1024; + bEndLoading = bSkip = bSkipOffset = bReadContRecs = bBlankLine = bExportBookStream = FALSE; + bWarnings = TRUE; + + pDumpModes = NULL; + ppRecNames = NULL; + + pFirst = pLast = pAct = NULL; + + cParSep = ','; + cComm1 = cComm2 = '/'; + + nFieldCnt = nItemCnt = nTabIndexCnt = 0; + + Init(); +} + + +Biff8RecDumper::~Biff8RecDumper() +{ + if( pDumpStream ) + { + pDumpStream->Close(); + delete pDumpStream; + } + + if( nInstances ) + { + nInstances--; + if( !nInstances ) + { + delete[] pBlankLine; + pBlankLine = NULL; + + delete[] pCharType; + pCharType = NULL; + + delete[] pCharVal; + pCharVal = NULL; + } + } + + if( pDumpModes ) + delete[] pDumpModes; + + if( ppRecNames ) + { + ByteString** pp = ppRecNames; + UINT16 n = nRecCnt; + while( n ) + { + if( *pp ) + delete *pp; + pp++; + n--; + } + delete[] ppRecNames; + } + + if( pTitle ) + delete pTitle; + + if( pOutName ) + delete pOutName; + + DUMP_ERR* p = pFirst; + DUMP_ERR* pD; + if( p ) + { + pD = p; + p = p->pNext; + delete pD; + } +} + + +BOOL Biff8RecDumper::Dump( XclImpStream& r ) +{ + const DUMP_ERR* pErr = FirstErr(); + + if( pErr ) + { + if( pDumpStream ) + { + SvFileStream& rOut = *pDumpStream; + while( pErr ) + { + rOut << "\nError"; + if( pErr->nLine ) + { + ByteString t; + t += ByteString::CreateFromInt32( pErr->nLine ); + rOut << " at line " << t.GetBuffer(); + } + + rOut << ": " << pErr->aText.GetBuffer(); + + if( pErr->pHint ) + rOut << " (" << pErr->pHint->GetBuffer() << ')'; + pErr = NextErr(); + } + rOut << '\n'; + } + } + else if( pDumpStream && !bSkip ) + { + SvStream& rOutStrm = *pDumpStream; + + if( bExportBookStream && pOutName ) + { + ByteString aBookOutName( *pOutName, 0, pOutName->Len() - 4 ); + aBookOutName.Append( "_book.xls" ); + SvFileStream aBook( String::CreateFromAscii( aBookOutName.GetBuffer() ), STREAM_WRITE|STREAM_SHARE_DENYWRITE|STREAM_TRUNC ); + if( aBook.IsOpen() ) + { + const sal_uInt32 nBufLen = 0xFFFF; + sal_uInt8 pBuffer[ nBufLen ]; + r.StoreGlobalPosition(); + while( r.StartNextRecord() ) + { + r.ResetRecord( false ); + sal_uInt16 nRecSize = (sal_uInt16) Min( r.GetRecSize(), nBufLen ); + aBook << r.GetRecId() << nRecSize; + r.Read( pBuffer, nRecSize ); + aBook.Write( pBuffer, nRecSize ); + } + r.SeekGlobalPosition(); + } + } + + if( pTitle ) + rOutStrm << pTitle->GetBuffer(); + + pIn = &r; + r.StoreGlobalPosition(); + + ::std::auto_ptr< XclDumpStorageHeader > xStrgHerader; + SotStorageRef xRootStrg = GetRootStorage(); + if( xRootStrg.Is() ) + xStrgHerader.reset( new XclDumpStorageHeader( *xRootStrg, rOutStrm, EMPTY_STRING ) ); + + ::std::auto_ptr< ScfProgressBar > xProgress( new ScfProgressBar( + GetDocShell(), String( RTL_CONSTASCII_USTRINGPARAM( "Dumper" ) ) ) ); + sal_Int32 nStreamSeg = xProgress->AddSegment( r.GetSvStreamSize() ); + xProgress->ActivateSegment( nStreamSeg ); + + while( r.StartNextRecord() ) + { + xProgress->ProgressAbs( r.GetSvStreamPos() ); + if( HasModeDump( r.GetRecId() ) ) + RecDump(); + } + + rOutStrm << "\n\n"; + + pIn = NULL; + xProgress.reset(); + + r.SeekGlobalPosition(); + + // dump substreams + if( xRootStrg.Is() ) + { + pIn = NULL; + bool bOldEncr = bEncrypted; + bEncrypted = false; + DumpRecordStream( xRootStrg, EXC_STREAM_USERNAMES, EMPTY_STRING ); + + pIn = &r; + bEncrypted = bOldEncr; + DumpRecordStream( xRootStrg, EXC_STREAM_REVLOG, EMPTY_STRING ); + + pIn = NULL; + + DumpCtlsStream(); + DumpVbaProjectStorage(); + } + } + + return !bEndLoading; +} + +#undef Read1 +#undef Read2 +#undef Read4 +#undef Read8 + +#endif + diff --git a/sc/source/filter/excel/colrowst.cxx b/sc/source/filter/excel/colrowst.cxx index 312604d7ab92..b1ec8752de7b 100644 --- a/sc/source/filter/excel/colrowst.cxx +++ b/sc/source/filter/excel/colrowst.cxx @@ -95,6 +95,12 @@ void XclImpColRowSettings::SetWidthRange( SCCOL nScCol1, SCCOL nScCol2, sal_uInt { DBG_ASSERT( (nScCol1 <= nScCol2) && ValidCol( nScCol2 ), "XclImpColRowSettings::SetColWidthRange - invalid column range" ); nScCol2 = ::std::min( nScCol2, MAXCOL ); + if (nScCol2 == 256) + // In BIFF8, the column range is 0-255, and the use of 256 probably + // means the range should extend to the max column if the loading app + // support columns beyond 255. + nScCol2 = MAXCOL; + nScCol1 = ::std::min( nScCol1, nScCol2 ); ::std::fill( maWidths.begin() + nScCol1, maWidths.begin() + nScCol2 + 1, nWidth ); for( ScfUInt8Vec::iterator aIt = maColFlags.begin() + nScCol1, aEnd = maColFlags.begin() + nScCol2 + 1; aIt != aEnd; ++aIt ) diff --git a/sc/source/filter/excel/excdoc.cxx b/sc/source/filter/excel/excdoc.cxx index 80cfdf7d14cb..e5303ffbdb50 100644 --- a/sc/source/filter/excel/excdoc.cxx +++ b/sc/source/filter/excel/excdoc.cxx @@ -68,11 +68,11 @@ #include "convuno.hxx" #include "patattr.hxx" #include "docoptio.hxx" +#include "tabprotection.hxx" #include "excdoc.hxx" #include "namebuff.hxx" -#include "xcl97dum.hxx" #include "xcl97rec.hxx" #include "xcl97esc.hxx" #include "xetable.hxx" @@ -118,7 +118,7 @@ static void lcl_AddCalcPr( XclExpRecordList<>& aRecList, ExcTable& self ) aRecList.AppendNewRecord( new XclRefmode( rDoc ) ); aRecList.AppendNewRecord( new XclIteration( rDoc ) ); aRecList.AppendNewRecord( new XclDelta( rDoc ) ); - aRecList.AppendNewRecord( new ExcDummy8_02 ); + aRecList.AppendNewRecord( new XclExpBoolRecord(0x005F, true) ); // SAVERECALC aRecList.AppendNewRecord( new XclExpXmlEndSingleElementRecord() ); // XML_calcPr } @@ -207,7 +207,16 @@ void ExcTable::FillAsHeader( ExcBoundsheetList& rBoundsheetList ) Add( new ExcDummy_00 ); else { - Add( new ExcDummy8_00a ); + if ( IsDocumentEncrypted() ) + Add( new XclExpFilePass(GetRoot()) ); + + Add( new XclExpInterfaceHdr ); + Add( new XclExpMMS ); + Add( new XclExpInterfaceEnd ); + Add( new XclExpWriteAccess ); + Add( new XclExpCodePage ); + Add( new XclExpDSF ); + Add( new XclExpExcel9File ); rR.pTabId = new XclExpChTrTabId( Max( nExcTabCount, nCodenames ) ); Add( rR.pTabId ); if( HasVbaStorage() ) @@ -217,7 +226,8 @@ void ExcTable::FillAsHeader( ExcBoundsheetList& rBoundsheetList ) if( rCodeName.Len() ) Add( new XclCodename( rCodeName ) ); } - Add( new ExcDummy8_00b ); + + Add( new XclExpFnGroupCount ); } // erst Namen- und Tabellen-Eintraege aufbauen @@ -237,12 +247,22 @@ void ExcTable::FillAsHeader( ExcBoundsheetList& rBoundsheetList ) aRecList.AppendRecord( CreateRecord( EXC_ID_NAME ) ); } - aRecList.AppendNewRecord( new XclExpWindowProtection( GetExtDocOptions().GetDocSettings().mbWinProtected ) ); - aRecList.AppendNewRecord( new XclExpDocProtection( rDoc.IsDocProtected() ) ); - aRecList.AppendNewRecord( new XclExpBoolRecord( EXC_ID_PASSWORD, false ) ); + // document protection options + const ScDocProtection* pProtect = GetDoc().GetDocProtection(); + if (pProtect && pProtect->isProtected()) + { + Add( new XclExpWindowProtection(pProtect->isOptionEnabled(ScDocProtection::WINDOWS)) ); + Add( new XclExpProtection(pProtect->isOptionEnabled(ScDocProtection::STRUCTURE)) ); +#if ENABLE_SHEET_PROTECTION + Add( new XclExpPassHash(pProtect->getPasswordHash(PASSHASH_XL)) ); +#endif + } if( GetBiff() == EXC_BIFF8 ) - Add( new ExcDummy8_040 ); + { + Add( new XclExpProt4Rev ); + Add( new XclExpProt4RevPass ); + } // document protection options if( GetOutput() == EXC_OUTPUT_BINARY ) @@ -253,6 +273,12 @@ void ExcTable::FillAsHeader( ExcBoundsheetList& rBoundsheetList ) Add( new XclExpXmlStartSingleElementRecord( XML_workbookPr ) ); + if ( GetBiff() == EXC_BIFF8 ) + { + Add( new XclExpBoolRecord(0x0040, false) ); // BACKUP + Add( new XclExpBoolRecord(0x008D, false) ); // HIDEOBJ + } + if( GetBiff() <= EXC_BIFF5 ) { Add( new ExcDummy_040 ); @@ -261,9 +287,11 @@ void ExcTable::FillAsHeader( ExcBoundsheetList& rBoundsheetList ) } else { + // BIFF8 Add( new Exc1904( rDoc ) ); Add( new XclExpBoolRecord( 0x000E, !rDoc.GetDocOptions().IsCalcAsShown() ) ); - Add( new ExcDummy8_041 ); + Add( new XclExpBoolRecord(0x01B7, false) ); // REFRESHALL + Add( new XclExpBoolRecord(0x00DA, false) ); // BOOKBOOL // OOXTODO: The following /workbook/workbookPr attributes are mapped // to various BIFF records that are not currently supported: // @@ -359,10 +387,14 @@ void ExcTable::FillAsHeader( ExcBoundsheetList& rBoundsheetList ) if( GetOutput() != EXC_OUTPUT_BINARY ) lcl_AddCalcPr( aRecList, *this ); + Add( new XclExpRecalcId ); + // MSODRAWINGGROUP per-document data aRecList.AppendRecord( GetObjectManager().CreateDrawingGroup() ); // Shared string table: SST, EXTSST aRecList.AppendRecord( CreateRecord( EXC_ID_SST ) ); + + Add( new XclExpBookExt ); } Add( new ExcEof ); @@ -422,8 +454,16 @@ void ExcTable::FillAsTable( size_t nCodeNameIdx ) // page settings (SETUP and various other records) aRecList.AppendRecord( xPageSett ); - if( rDoc.IsTabProtected( mnScTab ) ) - Add( new XclProtection() ); + const ScTableProtection* pTabProtect = rDoc.GetTabProtection(mnScTab); + if (pTabProtect && pTabProtect->isProtected()) + { + Add( new XclExpProtection(true) ); + Add( new XclExpBoolRecord(0x00DD, pTabProtect->isOptionEnabled(ScTableProtection::SCENARIOS)) ); + Add( new XclExpBoolRecord(0x0063, pTabProtect->isOptionEnabled(ScTableProtection::OBJECTS)) ); +#if ENABLE_SHEET_PROTECTION + Add( new XclExpPassHash(pTabProtect->getPasswordHash(PASSHASH_XL)) ); +#endif + } // local link table: EXTERNCOUNT, EXTERNSHEET if( eBiff <= EXC_BIFF5 ) @@ -459,6 +499,9 @@ void ExcTable::FillAsTable( size_t nCodeNameIdx ) if( eBiff == EXC_BIFF8 ) { + // sheet protection options + Add( new XclExpSheetProtectOptions( GetRoot(), mnScTab ) ); + // web queries Add( new XclExpWebQueryBuffer( GetRoot() ) ); @@ -759,7 +802,7 @@ void ExcDocument::WriteXml( SvStream& rStrm ) rWorkbook->endElement( XML_workbook ); rWorkbook.reset(); - aStrm.commit(); + aStrm.commitStorage(); } #if 0 if( pExpChangeTrack ) diff --git a/sc/source/filter/excel/excel.cxx b/sc/source/filter/excel/excel.cxx index 7072785b8936..3965d0acaf4e 100644 --- a/sc/source/filter/excel/excel.cxx +++ b/sc/source/filter/excel/excel.cxx @@ -39,6 +39,7 @@ #include <tools/globname.hxx> #include <comphelper/mediadescriptor.hxx> #include <comphelper/processfactory.hxx> +#include <com/sun/star/beans/NamedValue.hpp> #include <com/sun/star/document/XFilter.hpp> #include <com/sun/star/document/XImporter.hpp> #include "scitems.hxx" @@ -86,9 +87,13 @@ FltError ScFormatFilterPluginImpl::ScImportExcel( SfxMedium& rMedium, ScDocument { uno::Reference< lang::XComponent > xComponent( pDocShell->GetModel(), uno::UNO_QUERY_THROW ); + uno::Sequence< beans::NamedValue > aArgSeq( 1 ); + aArgSeq[ 0 ].Name = CREATE_OUSTRING( "UseBiffFilter" ); + aArgSeq[ 0 ].Value <<= bUseOoxFilter; + uno::Sequence< uno::Any > aArgs( 2 ); aArgs[ 0 ] <<= getProcessServiceFactory(); - aArgs[ 1 ] <<= !bUseOoxFilter; + aArgs[ 1 ] <<= aArgSeq; uno::Reference< document::XImporter > xImporter( ScfApiHelper::CreateInstanceWithArgs( CREATE_OUSTRING( "com.sun.star.comp.oox.ExcelBiffFilter" ), aArgs ), uno::UNO_QUERY_THROW ); xImporter->setTargetDocument( xComponent ); diff --git a/sc/source/filter/excel/excimp8.cxx b/sc/source/filter/excel/excimp8.cxx index b62470ceee3b..1d209b91bc68 100644 --- a/sc/source/filter/excel/excimp8.cxx +++ b/sc/source/filter/excel/excimp8.cxx @@ -160,12 +160,6 @@ void ImportExcel8::Iteration( void ) } -void ImportExcel8:: WinProtection( void ) -{ - if( aIn.ReaduInt16() != 0 ) - GetExtDocOptions().GetDocSettings().mbWinProtected = true; -} - void ImportExcel8::Boundsheet( void ) { UINT8 nLen; @@ -249,6 +243,11 @@ void ImportExcel8::Codename( BOOL bWorkbookGlobals ) } } +void ImportExcel8::SheetProtection( void ) +{ + GetSheetProtectBuffer().ReadOptions( aIn, GetCurrScTab() ); +} + bool lcl_hasVBAEnabled() { uno::Reference< beans::XPropertySet > xProps( ::comphelper::getProcessServiceFactory(), uno::UNO_QUERY); @@ -295,6 +294,8 @@ void ImportExcel8::PostDocLoad( void ) pExcRoot->pAutoFilterBuffer->Apply(); GetWebQueryBuffer().Apply(); //! test if extant + GetSheetProtectBuffer().Apply(); + GetDocProtectBuffer().Apply(); ImportExcel::PostDocLoad(); @@ -426,6 +427,38 @@ void XclImpAutoFilterData::InsertQueryParam() } } +static void ExcelQueryToOooQuery( ScQueryEntry& rEntry ) +{ + if( ( rEntry.eOp != SC_EQUAL && rEntry.eOp != SC_NOT_EQUAL ) || rEntry.pStr == NULL ) + return; + else + { + xub_StrLen nLen = rEntry.pStr->Len(); + sal_Unicode nStart = rEntry.pStr->GetChar( 0 ); + sal_Unicode nEnd = rEntry.pStr->GetChar( nLen-1 ); + if( nLen >2 && nStart == '*' && nEnd == '*' ) + { + rEntry.pStr->Erase( nLen-1, 1 ); + rEntry.pStr->Erase( 0, 1 ); + rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_CONTAINS : SC_DOES_NOT_CONTAIN; + } + else if( nLen > 1 && nStart == '*' && nEnd != '*' ) + { + rEntry.pStr->Erase( 0, 1 ); + rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_ENDS_WITH : SC_DOES_NOT_END_WITH; + } + else if( nLen > 1 && nStart != '*' && nEnd == '*' ) + { + rEntry.pStr->Erase( nLen-1, 1 ); + rEntry.eOp = ( rEntry.eOp == SC_EQUAL ) ? SC_BEGINS_WITH : SC_DOES_NOT_BEGIN_WITH; + } + else if( nLen == 2 && nStart == '*' && nEnd == '*' ) + { + rEntry.pStr->Erase( 0, 1 ); + } + } +} + void XclImpAutoFilterData::ReadAutoFilter( XclImpStream& rStrm ) { UINT16 nCol, nFlags; @@ -463,14 +496,14 @@ void XclImpAutoFilterData::ReadAutoFilter( XclImpStream& rStrm ) BOOL bIgnore; UINT8 nStrLen[ 2 ] = { 0, 0 }; - String* pEntryStr[ 2 ] = { NULL, NULL }; + ScQueryEntry *pQueryEntries[ 2 ] = { NULL, NULL }; for( nE = 0; nE < 2; nE++ ) { if( nFirstEmpty < nCount ) { ScQueryEntry& aEntry = aParam.GetEntry( nFirstEmpty ); - pEntryStr[ nE ] = aEntry.pStr; + pQueryEntries[ nE ] = &aEntry; bIgnore = FALSE; rStrm >> nType >> nOper; @@ -558,8 +591,12 @@ void XclImpAutoFilterData::ReadAutoFilter( XclImpStream& rStrm ) } for( nE = 0; nE < 2; nE++ ) - if( nStrLen[ nE ] && pEntryStr[ nE ] ) - pEntryStr[ nE ]->Assign( rStrm.ReadUniString( nStrLen[ nE ] ) ); + if( nStrLen[ nE ] && pQueryEntries[ nE ] ) + { + pQueryEntries[ nE ]->pStr->Assign ( rStrm.ReadUniString( nStrLen[ nE ] ) ); + ExcelQueryToOooQuery( *pQueryEntries[ nE ] ); + } + } } diff --git a/sc/source/filter/excel/excrecds.cxx b/sc/source/filter/excel/excrecds.cxx index 9d50ea0db534..5e31a2229919 100644 --- a/sc/source/filter/excel/excrecds.cxx +++ b/sc/source/filter/excel/excrecds.cxx @@ -101,6 +101,7 @@ #include <oox/core/tokens.hxx> +using ::com::sun::star::uno::Sequence; using ::rtl::OString; @@ -433,7 +434,9 @@ ExcBundlesheetBase::ExcBundlesheetBase() : void ExcBundlesheetBase::UpdateStreamPos( XclExpStream& rStrm ) { rStrm.SetSvStreamPos( nOwnPos ); + rStrm.DisableEncryption(); rStrm << static_cast<sal_uInt32>(nStrPos); + rStrm.EnableEncryption(); } @@ -533,7 +536,7 @@ void XclExpWsbool::SaveXml( XclExpXmlStream& rStrm ) // XclExpWindowProtection =============================================================== XclExpWindowProtection::XclExpWindowProtection(bool bValue) : - XclExpBoolRecord(EXC_ID_WINDOWPROTECT,bValue) + XclExpBoolRecord(EXC_ID_WINDOWPROTECT, bValue) { } @@ -546,13 +549,35 @@ void XclExpWindowProtection::SaveXml( XclExpXmlStream& rStrm ) // XclExpDocProtection =============================================================== -XclExpDocProtection::XclExpDocProtection(bool bValue) : - XclExpBoolRecord(EXC_ID_PROTECT,bValue) +XclExpProtection::XclExpProtection(bool bValue) : + XclExpBoolRecord(EXC_ID_PROTECT, bValue) { } // ============================================================================ +XclExpPassHash::XclExpPassHash(const Sequence<sal_Int8>& aHash) : + XclExpRecord(EXC_ID_PASSWORD, 2), + mnHash(0x0000) +{ + if (aHash.getLength() >= 2) + { + mnHash = ((aHash[0] << 8) & 0xFFFF); + mnHash |= (aHash[1] & 0xFF); + } +} + +XclExpPassHash::~XclExpPassHash() +{ +} + +void XclExpPassHash::WriteBody(XclExpStream& rStrm) +{ + rStrm << mnHash; +} + +// ============================================================================ + XclExpFiltermode::XclExpFiltermode() : XclExpEmptyRecord( EXC_ID_FILTERMODE ) { @@ -700,7 +725,31 @@ BOOL XclExpAutofilter::AddEntry( const ScQueryEntry& rEntry ) String sText; if( rEntry.pStr ) + { sText.Assign( *rEntry.pStr ); + switch( rEntry.eOp ) + { + case SC_CONTAINS: + case SC_DOES_NOT_CONTAIN: + { + sText.InsertAscii( "*" , 0 ); + sText.AppendAscii( "*" ); + } + break; + case SC_BEGINS_WITH: + case SC_DOES_NOT_BEGIN_WITH: + sText.AppendAscii( "*" ); + break; + case SC_ENDS_WITH: + case SC_DOES_NOT_END_WITH: + sText.InsertAscii( "*" , 0 ); + break; + default: + { + //nothing + } + } + } BOOL bLen = sText.Len() > 0; @@ -760,6 +809,14 @@ BOOL XclExpAutofilter::AddEntry( const ScQueryEntry& rEntry ) case SC_LESS_EQUAL: nOper = EXC_AFOPER_LESSEQUAL; break; case SC_GREATER_EQUAL: nOper = EXC_AFOPER_GREATEREQUAL; break; case SC_NOT_EQUAL: nOper = EXC_AFOPER_NOTEQUAL; break; + case SC_CONTAINS: + case SC_BEGINS_WITH: + case SC_ENDS_WITH: + nOper = EXC_AFOPER_EQUAL; break; + case SC_DOES_NOT_CONTAIN: + case SC_DOES_NOT_BEGIN_WITH: + case SC_DOES_NOT_END_WITH: + nOper = EXC_AFOPER_NOTEQUAL; break; default:; } bConflict = !AddCondition( rEntry.eConnect, nType, nOper, fVal, pText ); diff --git a/sc/source/filter/excel/expop2.cxx b/sc/source/filter/excel/expop2.cxx index 3b0095f64735..774f517dada6 100644 --- a/sc/source/filter/excel/expop2.cxx +++ b/sc/source/filter/excel/expop2.cxx @@ -102,7 +102,7 @@ FltError ExportBiff5::Write() SvxImportMSVBasic aBasicImport( *pDocShell, *xRootStrg, bWriteBasicCode, bWriteBasicStrg ); ULONG nErr = aBasicImport.SaveOrDelMSVBAStorage( TRUE, EXC_STORAGE_VBA_PROJECT ); if( nErr != ERRCODE_NONE ) - pDocShell->SetError( nErr ); + pDocShell->SetError( nErr, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); } pExcDoc->ReadDoc(); // ScDoc -> ExcDoc @@ -191,7 +191,7 @@ FltError ExportXml2007::Write() SvxImportMSVBasic aBasicImport( *pDocShell, *xRootStrg, bWriteBasicCode, bWriteBasicStrg ); ULONG nErr = aBasicImport.SaveOrDelMSVBAStorage( TRUE, EXC_STORAGE_VBA_PROJECT ); if( nErr != ERRCODE_NONE ) - pDocShell->SetError( nErr ); + pDocShell->SetError( nErr, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); } pExcDoc->ReadDoc(); // ScDoc -> ExcDoc diff --git a/sc/source/filter/excel/impop.cxx b/sc/source/filter/excel/impop.cxx index 41f5e6d17234..c43c35b159ef 100644 --- a/sc/source/filter/excel/impop.cxx +++ b/sc/source/filter/excel/impop.cxx @@ -84,6 +84,7 @@ #include "xiview.hxx" #include "xilink.hxx" #include "xiescher.hxx" +#include "xicontent.hxx" #include "excimp8.hxx" #include "excform.hxx" @@ -418,14 +419,12 @@ void ImportExcel::Eof( void ) } -BOOL ImportExcel::Password( void ) +void ImportExcel::SheetPassword( void ) { - // POST: return = TRUE, wenn Password <> 0 - UINT16 nPasswd; - - aIn >> nPasswd; + if (GetRoot().GetBiff() != EXC_BIFF8) + return; - return nPasswd != 0x0000; + GetRoot().GetSheetProtectBuffer().ReadPasswordHash( aIn, GetCurrScTab() ); } @@ -439,6 +438,15 @@ void ImportExcel::Externsheet( void ) } +void ImportExcel:: WinProtection( void ) +{ + if (GetRoot().GetBiff() != EXC_BIFF8) + return; + + GetRoot().GetDocProtectBuffer().ReadWinProtect( aIn ); +} + + void ImportExcel::Columndefault( void ) {// Default Cell Attributes UINT16 nColMic, nColMac; @@ -570,27 +578,33 @@ void ImportExcel::Defrowheight2( void ) } -void ImportExcel::Protect( void ) +void ImportExcel::SheetProtect( void ) { - if( aIn.ReaduInt16() ) - { - uno::Sequence<sal_Int8> aEmptyPass; - GetDoc().SetTabProtection( GetCurrScTab(), TRUE, aEmptyPass ); - } + if (GetRoot().GetBiff() != EXC_BIFF8) + return; + + GetRoot().GetSheetProtectBuffer().ReadProtect( aIn, GetCurrScTab() ); } void ImportExcel::DocProtect( void ) { - if( aIn.ReaduInt16() ) - { - uno::Sequence<sal_Int8> aEmptyPass; - GetDoc().SetDocProtection( TRUE, aEmptyPass ); - } + if (GetRoot().GetBiff() != EXC_BIFF8) + return; + + GetRoot().GetDocProtectBuffer().ReadDocProtect( aIn ); } +void ImportExcel::DocPasssword( void ) +{ + if (GetRoot().GetBiff() != EXC_BIFF8) + return; + + GetRoot().GetDocProtectBuffer().ReadPasswordHash( aIn ); +} void ImportExcel::Codepage( void ) { + maStrm.EnableDecryption(); SetCodePage( maStrm.ReaduInt16() ); } diff --git a/sc/source/filter/excel/namebuff.cxx b/sc/source/filter/excel/namebuff.cxx index df53c3edcd3c..b01f5a728263 100644 --- a/sc/source/filter/excel/namebuff.cxx +++ b/sc/source/filter/excel/namebuff.cxx @@ -127,6 +127,9 @@ void ShrfmlaBuffer::Store( const ScRange& rRange, const ScTokenArray& rToken ) DBG_ASSERT( mnCurrIdx <= 0xFFFF, "*ShrfmlaBuffer::Store(): Gleich wird mir schlecht...!" ); ScRangeData* pData = new ScRangeData( pExcRoot->pIR->GetDocPtr(), aName, rToken, rRange.aStart, RT_SHARED ); + const ScAddress& rMaxPos = pExcRoot->pIR->GetMaxPos(); + pData->SetMaxCol(rMaxPos.Col()); + pData->SetMaxRow(rMaxPos.Row()); pData->SetIndex( static_cast< USHORT >( mnCurrIdx ) ); pExcRoot->pIR->GetNamedRanges().Insert( pData ); index_hash[rRange.aStart] = static_cast< USHORT >( mnCurrIdx ); diff --git a/sc/source/filter/excel/read.cxx b/sc/source/filter/excel/read.cxx index 21497f2927a3..8be7f2d94220 100644 --- a/sc/source/filter/excel/read.cxx +++ b/sc/source/filter/excel/read.cxx @@ -356,7 +356,7 @@ FltError ImportExcel::Read( void ) Eof(); eAkt = Z_Ende; break; - case 0x12: Protect(); break; // SHEET PROTECTION + case 0x12: SheetProtect(); break; // SHEET PROTECTION case 0x14: case 0x15: rPageSett.ReadHeaderFooter( maStrm ); break; case 0x17: Externsheet(); break; // EXTERNSHEET [ 2345] @@ -471,7 +471,7 @@ FltError ImportExcel::Read( void ) Eof(); eAkt = Z_Biff4E; break; - case 0x12: Protect(); break; // SHEET PROTECTION + case 0x12: SheetProtect(); break; // SHEET PROTECTION case 0x14: case 0x15: rPageSett.ReadHeaderFooter( maStrm ); break; case 0x1A: @@ -598,7 +598,7 @@ FltError ImportExcel::Read( void ) eAkt = Z_Biff5T; aIn.SeekGlobalPosition(); // und zurueck an alte Position break; - case 0x12: Protect(); break; // SHEET PROTECTION + case 0x12: SheetProtect(); break; // SHEET PROTECTION case 0x1A: case 0x1B: rPageSett.ReadPageBreaks( maStrm ); break; case 0x1D: rTabViewSett.ReadSelection( maStrm ); break; @@ -898,6 +898,7 @@ FltError ImportExcel8::Read( void ) } break; case 0x12: DocProtect(); break; // PROTECT [ 5678] + case 0x13: DocPasssword(); break; case 0x19: WinProtection(); break; case 0x2F: // FILEPASS [ 2345 ] eLastErr = XclImpDecryptHelper::ReadFilepass( maStrm ); @@ -1042,7 +1043,8 @@ FltError ImportExcel8::Read( void ) eAkt = EXC_STATE_SHEET; aIn.SeekGlobalPosition(); // und zurueck an alte Position break; - case 0x12: Protect(); break; + case 0x12: SheetProtect(); break; + case 0x13: SheetPassword(); break; case 0x42: Codepage(); break; // CODEPAGE [ 2345 ] case 0x55: DefColWidth(); break; case 0x7D: Colinfo(); break; // COLINFO [ 345 ] @@ -1058,6 +1060,7 @@ FltError ImportExcel8::Read( void ) case 0x0221: Array34(); break; // ARRAY [ 34 ] case 0x0225: Defrowheight345();break;//DEFAULTROWHEI[ 345 ] case 0x04BC: Shrfmla(); break; // SHRFMLA [ 5 ] + case 0x0867: SheetProtection(); break; // SHEETPROTECTION } } break; diff --git a/sc/source/filter/excel/xechart.cxx b/sc/source/filter/excel/xechart.cxx index bac636fc798d..b416e59b92ac 100644 --- a/sc/source/filter/excel/xechart.cxx +++ b/sc/source/filter/excel/xechart.cxx @@ -815,10 +815,11 @@ sal_uInt16 XclExpChSourceLink::ConvertDataSequence( Reference< XDataSequence > x if( !xDataSeq.is() ) return nDefCount; - // compile the range representation string into token array + // Compile the range representation string into token array. Note that the + // source range text depends on the current grammar. OUString aRangeRepr = xDataSeq->getSourceRangeRepresentation(); ScCompiler aComp( GetDocPtr(), ScAddress() ); - aComp.SetGrammar( FormulaGrammar::GRAM_ENGLISH ); + aComp.SetGrammar( GetDocPtr()->GetGrammar() ); ScTokenArray* pArray = aComp.CompileString( aRangeRepr ); if( !pArray ) return nDefCount; @@ -1714,7 +1715,7 @@ bool XclExpChSeries::ConvertDataSeries( Reference< XDataSource > xDataSource( xDataSeries, UNO_QUERY ); if( xDataSource.is() ) { - Reference< XDataSequence > xYValueSeq, xTitleSeq, xXValueSeq; + Reference< XDataSequence > xYValueSeq, xTitleSeq, xXValueSeq, xBubbleSeq; // find first sequence with role 'values-y' Sequence< Reference< XLabeledDataSequence > > aLabeledSeqVec = xDataSource->getDataSequences(); @@ -1730,12 +1731,18 @@ bool XclExpChSeries::ConvertDataSeries( if( !xYValueSeq.is() && (aRole == EXC_CHPROP_ROLE_YVALUES) ) { xYValueSeq = xTmpValueSeq; - xTitleSeq = (*pIt)->getLabel(); // ignore role of label sequence + if( !xTitleSeq.is() ) + xTitleSeq = (*pIt)->getLabel(); // ignore role of label sequence } else if( !xXValueSeq.is() && !rTypeInfo.mbCategoryAxis && (aRole == EXC_CHPROP_ROLE_XVALUES) ) { xXValueSeq = xTmpValueSeq; } + else if( !xBubbleSeq.is() && (rTypeInfo.meTypeId == EXC_CHTYPEID_BUBBLES) && (aRole == EXC_CHPROP_ROLE_SIZEVALUES) ) + { + xBubbleSeq = xTmpValueSeq; + xTitleSeq = (*pIt)->getLabel(); // ignore role of label sequence + } } } @@ -1752,6 +1759,10 @@ bool XclExpChSeries::ConvertDataSeries( // X values of XY charts maData.mnCategCount = mxCategLink->ConvertDataSequence( xXValueSeq, false, maData.mnValueCount ); + // size values of bubble charts + if( mxBubbleLink.is() ) + mxBubbleLink->ConvertDataSequence( xBubbleSeq, false, maData.mnValueCount ); + // series formatting XclChDataPointPos aPointPos( mnSeriesIdx ); ScfPropertySet aSeriesProp( xDataSeries ); diff --git a/sc/source/filter/excel/xeescher.cxx b/sc/source/filter/excel/xeescher.cxx index 0c49d4e96702..4853fff46d9c 100644 --- a/sc/source/filter/excel/xeescher.cxx +++ b/sc/source/filter/excel/xeescher.cxx @@ -546,6 +546,9 @@ XclExpTbxControlObj::XclExpTbxControlObj( XclExpObjectManager& rObjMgr, Referenc mrEscherEx.OpenContainer( ESCHER_SpContainer ); mrEscherEx.AddShape( ESCHER_ShpInst_HostControl, SHAPEFLAG_HAVEANCHOR | SHAPEFLAG_HAVESPT ); EscherPropertyContainer aPropOpt; + bool bVisible = aCtrlProp.GetBoolProperty( CREATE_OUSTRING( "EnableVisible" ) ); + aPropOpt.AddOpt( ESCHER_Prop_fPrint, bVisible ? 0x00080000 : 0x00080002 ); // visible flag + aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x01000100 ); // bool field aPropOpt.AddOpt( ESCHER_Prop_lTxid, 0 ); // Text ID aPropOpt.AddOpt( ESCHER_Prop_WrapText, 0x00000001 ); @@ -1000,7 +1003,7 @@ XclExpNote::XclExpNote( const XclExpRoot& rRoot, const ScAddress& rScPos, { // TODO: additional text if( pScNote ) - if( SdrCaptionObj* pCaption = pScNote->GetCaption() ) + if( SdrCaptionObj* pCaption = pScNote->GetOrCreateCaption( maScPos ) ) if( const OutlinerParaObject* pOPO = pCaption->GetOutlinerParaObject() ) mnObjId = rRoot.GetObjectManager().AddObj( new XclObjComment( rRoot.GetObjectManager(), pCaption->GetLogicRect(), pOPO->GetTextObject(), pCaption, mbVisible ) ); diff --git a/sc/source/filter/excel/xeformula.cxx b/sc/source/filter/excel/xeformula.cxx index e065099b2824..457c31d4ab04 100644 --- a/sc/source/filter/excel/xeformula.cxx +++ b/sc/source/filter/excel/xeformula.cxx @@ -619,7 +619,7 @@ void XclExpFmlaCompImpl::Init( XclFormulaType eType, const ScTokenArray& rScTokA DBG_ASSERT( mbOk, "XclExpFmlaCompImpl::Init - missing cell address" ); // clone the passed token array, convert references relative to current cell position mxOwnScTokArr.reset( rScTokArr.Clone() ); - ScCompiler::MoveRelWrap( *mxOwnScTokArr, GetDocPtr(), *pScBasePos ); + ScCompiler::MoveRelWrap( *mxOwnScTokArr, GetDocPtr(), *pScBasePos, MAXCOL, MAXROW ); // don't remember pScBasePos in mpScBasePos, shared formulas use real relative refs break; default:; diff --git a/sc/source/filter/excel/xeroot.cxx b/sc/source/filter/excel/xeroot.cxx index 0d658541eee8..636a83ea3e47 100644 --- a/sc/source/filter/excel/xeroot.cxx +++ b/sc/source/filter/excel/xeroot.cxx @@ -32,7 +32,11 @@ #include "precompiled_sc.hxx" #include <sfx2/docfile.hxx> +#include <sfx2/sfxsids.hrc> #include <svtools/saveopt.hxx> +#include <svtools/itemset.hxx> +#include <svtools/stritem.hxx> +#include <svtools/eitem.hxx> #include "xecontent.hxx" #include "xltracer.hxx" #include "xeescher.hxx" @@ -44,8 +48,10 @@ #include "xestyle.hxx" #include "xeroot.hxx" -// for filter manager -#include "excrecds.hxx" +#include "excrecds.hxx" // for filter manager +#include "tabprotection.hxx" +#include "document.hxx" +#include "scextopt.hxx" // Global data ================================================================ @@ -230,6 +236,40 @@ XclExpRecordRef XclExpRoot::CreateRecord( sal_uInt16 nRecId ) const return xRec; } +bool XclExpRoot::IsDocumentEncrypted() const +{ + // We need to encrypt the content when the document structure is protected. + const ScDocProtection* pDocProt = GetDoc().GetDocProtection(); + if (pDocProt && pDocProt->isProtected() && pDocProt->isOptionEnabled(ScDocProtection::STRUCTURE)) + return true; + + if (GetPassword().Len() > 0) + // Password is entered directly into the save dialog. + return true; + + return false; +} + +const String XclExpRoot::GetPassword() const +{ + SfxItemSet* pSet = GetMedium().GetItemSet(); + if (!pSet) + return String(); + + const SfxPoolItem* pItem = NULL; + if (SFX_ITEM_SET == pSet->GetItemState(SID_PASSWORD, sal_True, &pItem)) + { + const SfxStringItem* pStrItem = dynamic_cast<const SfxStringItem*>(pItem); + if (pStrItem) + { + // Password from the save dialog. + return pStrItem->GetValue(); + } + } + + return String(); +} + XclExpRootData::XclExpLinkMgrRef XclExpRoot::GetLocalLinkMgrRef() const { return IsInGlobals() ? mrExpData.mxGlobLinkMgr : mrExpData.mxLocLinkMgr; diff --git a/sc/source/filter/excel/xestream.cxx b/sc/source/filter/excel/xestream.cxx index 9cb054d2ada2..6b2f53c8056a 100644 --- a/sc/source/filter/excel/xestream.cxx +++ b/sc/source/filter/excel/xestream.cxx @@ -51,6 +51,8 @@ #include <oox/core/tokens.hxx> #include <formula/grammar.hxx> +#define DEBUG_XL_ENCRYPTION 0 + using ::com::sun::star::beans::PropertyValue; using ::com::sun::star::io::XOutputStream; using ::com::sun::star::io::XStream; @@ -63,7 +65,10 @@ using ::com::sun::star::uno::UNO_QUERY; using ::rtl::OString; using ::rtl::OUString; using ::utl::OStreamWrapper; +using ::std::vector; + using namespace formula; + // ============================================================================ XclExpStream::XclExpStream( SvStream& rOutStrm, const XclExpRoot& rRoot, sal_uInt16 nMaxRecSize ) : @@ -92,16 +97,19 @@ XclExpStream::~XclExpStream() void XclExpStream::StartRecord( sal_uInt16 nRecId, sal_Size nRecSize ) { DBG_ASSERT( !mbInRec, "XclExpStream::StartRecord - another record still open" ); + DisableEncryption(); mnMaxContSize = mnCurrMaxSize = mnMaxRecSize; mnPredictSize = nRecSize; mbInRec = true; InitRecord( nRecId ); SetSliceSize( 0 ); + EnableEncryption(); } void XclExpStream::EndRecord() { DBG_ASSERT( mbInRec, "XclExpStream::EndRecord - no record open" ); + DisableEncryption(); UpdateRecSize(); mrStrm.Seek( STREAM_SEEK_TO_END ); mbInRec = false; @@ -113,6 +121,86 @@ void XclExpStream::SetSliceSize( sal_uInt16 nSize ) mnSliceSize = 0; } +XclExpStream& XclExpStream::operator<<( sal_Int8 nValue ) +{ + PrepareWrite( 1 ); + if (mbUseEncrypter && HasValidEncrypter()) + mxEncrypter->Encrypt(mrStrm, nValue); + else + mrStrm << nValue; + return *this; +} + +XclExpStream& XclExpStream::operator<<( sal_uInt8 nValue ) +{ + PrepareWrite( 1 ); + if (mbUseEncrypter && HasValidEncrypter()) + mxEncrypter->Encrypt(mrStrm, nValue); + else + mrStrm << nValue; + return *this; +} + +XclExpStream& XclExpStream::operator<<( sal_Int16 nValue ) +{ + PrepareWrite( 2 ); + if (mbUseEncrypter && HasValidEncrypter()) + mxEncrypter->Encrypt(mrStrm, nValue); + else + mrStrm << nValue; + return *this; +} + +XclExpStream& XclExpStream::operator<<( sal_uInt16 nValue ) +{ + PrepareWrite( 2 ); + if (mbUseEncrypter && HasValidEncrypter()) + mxEncrypter->Encrypt(mrStrm, nValue); + else + mrStrm << nValue; + return *this; +} + +XclExpStream& XclExpStream::operator<<( sal_Int32 nValue ) +{ + PrepareWrite( 4 ); + if (mbUseEncrypter && HasValidEncrypter()) + mxEncrypter->Encrypt(mrStrm, nValue); + else + mrStrm << nValue; + return *this; +} + +XclExpStream& XclExpStream::operator<<( sal_uInt32 nValue ) +{ + PrepareWrite( 4 ); + if (mbUseEncrypter && HasValidEncrypter()) + mxEncrypter->Encrypt(mrStrm, nValue); + else + mrStrm << nValue; + return *this; +} + +XclExpStream& XclExpStream::operator<<( float fValue ) +{ + PrepareWrite( 4 ); + if (mbUseEncrypter && HasValidEncrypter()) + mxEncrypter->Encrypt(mrStrm, fValue); + else + mrStrm << fValue; + return *this; +} + +XclExpStream& XclExpStream::operator<<( double fValue ) +{ + PrepareWrite( 8 ); + if (mbUseEncrypter && HasValidEncrypter()) + mxEncrypter->Encrypt(mrStrm, fValue); + else + mrStrm << fValue; + return *this; +} + sal_Size XclExpStream::Write( const void* pData, sal_Size nBytes ) { sal_Size nRet = 0; @@ -127,9 +215,21 @@ sal_Size XclExpStream::Write( const void* pData, sal_Size nBytes ) while( bValid && (nBytesLeft > 0) ) { sal_Size nWriteLen = ::std::min< sal_Size >( PrepareWrite(), nBytesLeft ); - sal_Size nWriteRet = mrStrm.Write( pBuffer, nWriteLen ); + sal_Size nWriteRet = nWriteLen; + if (mbUseEncrypter && HasValidEncrypter()) + { + DBG_ASSERT(nWriteLen > 0, "XclExpStream::Write: write length is 0!"); + vector<sal_uInt8> aBytes(nWriteLen); + memcpy(&aBytes[0], pBuffer, nWriteLen); + mxEncrypter->EncryptBytes(mrStrm, aBytes); + // TODO: How do I check if all the bytes have been successfully written ? + } + else + { + nWriteRet = mrStrm.Write( pBuffer, nWriteLen ); bValid = (nWriteLen == nWriteRet); DBG_ASSERT( bValid, "XclExpStream::Write - stream write error" ); + } pBuffer += nWriteRet; nRet += nWriteRet; nBytesLeft -= nWriteRet; @@ -265,6 +365,26 @@ void XclExpStream::WriteCharBuffer( const ScfUInt8Vec& rBuffer ) Write( &rBuffer[ 0 ], rBuffer.size() ); } +void XclExpStream::SetEncrypter( XclExpEncrypterRef xEncrypter ) +{ + mxEncrypter = xEncrypter; +} + +bool XclExpStream::HasValidEncrypter() const +{ + return mxEncrypter.is() && mxEncrypter->IsValid(); +} + +void XclExpStream::EnableEncryption( bool bEnable ) +{ + mbUseEncrypter = bEnable && HasValidEncrypter(); +} + +void XclExpStream::DisableEncryption() +{ + EnableEncryption(false); +} + sal_Size XclExpStream::SetSvStreamPos( sal_Size nPos ) { DBG_ASSERT( !mbInRec, "XclExpStream::SetSvStreamPos - not allowed inside of a record" ); @@ -356,6 +476,193 @@ void XclExpStream::WriteRawZeroBytes( sal_Size nBytes ) // ============================================================================ +XclExpBiff8Encrypter::XclExpBiff8Encrypter( const XclExpRoot& rRoot, const sal_uInt8 nDocId[16], + const sal_uInt8 nSalt[16] ) : + mrRoot(rRoot), + mnOldPos(STREAM_SEEK_TO_END), + mbValid(false) +{ + String aPass = rRoot.GetPassword(); + if (aPass.Len() == 0) + // Empty password. Get the default biff8 password. + aPass = XclCryptoHelper::GetBiff8WbProtPassword(); + Init(aPass, nDocId, nSalt); +} + +XclExpBiff8Encrypter::~XclExpBiff8Encrypter() +{ +} + +bool XclExpBiff8Encrypter::IsValid() const +{ + return mbValid; +} + +void XclExpBiff8Encrypter::GetSaltDigest( sal_uInt8 nSaltDigest[16] ) const +{ + memcpy(nSaltDigest, mnSaltDigest, 16); +} + +void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_uInt8 nData ) +{ + vector<sal_uInt8> aByte(1); + aByte[0] = nData; + EncryptBytes(rStrm, aByte); +} + +void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_uInt16 nData ) +{ + ::std::vector<sal_uInt8> pnBytes(2); + pnBytes[0] = nData & 0xFF; + pnBytes[1] = (nData >> 8) & 0xFF; + EncryptBytes(rStrm, pnBytes); +} + +void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_uInt32 nData ) +{ + ::std::vector<sal_uInt8> pnBytes(4); + pnBytes[0] = nData & 0xFF; + pnBytes[1] = (nData >> 8) & 0xFF; + pnBytes[2] = (nData >> 16) & 0xFF; + pnBytes[3] = (nData >> 24) & 0xFF; + EncryptBytes(rStrm, pnBytes); +} + +void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, float fValue ) +{ + ::std::vector<sal_uInt8> pnBytes(4); + memcpy(&pnBytes[0], &fValue, 4); + EncryptBytes(rStrm, pnBytes); +} + +void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, double fValue ) +{ + ::std::vector<sal_uInt8> pnBytes(8); + memcpy(&pnBytes[0], &fValue, 8); + EncryptBytes(rStrm, pnBytes); +} + +void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_Int8 nData ) +{ + Encrypt(rStrm, static_cast<sal_uInt8>(nData)); +} + +void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_Int16 nData ) +{ + Encrypt(rStrm, static_cast<sal_uInt16>(nData)); +} + +void XclExpBiff8Encrypter::Encrypt( SvStream& rStrm, sal_Int32 nData ) +{ + Encrypt(rStrm, static_cast<sal_uInt32>(nData)); +} + +void XclExpBiff8Encrypter::Init( const String& aPass, const sal_uInt8 nDocId[16], + const sal_uInt8 nSalt[16] ) +{ + memset(mnSaltDigest, 0, sizeof(mnSaltDigest)); + + xub_StrLen nLen = aPass.Len(); + bool bValid = (0 < nLen) && (nLen < 16); + if ( bValid ) + { + // transform String to sal_uInt16 array + memset(mnPassw, 0, sizeof(mnPassw)); + for (xub_StrLen nChar = 0; nChar < nLen; ++nChar) + mnPassw[nChar] = static_cast<sal_uInt16>(aPass.GetChar(nChar)); + + // copy document ID + memcpy(mnDocId, nDocId, sizeof(mnDocId)); + + // init codec + maCodec.InitKey(mnPassw, mnDocId); + + // generate salt hash. + ::svx::MSCodec_Std97 aCodec; + aCodec.InitKey(mnPassw, mnDocId); + aCodec.CreateSaltDigest(nSalt, mnSaltDigest); + + // verify to make sure it's in good shape. + bValid = maCodec.VerifyKey(nSalt, mnSaltDigest); + } + + mbValid = bValid; +} + +sal_uInt32 XclExpBiff8Encrypter::GetBlockPos( sal_Size nStrmPos ) const +{ + return static_cast<sal_uInt32>(nStrmPos / EXC_ENCR_BLOCKSIZE); +} + +sal_uInt16 XclExpBiff8Encrypter::GetOffsetInBlock( sal_Size nStrmPos ) const +{ + return static_cast<sal_uInt16>(nStrmPos % EXC_ENCR_BLOCKSIZE); +} + +void XclExpBiff8Encrypter::EncryptBytes( SvStream& rStrm, vector<sal_uInt8>& aBytes ) +{ + sal_Size nStrmPos = rStrm.Tell(); + sal_uInt16 nBlockOffset = GetOffsetInBlock(nStrmPos); + sal_uInt32 nBlockPos = GetBlockPos(nStrmPos); + +#if DEBUG_XL_ENCRYPTION + fprintf(stdout, "XclExpBiff8Encrypter::EncryptBytes: stream pos = %ld offset in block = %d block pos = %ld\n", + nStrmPos, nBlockOffset, nBlockPos); +#endif + + sal_uInt16 nSize = static_cast< sal_uInt16 >( aBytes.size() ); + if (nSize == 0) + return; + +#if DEBUG_XL_ENCRYPTION + fprintf(stdout, "RAW: "); + for (sal_uInt16 i = 0; i < nSize; ++i) + fprintf(stdout, "%2.2X ", aBytes[i]); + fprintf(stdout, "\n"); +#endif + + if (mnOldPos != nStrmPos) + { + sal_uInt16 nOldOffset = GetOffsetInBlock(mnOldPos); + sal_uInt32 nOldBlockPos = GetBlockPos(mnOldPos); + + if ( (nBlockPos != nOldBlockPos) || (nBlockOffset < nOldOffset) ) + { + maCodec.InitCipher(nBlockPos); + nOldOffset = 0; + } + + if (nBlockOffset > nOldOffset) + maCodec.Skip(nBlockOffset - nOldOffset); + } + + sal_uInt16 nBytesLeft = nSize; + sal_uInt16 nPos = 0; + while (nBytesLeft > 0) + { + sal_uInt16 nBlockLeft = EXC_ENCR_BLOCKSIZE - nBlockOffset; + sal_uInt16 nEncBytes = ::std::min(nBlockLeft, nBytesLeft); + + bool bRet = maCodec.Encode(&aBytes[nPos], nEncBytes, &aBytes[nPos], nEncBytes); + DBG_ASSERT(bRet, "XclExpBiff8Encrypter::EncryptBytes: encryption failed!!"); + bRet = bRet; // to remove a silly compiler warning. + + sal_Size nRet = rStrm.Write(&aBytes[nPos], nEncBytes); + DBG_ASSERT(nRet == nEncBytes, "XclExpBiff8Encrypter::EncryptBytes: fail to write to stream!!"); + nRet = nRet; // to remove a silly compiler warning. + + nStrmPos = rStrm.Tell(); + nBlockOffset = GetOffsetInBlock(nStrmPos); + nBlockPos = GetBlockPos(nStrmPos); + if (nBlockOffset == 0) + maCodec.InitCipher(nBlockPos); + + nBytesLeft -= nEncBytes; + nPos += nEncBytes; + } + mnOldPos = nStrmPos; +} + rtl::OUString XclXmlUtils::GetStreamName( const char* sStreamDir, const char* sStream, sal_Int32 nId ) { rtl::OUStringBuffer sBuf; @@ -666,7 +973,7 @@ sax_fastparser::FSHelperPtr XclExpXmlStream::CreateOutputStream ( if( pRelationshipId ) *pRelationshipId = sRelationshipId; - sax_fastparser::FSHelperPtr p = openOutputStreamWithSerializer( sFullStream, OUString::createFromAscii( sContentType ) ); + sax_fastparser::FSHelperPtr p = openFragmentStreamWithSerializer( sFullStream, OUString::createFromAscii( sContentType ) ); maOpenedStreamMap[ sFullStream ] = std::make_pair( sRelationshipId, p ); @@ -683,14 +990,14 @@ sal_Int32 XclExpXmlStream::getSchemeClr( sal_Int32 /*nColorSchemeToken*/ ) const return -1; } -const oox::vml::DrawingPtr XclExpXmlStream::getDrawings() +oox::vml::Drawing* XclExpXmlStream::getVmlDrawing() { - return oox::vml::DrawingPtr(); + return 0; } const oox::drawingml::Theme* XclExpXmlStream::getCurrentTheme() const { - return NULL; + return 0; } const oox::drawingml::table::TableStyleListPtr XclExpXmlStream::getTableStyles() diff --git a/sc/source/filter/excel/xichart.cxx b/sc/source/filter/excel/xichart.cxx index 663add62426a..4c2551387524 100644 --- a/sc/source/filter/excel/xichart.cxx +++ b/sc/source/filter/excel/xichart.cxx @@ -72,6 +72,9 @@ #include "document.hxx" #include "drwlayer.hxx" #include "rangeutl.hxx" +#include "tokenarray.hxx" +#include "token.hxx" +#include "compiler.hxx" #include "fprogressbar.hxx" #include "xltracer.hxx" #include "xistream.hxx" @@ -79,9 +82,6 @@ #include "xistyle.hxx" #include "xipage.hxx" #include "xiview.hxx" -#include "tokenarray.hxx" -#include "token.hxx" -#include "compiler.hxx" using ::rtl::OUString; using ::rtl::OUStringBuffer; @@ -643,8 +643,11 @@ Reference< XLabeledDataSequence > lclCreateLabeledDataSequence( // ---------------------------------------------------------------------------- XclImpChSourceLink::XclImpChSourceLink( const XclImpChRoot& rRoot ) : - XclImpChRoot( rRoot ), - mpTokenArray(static_cast<ScTokenArray*>(NULL)) + XclImpChRoot( rRoot ) +{ +} + +XclImpChSourceLink::~XclImpChSourceLink() { } @@ -655,18 +658,16 @@ void XclImpChSourceLink::ReadChSourceLink( XclImpStream& rStrm ) >> maData.mnFlags >> maData.mnNumFmtIdx; + mxTokenArray.reset(); if( GetLinkType() == EXC_CHSRCLINK_WORKSHEET ) { // read token array XclTokenArray aXclTokArr; rStrm >> aXclTokArr; - // convert xcl formula tokens to Calc's. - const ScTokenArray* pTokenArray = - GetFormulaCompiler().CreateFormula(EXC_FMLATYPE_CHART, aXclTokArr); - - if (pTokenArray) - mpTokenArray.reset(pTokenArray->Clone()); + // convert BIFF formula tokens to Calc token array + if( const ScTokenArray* pTokens = GetFormulaCompiler().CreateFormula( EXC_FMLATYPE_CHART, aXclTokArr ) ) + mxTokenArray.reset( pTokens->Clone() ); } // try to read a following CHSTRING record @@ -693,38 +694,37 @@ void XclImpChSourceLink::SetTextFormats( const XclFormatRunVec& rFormats ) sal_uInt16 XclImpChSourceLink::GetCellCount() const { - using namespace ::formula; - sal_uInt32 nCellCount = 0; - mpTokenArray->Reset(); - for (const FormulaToken* p = mpTokenArray->First(); p; p = mpTokenArray->Next()) + if( mxTokenArray.is() ) { - switch (p->GetType()) + mxTokenArray->Reset(); + for( const FormulaToken* pToken = mxTokenArray->First(); pToken; pToken = mxTokenArray->Next() ) { - case svSingleRef: - case svExternalSingleRef: - // single cell - ++nCellCount; - break; - case svDoubleRef: - case svExternalDoubleRef: + switch( pToken->GetType() ) { - // cell range - const ScComplexRefData& rData = static_cast<const ScToken*>(p)->GetDoubleRef(); - const ScSingleRefData& s = rData.Ref1; - const ScSingleRefData& e = rData.Ref2; - SCsTAB nTab = e.nTab - s.nTab; - SCsCOL nCol = e.nCol - s.nCol; - SCsROW nRow = e.nRow - s.nRow; - nCellCount += static_cast<sal_uInt32>(nCol+1) * - static_cast<sal_uInt32>(nRow+1) * - static_cast<sal_uInt32>(nTab+1); + case ::formula::svSingleRef: + case ::formula::svExternalSingleRef: + // single cell + ++nCellCount; + break; + case ::formula::svDoubleRef: + case ::formula::svExternalDoubleRef: + { + // cell range + const ScComplexRefData& rComplexRef = static_cast< const ScToken* >( pToken )->GetDoubleRef(); + const ScSingleRefData& rRef1 = rComplexRef.Ref1; + const ScSingleRefData& rRef2 = rComplexRef.Ref2; + sal_uInt32 nTabs = static_cast< sal_uInt32 >( rRef2.nTab - rRef1.nTab + 1 ); + sal_uInt32 nCols = static_cast< sal_uInt32 >( rRef2.nCol - rRef1.nCol + 1 ); + sal_uInt32 nRows = static_cast< sal_uInt32 >( rRef2.nRow - rRef1.nRow + 1 ); + nCellCount += nCols * nRows * nTabs; + } + break; + default: ; } - break; - default: ; } } - return limit_cast<sal_uInt16>(nCellCount); + return limit_cast< sal_uInt16 >( nCellCount ); } void XclImpChSourceLink::ConvertNumFmt( ScfPropertySet& rPropSet, bool bPercent ) const @@ -743,25 +743,23 @@ Reference< XDataSequence > XclImpChSourceLink::CreateDataSequence( const OUStrin { Reference< XDataSequence > xDataSeq; Reference< XDataProvider > xDataProv = GetDataProvider(); - if( xDataProv.is() ) + if( xDataProv.is() && mxTokenArray.is() ) { - if (mpTokenArray) + ScCompiler aComp( GetDocPtr(), ScAddress(), *mxTokenArray ); + aComp.SetGrammar( ::formula::FormulaGrammar::GRAM_ENGLISH ); + OUStringBuffer aRangeRep; + aComp.CreateStringFromTokenArray( aRangeRep ); + try { - ScCompiler aComp(GetDocPtr(), ScAddress(), *mpTokenArray); - aComp.SetGrammar(::formula::FormulaGrammar::GRAM_ENGLISH); - OUStringBuffer aBuf; - aComp.CreateStringFromTokenArray(aBuf); - xDataSeq = xDataProv->createDataSequenceByRangeRepresentation( - aBuf.makeStringAndClear()); + xDataSeq = xDataProv->createDataSequenceByRangeRepresentation( aRangeRep.makeStringAndClear() ); + // set sequence role + ScfPropertySet aSeqProp( xDataSeq ); + aSeqProp.SetProperty( EXC_CHPROP_ROLE, rRole ); } - else + catch( Exception& ) { // DBG_ERRORFILE( "XclImpChSourceLink::CreateDataSequence - cannot create data sequence" ); } - - // set sequence role - ScfPropertySet aSeqProp( xDataSeq ); - aSeqProp.SetProperty( EXC_CHPROP_ROLE, rRole ); } return xDataSeq; } @@ -1787,6 +1785,14 @@ Reference< XDataSeries > XclImpChSeries::CreateDataSeries() const CreateCategSequence( EXC_CHPROP_ROLE_XVALUES ); if( xXValueSeq.is() ) aLabeledSeqVec.push_back( xXValueSeq ); + // add size values of bubble charts + if( rTypeInfo.meTypeId == EXC_CHTYPEID_BUBBLES ) + { + Reference< XLabeledDataSequence > xSizeValueSeq = + lclCreateLabeledDataSequence( mxBubbleLink, EXC_CHPROP_ROLE_SIZEVALUES, mxTitleLink.get() ); + if( xSizeValueSeq.is() ) + aLabeledSeqVec.push_back( xSizeValueSeq ); + } } // attach labeled data sequences to series if( !aLabeledSeqVec.empty() ) diff --git a/sc/source/filter/excel/xicontent.cxx b/sc/source/filter/excel/xicontent.cxx index 98cb602af5eb..239fbb57a545 100644 --- a/sc/source/filter/excel/xicontent.cxx +++ b/sc/source/filter/excel/xicontent.cxx @@ -41,6 +41,7 @@ #include "scitems.hxx" #include <svx/eeitem.hxx> #include <svtools/intitem.hxx> +#include <svtools/stritem.hxx> #include <svx/flditem.hxx> #include <svx/fhgtitem.hxx> #include <svx/wghtitem.hxx> @@ -67,6 +68,12 @@ #include "xiname.hxx" #include "excform.hxx" +#include "tabprotection.hxx" + +#include <memory> + +using ::com::sun::star::uno::Sequence; +using ::std::auto_ptr; // Shared string table ======================================================== @@ -1089,12 +1096,191 @@ ErrCode XclImpDecryptHelper::ReadFilepass( XclImpStream& rStrm ) case EXC_BIFF8: xDecr = lclReadFilepass8( rStrm ); break; default: DBG_ERROR_BIFF(); }; + + if (!xDecr.is()) + return EXC_ENCR_ERROR_UNSUPP_CRYPT; + // set decrypter at import stream rStrm.SetDecrypter( xDecr ); - // remember encryption for export - rStrm.GetRoot().GetExtDocOptions().GetDocSettings().mbEncrypted = true; - return xDecr.is() ? xDecr->GetError() : EXC_ENCR_ERROR_UNSUPP_CRYPT; + // Store the document password for export. + SfxItemSet* pSet = rStrm.GetRoot().GetDocShell()->GetMedium()->GetItemSet(); + if (pSet) + { + String aPass = xDecr->GetPassword(); + pSet->Put( SfxStringItem(SID_PASSWORD, aPass) ); + } + + return xDecr->GetError(); +} + +// Document protection ======================================================== + +XclImpDocProtectBuffer::XclImpDocProtectBuffer( const XclImpRoot& rRoot ) : + XclImpRoot( rRoot ), + mnPassHash(0x0000), + mbDocProtect(false), + mbWinProtect(false) +{ +} + +void XclImpDocProtectBuffer::ReadDocProtect( XclImpStream& rStrm ) +{ + mbDocProtect = rStrm.ReaduInt16() ? true : false; +} + +void XclImpDocProtectBuffer::ReadWinProtect( XclImpStream& rStrm ) +{ + mbWinProtect = rStrm.ReaduInt16() ? true : false; +} + +void XclImpDocProtectBuffer::ReadPasswordHash( XclImpStream& rStrm ) +{ + rStrm.EnableDecryption(); + mnPassHash = rStrm.ReaduInt16(); +} + +void XclImpDocProtectBuffer::Apply() const +{ + if (!mbDocProtect && !mbWinProtect) + // Excel requires either the structure or windows protection is set. + // If neither is set then the document is not protected at all. + return; + + auto_ptr<ScDocProtection> pProtect(new ScDocProtection); + pProtect->setProtected(true); + +#if ENABLE_SHEET_PROTECTION + if (mnPassHash) + { + // 16-bit password pash. + Sequence<sal_Int8> aPass(2); + aPass[0] = (mnPassHash >> 8) & 0xFF; + aPass[1] = mnPassHash & 0xFF; + pProtect->setPasswordHash(aPass, PASSHASH_XL); + } +#endif + + // document protection options + pProtect->setOption(ScDocProtection::STRUCTURE, mbDocProtect); + pProtect->setOption(ScDocProtection::WINDOWS, mbWinProtect); + + GetDoc().SetDocProtection(pProtect.get()); +} + +// Sheet Protection =========================================================== + +XclImpSheetProtectBuffer::Sheet::Sheet() : + mbProtected(false), + mnPasswordHash(0x0000), + mnOptions(0x4400) +{ +} + +// ---------------------------------------------------------------------------- + +XclImpSheetProtectBuffer::Sheet::Sheet(const Sheet& r) : + mbProtected(r.mbProtected), + mnPasswordHash(r.mnPasswordHash), + mnOptions(r.mnOptions) +{ +} + +XclImpSheetProtectBuffer::XclImpSheetProtectBuffer( const XclImpRoot& rRoot ) : + XclImpRoot( rRoot ) +{ +} + +void XclImpSheetProtectBuffer::ReadProtect( XclImpStream& rStrm, SCTAB nTab ) +{ + if ( rStrm.ReaduInt16() ) + { + Sheet* pSheet = GetSheetItem(nTab); + if (pSheet) + pSheet->mbProtected = true; + } +} + +void XclImpSheetProtectBuffer::ReadOptions( XclImpStream& rStrm, SCTAB nTab ) +{ + rStrm.Ignore(19); + sal_uInt16 nOptions; + rStrm >> nOptions; + + Sheet* pSheet = GetSheetItem(nTab); + if (pSheet) + pSheet->mnOptions = nOptions; +} + +void XclImpSheetProtectBuffer::ReadPasswordHash( XclImpStream& rStrm, SCTAB nTab ) +{ + sal_uInt16 nHash; + rStrm >> nHash; + Sheet* pSheet = GetSheetItem(nTab); + if (pSheet) + pSheet->mnPasswordHash = nHash; +} + +void XclImpSheetProtectBuffer::Apply() const +{ + for (ProtectedSheetMap::const_iterator itr = maProtectedSheets.begin(), itrEnd = maProtectedSheets.end(); + itr != itrEnd; ++itr) + { + if (!itr->second.mbProtected) + // This sheet is (for whatever reason) not protected. + continue; + + auto_ptr<ScTableProtection> pProtect(new ScTableProtection); + pProtect->setProtected(true); + +#if ENABLE_SHEET_PROTECTION + // 16-bit hash password + const sal_uInt16 nHash = itr->second.mnPasswordHash; + if (nHash) + { + Sequence<sal_Int8> aPass(2); + aPass[0] = (nHash >> 8) & 0xFF; + aPass[1] = nHash & 0xFF; + pProtect->setPasswordHash(aPass, PASSHASH_XL); + } +#endif + + // sheet protection options + const sal_uInt16 nOptions = itr->second.mnOptions; + pProtect->setOption( ScTableProtection::OBJECTS, (nOptions & 0x0001) ); + pProtect->setOption( ScTableProtection::SCENARIOS, (nOptions & 0x0002) ); + pProtect->setOption( ScTableProtection::FORMAT_CELLS, (nOptions & 0x0004) ); + pProtect->setOption( ScTableProtection::FORMAT_COLUMNS, (nOptions & 0x0008) ); + pProtect->setOption( ScTableProtection::FORMAT_ROWS, (nOptions & 0x0010) ); + pProtect->setOption( ScTableProtection::INSERT_COLUMNS, (nOptions & 0x0020) ); + pProtect->setOption( ScTableProtection::INSERT_ROWS, (nOptions & 0x0040) ); + pProtect->setOption( ScTableProtection::INSERT_HYPERLINKS, (nOptions & 0x0080) ); + pProtect->setOption( ScTableProtection::DELETE_COLUMNS, (nOptions & 0x0100) ); + pProtect->setOption( ScTableProtection::DELETE_ROWS, (nOptions & 0x0200) ); + pProtect->setOption( ScTableProtection::SELECT_LOCKED_CELLS, (nOptions & 0x0400) ); + pProtect->setOption( ScTableProtection::SORT, (nOptions & 0x0800) ); + pProtect->setOption( ScTableProtection::AUTOFILTER, (nOptions & 0x1000) ); + pProtect->setOption( ScTableProtection::PIVOT_TABLES, (nOptions & 0x2000) ); + pProtect->setOption( ScTableProtection::SELECT_UNLOCKED_CELLS, (nOptions & 0x4000) ); + + // all done. now commit. + GetDoc().SetTabProtection(itr->first, pProtect.get()); + } +} + +XclImpSheetProtectBuffer::Sheet* XclImpSheetProtectBuffer::GetSheetItem( SCTAB nTab ) +{ + ProtectedSheetMap::iterator itr = maProtectedSheets.find(nTab); + if (itr == maProtectedSheets.end()) + { + // new sheet + if ( !maProtectedSheets.insert( ProtectedSheetMap::value_type(nTab, Sheet()) ).second ) + return NULL; + + itr = maProtectedSheets.find(nTab); + } + + return &itr->second; } // ============================================================================ diff --git a/sc/source/filter/excel/xiescher.cxx b/sc/source/filter/excel/xiescher.cxx index 84a385cabd97..eb8e1f677fce 100644 --- a/sc/source/filter/excel/xiescher.cxx +++ b/sc/source/filter/excel/xiescher.cxx @@ -1653,23 +1653,19 @@ void XclImpNoteObj::SetNoteData( const ScAddress& rScPos, sal_uInt16 nNoteFlags void XclImpNoteObj::DoPreProcessSdrObj( XclImpDffConverter& rDffConv, SdrObject& rSdrObj ) const { - SdrTextObj* pTextObj = dynamic_cast< SdrTextObj* >( &rSdrObj ); - if( pTextObj && maScPos.IsValid() ) + // create formatted text + XclImpTextObj::DoPreProcessSdrObj( rDffConv, rSdrObj ); + OutlinerParaObject* pOutlinerObj = rSdrObj.GetOutlinerParaObject(); + if( maScPos.IsValid() && pOutlinerObj ) { - if( ScPostIt* pNote = GetDoc().GetOrCreateNote( maScPos ) ) - { - if( SdrCaptionObj* pCaption = pNote->GetCaption() ) - { - // create formatted text - XclImpTextObj::DoPreProcessSdrObj( rDffConv, *pCaption ); - // set textbox rectangle from imported object - pCaption->NbcSetLogicRect( pTextObj->GetLogicRect() ); - // copy all items from imported object (resets shadow items) - pNote->SetCaptionItems( pTextObj->GetMergedItemSet() ); - // move caption to correct layer (visible/hidden) - pNote->ShowCaption( ::get_flag( mnNoteFlags, EXC_NOTE_VISIBLE ) ); - } - } + // create cell note with all data from drawing object + ScNoteUtil::CreateNoteFromObjectData( + GetDoc(), maScPos, + rSdrObj.GetMergedItemSet().Clone(), // new object on heap expected + new OutlinerParaObject( *pOutlinerObj ), // new object on heap expected + rSdrObj.GetLogicRect(), + ::get_flag( mnNoteFlags, EXC_NOTE_VISIBLE ), + false ); } } @@ -1711,7 +1707,7 @@ void XclImpControlHelper::ProcessControl( const XclImpDrawObjBase& rDrawObj ) co aPropSet.SetStringProperty( CREATE_OUSTRING( "Name" ), rDrawObj.GetObjName() ); // control visible and printable? -// aPropSet.SetBoolProperty( CREATE_OUSTRING( "EnableVisible" ), rDrawObj.IsVisible() ); // waiting for #i88878# + aPropSet.SetBoolProperty( CREATE_OUSTRING( "EnableVisible" ), rDrawObj.IsVisible() ); aPropSet.SetBoolProperty( CREATE_OUSTRING( "Printable" ), rDrawObj.IsPrintable() ); // sheet links @@ -3905,7 +3901,7 @@ void XclImpSheetDrawing::ReadNote3( XclImpStream& rStrm ) nTotalLen = 0; } } - ScNoteUtil::CreateNoteFromString( GetDoc(), aScNotePos, aNoteText, false ); + ScNoteUtil::CreateNoteFromString( GetDoc(), aScNotePos, aNoteText, false, false ); } } diff --git a/sc/source/filter/excel/xilink.cxx b/sc/source/filter/excel/xilink.cxx index 16a3edf46373..2c2426382178 100644 --- a/sc/source/filter/excel/xilink.cxx +++ b/sc/source/filter/excel/xilink.cxx @@ -263,6 +263,7 @@ void XclImpTabInfo::ReadTabid( XclImpStream& rStrm ) DBG_ASSERT_BIFF( rStrm.GetRoot().GetBiff() == EXC_BIFF8 ); if( rStrm.GetRoot().GetBiff() == EXC_BIFF8 ) { + rStrm.EnableDecryption(); sal_Size nReadCount = rStrm.GetRecLeft() / 2; DBG_ASSERT( nReadCount <= 0xFFFF, "XclImpTabInfo::ReadTabid - record too long" ); maTabIdVec.clear(); diff --git a/sc/source/filter/excel/xiroot.cxx b/sc/source/filter/excel/xiroot.cxx index c64c10466d56..f6723f1d3887 100644 --- a/sc/source/filter/excel/xiroot.cxx +++ b/sc/source/filter/excel/xiroot.cxx @@ -52,6 +52,7 @@ XclImpRootData::XclImpRootData( XclBiff eBiff, SfxMedium& rMedium, SotStorageRef xRootStrg, ScDocument& rDoc, rtl_TextEncoding eTextEnc ) : XclRootData( eBiff, rMedium, xRootStrg, rDoc, eTextEnc, false ), + mbPassQueried( false ), mbHasCodePage( false ) { } @@ -86,6 +87,8 @@ XclImpRoot::XclImpRoot( XclImpRootData& rImpRootData ) : GetOldRoot().pAutoFilterBuffer = new XclImpAutoFilterBuffer; mrImpData.mxWebQueryBfr.reset( new XclImpWebQueryBuffer( GetRoot() ) ); mrImpData.mxPTableMgr.reset( new XclImpPivotTableManager( GetRoot() ) ); + mrImpData.mxTabProtect.reset( new XclImpSheetProtectBuffer( GetRoot() ) ); + mrImpData.mxDocProtect.reset( new XclImpDocProtectBuffer( GetRoot() ) ); } mrImpData.mxPageSett.reset( new XclImpPageSettings( GetRoot() ) ); @@ -238,6 +241,18 @@ XclImpPivotTableManager& XclImpRoot::GetPivotTableManager() const return *mrImpData.mxPTableMgr; } +XclImpSheetProtectBuffer& XclImpRoot::GetSheetProtectBuffer() const +{ + DBG_ASSERT( mrImpData.mxTabProtect.is(), "XclImpRoot::GetSheetProtectBuffer - invalid call, wrong BIFF" ); + return *mrImpData.mxTabProtect; +} + +XclImpDocProtectBuffer& XclImpRoot::GetDocProtectBuffer() const +{ + DBG_ASSERT( mrImpData.mxDocProtect.is(), "XclImpRoot::GetDocProtectBuffer - invalid call, wrong BIFF" ); + return *mrImpData.mxDocProtect; +} + XclImpPageSettings& XclImpRoot::GetPageSettings() const { return *mrImpData.mxPageSett; @@ -261,5 +276,16 @@ String XclImpRoot::GetScAddInName( const String& rXclName ) const return rXclName; } +const String& XclImpRoot::QueryPassword() const +{ + if( !mrImpData.mbPassQueried ) + { + mrImpData.maPassw = ScfApiHelper::QueryPasswordForMedium( GetMedium() ); + // set to true, even if dialog has been cancelled (never ask twice) + mrImpData.mbPassQueried = true; + } + return mrImpData.maPassw; +} + // ============================================================================ diff --git a/sc/source/filter/excel/xistream.cxx b/sc/source/filter/excel/xistream.cxx index b7f0d3841645..e7780c065118 100644 --- a/sc/source/filter/excel/xistream.cxx +++ b/sc/source/filter/excel/xistream.cxx @@ -36,6 +36,8 @@ #include "xlstring.hxx" #include "xiroot.hxx" +#include <vector> + // ============================================================================ // Decryption // ============================================================================ @@ -97,11 +99,21 @@ sal_uInt16 XclImpDecrypter::Read( SvStream& rStrm, void* pData, sal_uInt16 nByte return nRet; } +const String XclImpDecrypter::GetPassword() const +{ + return maPass; +} + void XclImpDecrypter::SetHasValidPassword( bool bValid ) { mnError = bValid ? ERRCODE_NONE : EXC_ENCR_ERROR_WRONG_PASS; } +void XclImpDecrypter::SetPassword( const String& rPass ) +{ + maPass = rPass; +} + // ---------------------------------------------------------------------------- XclImpBiff5Decrypter::XclImpBiff5Decrypter( const XclImpRoot& rRoot, sal_uInt16 nKey, sal_uInt16 nHash ) @@ -157,6 +169,9 @@ void XclImpBiff5Decrypter::Init( const ByteString& rPass, sal_uInt16 nKey, sal_u // init codec maCodec.InitKey( mpnPassw ); bValid = maCodec.VerifyKey( nKey, nHash ); + + String aUniPass( rPass, RTL_TEXTENCODING_MS_1252 ); + SetPassword( aUniPass ); } SetHasValidPassword( bValid ); @@ -255,6 +270,8 @@ void XclImpBiff8Decrypter::Init( // init codec maCodec.InitKey( mpnPassw, mpnDocId ); bValid = maCodec.VerifyKey( pnSaltData, pnSaltHash ); + + SetPassword(rPass); } SetHasValidPassword( bValid ); diff --git a/sc/source/filter/excel/xlchart.cxx b/sc/source/filter/excel/xlchart.cxx index e41ce7711709..8a590fda4bfc 100644 --- a/sc/source/filter/excel/xlchart.cxx +++ b/sc/source/filter/excel/xlchart.cxx @@ -511,6 +511,7 @@ const sal_Char SERVICE_CHART2_LINE[] = "com.sun.star.chart2.LineChartType"; const sal_Char SERVICE_CHART2_NET[] = "com.sun.star.chart2.NetChartType"; const sal_Char SERVICE_CHART2_PIE[] = "com.sun.star.chart2.PieChartType"; const sal_Char SERVICE_CHART2_SCATTER[] = "com.sun.star.chart2.ScatterChartType"; +const sal_Char SERVICE_CHART2_BUBBLE[] = "com.sun.star.chart2.BubbleChartType"; const sal_Char SERVICE_CHART2_SURFACE[] = "com.sun.star.chart2.ColumnChartType"; // Todo namespace csscd = ::com::sun::star::chart::DataLabelPlacement; @@ -529,7 +530,7 @@ static const XclChTypeInfo spTypeInfos[] = { EXC_CHTYPEID_DONUT, EXC_CHTYPECATEG_PIE, EXC_ID_CHPIE, SERVICE_CHART2_PIE, EXC_CHVARPOINT_MULTI, csscd::AVOID_OVERLAP, false, true, true, true, true, false, true, false, false, true, false }, { EXC_CHTYPEID_PIEEXT, EXC_CHTYPECATEG_PIE, EXC_ID_CHPIEEXT, SERVICE_CHART2_PIE, EXC_CHVARPOINT_MULTI, csscd::AVOID_OVERLAP, false, false, true, true, true, true, true, false, false, false, false }, { EXC_CHTYPEID_SCATTER, EXC_CHTYPECATEG_SCATTER, EXC_ID_CHSCATTER, SERVICE_CHART2_SCATTER, EXC_CHVARPOINT_SINGLE, csscd::RIGHT, true, false, false, false, true, false, false, false, false, false, false }, - { EXC_CHTYPEID_BUBBLES, EXC_CHTYPECATEG_SCATTER, EXC_ID_CHSCATTER, SERVICE_CHART2_SCATTER, EXC_CHVARPOINT_SINGLE, csscd::RIGHT, false, false, false, true, true, false, false, false, false, false, false }, + { EXC_CHTYPEID_BUBBLES, EXC_CHTYPECATEG_SCATTER, EXC_ID_CHSCATTER, SERVICE_CHART2_BUBBLE, EXC_CHVARPOINT_SINGLE, csscd::RIGHT, false, false, false, true, true, false, false, false, false, false, false }, { EXC_CHTYPEID_SURFACE, EXC_CHTYPECATEG_SURFACE, EXC_ID_CHSURFACE, SERVICE_CHART2_SURFACE, EXC_CHVARPOINT_NONE, csscd::RIGHT, false, true, false, true, true, false, true, false, false, false, false }, { EXC_CHTYPEID_UNKNOWN, EXC_CHTYPECATEG_BAR, EXC_ID_CHBAR, SERVICE_CHART2_COLUMN, EXC_CHVARPOINT_SINGLE, csscd::OUTSIDE, true, true, false, true, true, false, true, false, true, false, true } }; diff --git a/sc/source/filter/excel/xlpage.cxx b/sc/source/filter/excel/xlpage.cxx index 56ef285228b2..d1bea1addcec 100644 --- a/sc/source/filter/excel/xlpage.cxx +++ b/sc/source/filter/excel/xlpage.cxx @@ -44,7 +44,7 @@ struct XclPaperSize { - SvxPaper mePaper; /// SVX paper size identifier. + Paper mePaper; /// SVX paper size identifier. long mnWidth; /// Paper width in twips. long mnHeight; /// Paper height in twips. }; @@ -54,97 +54,114 @@ struct XclPaperSize static const XclPaperSize pPaperSizeTable[] = { -/* 0*/ { SVX_PAPER_USER, 0, 0 }, // undefined - { SVX_PAPER_LETTER, IN2TWIPS( 8.5 ), IN2TWIPS( 11 ) }, // Letter - { SVX_PAPER_USER, IN2TWIPS( 8.5 ), IN2TWIPS( 11 ) }, // Letter Small - { SVX_PAPER_TABLOID, IN2TWIPS( 11 ), IN2TWIPS( 17 ) }, // Tabloid - { SVX_PAPER_USER, IN2TWIPS( 17 ), IN2TWIPS( 11 ) }, // Ledger -/* 5*/ { SVX_PAPER_LEGAL, IN2TWIPS( 8.5 ), IN2TWIPS( 14 ) }, // Legal - { SVX_PAPER_USER, IN2TWIPS( 5.5 ), IN2TWIPS( 8.5 ) }, // Statement - { SVX_PAPER_USER, IN2TWIPS( 7.25 ), IN2TWIPS( 10.5 ) }, // Executive - { SVX_PAPER_A3, MM2TWIPS( 297 ), MM2TWIPS( 420 ) }, // A3 - { SVX_PAPER_A4, MM2TWIPS( 210 ), MM2TWIPS( 297 ) }, // A4 -/* 10*/ { SVX_PAPER_USER, MM2TWIPS( 210 ), MM2TWIPS( 297 ) }, // A4 Small - { SVX_PAPER_A5, MM2TWIPS( 148 ), MM2TWIPS( 210 ) }, // A5 - { SVX_PAPER_B4_JIS, MM2TWIPS( 257 ), MM2TWIPS( 364 ) }, // B4 (JIS) - { SVX_PAPER_B5_JIS, MM2TWIPS( 182 ), MM2TWIPS( 257 ) }, // B5 (JIS) - { SVX_PAPER_USER, IN2TWIPS( 8.5 ), IN2TWIPS( 13 ) }, // Folio -/* 15*/ { SVX_PAPER_USER, MM2TWIPS( 215 ), MM2TWIPS( 275 ) }, // Quarto - { SVX_PAPER_USER, IN2TWIPS( 10 ), IN2TWIPS( 14 ) }, // 10x14 - { SVX_PAPER_USER, IN2TWIPS( 11 ), IN2TWIPS( 17 ) }, // 11x17 - { SVX_PAPER_USER, IN2TWIPS( 8.5 ), IN2TWIPS( 11 ) }, // Note - { SVX_PAPER_COM9, IN2TWIPS( 3.875 ), IN2TWIPS( 8.875 ) }, // Envelope #9 -/* 20*/ { SVX_PAPER_COM10, IN2TWIPS( 4.125 ), IN2TWIPS( 9.5 ) }, // Envelope #10 - { SVX_PAPER_COM11, IN2TWIPS( 4.5 ), IN2TWIPS( 10.375 ) }, // Envelope #11 - { SVX_PAPER_COM12, IN2TWIPS( 4.75 ), IN2TWIPS( 11 ) }, // Envelope #12 - { SVX_PAPER_USER, IN2TWIPS( 5 ), IN2TWIPS( 11.5 ) }, // Envelope #14 - { SVX_PAPER_C, IN2TWIPS( 17 ), IN2TWIPS( 22 ) }, // ANSI-C -/* 25*/ { SVX_PAPER_D, IN2TWIPS( 22 ), IN2TWIPS( 34 ) }, // ANSI-D - { SVX_PAPER_E, IN2TWIPS( 34 ), IN2TWIPS( 44 ) }, // ANSI-E - { SVX_PAPER_DL, MM2TWIPS( 110 ), MM2TWIPS( 220 ) }, // Envelope DL - { SVX_PAPER_C5, MM2TWIPS( 162 ), MM2TWIPS( 229 ) }, // Envelope C5 - { SVX_PAPER_USER, MM2TWIPS( 324 ), MM2TWIPS( 458 ) }, // Envelope C3 -/* 30*/ { SVX_PAPER_C4, MM2TWIPS( 229 ), MM2TWIPS( 324 ) }, // Envelope C4 - { SVX_PAPER_C6, MM2TWIPS( 114 ), MM2TWIPS( 162 ) }, // Envelope C6 - { SVX_PAPER_C65, MM2TWIPS( 114 ), MM2TWIPS( 229 ) }, // Envelope C65 - { SVX_PAPER_B4, MM2TWIPS( 250 ), MM2TWIPS( 353 ) }, // B4 (ISO) - { SVX_PAPER_B5, MM2TWIPS( 176 ), MM2TWIPS( 250 ) }, // B5 (ISO) -/* 35*/ { SVX_PAPER_B6, MM2TWIPS( 125 ), MM2TWIPS( 176 ) }, // B6 (ISO) - { SVX_PAPER_USER, MM2TWIPS( 110 ), MM2TWIPS( 230 ) }, // Envelope Italy - { SVX_PAPER_MONARCH, IN2TWIPS( 3.875 ), IN2TWIPS( 7.5 ) }, // Envelope Monarch - { SVX_PAPER_COM675, IN2TWIPS( 3.625 ), IN2TWIPS( 6.5 ) }, // 6 3/4 Envelope - { SVX_PAPER_USER, IN2TWIPS( 14.875 ), IN2TWIPS( 11 ) }, // US Std Fanfold -/* 40*/ { SVX_PAPER_USER, IN2TWIPS( 8.5 ), IN2TWIPS( 12 ) }, // German Std Fanfold - { SVX_PAPER_USER, IN2TWIPS( 8.5 ), IN2TWIPS( 13 ) }, // German Legal Fanfold - { SVX_PAPER_B4, MM2TWIPS( 250 ), MM2TWIPS( 353 ) }, // B4 (ISO) - { SVX_PAPER_USER, MM2TWIPS( 100 ), MM2TWIPS( 148 ) }, // Japanese Postcard - { SVX_PAPER_USER, IN2TWIPS( 9 ), IN2TWIPS( 11 ) }, // 9x11 -/* 45*/ { SVX_PAPER_USER, IN2TWIPS( 10 ), IN2TWIPS( 11 ) }, // 10x11 - { SVX_PAPER_USER, IN2TWIPS( 15 ), IN2TWIPS( 11 ) }, // 15x11 - { SVX_PAPER_USER, MM2TWIPS( 220 ), MM2TWIPS( 220 ) }, // Envelope Invite - { SVX_PAPER_USER, 0, 0 }, // undefined - { SVX_PAPER_USER, 0, 0 }, // undefined -/* 50*/ { SVX_PAPER_USER, IN2TWIPS( 9.5 ), IN2TWIPS( 12 ) }, // Letter Extra - { SVX_PAPER_USER, IN2TWIPS( 9.5 ), IN2TWIPS( 15 ) }, // Legal Extra - { SVX_PAPER_USER, IN2TWIPS( 11.69 ), IN2TWIPS( 18 ) }, // Tabloid Extra - { SVX_PAPER_USER, MM2TWIPS( 235 ), MM2TWIPS( 322 ) }, // A4 Extra - { SVX_PAPER_USER, IN2TWIPS( 8.5 ), IN2TWIPS( 11 ) }, // Letter Transverse -/* 55*/ { SVX_PAPER_USER, MM2TWIPS( 210 ), MM2TWIPS( 297 ) }, // A4 Transverse - { SVX_PAPER_USER, IN2TWIPS( 9.5 ), IN2TWIPS( 12 ) }, // Letter Extra Transverse - { SVX_PAPER_USER, MM2TWIPS( 227 ), MM2TWIPS( 356 ) }, // Super A/A4 - { SVX_PAPER_USER, MM2TWIPS( 305 ), MM2TWIPS( 487 ) }, // Super B/A3 - { SVX_PAPER_USER, IN2TWIPS( 8.5 ), IN2TWIPS( 12.69 ) }, // Letter Plus -/* 60*/ { SVX_PAPER_USER, MM2TWIPS( 210 ), MM2TWIPS( 330 ) }, // A4 Plus - { SVX_PAPER_USER, MM2TWIPS( 148 ), MM2TWIPS( 210 ) }, // A5 Transverse - { SVX_PAPER_USER, MM2TWIPS( 182 ), MM2TWIPS( 257 ) }, // B5 (JIS) Transverse - { SVX_PAPER_USER, MM2TWIPS( 322 ), MM2TWIPS( 445 ) }, // A3 Extra - { SVX_PAPER_USER, MM2TWIPS( 174 ), MM2TWIPS( 235 ) }, // A5 Extra -/* 65*/ { SVX_PAPER_USER, MM2TWIPS( 201 ), MM2TWIPS( 276 ) }, // B5 (ISO) Extra - { SVX_PAPER_A2, MM2TWIPS( 420 ), MM2TWIPS( 594 ) }, // A2 - { SVX_PAPER_USER, MM2TWIPS( 297 ), MM2TWIPS( 420 ) }, // A3 Transverse - { SVX_PAPER_USER, MM2TWIPS( 322 ), MM2TWIPS( 445 ) }, // A3 Extra Transverse - { SVX_PAPER_USER, MM2TWIPS( 200 ), MM2TWIPS( 148 ) }, // Double Japanese Postcard -/* 70*/ { SVX_PAPER_USER, MM2TWIPS( 105 ), MM2TWIPS( 148 ) }, // A6 - { SVX_PAPER_USER, 0, 0 }, // undefined - { SVX_PAPER_USER, 0, 0 }, // undefined - { SVX_PAPER_USER, 0, 0 }, // undefined - { SVX_PAPER_USER, 0, 0 }, // undefined -/* 75*/ { SVX_PAPER_USER, IN2TWIPS( 11 ), IN2TWIPS( 8.5 ) }, // Letter Rotated - { SVX_PAPER_USER, MM2TWIPS( 420 ), MM2TWIPS( 297 ) }, // A3 Rotated - { SVX_PAPER_USER, MM2TWIPS( 297 ), MM2TWIPS( 210 ) }, // A4 Rotated - { SVX_PAPER_USER, MM2TWIPS( 210 ), MM2TWIPS( 148 ) }, // A5 Rotated - { SVX_PAPER_USER, MM2TWIPS( 364 ), MM2TWIPS( 257 ) }, // B4 (JIS) Rotated -/* 80*/ { SVX_PAPER_USER, MM2TWIPS( 257 ), MM2TWIPS( 182 ) }, // B5 (JIS) Rotated - { SVX_PAPER_USER, MM2TWIPS( 148 ), MM2TWIPS( 100 ) }, // Japanese Postcard Rotated - { SVX_PAPER_USER, MM2TWIPS( 148 ), MM2TWIPS( 200 ) }, // Double Japanese Postcard Rotated - { SVX_PAPER_USER, MM2TWIPS( 148 ), MM2TWIPS( 105 ) }, // A6 Rotated - { SVX_PAPER_USER, 0, 0 }, // undefined -/* 85*/ { SVX_PAPER_USER, 0, 0 }, // undefined - { SVX_PAPER_USER, 0, 0 }, // undefined - { SVX_PAPER_USER, 0, 0 }, // undefined - { SVX_PAPER_B6_JIS, MM2TWIPS( 128 ), MM2TWIPS( 182 ) }, // B6 (JIS) - { SVX_PAPER_USER, MM2TWIPS( 182 ), MM2TWIPS( 128 ) }, // B6 (JIS) Rotated -/* 90*/ { SVX_PAPER_USER, IN2TWIPS( 12 ), IN2TWIPS( 11 ) } // 12x11 +/* 0*/ { PAPER_USER, 0, 0 }, // undefined + { PAPER_LETTER, IN2TWIPS( 8.5 ), IN2TWIPS( 11 ) }, // Letter + { PAPER_USER, IN2TWIPS( 8.5 ), IN2TWIPS( 11 ) }, // Letter Small + { PAPER_TABLOID, IN2TWIPS( 11 ), IN2TWIPS( 17 ) }, // Tabloid + { PAPER_LEDGER, IN2TWIPS( 17 ), IN2TWIPS( 11 ) }, // Ledger +/* 5*/ { PAPER_LEGAL, IN2TWIPS( 8.5 ), IN2TWIPS( 14 ) }, // Legal + { PAPER_STATEMENT, IN2TWIPS( 5.5 ), IN2TWIPS( 8.5 ) }, // Statement + { PAPER_EXECUTIVE, IN2TWIPS( 7.25 ), IN2TWIPS( 10.5 ) }, // Executive + { PAPER_A3, MM2TWIPS( 297 ), MM2TWIPS( 420 ) }, // A3 + { PAPER_A4, MM2TWIPS( 210 ), MM2TWIPS( 297 ) }, // A4 +/* 10*/ { PAPER_USER, MM2TWIPS( 210 ), MM2TWIPS( 297 ) }, // A4 Small + { PAPER_A5, MM2TWIPS( 148 ), MM2TWIPS( 210 ) }, // A5 + //See: http://wiki.services.openoffice.org/wiki/DefaultPaperSize comments + //near DMPAPER_B4 in vcl + //i.e. + //http://msdn.microsoft.com/en-us/library/bb241398.aspx makes the claim: + //xlPaperB4 12 B4 (250 mm x 354 mm) + //xlPaperB5 13 A5 (148 mm x 210 mm) + //but, a paper enum called B5 is surely not actually "A5", and furthermore + //the XlPaperSize enumeration otherwise follows the DMPAPER values + //http://msdn.microsoft.com/en-us/library/ms776398(VS.85).aspx + //which has + //DMPAPER_B4 12 B4 (JIS) 250 x 354 + //DMPAPER_B5 13 B5 (JIS) 182 x 257 mm + //which claim them to be the JIS sizes. Though that document then gives + //"B4 (JIS)" an *ISO* B4 size in the text, but + //http://partners.adobe.com/public/developer/en/ps/5003.PPD_Spec_v4.3.pdf + //claims that the MS DMPAPER_B4 and DMPAPER_B5 truly are the JIS sizes + //which at least makes some sort of sense. (cmc) + { PAPER_B4_JIS, MM2TWIPS( 257 ), MM2TWIPS( 364 ) }, // B4 (JIS) + { PAPER_B5_JIS, MM2TWIPS( 182 ), MM2TWIPS( 257 ) }, // B5 (JIS) + { PAPER_USER, IN2TWIPS( 8.5 ), IN2TWIPS( 13 ) }, // Folio +/* 15*/ { PAPER_QUARTO, MM2TWIPS( 215 ), MM2TWIPS( 275 ) }, // Quarto + { PAPER_10x14, IN2TWIPS( 10 ), IN2TWIPS( 14 ) }, // 10x14 + { PAPER_USER, IN2TWIPS( 11 ), IN2TWIPS( 17 ) }, // 11x17 + { PAPER_USER, IN2TWIPS( 8.5 ), IN2TWIPS( 11 ) }, // Note + { PAPER_ENV_9, IN2TWIPS( 3.875 ), IN2TWIPS( 8.875 ) }, // Envelope #9 +/* 20*/ { PAPER_ENV_10, IN2TWIPS( 4.125 ), IN2TWIPS( 9.5 ) }, // Envelope #10 + { PAPER_ENV_11, IN2TWIPS( 4.5 ), IN2TWIPS( 10.375 ) }, // Envelope #11 + { PAPER_ENV_12, IN2TWIPS( 4.75 ), IN2TWIPS( 11 ) }, // Envelope #12 + { PAPER_ENV_14, IN2TWIPS( 5 ), IN2TWIPS( 11.5 ) }, // Envelope #14 + { PAPER_C, IN2TWIPS( 17 ), IN2TWIPS( 22 ) }, // ANSI-C +/* 25*/ { PAPER_D, IN2TWIPS( 22 ), IN2TWIPS( 34 ) }, // ANSI-D + { PAPER_E, IN2TWIPS( 34 ), IN2TWIPS( 44 ) }, // ANSI-E + { PAPER_ENV_DL, MM2TWIPS( 110 ), MM2TWIPS( 220 ) }, // Envelope DL + { PAPER_ENV_C5, MM2TWIPS( 162 ), MM2TWIPS( 229 ) }, // Envelope C5 + { PAPER_ENV_C3, MM2TWIPS( 324 ), MM2TWIPS( 458 ) }, // Envelope C3 +/* 30*/ { PAPER_ENV_C4, MM2TWIPS( 229 ), MM2TWIPS( 324 ) }, // Envelope C4 + { PAPER_ENV_C6, MM2TWIPS( 114 ), MM2TWIPS( 162 ) }, // Envelope C6 + { PAPER_ENV_C65, MM2TWIPS( 114 ), MM2TWIPS( 229 ) }, // Envelope C65 + { PAPER_B4_ISO, MM2TWIPS( 250 ), MM2TWIPS( 353 ) }, // B4 (ISO) + { PAPER_B5_ISO, MM2TWIPS( 176 ), MM2TWIPS( 250 ) }, // B5 (ISO) +/* 35*/ { PAPER_B6_ISO, MM2TWIPS( 125 ), MM2TWIPS( 176 ) }, // B6 (ISO) + { PAPER_ENV_ITALY, MM2TWIPS( 110 ), MM2TWIPS( 230 ) }, // Envelope Italy + { PAPER_ENV_MONARCH, IN2TWIPS( 3.875 ), IN2TWIPS( 7.5 ) }, // Envelope Monarch + { PAPER_ENV_PERSONAL, IN2TWIPS( 3.625 ), IN2TWIPS( 6.5 ) }, // 6 3/4 Envelope + { PAPER_FANFOLD_US, IN2TWIPS( 14.875 ), IN2TWIPS( 11 ) }, // US Std Fanfold +/* 40*/ { PAPER_FANFOLD_DE, IN2TWIPS( 8.5 ), IN2TWIPS( 12 ) }, // German Std Fanfold + { PAPER_FANFOLD_LEGAL_DE, IN2TWIPS( 8.5 ), IN2TWIPS( 13 ) }, // German Legal Fanfold + { PAPER_B4_ISO, MM2TWIPS( 250 ), MM2TWIPS( 353 ) }, // B4 (ISO) + { PAPER_POSTCARD_JP,MM2TWIPS( 100 ), MM2TWIPS( 148 ) }, // Japanese Postcard + { PAPER_9x11, IN2TWIPS( 9 ), IN2TWIPS( 11 ) }, // 9x11 +/* 45*/ { PAPER_10x11, IN2TWIPS( 10 ), IN2TWIPS( 11 ) }, // 10x11 + { PAPER_15x11, IN2TWIPS( 15 ), IN2TWIPS( 11 ) }, // 15x11 + { PAPER_ENV_INVITE, MM2TWIPS( 220 ), MM2TWIPS( 220 ) }, // Envelope Invite + { PAPER_USER, 0, 0 }, // undefined + { PAPER_USER, 0, 0 }, // undefined +/* 50*/ { PAPER_USER, IN2TWIPS( 9.5 ), IN2TWIPS( 12 ) }, // Letter Extra + { PAPER_USER, IN2TWIPS( 9.5 ), IN2TWIPS( 15 ) }, // Legal Extra + { PAPER_USER, IN2TWIPS( 11.69 ), IN2TWIPS( 18 ) }, // Tabloid Extra + { PAPER_USER, MM2TWIPS( 235 ), MM2TWIPS( 322 ) }, // A4 Extra + { PAPER_USER, IN2TWIPS( 8.5 ), IN2TWIPS( 11 ) }, // Letter Transverse +/* 55*/ { PAPER_USER, MM2TWIPS( 210 ), MM2TWIPS( 297 ) }, // A4 Transverse + { PAPER_USER, IN2TWIPS( 9.5 ), IN2TWIPS( 12 ) }, // Letter Extra Transverse + { PAPER_A_PLUS, MM2TWIPS( 227 ), MM2TWIPS( 356 ) }, // Super A/A4 + { PAPER_B_PLUS, MM2TWIPS( 305 ), MM2TWIPS( 487 ) }, // Super B/A3 + { PAPER_LETTER_PLUS,IN2TWIPS( 8.5 ), IN2TWIPS( 12.69 ) }, // Letter Plus +/* 60*/ { PAPER_A4_PLUS, MM2TWIPS( 210 ), MM2TWIPS( 330 ) }, // A4 Plus + { PAPER_USER, MM2TWIPS( 148 ), MM2TWIPS( 210 ) }, // A5 Transverse + { PAPER_USER, MM2TWIPS( 182 ), MM2TWIPS( 257 ) }, // B5 (JIS) Transverse + { PAPER_USER, MM2TWIPS( 322 ), MM2TWIPS( 445 ) }, // A3 Extra + { PAPER_USER, MM2TWIPS( 174 ), MM2TWIPS( 235 ) }, // A5 Extra +/* 65*/ { PAPER_USER, MM2TWIPS( 201 ), MM2TWIPS( 276 ) }, // B5 (ISO) Extra + { PAPER_A2, MM2TWIPS( 420 ), MM2TWIPS( 594 ) }, // A2 + { PAPER_USER, MM2TWIPS( 297 ), MM2TWIPS( 420 ) }, // A3 Transverse + { PAPER_USER, MM2TWIPS( 322 ), MM2TWIPS( 445 ) }, // A3 Extra Transverse + { PAPER_DOUBLEPOSTCARD_JP, MM2TWIPS( 200 ), MM2TWIPS( 148 ) }, // Double Japanese Postcard +/* 70*/ { PAPER_A6, MM2TWIPS( 105 ), MM2TWIPS( 148 ) }, // A6 + { PAPER_USER, 0, 0 }, // undefined + { PAPER_USER, 0, 0 }, // undefined + { PAPER_USER, 0, 0 }, // undefined + { PAPER_USER, 0, 0 }, // undefined +/* 75*/ { PAPER_USER, IN2TWIPS( 11 ), IN2TWIPS( 8.5 ) }, // Letter Rotated + { PAPER_USER, MM2TWIPS( 420 ), MM2TWIPS( 297 ) }, // A3 Rotated + { PAPER_USER, MM2TWIPS( 297 ), MM2TWIPS( 210 ) }, // A4 Rotated + { PAPER_USER, MM2TWIPS( 210 ), MM2TWIPS( 148 ) }, // A5 Rotated + { PAPER_USER, MM2TWIPS( 364 ), MM2TWIPS( 257 ) }, // B4 (JIS) Rotated +/* 80*/ { PAPER_USER, MM2TWIPS( 257 ), MM2TWIPS( 182 ) }, // B5 (JIS) Rotated + { PAPER_USER, MM2TWIPS( 148 ), MM2TWIPS( 100 ) }, // Japanese Postcard Rotated + { PAPER_USER, MM2TWIPS( 148 ), MM2TWIPS( 200 ) }, // Double Japanese Postcard Rotated + { PAPER_USER, MM2TWIPS( 148 ), MM2TWIPS( 105 ) }, // A6 Rotated + { PAPER_USER, 0, 0 }, // undefined +/* 85*/ { PAPER_USER, 0, 0 }, // undefined + { PAPER_USER, 0, 0 }, // undefined + { PAPER_USER, 0, 0 }, // undefined + { PAPER_B6_JIS, MM2TWIPS( 128 ), MM2TWIPS( 182 ) }, // B6 (JIS) + { PAPER_USER, MM2TWIPS( 182 ), MM2TWIPS( 128 ) }, // B6 (JIS) Rotated +/* 90*/ { PAPER_12x11, IN2TWIPS( 12 ), IN2TWIPS( 11 ) } // 12x11 }; #undef IN2TWIPS @@ -193,15 +210,14 @@ Size XclPageData::GetScPaperSize() const pEntry += mnPaperSize; Size aSize; - if( pEntry->mePaper == SVX_PAPER_USER ) + if( pEntry->mePaper == PAPER_USER ) aSize = Size( pEntry->mnWidth, pEntry->mnHeight ); else aSize = SvxPaperInfo::GetPaperSize( pEntry->mePaper ); // invalid size -> back to default if( !aSize.Width() || !aSize.Height() ) - aSize = SvxPaperInfo::GetPaperSize( SvxPaperInfo::GetDefaultSvxPaper( - Application::GetSettings().GetLanguage() ) ); + aSize = SvxPaperInfo::GetDefaultPaperSize(); if( !mbPortrait ) ::std::swap( aSize.Width(), aSize.Height() ); diff --git a/sc/source/filter/excel/xlroot.cxx b/sc/source/filter/excel/xlroot.cxx index bdc75df21c13..8f5ddadd0370 100644 --- a/sc/source/filter/excel/xlroot.cxx +++ b/sc/source/filter/excel/xlroot.cxx @@ -92,8 +92,7 @@ XclRootData::XclRootData( XclBiff eBiff, SfxMedium& rMedium, mxRD( new RootData ),//! mnCharWidth( 110 ), mnScTab( 0 ), - mbExport( bExport ), - mbHasPassw( false ) + mbExport( bExport ) { // default script type, e.g. for empty cells switch( ScGlobal::GetDefaultScriptType() ) @@ -199,17 +198,6 @@ void XclRoot::SetCharWidth( const XclFontData& rFontData ) } } -const String& XclRoot::QueryPassword() const -{ - if( !mrData.mbHasPassw ) - { - mrData.maPassw = ScfApiHelper::QueryPasswordForMedium( GetMedium() ); - // set to true, even if dialog has been cancelled (never ask twice) - mrData.mbHasPassw = true; - } - return mrData.maPassw; -} - bool XclRoot::HasVbaStorage() const { SotStorageRef xRootStrg = GetRootStorage(); diff --git a/sc/source/filter/excel/xlstyle.cxx b/sc/source/filter/excel/xlstyle.cxx index e8fab52ca819..4e5bf9b7570a 100644 --- a/sc/source/filter/excel/xlstyle.cxx +++ b/sc/source/filter/excel/xlstyle.cxx @@ -664,6 +664,8 @@ void XclFontPropSetHelper::ReadFontProperties( XclFontData& rFontData, sal_Int16 nApiEscapement = 0; sal_Int8 nApiEscHeight = 0; maHlpChEscapement.ReadFromPropertySet( rPropSet ); + maHlpChEscapement.ReadFromPropertySet( rPropSet ); + maHlpChEscapement.ReadFromPropertySet( rPropSet ); maHlpChEscapement >> nApiEscapement >> nApiEscHeight; rFontData.SetApiEscapement( nApiEscapement ); } diff --git a/sc/source/filter/html/htmlimp.cxx b/sc/source/filter/html/htmlimp.cxx index abc7d2b21392..5591e8ec993e 100644 --- a/sc/source/filter/html/htmlimp.cxx +++ b/sc/source/filter/html/htmlimp.cxx @@ -99,7 +99,7 @@ ScHTMLImport::ScHTMLImport( ScDocument* pDocP, const String& rBaseURL, const ScR if ( !aPageSize.Width() || !aPageSize.Height() ) { DBG_ERRORFILE("PageSize Null ?!?!?"); - aPageSize = SvxPaperInfo::GetPaperSize( SVX_PAPER_A4 ); + aPageSize = SvxPaperInfo::GetPaperSize( PAPER_A4 ); } aPageSize.Width() -= nLeftMargin + nRightMargin; aPageSize.Height() -= nTopMargin + nBottomMargin; @@ -109,7 +109,7 @@ ScHTMLImport::ScHTMLImport( ScDocument* pDocP, const String& rBaseURL, const ScR { DBG_ERRORFILE("kein StyleSheet?!?"); aPageSize = pDefaultDev->LogicToPixel( - SvxPaperInfo::GetPaperSize( SVX_PAPER_A4 ), MapMode( MAP_TWIP ) ); + SvxPaperInfo::GetPaperSize( PAPER_A4 ), MapMode( MAP_TWIP ) ); } if( bCalcWidthHeight ) mpParser = new ScHTMLLayoutParser( mpEngine, rBaseURL, aPageSize, pDocP ); diff --git a/sc/source/filter/html/htmlpars.cxx b/sc/source/filter/html/htmlpars.cxx index 7fed8e84942a..36bbfe1d2787 100644 --- a/sc/source/filter/html/htmlpars.cxx +++ b/sc/source/filter/html/htmlpars.cxx @@ -49,10 +49,10 @@ #include <svx/udlnitem.hxx> #include <svx/wghtitem.hxx> #include <svx/boxitem.hxx> -#include <sfx2/frmhtml.hxx> #include <sfx2/objsh.hxx> #include <svtools/eitem.hxx> #include <svtools/filter.hxx> +#include <svtools/parhtml.hxx> #include <svtools/htmlkywd.hxx> #include <svtools/htmltokn.h> #include <sfx2/docfile.hxx> @@ -1544,25 +1544,12 @@ void ScHTMLLayoutParser::ProcToken( ImportInfo* pInfo ) { case HTML_META: { - USHORT nContentOpt = HTML_O_CONTENT; - rtl_TextEncoding eEnc = RTL_TEXTENCODING_DONTKNOW; HTMLParser* pParser = (HTMLParser*) pInfo->pParser; - const HTMLOptions* pOptions = pParser->GetOptions( &nContentOpt ); uno::Reference<document::XDocumentPropertiesSupplier> xDPS( mpDoc->GetDocumentShell()->GetModel(), uno::UNO_QUERY_THROW); - SfxFrameHTMLParser::ParseMetaOptions( + pParser->ParseMetaOptions( xDPS->getDocumentProperties(), - mpDoc->GetDocumentShell()->GetHeaderAttributes(), - pOptions, eEnc ); - // If the encoding is set by a META tag, it may only overwrite the - // current encoding if both, the current and the new encoding, are 1-BYTE - // encodings. Everything else cannot lead to reasonable results. - if ( rtl_isOctetTextEncoding( eEnc ) && - rtl_isOctetTextEncoding( pParser->GetSrcEncoding() ) ) - { - eEnc = GetExtendedCompatibilityTextEncoding( eEnc ); - pParser->SetSrcEncoding( eEnc ); - } + mpDoc->GetDocumentShell()->GetHeaderAttributes() ); } break; case HTML_TITLE_ON: @@ -1728,31 +1715,29 @@ void ScHTMLLayoutParser::ProcToken( ImportInfo* pInfo ) // ============================================================================ template< typename Type > -inline Type bound( const Type& rValue, const Type& rMin, const Type& rMax ) +inline Type getLimitedValue( const Type& rValue, const Type& rMin, const Type& rMax ) { return ::std::max( ::std::min( rValue, rMax ), rMin ); } - // ============================================================================ /** Iterates through all HTML tag options of the passed ImportInfo struct. */ class ScHTMLOptionIterator { private: - const HTMLOptions* mpOptions; /// The options array. - const HTMLOption* mpCurrOption; /// Current option. - sal_uInt16 mnCount; /// Size of the options array. - sal_uInt16 mnIndex; /// Next option to return. + const HTMLOptions* mpOptions; /// The options array. + const HTMLOption* mpCurrOption; /// Current option. + sal_uInt16 mnCount; /// Size of the options array. + sal_uInt16 mnIndex; /// Next option to return. public: - explicit ScHTMLOptionIterator( const ImportInfo& rInfo ); + explicit ScHTMLOptionIterator( const ImportInfo& rInfo ); - inline bool is() const { return mnIndex < mnCount; } - inline const HTMLOption* operator->() const { return mpCurrOption; } - inline const HTMLOption& operator*() const { return *mpCurrOption; } - ScHTMLOptionIterator& operator++(); + inline bool is() const { return mnIndex < mnCount; } + inline const HTMLOption* operator->() const { return mpCurrOption; } + inline const HTMLOption& operator*() const { return *mpCurrOption; } + ScHTMLOptionIterator& operator++(); }; - // ---------------------------------------------------------------------------- ScHTMLOptionIterator::ScHTMLOptionIterator( const ImportInfo& rInfo ) : @@ -1777,7 +1762,6 @@ ScHTMLOptionIterator& ScHTMLOptionIterator::operator++() return *this; } - // ============================================================================ ScHTMLEntry::ScHTMLEntry( const SfxItemSet& rItemSet, ScHTMLTableId nTableId ) : @@ -1832,14 +1816,15 @@ void ScHTMLEntry::Strip( const EditEngine& rEditEngine ) } } - // ============================================================================ /** A map of ScHTMLTable objects. - @descr Organizes the tables with a unique table key. Stores nested tables inside - the parent table and forms in this way a tree structure of tables. - An instance of this class ownes the contained table objects and deletes them - on destruction. */ + + Organizes the tables with a unique table key. Stores nested tables inside + the parent table and forms in this way a tree structure of tables. An + instance of this class ownes the contained table objects and deletes them + on destruction. + */ class ScHTMLTableMap { private: @@ -1851,36 +1836,35 @@ public: typedef ScHTMLTableStdMap::const_iterator const_iterator; private: - ScHTMLTable& mrParentTable; /// Reference to parent table. - ScHTMLTableStdMap maTables; /// Container for all table objects. - mutable ScHTMLTable* mpCurrTable; /// Current table, used for fast search. + ScHTMLTable& mrParentTable; /// Reference to parent table. + ScHTMLTableStdMap maTables; /// Container for all table objects. + mutable ScHTMLTable* mpCurrTable; /// Current table, used for fast search. public: - explicit ScHTMLTableMap( ScHTMLTable& rParentTable ); - virtual ~ScHTMLTableMap(); + explicit ScHTMLTableMap( ScHTMLTable& rParentTable ); + virtual ~ScHTMLTableMap(); - inline iterator begin() { return maTables.begin(); } - inline const_iterator begin() const { return maTables.begin(); } - inline iterator end() { return maTables.end(); } - inline const_iterator end() const { return maTables.end(); } - inline bool empty() const { return maTables.empty(); } + inline iterator begin() { return maTables.begin(); } + inline const_iterator begin() const { return maTables.begin(); } + inline iterator end() { return maTables.end(); } + inline const_iterator end() const { return maTables.end(); } + inline bool empty() const { return maTables.empty(); } /** Returns the specified table. @param nTableId Unique identifier of the table. @param bDeep true = searches deep in all nested table; false = only in this container. */ - ScHTMLTable* FindTable( ScHTMLTableId nTableId, bool bDeep = true ) const; + ScHTMLTable* FindTable( ScHTMLTableId nTableId, bool bDeep = true ) const; /** Inserts a new table into the container. This container owns the created table. @param bPreFormText true = New table is based on preformatted text (<pre> tag). */ - ScHTMLTable* CreateTable( const ImportInfo& rInfo, bool bPreFormText ); + ScHTMLTable* CreateTable( const ImportInfo& rInfo, bool bPreFormText ); private: /** Sets a working table with its index for search optimization. */ - inline void SetCurrTable( ScHTMLTable* pTable ) const - { if( pTable ) mpCurrTable = pTable; } + inline void SetCurrTable( ScHTMLTable* pTable ) const + { if( pTable ) mpCurrTable = pTable; } }; - // ---------------------------------------------------------------------------- ScHTMLTableMap::ScHTMLTableMap( ScHTMLTable& rParentTable ) : @@ -1921,28 +1905,29 @@ ScHTMLTable* ScHTMLTableMap::CreateTable( const ImportInfo& rInfo, bool bPreForm return pTable; } - // ---------------------------------------------------------------------------- /** Simplified forward iterator for convenience. - @descr Before the iterator can be dereferenced, it must be tested with the - is() method. The iterator may be invalid directly after construction - (i.e. empty container). */ + + Before the iterator can be dereferenced, it must be tested with the is() + method. The iterator may be invalid directly after construction (e.g. empty + container). + */ class ScHTMLTableIterator { -private: - ScHTMLTableMap::const_iterator maIter; - ScHTMLTableMap::const_iterator maEnd; - public: /** Constructs the iterator for the passed table map. @param pTableMap Pointer to the table map (is allowed to be NULL). */ - explicit ScHTMLTableIterator( const ScHTMLTableMap* pTableMap ); + explicit ScHTMLTableIterator( const ScHTMLTableMap* pTableMap ); - inline bool is() const { return maIter != maEnd; } - inline ScHTMLTable* operator->() { return maIter->second.get(); } - inline ScHTMLTable& operator*() { return *maIter->second; } + inline bool is() const { return maIter != maEnd; } + inline ScHTMLTable* operator->() { return maIter->second.get(); } + inline ScHTMLTable& operator*() { return *maIter->second; } inline ScHTMLTableIterator& operator++() { ++maIter; return *this; } + +private: + ScHTMLTableMap::const_iterator maIter; + ScHTMLTableMap::const_iterator maEnd; }; ScHTMLTableIterator::ScHTMLTableIterator( const ScHTMLTableMap* pTableMap ) @@ -1954,7 +1939,6 @@ ScHTMLTableIterator::ScHTMLTableIterator( const ScHTMLTableMap* pTableMap ) } } - // ============================================================================ ScHTMLTableAutoId::ScHTMLTableAutoId( ScHTMLTableId& rnUnusedId ) : @@ -1964,7 +1948,6 @@ ScHTMLTableAutoId::ScHTMLTableAutoId( ScHTMLTableId& rnUnusedId ) : ++mrnUnusedId; } - // ---------------------------------------------------------------------------- ScHTMLTable::ScHTMLTable( ScHTMLTable& rParentTable, const ImportInfo& rInfo, bool bPreFormText ) : @@ -2023,7 +2006,7 @@ ScHTMLTable::ScHTMLTable( SfxItemPool& rPool, EditEngine& rEditEngine, ScEEParse // open the first "cell" of the document ImplRowOn(); ImplDataOn( ScHTMLSize( 1, 1 ) ); - mpCurrEntry = CreateEntry(); + mxCurrEntry = CreateEntry(); } ScHTMLTable::~ScHTMLTable() @@ -2033,45 +2016,46 @@ ScHTMLTable::~ScHTMLTable() const SfxItemSet& ScHTMLTable::GetCurrItemSet() const { // first try cell item set, then row item set, then table item set - return mpDataItemSet.get() ? *mpDataItemSet : (mpRowItemSet.get() ? *mpRowItemSet : maTableItemSet); + return mxDataItemSet.get() ? *mxDataItemSet : (mxRowItemSet.get() ? *mxRowItemSet : maTableItemSet); } ScHTMLSize ScHTMLTable::GetSpan( const ScHTMLPos& rCellPos ) const { ScHTMLSize aSpan( 1, 1 ); - if( ScRange* pRange = maLockList.Find( rCellPos.MakeAddr() ) ) + ScRange* pRange = 0; + if( ((pRange = maVMergedCells.Find( rCellPos.MakeAddr() )) != 0) || ((pRange = maHMergedCells.Find( rCellPos.MakeAddr() )) != 0) ) aSpan.Set( pRange->aEnd.Col() - pRange->aStart.Col() + 1, pRange->aEnd.Row() - pRange->aStart.Row() + 1 ); return aSpan; } ScHTMLTable* ScHTMLTable::FindNestedTable( ScHTMLTableId nTableId ) const { - return mpNestedTables.get() ? mpNestedTables->FindTable( nTableId, true ) : 0; + return mxNestedTables.get() ? mxNestedTables->FindTable( nTableId, true ) : 0; } void ScHTMLTable::PutItem( const SfxPoolItem& rItem ) { - DBG_ASSERT( mpCurrEntry.get(), "ScHTMLTable::PutItem - no current entry" ); - if( mpCurrEntry.get() && mpCurrEntry->IsEmpty() ) - mpCurrEntry->GetItemSet().Put( rItem ); + DBG_ASSERT( mxCurrEntry.get(), "ScHTMLTable::PutItem - no current entry" ); + if( mxCurrEntry.get() && mxCurrEntry->IsEmpty() ) + mxCurrEntry->GetItemSet().Put( rItem ); } void ScHTMLTable::PutText( const ImportInfo& rInfo ) { - DBG_ASSERT( mpCurrEntry.get(), "ScHTMLTable::PutText - no current entry" ); - if( mpCurrEntry.get() ) + DBG_ASSERT( mxCurrEntry.get(), "ScHTMLTable::PutText - no current entry" ); + if( mxCurrEntry.get() ) { - if( !mpCurrEntry->HasContents() && IsSpaceCharInfo( rInfo ) ) - mpCurrEntry->AdjustStart( rInfo ); + if( !mxCurrEntry->HasContents() && IsSpaceCharInfo( rInfo ) ) + mxCurrEntry->AdjustStart( rInfo ); else - mpCurrEntry->AdjustEnd( rInfo ); + mxCurrEntry->AdjustEnd( rInfo ); } } void ScHTMLTable::InsertPara( const ImportInfo& rInfo ) { - if( mpCurrEntry.get() && mbDataOn && !IsEmptyCell() ) - mpCurrEntry->SetImportAlways(); + if( mxCurrEntry.get() && mbDataOn && !IsEmptyCell() ) + mxCurrEntry->SetImportAlways(); PushEntry( rInfo ); CreateNewEntry( rInfo ); InsertLeadingEmptyLine(); @@ -2097,10 +2081,10 @@ void ScHTMLTable::InsertLeadingEmptyLine() void ScHTMLTable::AnchorOn() { - DBG_ASSERT( mpCurrEntry.get(), "ScHTMLTable::AnchorOn - no current entry" ); + DBG_ASSERT( mxCurrEntry.get(), "ScHTMLTable::AnchorOn - no current entry" ); // don't skip entries with single hyperlinks - if( mpCurrEntry.get() ) - mpCurrEntry->SetImportAlways(); + if( mxCurrEntry.get() ) + mxCurrEntry->SetImportAlways(); } ScHTMLTable* ScHTMLTable::TableOn( const ImportInfo& rInfo ) @@ -2131,7 +2115,7 @@ void ScHTMLTable::RowOn( const ImportInfo& rInfo ) if( mpParentTable && !mbPreFormText ) // no rows allowed in global and preformatted tables { ImplRowOn(); - ProcessFormatOptions( *mpRowItemSet, rInfo ); + ProcessFormatOptions( *mxRowItemSet, rInfo ); } CreateNewEntry( rInfo ); } @@ -2157,10 +2141,10 @@ void ScHTMLTable::DataOn( const ImportInfo& rInfo ) switch( aIter->GetToken() ) { case HTML_O_COLSPAN: - aSpanSize.mnCols = static_cast< SCCOL >( bound( aIter->GetString().ToInt32(), static_cast<sal_Int32>(1), static_cast<sal_Int32>(256) ) ); + aSpanSize.mnCols = static_cast< SCCOL >( getLimitedValue< sal_Int32 >( aIter->GetString().ToInt32(), 1, 256 ) ); break; case HTML_O_ROWSPAN: - aSpanSize.mnRows = static_cast< SCROW >( bound( aIter->GetString().ToInt32(), static_cast<sal_Int32>(1), static_cast<sal_Int32>(256) ) ); + aSpanSize.mnRows = static_cast< SCROW >( getLimitedValue< sal_Int32 >( aIter->GetString().ToInt32(), 1, 256 ) ); break; case HTML_O_SDVAL: pValStr.reset( new String( aIter->GetString() ) ); @@ -2172,10 +2156,10 @@ void ScHTMLTable::DataOn( const ImportInfo& rInfo ) } ImplDataOn( aSpanSize ); - ProcessFormatOptions( *mpDataItemSet, rInfo ); + ProcessFormatOptions( *mxDataItemSet, rInfo ); CreateNewEntry( rInfo ); - mpCurrEntry->pValStr = pValStr.release(); - mpCurrEntry->pNumStr = pNumStr.release(); + mxCurrEntry->pValStr = pValStr.release(); + mxCurrEntry->pNumStr = pNumStr.release(); } else CreateNewEntry( rInfo ); @@ -2199,7 +2183,7 @@ void ScHTMLTable::BodyOn( const ImportInfo& rInfo ) ImplRowOn(); if( bPushed || !mbDataOn ) ImplDataOn( ScHTMLSize( 1, 1 ) ); - ProcessFormatOptions( *mpDataItemSet, rInfo ); + ProcessFormatOptions( *mxDataItemSet, rInfo ); } CreateNewEntry( rInfo ); } @@ -2233,29 +2217,33 @@ ScHTMLTable* ScHTMLTable::CloseTable( const ImportInfo& rInfo ) SCCOLROW ScHTMLTable::GetDocSize( ScHTMLOrient eOrient, SCCOLROW nCellPos ) const { - const ScSizeVec& rSizes = maSizes[ eOrient ]; - return (static_cast< size_t >( nCellPos ) < rSizes.size()) ? rSizes[ nCellPos ] : 0; + const ScSizeVec& rSizes = maCumSizes[ eOrient ]; + size_t nIndex = static_cast< size_t >( nCellPos ); + if( nIndex >= rSizes.size() ) return 0; + return (nIndex == 0) ? rSizes.front() : (rSizes[ nIndex ] - rSizes[ nIndex - 1 ]); } SCCOLROW ScHTMLTable::GetDocSize( ScHTMLOrient eOrient, SCCOLROW nCellBegin, SCCOLROW nCellEnd ) const { - SCCOLROW nSize = 0; - for( SCCOLROW nCellPos = nCellBegin; nCellPos < nCellEnd; ++nCellPos ) - nSize += GetDocSize( eOrient, nCellPos ); - return nSize; + const ScSizeVec& rSizes = maCumSizes[ eOrient ]; + size_t nBeginIdx = static_cast< size_t >( ::std::max< SCCOLROW >( nCellBegin, 0 ) ); + size_t nEndIdx = static_cast< size_t >( ::std::min< SCCOLROW >( nCellEnd, static_cast< SCCOLROW >( rSizes.size() ) ) ); + if (nBeginIdx >= nEndIdx ) return 0; + return rSizes[ nEndIdx - 1 ] - ((nBeginIdx == 0) ? 0 : rSizes[ nBeginIdx - 1 ]); } SCCOLROW ScHTMLTable::GetDocSize( ScHTMLOrient eOrient ) const { - return GetDocSize( eOrient, 0, maSize.Get( eOrient ) ); + const ScSizeVec& rSizes = maCumSizes[ eOrient ]; + return rSizes.empty() ? 0 : rSizes.back(); } ScHTMLSize ScHTMLTable::GetDocSize( const ScHTMLPos& rCellPos ) const { - ScHTMLSize aCellSpan( GetSpan( rCellPos ) ); + ScHTMLSize aCellSpan = GetSpan( rCellPos ); return ScHTMLSize( - static_cast<SCCOL>(GetDocSize( tdCol, rCellPos.mnCol, rCellPos.mnCol + aCellSpan.mnCols )), - static_cast<SCROW>(GetDocSize( tdRow, static_cast<SCCOLROW>(rCellPos.mnRow), static_cast<SCCOLROW>(rCellPos.mnRow + aCellSpan.mnRows) )) ); + static_cast< SCCOL >( GetDocSize( tdCol, rCellPos.mnCol, rCellPos.mnCol + aCellSpan.mnCols ) ), + static_cast< SCROW >( GetDocSize( tdRow, rCellPos.mnRow, rCellPos.mnRow + aCellSpan.mnRows ) ) ); } SCCOLROW ScHTMLTable::GetDocPos( ScHTMLOrient eOrient, SCCOLROW nCellPos ) const @@ -2265,13 +2253,15 @@ SCCOLROW ScHTMLTable::GetDocPos( ScHTMLOrient eOrient, SCCOLROW nCellPos ) const ScHTMLPos ScHTMLTable::GetDocPos( const ScHTMLPos& rCellPos ) const { - return ScHTMLPos( static_cast<SCCOL>(GetDocPos( tdCol, static_cast<SCCOLROW>(rCellPos.mnCol)) ), static_cast<SCROW>(GetDocPos( tdRow, static_cast<SCCOLROW>(rCellPos.mnRow) )) ); + return ScHTMLPos( + static_cast< SCCOL >( GetDocPos( tdCol, rCellPos.mnCol ) ), + static_cast< SCROW >( GetDocPos( tdRow, rCellPos.mnRow ) ) ); } void ScHTMLTable::GetDocRange( ScRange& rRange ) const { rRange.aStart = rRange.aEnd = maDocBasePos.MakeAddr(); - rRange.aEnd.Move( static_cast<SCsCOL>(GetDocSize( tdCol )) - 1, GetDocSize( tdRow ) - 1, 0 ); + rRange.aEnd.Move( static_cast< SCsCOL >( GetDocSize( tdCol ) ) - 1, static_cast< SCsROW >( GetDocSize( tdRow ) ) - 1, 0 ); } void ScHTMLTable::ApplyCellBorders( ScDocument* pDoc, const ScAddress& rFirstPos ) const @@ -2294,8 +2284,8 @@ void ScHTMLTable::ApplyCellBorders( ScDocument* pDoc, const ScAddress& rFirstPos { SvxBorderLine* pLeftLine = (nCol == 0) ? &aOuterLine : &aInnerLine; SvxBorderLine* pRightLine = (nCol == nLastCol) ? &aOuterLine : &aInnerLine; - SCCOL nCellCol1 = static_cast<SCCOL>(GetDocPos( tdCol, nCol )) + rFirstPos.Col(); - SCCOL nCellCol2 = nCellCol1 + static_cast<SCCOL>(GetDocSize( tdCol, nCol )) - 1; + SCCOL nCellCol1 = static_cast< SCCOL >( GetDocPos( tdCol, nCol ) ) + rFirstPos.Col(); + SCCOL nCellCol2 = nCellCol1 + static_cast< SCCOL >( GetDocSize( tdCol, nCol ) ) - 1; for( SCROW nRow = 0; nRow <= nLastRow; ++nRow ) { SvxBorderLine* pTopLine = (nRow == 0) ? &aOuterLine : &aInnerLine; @@ -2317,11 +2307,10 @@ void ScHTMLTable::ApplyCellBorders( ScDocument* pDoc, const ScAddress& rFirstPos } } - for( ScHTMLTableIterator aIter( mpNestedTables.get() ); aIter.is(); ++aIter ) + for( ScHTMLTableIterator aIter( mxNestedTables.get() ); aIter.is(); ++aIter ) aIter->ApplyCellBorders( pDoc, rFirstPos ); } - // ---------------------------------------------------------------------------- bool ScHTMLTable::IsEmptyCell() const @@ -2341,37 +2330,39 @@ ScHTMLTable::ScHTMLEntryPtr ScHTMLTable::CreateEntry() const void ScHTMLTable::CreateNewEntry( const ImportInfo& rInfo ) { - DBG_ASSERT( !mpCurrEntry.get(), "ScHTMLTable::CreateNewEntry - old entry still present" ); - mpCurrEntry = CreateEntry(); - mpCurrEntry->aSel = rInfo.aSelection; + DBG_ASSERT( !mxCurrEntry.get(), "ScHTMLTable::CreateNewEntry - old entry still present" ); + mxCurrEntry = CreateEntry(); + mxCurrEntry->aSel = rInfo.aSelection; } -void ScHTMLTable::ImplPushEntryToList( ScHTMLEntryList& rEntryList, ScHTMLEntryPtr& rpEntry ) +void ScHTMLTable::ImplPushEntryToList( ScHTMLEntryList& rEntryList, ScHTMLEntryPtr& rxEntry ) { // HTML entry list does not own the entries - rEntryList.push_back( rpEntry.get() ); + rEntryList.push_back( rxEntry.get() ); // mrEEParseList (reference to member of ScEEParser) owns the entries - mrEEParseList.Insert( rpEntry.release(), LIST_APPEND ); + mrEEParseList.Insert( rxEntry.release(), LIST_APPEND ); } -bool ScHTMLTable::PushEntry( ScHTMLEntryPtr& rpEntry ) +bool ScHTMLTable::PushEntry( ScHTMLEntryPtr& rxEntry ) { bool bPushed = false; - if( rpEntry.get() && rpEntry->HasContents() ) + if( rxEntry.get() && rxEntry->HasContents() ) { if( mpCurrEntryList ) { if( mbPushEmptyLine ) { - ScHTMLEntryPtr pEmptyEntry = CreateEntry(); - ImplPushEntryToList( *mpCurrEntryList, pEmptyEntry ); + ScHTMLEntryPtr xEmptyEntry = CreateEntry(); + ImplPushEntryToList( *mpCurrEntryList, xEmptyEntry ); mbPushEmptyLine = false; } - ImplPushEntryToList( *mpCurrEntryList, rpEntry ); + ImplPushEntryToList( *mpCurrEntryList, rxEntry ); bPushed = true; } else if( mpParentTable ) - bPushed = mpParentTable->PushEntry( rpEntry ); + { + bPushed = mpParentTable->PushEntry( rxEntry ); + } else { DBG_ERRORFILE( "ScHTMLTable::PushEntry - cannot push entry, no parent found" ); @@ -2382,24 +2373,24 @@ bool ScHTMLTable::PushEntry( ScHTMLEntryPtr& rpEntry ) bool ScHTMLTable::PushEntry( const ImportInfo& rInfo, bool bLastInCell ) { - DBG_ASSERT( mpCurrEntry.get(), "ScHTMLTable::PushEntry - no current entry" ); + DBG_ASSERT( mxCurrEntry.get(), "ScHTMLTable::PushEntry - no current entry" ); bool bPushed = false; - if( mpCurrEntry.get() ) + if( mxCurrEntry.get() ) { - mpCurrEntry->AdjustEnd( rInfo ); - mpCurrEntry->Strip( mrEditEngine ); + mxCurrEntry->AdjustEnd( rInfo ); + mxCurrEntry->Strip( mrEditEngine ); // import entry always, if it is the last in cell, and cell is still empty if( bLastInCell && IsEmptyCell() ) { - mpCurrEntry->SetImportAlways(); + mxCurrEntry->SetImportAlways(); // don't insert empty lines before single empty entries - if( mpCurrEntry->IsEmpty() ) + if( mxCurrEntry->IsEmpty() ) mbPushEmptyLine = false; } - bPushed = PushEntry( mpCurrEntry ); - mpCurrEntry.reset(); + bPushed = PushEntry( mxCurrEntry ); + mxCurrEntry.reset(); } return bPushed; } @@ -2410,27 +2401,27 @@ bool ScHTMLTable::PushTableEntry( ScHTMLTableId nTableId ) bool bPushed = false; if( nTableId != SC_HTML_GLOBAL_TABLE ) { - ScHTMLEntryPtr pEntry( new ScHTMLEntry( maTableItemSet, nTableId ) ); - bPushed = PushEntry( pEntry ); + ScHTMLEntryPtr xEntry( new ScHTMLEntry( maTableItemSet, nTableId ) ); + bPushed = PushEntry( xEntry ); } return bPushed; } ScHTMLTable* ScHTMLTable::GetExistingTable( ScHTMLTableId nTableId ) const { - ScHTMLTable* pTable = ((nTableId != SC_HTML_GLOBAL_TABLE) && mpNestedTables.get()) ? - mpNestedTables->FindTable( nTableId, false ) : 0; + ScHTMLTable* pTable = ((nTableId != SC_HTML_GLOBAL_TABLE) && mxNestedTables.get()) ? + mxNestedTables->FindTable( nTableId, false ) : 0; DBG_ASSERT( pTable || (nTableId == SC_HTML_GLOBAL_TABLE), "ScHTMLTable::GetExistingTable - table not found" ); return pTable; } ScHTMLTable* ScHTMLTable::InsertNestedTable( const ImportInfo& rInfo, bool bPreFormText ) { - if( !mpNestedTables.get() ) - mpNestedTables.reset( new ScHTMLTableMap( *this ) ); + if( !mxNestedTables.get() ) + mxNestedTables.reset( new ScHTMLTableMap( *this ) ); if( bPreFormText ) // enclose new preformatted table with empty lines InsertLeadingEmptyLine(); - return mpNestedTables->CreateTable( rInfo, bPreFormText ); + return mxNestedTables->CreateTable( rInfo, bPreFormText ); } void ScHTMLTable::InsertNewCell( const ScHTMLSize& rSpanSize ) @@ -2438,20 +2429,29 @@ void ScHTMLTable::InsertNewCell( const ScHTMLSize& rSpanSize ) ScRange* pRange; // find an unused cell - while( (pRange = maLockList.Find( maCurrCell.MakeAddr() )) != 0 ) + while( (pRange = maVMergedCells.Find( maCurrCell.MakeAddr() )) != 0 ) maCurrCell.mnCol = pRange->aEnd.Col() + 1; mpCurrEntryList = &maEntryMap[ maCurrCell ]; // try to find collisions, shrink existing ranges SCCOL nColEnd = maCurrCell.mnCol + rSpanSize.mnCols; for( ScAddress aAddr( maCurrCell.MakeAddr() ); aAddr.Col() < nColEnd; aAddr.IncCol() ) - if( (pRange = maLockList.Find( aAddr )) != 0 ) + if( (pRange = maVMergedCells.Find( aAddr )) != 0 ) pRange->aEnd.SetRow( maCurrCell.mnRow - 1 ); - // insert the new range into the lock list + // insert the new range into the cell lists ScRange aNewRange( maCurrCell.MakeAddr() ); aNewRange.aEnd.Move( rSpanSize.mnCols - 1, rSpanSize.mnRows - 1, 0 ); - maLockList.Append( aNewRange ); + if( rSpanSize.mnCols > 1 ) + { + maVMergedCells.Append( aNewRange ); + } + else + { + if( rSpanSize.mnRows > 1 ) + maHMergedCells.Append( aNewRange ); + maUsedCells.Join( aNewRange ); + } // adjust table size maSize.mnCols = ::std::max< SCCOL >( maSize.mnCols, aNewRange.aEnd.Col() + 1 ); @@ -2462,7 +2462,7 @@ void ScHTMLTable::ImplRowOn() { if( mbRowOn ) ImplRowOff(); - mpRowItemSet.reset( new SfxItemSet( maTableItemSet ) ); + mxRowItemSet.reset( new SfxItemSet( maTableItemSet ) ); maCurrCell.mnCol = 0; mbRowOn = true; mbDataOn = false; @@ -2474,7 +2474,7 @@ void ScHTMLTable::ImplRowOff() ImplDataOff(); if( mbRowOn ) { - mpRowItemSet.reset(); + mxRowItemSet.reset(); ++maCurrCell.mnRow; mbRowOn = mbDataOn = false; } @@ -2486,7 +2486,7 @@ void ScHTMLTable::ImplDataOn( const ScHTMLSize& rSpanSize ) ImplDataOff(); if( !mbRowOn ) ImplRowOn(); - mpDataItemSet.reset( new SfxItemSet( *mpRowItemSet ) ); + mxDataItemSet.reset( new SfxItemSet( *mxRowItemSet ) ); InsertNewCell( rSpanSize ); mbDataOn = true; mbPushEmptyLine = false; @@ -2496,7 +2496,7 @@ void ScHTMLTable::ImplDataOff() { if( mbDataOn ) { - mpDataItemSet.reset(); + mxDataItemSet.reset(); ++maCurrCell.mnCol; mpCurrEntryList = 0; mbDataOn = false; @@ -2559,11 +2559,17 @@ void ScHTMLTable::ProcessFormatOptions( SfxItemSet& rItemSet, const ImportInfo& void ScHTMLTable::SetDocSize( ScHTMLOrient eOrient, SCCOLROW nCellPos, SCCOLROW nSize ) { - ScSizeVec& rSizes = maSizes[ eOrient ]; - if( static_cast< size_t >( nCellPos ) >= rSizes.size() ) - rSizes.resize( static_cast< size_t >( nCellPos + 1 ), 1 ); // expand with minimum height/width == 1 - if( rSizes[ nCellPos ] < nSize ) - rSizes[ nCellPos ] = nSize; + DBG_ASSERT( nCellPos >= 0, "ScHTMLTable::SetDocSize - unexpected negative position" ); + ScSizeVec& rSizes = maCumSizes[ eOrient ]; + size_t nIndex = static_cast< size_t >( nCellPos ); + // expand with height/width == 1 + while( nIndex >= rSizes.size() ) + rSizes.push_back( rSizes.empty() ? 1 : (rSizes.back() + 1) ); + // update size of passed position and all following + SCsCOLROW nDiff = nSize - ((nIndex == 0) ? rSizes.front() : (rSizes[ nIndex ] - rSizes[ nIndex - 1 ])); + if( nDiff != 0 ) + for( ScSizeVec::iterator aIt = rSizes.begin() + nIndex, aEnd = rSizes.end(); aIt != aEnd; ++aIt ) + *aIt += nDiff; } void ScHTMLTable::CalcNeededDocSize( @@ -2582,31 +2588,35 @@ void ScHTMLTable::CalcNeededDocSize( SetDocSize( eOrient, nCellPos, nRealDocSize ); } - // ---------------------------------------------------------------------------- void ScHTMLTable::FillEmptyCells() { - for( ScHTMLTableIterator aIter( mpNestedTables.get() ); aIter.is(); ++aIter ) + for( ScHTMLTableIterator aIter( mxNestedTables.get() ); aIter.is(); ++aIter ) aIter->FillEmptyCells(); + for( const ScRange* pRange = maVMergedCells.First(); pRange; pRange = maVMergedCells.Next() ) + maUsedCells.Join( *pRange ); + for( ScAddress aAddr; aAddr.Row() < maSize.mnRows; aAddr.IncRow() ) { for( aAddr.SetCol( 0 ); aAddr.Col() < maSize.mnCols; aAddr.IncCol() ) { - if( !maLockList.Find( aAddr ) ) + if( !maUsedCells.Find( aAddr ) ) { // create a range for the lock list (used to calc. cell span) ScRange aRange( aAddr ); do + { aRange.aEnd.IncCol(); - while( (aRange.aEnd.Col() < maSize.mnCols) && !maLockList.Find( aRange.aEnd ) ); + } + while( (aRange.aEnd.Col() < maSize.mnCols) && !maUsedCells.Find( aRange.aEnd ) ); aRange.aEnd.IncCol( -1 ); - maLockList.Append( aRange ); + maUsedCells.Join( aRange ); // insert a dummy entry - ScHTMLEntryPtr pEntry = CreateEntry(); - ImplPushEntryToList( maEntryMap[ ScHTMLPos( aAddr ) ], pEntry ); + ScHTMLEntryPtr xEntry = CreateEntry(); + ImplPushEntryToList( maEntryMap[ ScHTMLPos( aAddr ) ], xEntry ); } } } @@ -2615,7 +2625,7 @@ void ScHTMLTable::FillEmptyCells() void ScHTMLTable::RecalcDocSize() { // recalc table sizes recursively from inner to outer - for( ScHTMLTableIterator aIter( mpNestedTables.get() ); aIter.is(); ++aIter ) + for( ScHTMLTableIterator aIter( mxNestedTables.get() ); aIter.is(); ++aIter ) aIter->RecalcDocSize(); /* Two passes: first calculates the sizes of single columns/rows, then @@ -2630,7 +2640,7 @@ void ScHTMLTable::RecalcDocSize() for( ScHTMLEntryMap::const_iterator aMapIter = maEntryMap.begin(); aMapIter != aMapIterEnd; ++aMapIter ) { const ScHTMLPos& rCellPos = aMapIter->first; - ScHTMLSize aCellSpan( GetSpan( rCellPos ) ); + ScHTMLSize aCellSpan = GetSpan( rCellPos ); const ScHTMLEntryList& rEntryList = aMapIter->second; ScHTMLEntryList::const_iterator aListIter; @@ -2650,7 +2660,7 @@ void ScHTMLTable::RecalcDocSize() ScHTMLTable* pTable = GetExistingTable( (*aListIter)->GetTableId() ); // find entry with maximum width if( bProcessColWidth && pTable ) - aDocSize.mnCols = ::std::max( aDocSize.mnCols, static_cast<SCCOL>(pTable->GetDocSize( tdCol )) ); + aDocSize.mnCols = ::std::max( aDocSize.mnCols, static_cast< SCCOL >( pTable->GetDocSize( tdCol ) ) ); // add up height of each entry if( bProcessRowHeight ) aDocSize.mnRows += pTable ? pTable->GetDocSize( tdRow ) : 1; @@ -2659,9 +2669,9 @@ void ScHTMLTable::RecalcDocSize() aDocSize.mnRows = 1; if( bProcessColWidth ) - CalcNeededDocSize( tdCol, static_cast<SCCOLROW>(rCellPos.mnCol), static_cast<SCCOLROW>(aCellSpan.mnCols), static_cast<SCCOLROW>(aDocSize.mnCols) ); + CalcNeededDocSize( tdCol, rCellPos.mnCol, aCellSpan.mnCols, aDocSize.mnCols ); if( bProcessRowHeight ) - CalcNeededDocSize( tdRow, static_cast<SCCOLROW>(rCellPos.mnRow), static_cast<SCCOLROW>(aCellSpan.mnRows), static_cast<SCCOLROW>(aDocSize.mnRows) ); + CalcNeededDocSize( tdRow, rCellPos.mnRow, aCellSpan.mnRows, aDocSize.mnRows ); } } } @@ -2695,12 +2705,12 @@ void ScHTMLTable::RecalcDocPos( const ScHTMLPos& rBasePos ) pTable->RecalcDocPos( aEntryDocPos ); // recalc nested table pEntry->nCol = SCCOL_MAX; pEntry->nRow = SCROW_MAX; - SCROW nTableRows = static_cast<SCROW>(pTable->GetDocSize( tdRow )); + SCROW nTableRows = static_cast< SCROW >( pTable->GetDocSize( tdRow ) ); // use this entry to pad empty space right of table if( mpParentTable ) // ... but not in global table { - SCCOL nStartCol = aEntryDocPos.mnCol + static_cast<SCCOL>(pTable->GetDocSize( tdCol )); + SCCOL nStartCol = aEntryDocPos.mnCol + static_cast< SCCOL >( pTable->GetDocSize( tdCol ) ); SCCOL nNextCol = aEntryDocPos.mnCol + aCellDocSize.mnCols; if( nStartCol < nNextCol ) { @@ -2736,11 +2746,11 @@ void ScHTMLTable::RecalcDocPos( const ScHTMLPos& rBasePos ) SCROW nFirstUnusedRow = aCellDocPos.mnRow + aCellDocSize.mnRows; while( aEntryDocPos.mnRow < nFirstUnusedRow ) { - ScHTMLEntryPtr pDummyEntry( new ScHTMLEntry( pEntry->GetItemSet() ) ); - pDummyEntry->nCol = aEntryDocPos.mnCol; - pDummyEntry->nRow = aEntryDocPos.mnRow; - pDummyEntry->nColOverlap = aCellDocSize.mnCols; - ImplPushEntryToList( rEntryList, pDummyEntry ); + ScHTMLEntryPtr xDummyEntry( new ScHTMLEntry( pEntry->GetItemSet() ) ); + xDummyEntry->nCol = aEntryDocPos.mnCol; + xDummyEntry->nRow = aEntryDocPos.mnRow; + xDummyEntry->nColOverlap = aCellDocSize.mnCols; + ImplPushEntryToList( rEntryList, xDummyEntry ); ++aEntryDocPos.mnRow; } } @@ -2748,7 +2758,6 @@ void ScHTMLTable::RecalcDocPos( const ScHTMLPos& rBasePos ) } } - // ============================================================================ ScHTMLGlobalTable::ScHTMLGlobalTable( SfxItemPool& rPool, EditEngine& rEditEngine, ScEEParseList& rEEParseList, ScHTMLTableId& rnUnusedId ) : @@ -2770,7 +2779,6 @@ void ScHTMLGlobalTable::Recalc() RecalcDocPos( GetDocPos() ); } - // ============================================================================ ScHTMLQueryParser::ScHTMLQueryParser( EditEngine* pEditEngine, ScDocument* pDoc ) : @@ -2778,8 +2786,8 @@ ScHTMLQueryParser::ScHTMLQueryParser( EditEngine* pEditEngine, ScDocument* pDoc mnUnusedId( SC_HTML_GLOBAL_TABLE ), mbTitleOn( false ) { - mpGlobTable.reset( new ScHTMLGlobalTable( *pPool, *pEdit, *pList, mnUnusedId ) ); - mpCurrTable = mpGlobTable.get(); + mxGlobTable.reset( new ScHTMLGlobalTable( *pPool, *pEdit, *pList, mnUnusedId ) ); + mpCurrTable = mxGlobTable.get(); } ScHTMLQueryParser::~ScHTMLQueryParser() @@ -2817,16 +2825,16 @@ ULONG ScHTMLQueryParser::Read( SvStream& rStrm, const String& rBaseURL ) ULONG nErr = pEdit->Read( rStrm, rBaseURL, EE_FORMAT_HTML, pAttributes ); pEdit->SetImportHdl( aOldLink ); - mpGlobTable->Recalc(); - nColMax = static_cast<SCCOL>(mpGlobTable->GetDocSize( tdCol ) - 1); - nRowMax = static_cast<SCROW>(mpGlobTable->GetDocSize( tdRow ) - 1); + mxGlobTable->Recalc(); + nColMax = static_cast< SCCOL >( mxGlobTable->GetDocSize( tdCol ) - 1 ); + nRowMax = static_cast< SCROW >( mxGlobTable->GetDocSize( tdRow ) - 1 ); return nErr; } const ScHTMLTable* ScHTMLQueryParser::GetGlobalTable() const { - return mpGlobTable.get(); + return mxGlobTable.get(); } void ScHTMLQueryParser::ProcessToken( const ImportInfo& rInfo ) @@ -2941,7 +2949,7 @@ void ScHTMLQueryParser::FontOn( const ImportInfo& rInfo ) break; case HTML_O_SIZE : { - sal_uInt32 nSize = bound( aIter->GetNumber(), static_cast<sal_uInt32>(1UL), SC_HTML_FONTSIZES ); + sal_uInt32 nSize = getLimitedValue< sal_uInt32 >( aIter->GetNumber(), 1, SC_HTML_FONTSIZES ); mpCurrTable->PutItem( SvxFontHeightItem( maFontHeights[ nSize - 1 ], 100, ATTR_FONT_HEIGHT ) ); } break; @@ -2960,26 +2968,13 @@ void ScHTMLQueryParser::MetaOn( const ImportInfo& rInfo ) { if( mpDoc->GetDocumentShell() ) { - sal_uInt16 nContentOpt = HTML_O_CONTENT; - rtl_TextEncoding eEnc = RTL_TEXTENCODING_DONTKNOW; HTMLParser* pParser = static_cast< HTMLParser* >( rInfo.pParser ); - const HTMLOptions* pOptions = pParser->GetOptions( &nContentOpt ); uno::Reference<document::XDocumentPropertiesSupplier> xDPS( mpDoc->GetDocumentShell()->GetModel(), uno::UNO_QUERY_THROW); - SfxFrameHTMLParser::ParseMetaOptions( + pParser->ParseMetaOptions( xDPS->getDocumentProperties(), - mpDoc->GetDocumentShell()->GetHeaderAttributes(), - pOptions, eEnc ); - // If the encoding is set by a META tag, it may only overwrite the - // current encoding if both, the current and the new encoding, are 1-BYTE - // encodings. Everything else cannot lead to reasonable results. - if( rtl_isOctetTextEncoding( eEnc ) && - rtl_isOctetTextEncoding( pParser->GetSrcEncoding() ) ) - { - eEnc = GetExtendedCompatibilityTextEncoding( eEnc ); - pParser->SetSrcEncoding( eEnc ); - } + mpDoc->GetDocumentShell()->GetHeaderAttributes() ); } } @@ -3030,7 +3025,6 @@ void ScHTMLQueryParser::CloseTable( const ImportInfo& rInfo ) mpCurrTable = mpCurrTable->CloseTable( rInfo ); } - // ---------------------------------------------------------------------------- IMPL_LINK( ScHTMLQueryParser, HTMLImportHdl, const ImportInfo*, pInfo ) @@ -3065,6 +3059,5 @@ IMPL_LINK( ScHTMLQueryParser, HTMLImportHdl, const ImportInfo*, pInfo ) return 0; } - // ============================================================================ diff --git a/sc/source/filter/inc/excimp8.hxx b/sc/source/filter/inc/excimp8.hxx index 2f3913f01c57..9bd633eae879 100644 --- a/sc/source/filter/inc/excimp8.hxx +++ b/sc/source/filter/inc/excimp8.hxx @@ -61,7 +61,6 @@ class ImportExcel8 : public ImportExcel void Precision( void ); // 0x0E void Delta( void ); // 0x10 void Iteration( void ); // 0x11 - void WinProtection( void ); // 0x19 void Boundsheet( void ); // 0x85 void FilterMode( void ); // 0x9B void AutoFilterInfo( void ); // 0x9D @@ -73,6 +72,7 @@ class ImportExcel8 : public ImportExcel void Hlink( void ); // 0x01B8 void Codename( BOOL bWBGlobals ); // 0x01BA + void SheetProtection( void ); // 0x0867 virtual void EndSheet( void ); virtual void PostDocLoad( void ); diff --git a/sc/source/filter/inc/excrecds.hxx b/sc/source/filter/inc/excrecds.hxx index da4115fc8003..1f2eee05fd55 100644 --- a/sc/source/filter/inc/excrecds.hxx +++ b/sc/source/filter/inc/excrecds.hxx @@ -246,10 +246,23 @@ class XclExpWindowProtection : public XclExpBoolRecord }; // EXC_ID_PROTECT Document Protection -class XclExpDocProtection : public XclExpBoolRecord +class XclExpProtection : public XclExpBoolRecord { public: - XclExpDocProtection(bool bValue); + XclExpProtection(bool bValue); +}; + +class XclExpPassHash : public XclExpRecord +{ +public: + XclExpPassHash(const ::com::sun::star::uno::Sequence<sal_Int8>& aHash); + virtual ~XclExpPassHash(); + +private: + virtual void WriteBody(XclExpStream& rStrm); + +private: + sal_uInt16 mnHash; }; diff --git a/sc/source/filter/inc/htmlpars.hxx b/sc/source/filter/inc/htmlpars.hxx index b75a44c618db..e3f53a5ddc5b 100644 --- a/sc/source/filter/inc/htmlpars.hxx +++ b/sc/source/filter/inc/htmlpars.hxx @@ -218,30 +218,29 @@ const ScHTMLTableId SC_HTML_GLOBAL_TABLE = 0; /** Used as table index for normal (non-table) entries in ScHTMLEntry structs. */ const ScHTMLTableId SC_HTML_NO_TABLE = 0; - // ============================================================================ /** A 2D cell position in an HTML table. */ struct ScHTMLPos { - SCCOL mnCol; - SCROW mnRow; - - inline explicit ScHTMLPos() : mnCol( 0 ), mnRow( 0 ) {} - inline explicit ScHTMLPos( SCCOL nCol, SCROW nRow ) : - mnCol( nCol ), mnRow( nRow ) {} - inline explicit ScHTMLPos( const ScAddress& rAddr ) { Set( rAddr ); } - - inline SCCOLROW Get( ScHTMLOrient eOrient ) const - { return (eOrient == tdCol) ? static_cast<SCCOLROW>(mnCol) : static_cast<SCCOLROW>(mnRow); } - inline void Set( SCCOL nCol, SCROW nRow ) - { mnCol = nCol; mnRow = nRow; } - inline void Set( const ScAddress& rAddr ) - { Set( rAddr.Col(), rAddr.Row() ); } - inline void Move( SCsCOL nColDiff, SCsROW nRowDiff ) - { mnCol = mnCol + nColDiff; mnRow = mnRow + nRowDiff; } - inline ScAddress MakeAddr() const - { return ScAddress( mnCol, mnRow, 0 ); } + SCCOL mnCol; + SCROW mnRow; + + inline explicit ScHTMLPos() : mnCol( 0 ), mnRow( 0 ) {} + inline explicit ScHTMLPos( SCCOL nCol, SCROW nRow ) : + mnCol( nCol ), mnRow( nRow ) {} + inline explicit ScHTMLPos( const ScAddress& rAddr ) { Set( rAddr ); } + + inline SCCOLROW Get( ScHTMLOrient eOrient ) const + { return (eOrient == tdCol) ? mnCol : mnRow; } + inline void Set( SCCOL nCol, SCROW nRow ) + { mnCol = nCol; mnRow = nRow; } + inline void Set( const ScAddress& rAddr ) + { Set( rAddr.Col(), rAddr.Row() ); } + inline void Move( SCsCOL nColDiff, SCsROW nRowDiff ) + { mnCol = mnCol + nColDiff; mnRow = mnRow + nRowDiff; } + inline ScAddress MakeAddr() const + { return ScAddress( mnCol, mnRow, 0 ); } }; inline bool operator==( const ScHTMLPos& rPos1, const ScHTMLPos& rPos2 ) @@ -254,25 +253,24 @@ inline bool operator<( const ScHTMLPos& rPos1, const ScHTMLPos& rPos2 ) return (rPos1.mnRow < rPos2.mnRow) || ((rPos1.mnRow == rPos2.mnRow) && (rPos1.mnCol < rPos2.mnCol)); } - // ---------------------------------------------------------------------------- /** A 2D cell size in an HTML table. */ struct ScHTMLSize { - SCCOL mnCols; - SCROW mnRows; - - inline explicit ScHTMLSize() : mnCols( 0 ), mnRows( 0 ) {} - inline explicit ScHTMLSize( SCCOL nCols, SCROW nRows ) : - mnCols( nCols ), mnRows( nRows ) {} - - inline SCCOLROW Get( ScHTMLOrient eOrient ) const - { return (eOrient == tdCol) ? static_cast<SCCOLROW>(mnCols) : static_cast<SCCOLROW>(mnRows); } - inline void Set( SCCOL nCols, SCROW nRows ) - { mnCols = nCols; mnRows = nRows; } - inline void Expand( SCsCOL nColDiff, SCsROW nRowDiff ) - { mnCols = mnCols + nColDiff; mnRows = mnRows + nRowDiff; } + SCCOL mnCols; + SCROW mnRows; + + inline explicit ScHTMLSize() : mnCols( 0 ), mnRows( 0 ) {} + inline explicit ScHTMLSize( SCCOL nCols, SCROW nRows ) : + mnCols( nCols ), mnRows( nRows ) {} + + inline SCCOLROW Get( ScHTMLOrient eOrient ) const + { return (eOrient == tdCol) ? mnCols : mnRows; } + inline void Set( SCCOL nCols, SCROW nRows ) + { mnCols = nCols; mnRows = nRows; } + inline void Expand( SCsCOL nColDiff, SCsROW nRowDiff ) + { mnCols = mnCols + nColDiff; mnRows = mnRows + nRowDiff; } }; inline bool operator==( const ScHTMLSize& rSize1, const ScHTMLSize& rSize2 ) @@ -280,183 +278,182 @@ inline bool operator==( const ScHTMLSize& rSize1, const ScHTMLSize& rSize2 ) return (rSize1.mnRows == rSize2.mnRows) && (rSize1.mnCols == rSize2.mnCols); } - // ============================================================================ /** A single entry containing a line of text or representing a table. */ struct ScHTMLEntry : public ScEEParseEntry { public: - explicit ScHTMLEntry( - const SfxItemSet& rItemSet, - ScHTMLTableId nTableId = SC_HTML_NO_TABLE ); + explicit ScHTMLEntry( + const SfxItemSet& rItemSet, + ScHTMLTableId nTableId = SC_HTML_NO_TABLE ); /** Returns true, if the selection of the entry is empty. */ - inline bool IsEmpty() const { return !aSel.HasRange(); } + inline bool IsEmpty() const { return !aSel.HasRange(); } /** Returns true, if the entry has any content to be imported. */ - bool HasContents() const; + bool HasContents() const; /** Returns true, if the entry represents a table. */ - inline bool IsTable() const { return nTab != SC_HTML_NO_TABLE; } + inline bool IsTable() const { return nTab != SC_HTML_NO_TABLE; } /** Returns true, if the entry represents a table. */ - inline ScHTMLTableId GetTableId() const { return nTab; } + inline ScHTMLTableId GetTableId() const { return nTab; } /** Sets or cleares the import always state. */ - inline void SetImportAlways( bool bSet = true ) { mbImportAlways = bSet; } + inline void SetImportAlways( bool bSet = true ) { mbImportAlways = bSet; } /** Sets start point of the entry selection to the start of the import info object. */ - void AdjustStart( const ImportInfo& rInfo ); + void AdjustStart( const ImportInfo& rInfo ); /** Sets end point of the entry selection to the end of the import info object. */ - void AdjustEnd( const ImportInfo& rInfo ); + void AdjustEnd( const ImportInfo& rInfo ); /** Deletes leading and trailing empty paragraphs from the entry. */ - void Strip( const EditEngine& rEditEngine ); + void Strip( const EditEngine& rEditEngine ); /** Returns read/write access to the item set of this entry. */ - inline SfxItemSet& GetItemSet() { return aItemSet; } + inline SfxItemSet& GetItemSet() { return aItemSet; } /** Returns read-only access to the item set of this entry. */ - inline const SfxItemSet& GetItemSet() const { return aItemSet; } + inline const SfxItemSet& GetItemSet() const { return aItemSet; } private: - bool mbImportAlways; /// true = Always import this entry. + bool mbImportAlways; /// true = Always import this entry. }; - // ============================================================================ /** This struct handles creation of unique table identifiers. */ struct ScHTMLTableAutoId { - const ScHTMLTableId mnTableId; /// The created unique table identifier. - ScHTMLTableId& mrnUnusedId; /// Reference to global unused identifier variable. + const ScHTMLTableId mnTableId; /// The created unique table identifier. + ScHTMLTableId& mrnUnusedId; /// Reference to global unused identifier variable. /** The constructor assigns an unused identifier to member mnTableId. */ - explicit ScHTMLTableAutoId( ScHTMLTableId& rnUnusedId ); + explicit ScHTMLTableAutoId( ScHTMLTableId& rnUnusedId ); }; - // ---------------------------------------------------------------------------- class ScHTMLTableMap; /** Stores data for one table in an HTML document. - @descr This class does the main work for importing an HTML document. It manages - the correct insertion of parse entries into the correct cells and the creation - of nested tables. Recalculation of resulting document size and position is done - recursively in all nested tables. */ + + This class does the main work for importing an HTML document. It manages + the correct insertion of parse entries into the correct cells and the + creation of nested tables. Recalculation of resulting document size and + position is done recursively in all nested tables. + */ class ScHTMLTable { public: /** Creates a new HTML table without content. - @descr Internally handles a current cell position. This position is invalid - until first calls of RowOn() and DataOn(). + @descr Internally handles a current cell position. This position is + invalid until first calls of RowOn() and DataOn(). @param rParentTable Reference to the parent table that owns this table. @param bPreFormText true = Table is based on preformatted text (<pre> tag). */ - explicit ScHTMLTable( - ScHTMLTable& rParentTable, - const ImportInfo& rInfo, - bool bPreFormText ); + explicit ScHTMLTable( + ScHTMLTable& rParentTable, + const ImportInfo& rInfo, + bool bPreFormText ); - virtual ~ScHTMLTable(); + virtual ~ScHTMLTable(); /** Returns the name of the table, specified in the TABLE tag. */ - inline const String& GetTableName() const { return maTableName; } + inline const String& GetTableName() const { return maTableName; } /** Returns the unique identifier of the table. */ - inline ScHTMLTableId GetTableId() const { return maTableId.mnTableId; } + inline ScHTMLTableId GetTableId() const { return maTableId.mnTableId; } /** Returns the table size. */ - inline const ScHTMLSize& GetSize() const { return maSize; } + inline const ScHTMLSize& GetSize() const { return maSize; } /** Returns the cell spanning of the specified cell. */ - ScHTMLSize GetSpan( const ScHTMLPos& rCellPos ) const; + ScHTMLSize GetSpan( const ScHTMLPos& rCellPos ) const; /** Searches in all nested tables for the specified table. @param nTableId Unique identifier of the table. */ - ScHTMLTable* FindNestedTable( ScHTMLTableId nTableId ) const; + ScHTMLTable* FindNestedTable( ScHTMLTableId nTableId ) const; /** Puts the item into the item set of the current entry. */ - void PutItem( const SfxPoolItem& rItem ); + void PutItem( const SfxPoolItem& rItem ); /** Inserts a text portion into current entry. */ - void PutText( const ImportInfo& rInfo ); + void PutText( const ImportInfo& rInfo ); /** Inserts a new line, if in preformatted text, else does nothing. */ - void InsertPara( const ImportInfo& rInfo ); + void InsertPara( const ImportInfo& rInfo ); /** Inserts a line break (<br> tag). @descr Inserts the current entry regardless if it is empty. */ - void BreakOn(); + void BreakOn(); /** Inserts a heading line (<p> and <h*> tags). */ - void HeadingOn(); + void HeadingOn(); /** Processes a hyperlink (<a> tag). */ - void AnchorOn(); + void AnchorOn(); /** Starts a *new* table nested in this table (<table> tag). @return Pointer to the new table. */ - ScHTMLTable* TableOn( const ImportInfo& rInfo ); + ScHTMLTable* TableOn( const ImportInfo& rInfo ); /** Closes *this* table (</table> tag). @return Pointer to the parent table. */ - ScHTMLTable* TableOff( const ImportInfo& rInfo ); + ScHTMLTable* TableOff( const ImportInfo& rInfo ); /** Starts a *new* table based on preformatted text (<pre> tag). @return Pointer to the new table. */ - ScHTMLTable* PreOn( const ImportInfo& rInfo ); + ScHTMLTable* PreOn( const ImportInfo& rInfo ); /** Closes *this* table based on preformatted text (</pre> tag). @return Pointer to the parent table. */ - ScHTMLTable* PreOff( const ImportInfo& rInfo ); + ScHTMLTable* PreOff( const ImportInfo& rInfo ); /** Starts next row (<tr> tag). @descr Cell address is invalid until first call of DataOn(). */ - void RowOn( const ImportInfo& rInfo ); + void RowOn( const ImportInfo& rInfo ); /** Closes the current row (<tr> tag). @descr Cell address is invalid until call of RowOn() and DataOn(). */ - void RowOff( const ImportInfo& rInfo ); + void RowOff( const ImportInfo& rInfo ); /** Starts the next cell (<td> or <th> tag). */ - void DataOn( const ImportInfo& rInfo ); + void DataOn( const ImportInfo& rInfo ); /** Closes the current cell (</td> or </th> tag). @descr Cell address is invalid until next call of DataOn(). */ - void DataOff( const ImportInfo& rInfo ); + void DataOff( const ImportInfo& rInfo ); /** Starts the body of the HTML document (<body> tag). */ - void BodyOn( const ImportInfo& rInfo ); + void BodyOn( const ImportInfo& rInfo ); /** Closes the body of the HTML document (</body> tag). */ - void BodyOff( const ImportInfo& rInfo ); + void BodyOff( const ImportInfo& rInfo ); /** Closes *this* table (</table> tag) or preformatted text (</pre> tag). @descr Used to close this table object regardless on opening tag type. @return Pointer to the parent table, or this, if no parent found. */ - ScHTMLTable* CloseTable( const ImportInfo& rInfo ); + ScHTMLTable* CloseTable( const ImportInfo& rInfo ); /** Returns the resulting document row/column count of the specified HTML row/column. */ - SCCOLROW GetDocSize( ScHTMLOrient eOrient, SCCOLROW nCellPos ) const; - /** Returns the resulting document row/column count in the range [nCellBegin, nCellEnd). */ - SCCOLROW GetDocSize( ScHTMLOrient eOrient, SCCOLROW nCellBegin, SCCOLROW nCellEnd ) const; + SCCOLROW GetDocSize( ScHTMLOrient eOrient, SCCOLROW nCellPos ) const; + /** Returns the resulting document row/column count in the half-open range [nCellBegin, nCellEnd). */ + SCCOLROW GetDocSize( ScHTMLOrient eOrient, SCCOLROW nCellBegin, SCCOLROW nCellEnd ) const; /** Returns the total document row/column count in the specified direction. */ - SCCOLROW GetDocSize( ScHTMLOrient eOrient ) const; + SCCOLROW GetDocSize( ScHTMLOrient eOrient ) const; /** Returns the total document row/column count of the specified HTML cell. */ - ScHTMLSize GetDocSize( const ScHTMLPos& rCellPos ) const; + ScHTMLSize GetDocSize( const ScHTMLPos& rCellPos ) const; /** Returns the resulting Calc position of the top left edge of the table. */ - inline const ScHTMLPos& GetDocPos() const { return maDocBasePos; } + inline const ScHTMLPos& GetDocPos() const { return maDocBasePos; } /** Calculates the resulting Calc position of the specified HTML column/row. */ - SCCOLROW GetDocPos( ScHTMLOrient eOrient, SCCOLROW nCellPos = 0 ) const; + SCCOLROW GetDocPos( ScHTMLOrient eOrient, SCCOLROW nCellPos = 0 ) const; /** Calculates the resulting Calc position of the specified HTML cell. */ - ScHTMLPos GetDocPos( const ScHTMLPos& rCellPos ) const; + ScHTMLPos GetDocPos( const ScHTMLPos& rCellPos ) const; /** Calculates the current Calc document area of this table. */ - void GetDocRange( ScRange& rRange ) const; + void GetDocRange( ScRange& rRange ) const; /** Applies border formatting to the passed document. */ - void ApplyCellBorders( ScDocument* pDoc, const ScAddress& rFirstPos ) const; + void ApplyCellBorders( ScDocument* pDoc, const ScAddress& rFirstPos ) const; protected: /** Creates a new HTML table without parent. @descr This constructor is used to create the "global table". */ - explicit ScHTMLTable( - SfxItemPool& rPool, - EditEngine& rEditEngine, - ScEEParseList& rEEParseList, - ScHTMLTableId& rnUnusedId ); + explicit ScHTMLTable( + SfxItemPool& rPool, + EditEngine& rEditEngine, + ScEEParseList& rEEParseList, + ScHTMLTableId& rnUnusedId ); /** Fills all empty cells in this and nested tables with dummy parse entries. */ - void FillEmptyCells(); + void FillEmptyCells(); /** Recalculates the size of all columns/rows in the table, regarding nested tables. */ - void RecalcDocSize(); + void RecalcDocSize(); /** Recalculates the position of all cell entries and nested tables. @param rBasePos The origin of the table in the Calc document. */ - void RecalcDocPos( const ScHTMLPos& rBasePos ); + void RecalcDocPos( const ScHTMLPos& rBasePos ); private: typedef ::std::auto_ptr< ScHTMLTableMap > ScHTMLTableMapPtr; @@ -467,172 +464,174 @@ private: typedef ::std::auto_ptr< ScHTMLEntry > ScHTMLEntryPtr; /** Returns true, if the current cell does not contain an entry yet. */ - bool IsEmptyCell() const; + bool IsEmptyCell() const; /** Returns the item set from cell, row, or table, depending on current state. */ - const SfxItemSet& GetCurrItemSet() const; + const SfxItemSet& GetCurrItemSet() const; /** Returns true, if import info represents a space character. */ - static bool IsSpaceCharInfo( const ImportInfo& rInfo ); + static bool IsSpaceCharInfo( const ImportInfo& rInfo ); /** Creates and returns a new empty flying entry at position (0,0). */ - ScHTMLEntryPtr CreateEntry() const; + ScHTMLEntryPtr CreateEntry() const; /** Creates a new flying entry. @param rInfo Contains the initial edit engine selection for the entry. */ - void CreateNewEntry( const ImportInfo& rInfo ); + void CreateNewEntry( const ImportInfo& rInfo ); /** Inserts an empty line in front of the next entry. */ - void InsertLeadingEmptyLine(); + void InsertLeadingEmptyLine(); /** Pushes the passed entry into the list of the current cell. */ - void ImplPushEntryToList( ScHTMLEntryList& rEntryList, ScHTMLEntryPtr& rpEntry ); + void ImplPushEntryToList( ScHTMLEntryList& rEntryList, ScHTMLEntryPtr& rxEntry ); /** Tries to insert the entry into the current cell. @descr If insertion is not possible (i.e., currently no cell open), the entry will be inserted into the parent table. @return true = Entry as been pushed into the current cell; false = Entry dropped. */ - bool PushEntry( ScHTMLEntryPtr& rpEntry ); + bool PushEntry( ScHTMLEntryPtr& rxEntry ); /** Puts the current entry into the entry list, if it is not empty. @param rInfo The import info struct containing the end position of the current entry. @param bLastInCell true = If cell is still empty, put this entry always. @return true = Entry as been pushed into the current cell; false = Entry dropped. */ - bool PushEntry( const ImportInfo& rInfo, bool bLastInCell = false ); + bool PushEntry( const ImportInfo& rInfo, bool bLastInCell = false ); /** Pushes a new entry into current cell which references a nested table. @return true = Entry as been pushed into the current cell; false = Entry dropped. */ - bool PushTableEntry( ScHTMLTableId nTableId ); + bool PushTableEntry( ScHTMLTableId nTableId ); /** Tries to find a table from the table container. @descr Assumes that the table is located in the current container or that the passed table identifier is 0. @param nTableId Unique identifier of the table or 0. */ - ScHTMLTable* GetExistingTable( ScHTMLTableId nTableId ) const; + ScHTMLTable* GetExistingTable( ScHTMLTableId nTableId ) const; /** Inserts a nested table in the current cell at the specified position. @param bPreFormText true = New table is based on preformatted text (<pre> tag). */ - ScHTMLTable* InsertNestedTable( const ImportInfo& rInfo, bool bPreFormText ); + ScHTMLTable* InsertNestedTable( const ImportInfo& rInfo, bool bPreFormText ); /** Inserts a new cell in an unused position, starting from current cell position. */ - void InsertNewCell( const ScHTMLSize& rSpanSize ); + void InsertNewCell( const ScHTMLSize& rSpanSize ); /** Set internal states for a new table row. */ - void ImplRowOn(); + void ImplRowOn(); /** Set internal states for leaving a table row. */ - void ImplRowOff(); + void ImplRowOff(); /** Set internal states for entering a new table cell. */ - void ImplDataOn( const ScHTMLSize& rSpanSize ); + void ImplDataOn( const ScHTMLSize& rSpanSize ); /** Set internal states for leaving a table cell. */ - void ImplDataOff(); + void ImplDataOff(); /** Inserts additional formatting options from import info into the item set. */ - void ProcessFormatOptions( SfxItemSet& rItemSet, const ImportInfo& rInfo ); + void ProcessFormatOptions( SfxItemSet& rItemSet, const ImportInfo& rInfo ); /** Updates the document column/row size of the specified column or row. @descr Only increases the present count, never decreases. */ - void SetDocSize( ScHTMLOrient eOrient, SCCOLROW nCellPos, SCCOLROW nSize ); + void SetDocSize( ScHTMLOrient eOrient, SCCOLROW nCellPos, SCCOLROW nSize ); /** Calculates and sets the resulting size the cell needs in the document. @descr Reduces the needed size in merged cells. @param nCellPos The first column/row position of the (merged) cell. @param nCellSpan The cell spanning in the specified orientation. @param nRealDocSize The raw document size of all entries of the cell. */ - void CalcNeededDocSize( - ScHTMLOrient eOrient, SCCOLROW nCellPos, - SCCOLROW nCellSpan, SCCOLROW nRealDocSize ); + void CalcNeededDocSize( + ScHTMLOrient eOrient, SCCOLROW nCellPos, + SCCOLROW nCellSpan, SCCOLROW nRealDocSize ); private: - ScHTMLTable* mpParentTable; /// Pointer to parent table. - ScHTMLTableMapPtr mpNestedTables; /// Table of nested HTML tables. - String maTableName; /// Table name from <table id> option. - ScHTMLTableAutoId maTableId; /// Unique identifier of this table. - SfxItemSet maTableItemSet; /// Items for the entire table. - SfxItemSetPtr mpRowItemSet; /// Items for the current table row. - SfxItemSetPtr mpDataItemSet; /// Items for the current cell. - ScRangeList maLockList; /// Locked cells (needed for merged cells). - EditEngine& mrEditEngine; /// Edit engine (from ScEEParser). - ScEEParseList& mrEEParseList; /// List that owns the parse entries (from ScEEParser). - ScHTMLEntryMap maEntryMap; /// List of entries for each cell. - ScHTMLEntryList* mpCurrEntryList; /// Current entry list from map for faster access. - ScHTMLEntryPtr mpCurrEntry; /// Working entry, not yet inserted in a list. - ScSizeVec maSizes[ 2 ]; /// Calc cell count of each HTML table column/row. - ScHTMLSize maSize; /// Size of the table. - ScHTMLPos maCurrCell; /// Address of current cell to fill. - ScHTMLPos maDocBasePos; /// Resulting base address in a Calc document. - bool mbBorderOn; /// true = Table borders on. - bool mbPreFormText; /// true = Table from preformatted text (<pre> tag). - bool mbRowOn; /// true = Inside of <tr> </tr>. - bool mbDataOn; /// true = Inside of <td> </td> or <th> </th>. - bool mbPushEmptyLine; /// true = Insert empty line before current entry. + ScHTMLTable* mpParentTable; /// Pointer to parent table. + ScHTMLTableMapPtr mxNestedTables; /// Table of nested HTML tables. + String maTableName; /// Table name from <table id> option. + ScHTMLTableAutoId maTableId; /// Unique identifier of this table. + SfxItemSet maTableItemSet; /// Items for the entire table. + SfxItemSetPtr mxRowItemSet; /// Items for the current table row. + SfxItemSetPtr mxDataItemSet; /// Items for the current cell. + ScRangeList maHMergedCells; /// List of all horizontally merged cells. + ScRangeList maVMergedCells; /// List of all vertically merged cells. + ScRangeList maUsedCells; /// List of all used cells. + EditEngine& mrEditEngine; /// Edit engine (from ScEEParser). + ScEEParseList& mrEEParseList; /// List that owns the parse entries (from ScEEParser). + ScHTMLEntryMap maEntryMap; /// List of entries for each cell. + ScHTMLEntryList* mpCurrEntryList; /// Current entry list from map for faster access. + ScHTMLEntryPtr mxCurrEntry; /// Working entry, not yet inserted in a list. + ScSizeVec maCumSizes[ 2 ]; /// Cumulated cell counts for each HTML table column/row. + ScHTMLSize maSize; /// Size of the table. + ScHTMLPos maCurrCell; /// Address of current cell to fill. + ScHTMLPos maDocBasePos; /// Resulting base address in a Calc document. + bool mbBorderOn; /// true = Table borders on. + bool mbPreFormText; /// true = Table from preformatted text (<pre> tag). + bool mbRowOn; /// true = Inside of <tr> </tr>. + bool mbDataOn; /// true = Inside of <td> </td> or <th> </th>. + bool mbPushEmptyLine; /// true = Insert empty line before current entry. }; - // ---------------------------------------------------------------------------- /** The "global table" representing the entire HTML document. */ class ScHTMLGlobalTable : public ScHTMLTable { public: - explicit ScHTMLGlobalTable( - SfxItemPool& rPool, - EditEngine& rEditEngine, - ScEEParseList& rEEParseList, - ScHTMLTableId& rnUnusedId ); + explicit ScHTMLGlobalTable( + SfxItemPool& rPool, + EditEngine& rEditEngine, + ScEEParseList& rEEParseList, + ScHTMLTableId& rnUnusedId ); - virtual ~ScHTMLGlobalTable(); + virtual ~ScHTMLGlobalTable(); /** Recalculates sizes and resulting positions of all document entries. */ - void Recalc(); + void Recalc(); }; - // ============================================================================ /** The HTML parser for data queries. Focuses on data import, not on layout. - @descr Builds the table structure correctly, ignores extended formatting - like pictures or column widths. */ + + Builds the table structure correctly, ignores extended formatting like + pictures or column widths. + */ class ScHTMLQueryParser : public ScHTMLParser { public: - explicit ScHTMLQueryParser( EditEngine* pEditEngine, ScDocument* pDoc ); - virtual ~ScHTMLQueryParser(); + explicit ScHTMLQueryParser( EditEngine* pEditEngine, ScDocument* pDoc ); + virtual ~ScHTMLQueryParser(); - virtual ULONG Read( SvStream& rStrm, const String& rBaseURL ); + virtual ULONG Read( SvStream& rStrm, const String& rBaseURL ); /** Returns the "global table" which contains the entire HTML document. */ - virtual const ScHTMLTable* GetGlobalTable() const; + virtual const ScHTMLTable* GetGlobalTable() const; private: /** Handles all possible tags in the HTML document. */ - void ProcessToken( const ImportInfo& rInfo ); + void ProcessToken( const ImportInfo& rInfo ); /** Inserts a text portion into current entry. */ - void InsertText( const ImportInfo& rInfo ); + void InsertText( const ImportInfo& rInfo ); /** Processes the <font> tag. */ - void FontOn( const ImportInfo& rInfo ); + void FontOn( const ImportInfo& rInfo ); /** Processes the <meta> tag. */ - void MetaOn( const ImportInfo& rInfo ); + void MetaOn( const ImportInfo& rInfo ); /** Opens the title of the HTML document (<title> tag). */ - void TitleOn( const ImportInfo& rInfo ); + void TitleOn( const ImportInfo& rInfo ); /** Closes the title of the HTML document (</title> tag). */ - void TitleOff( const ImportInfo& rInfo ); + void TitleOff( const ImportInfo& rInfo ); /** Opens a new table at the current position. */ - void TableOn( const ImportInfo& rInfo ); + void TableOn( const ImportInfo& rInfo ); /** Closes the current table. */ - void TableOff( const ImportInfo& rInfo ); + void TableOff( const ImportInfo& rInfo ); /** Opens a new table based on preformatted text. */ - void PreOn( const ImportInfo& rInfo ); + void PreOn( const ImportInfo& rInfo ); /** Closes the current preformatted text table. */ - void PreOff( const ImportInfo& rInfo ); + void PreOff( const ImportInfo& rInfo ); /** Closes the current table, regardless on opening tag. */ - void CloseTable( const ImportInfo& rInfo ); + void CloseTable( const ImportInfo& rInfo ); DECL_LINK( HTMLImportHdl, const ImportInfo* ); private: typedef ::std::auto_ptr< ScHTMLGlobalTable > ScHTMLGlobalTablePtr; - String maTitle; /// The title of the document. - ScHTMLGlobalTablePtr mpGlobTable; /// Contains the entire imported document. - ScHTMLTable* mpCurrTable; /// Pointer to current table (performance). - ScHTMLTableId mnUnusedId; /// First unused table identifier. - bool mbTitleOn; /// true = Inside of <title> </title>. + String maTitle; /// The title of the document. + ScHTMLGlobalTablePtr mxGlobTable; /// Contains the entire imported document. + ScHTMLTable* mpCurrTable; /// Pointer to current table (performance). + ScHTMLTableId mnUnusedId; /// First unused table identifier. + bool mbTitleOn; /// true = Inside of <title> </title>. }; diff --git a/sc/source/filter/inc/imp_op.hxx b/sc/source/filter/inc/imp_op.hxx index 66a58ffb67a4..f8dad9a45c48 100644 --- a/sc/source/filter/inc/imp_op.hxx +++ b/sc/source/filter/inc/imp_op.hxx @@ -135,9 +135,11 @@ protected: void Bof2( void ); // 0x09 void Eof( void ); // 0x0A void DocProtect( void ); // 0x12 - void Protect( void ); // 0x12 Sheet Protection - BOOL Password( void ); // 0x13 + void SheetProtect( void ); // 0x12 Sheet Protection + void DocPasssword( void ); // 0x13 document password + void SheetPassword( void ); // 0x13 sheet password void Externsheet( void ); // 0x17 + void WinProtection( void ); // 0x19 void Columndefault( void ); // 0x20 void Array25( void ); // 0x21 void Rec1904( void ); // 0x22 diff --git a/sc/source/filter/inc/xcl97rec.hxx b/sc/source/filter/inc/xcl97rec.hxx index 8d48e7119629..7729e0ab11cc 100644 --- a/sc/source/filter/inc/xcl97rec.hxx +++ b/sc/source/filter/inc/xcl97rec.hxx @@ -398,23 +398,24 @@ public: virtual sal_Size GetLen() const; }; +// ============================================================================ -// ---- class XclProtection ------------------------------------------ - -class XclProtection : public ExcDummyRec +/** Represents a SHEETPROTECTION record that stores sheet protection + options. Note that a sheet still needs to save its sheet protection + options even when it's not protected. */ +class XclExpSheetProtectOptions : public XclExpRecord { - // replacement for records PROTECT, SCENPROTECT, OBJPROTECT... -private: - static const BYTE pMyData[]; - static const sal_Size nMyLen; public: - virtual sal_Size GetLen( void ) const; - virtual const BYTE* GetData( void ) const; -}; + explicit XclExpSheetProtectOptions( const XclExpRoot& rRoot, SCTAB nTab ); +private: + virtual void WriteBody( XclExpStream& rStrm ); -// ------------------------------------------------------------------- +private: + sal_uInt16 mnOptions; /// Encoded sheet protection options. +}; +// ============================================================================ class XclCalccount : public ExcRecord { @@ -478,5 +479,162 @@ public: virtual void SaveXml( XclExpXmlStream& rStrm ); }; +// ============================================================================ + +class XclExpFilePass : public XclExpRecord +{ +public: + explicit XclExpFilePass( const XclExpRoot& rRoot ); + virtual ~XclExpFilePass(); + +private: + virtual void WriteBody( XclExpStream& rStrm ); + +private: + const XclExpRoot& mrRoot; +}; + +// ============================================================================ + +class XclExpFnGroupCount : public XclExpRecord +{ +public: + explicit XclExpFnGroupCount(); + virtual ~XclExpFnGroupCount(); + +private: + virtual void WriteBody( XclExpStream& rStrm ); +}; + +// ============================================================================ + +/** Beginning of User Interface Records */ +class XclExpInterfaceHdr : public XclExpRecord +{ +public: + explicit XclExpInterfaceHdr(); + virtual ~XclExpInterfaceHdr(); + +private: + virtual void WriteBody( XclExpStream& rStrm ); +}; + +// ============================================================================ + +/** Beginning of User Interface Records */ +class XclExpInterfaceEnd : public XclExpRecord +{ +public: + explicit XclExpInterfaceEnd(); + virtual ~XclExpInterfaceEnd(); + +private: + virtual void WriteBody( XclExpStream& rStrm ); +}; + +// ============================================================================ + +/** ADDMENU/DELMENU Record Group Count */ +class XclExpMMS : public XclExpRecord +{ +public: + explicit XclExpMMS(); + virtual ~XclExpMMS(); + +private: + virtual void WriteBody( XclExpStream& rStrm ); +}; + +// ============================================================================ + +/** Write Access User Name - This record contains the user name, which is + the name you type when you install Excel. */ +class XclExpWriteAccess : public XclExpRecord +{ +public: + explicit XclExpWriteAccess(); + virtual ~XclExpWriteAccess(); + +private: + virtual void WriteBody( XclExpStream& rStrm ); +}; + +// ============================================================================ + +class XclExpCodePage : public XclExpRecord +{ +public: + explicit XclExpCodePage(); + virtual ~XclExpCodePage(); + +private: + virtual void WriteBody( XclExpStream& rStrm ); +}; + +// ============================================================================ + +class XclExpDSF : public XclExpRecord +{ +public: + explicit XclExpDSF(); + virtual ~XclExpDSF(); + +private: + virtual void WriteBody( XclExpStream& rStrm ); +}; + +// ============================================================================ + +class XclExpProt4Rev : public XclExpRecord +{ +public: + explicit XclExpProt4Rev(); + virtual ~XclExpProt4Rev(); + +private: + virtual void WriteBody( XclExpStream& rStrm ); +}; + +// ============================================================================ + +class XclExpProt4RevPass : public XclExpRecord +{ +public: + explicit XclExpProt4RevPass(); + virtual ~XclExpProt4RevPass(); + +private: + virtual void WriteBody( XclExpStream& rStrm ); +}; + +// ============================================================================ + +/** What's this record for? It is a zero-byte record. */ +class XclExpExcel9File : public XclExpRecord +{ +public: + explicit XclExpExcel9File(); + virtual ~XclExpExcel9File(); + +private: + virtual void WriteBody( XclExpStream& rStrm ); +}; + +// ============================================================================ + +class XclExpRecalcId : public XclExpDummyRecord +{ +public: + explicit XclExpRecalcId(); +}; + +// ============================================================================ + +class XclExpBookExt : public XclExpDummyRecord +{ +public: + explicit XclExpBookExt(); +}; + #endif // _XCL97REC_HXX diff --git a/sc/source/filter/inc/xeroot.hxx b/sc/source/filter/inc/xeroot.hxx index 6ca53ed8655f..27975a723792 100644 --- a/sc/source/filter/inc/xeroot.hxx +++ b/sc/source/filter/inc/xeroot.hxx @@ -159,7 +159,12 @@ public: @param nRecId Identifier that specifies which record is returned. */ XclExpRecordRef CreateRecord( sal_uInt16 nRecId ) const; + bool IsDocumentEncrypted() const; + + const String GetPassword() const; + private: + /** Returns the local or global link manager, depending on current context. */ XclExpRootData::XclExpLinkMgrRef GetLocalLinkMgrRef() const; diff --git a/sc/source/filter/inc/xestream.hxx b/sc/source/filter/inc/xestream.hxx index 8792f26c6582..676b0d550875 100644 --- a/sc/source/filter/inc/xestream.hxx +++ b/sc/source/filter/inc/xestream.hxx @@ -43,6 +43,9 @@ #include "xlstream.hxx" #include "xestring.hxx" +#include <svx/mscodec.hxx> +#include <vector> + /* ============================================================================ Output stream class for Excel export - CONTINUE record handling @@ -50,6 +53,8 @@ Output stream class for Excel export ============================================================================ */ class XclExpRoot; +class XclExpBiff8Encrypter; +typedef ScfRef< XclExpBiff8Encrypter > XclExpEncrypterRef; /** This class is used to export Excel record streams. @descr An instance is constructed with an SvStream and the maximum size of Excel @@ -108,14 +113,14 @@ public: /** Sets data slice length. 0 = no slices. */ void SetSliceSize( sal_uInt16 nSize ); - inline XclExpStream& operator<<( sal_Int8 nValue ); - inline XclExpStream& operator<<( sal_uInt8 nValue ); - inline XclExpStream& operator<<( sal_Int16 nValue ); - inline XclExpStream& operator<<( sal_uInt16 nValue ); - inline XclExpStream& operator<<( sal_Int32 nValue ); - inline XclExpStream& operator<<( sal_uInt32 nValue ); - inline XclExpStream& operator<<( float fValue ); - inline XclExpStream& operator<<( double fValue ); + XclExpStream& operator<<( sal_Int8 nValue ); + XclExpStream& operator<<( sal_uInt8 nValue ); + XclExpStream& operator<<( sal_Int16 nValue ); + XclExpStream& operator<<( sal_uInt16 nValue ); + XclExpStream& operator<<( sal_Int32 nValue ); + XclExpStream& operator<<( sal_uInt32 nValue ); + XclExpStream& operator<<( float fValue ); + XclExpStream& operator<<( double fValue ); /** Writes nBytes bytes from memory. */ sal_Size Write( const void* pData, sal_Size nBytes ); @@ -158,6 +163,14 @@ public: /** Returns the absolute position of the system stream. */ inline sal_Size GetSvStreamPos() const { return mrStrm.Tell(); } + void SetEncrypter( XclExpEncrypterRef xEncrypter ); + + bool HasValidEncrypter() const; + + void EnableEncryption( bool bEnable = true ); + + void DisableEncryption(); + private: /** Writes header data, internal setup. */ void InitRecord( sal_uInt16 nRecId ); @@ -180,6 +193,9 @@ private: SvStream& mrStrm; /// Reference to the system output stream. const XclExpRoot& mrRoot; /// Filter root data. + bool mbUseEncrypter; + XclExpEncrypterRef mxEncrypter; + // length data sal_uInt16 mnMaxRecSize; /// Maximum size of record content. sal_uInt16 mnMaxContSize; /// Maximum size of CONTINUE content. @@ -197,64 +213,50 @@ private: // ---------------------------------------------------------------------------- -inline XclExpStream& XclExpStream::operator<<( sal_Int8 nValue ) -{ - PrepareWrite( 1 ); - mrStrm << nValue; - return *this; -} -inline XclExpStream& XclExpStream::operator<<( sal_uInt8 nValue ) -{ - PrepareWrite( 1 ); - mrStrm << nValue; - return *this; -} +// ============================================================================ -inline XclExpStream& XclExpStream::operator<<( sal_Int16 nValue ) +class XclExpBiff8Encrypter { - PrepareWrite( 2 ); - mrStrm << nValue; - return *this; -} +public: + explicit XclExpBiff8Encrypter( const XclExpRoot& rRoot, const sal_uInt8 nDocId[16], + const sal_uInt8 nSalt[16] ); + ~XclExpBiff8Encrypter(); -inline XclExpStream& XclExpStream::operator<<( sal_uInt16 nValue ) -{ - PrepareWrite( 2 ); - mrStrm << nValue; - return *this; -} + bool IsValid() const; -inline XclExpStream& XclExpStream::operator<<( sal_Int32 nValue ) -{ - PrepareWrite( 4 ); - mrStrm << nValue; - return *this; -} + void GetSaltDigest( sal_uInt8 nSaltDigest[16] ) const; -inline XclExpStream& XclExpStream::operator<<( sal_uInt32 nValue ) -{ - PrepareWrite( 4 ); - mrStrm << nValue; - return *this; -} + void Encrypt( SvStream& rStrm, sal_uInt8 nData ); + void Encrypt( SvStream& rStrm, sal_uInt16 nData ); + void Encrypt( SvStream& rStrm, sal_uInt32 nData ); -inline XclExpStream& XclExpStream::operator<<( float fValue ) -{ - PrepareWrite( 4 ); - mrStrm << fValue; - return *this; -} + void Encrypt( SvStream& rStrm, sal_Int8 nData ); + void Encrypt( SvStream& rStrm, sal_Int16 nData ); + void Encrypt( SvStream& rStrm, sal_Int32 nData ); -inline XclExpStream& XclExpStream::operator<<( double fValue ) -{ - PrepareWrite( 8 ); - mrStrm << fValue; - return *this; -} + void Encrypt( SvStream& rStrm, float fValue ); + void Encrypt( SvStream& rStrm, double fValue ); + void EncryptBytes( SvStream& rStrm, ::std::vector<sal_uInt8>& aBytes ); -// ============================================================================ +private: + void Init( const String& aPass, const sal_uInt8 nDocId[16], + const sal_uInt8 nSalt[16] ); + + sal_uInt32 GetBlockPos( sal_Size nStrmPos ) const; + sal_uInt16 GetOffsetInBlock( sal_Size nStrmPos ) const; + +private: + ::svx::MSCodec_Std97 maCodec; /// Crypto algorithm implementation. + sal_uInt16 mnPassw[16]; /// Cached password data for copy construction. + sal_uInt8 mnDocId[16]; /// Cached document ID for copy construction. + sal_uInt8 mnSaltDigest[16]; + + const XclExpRoot& mrRoot; + sal_Size mnOldPos; /// Last known stream position + bool mbValid; +}; // ---------------------------------------------------------------------------- @@ -335,7 +337,7 @@ public: // only needed for import; ignore virtual bool importDocument() throw(); virtual sal_Int32 getSchemeClr( sal_Int32 nColorSchemeToken ) const; - virtual const oox::vml::DrawingPtr getDrawings(); + virtual oox::vml::Drawing* getVmlDrawing(); virtual const oox::drawingml::Theme* getCurrentTheme() const; virtual const oox::drawingml::table::TableStyleListPtr getTableStyles(); virtual oox::drawingml::chart::ChartConverter& getChartConverter(); diff --git a/sc/source/filter/inc/xetable.hxx b/sc/source/filter/inc/xetable.hxx index 7be4f406ee23..5322b0c47f01 100644 --- a/sc/source/filter/inc/xetable.hxx +++ b/sc/source/filter/inc/xetable.hxx @@ -1088,7 +1088,5 @@ private: XclExpDvalRef mxDval; /// Data validation with DVAL and DV records. }; -// ============================================================================ - #endif diff --git a/sc/source/filter/inc/xichart.hxx b/sc/source/filter/inc/xichart.hxx index 36ddc773dd5f..dc650b3f0373 100644 --- a/sc/source/filter/inc/xichart.hxx +++ b/sc/source/filter/inc/xichart.hxx @@ -44,8 +44,6 @@ #include "xiescher.hxx" #include "xistring.hxx" -#include <boost/shared_ptr.hpp> - namespace com { namespace sun { namespace star { namespace frame { @@ -375,6 +373,7 @@ public: public: explicit XclImpChSourceLink( const XclImpChRoot& rRoot ); + virtual ~XclImpChSourceLink(); /** Reads the CHSOURCELINK record (link to source data). */ void ReadChSourceLink( XclImpStream& rStrm ); @@ -407,10 +406,7 @@ public: private: XclChSourceLink maData; /// Contents of the CHSOURCELINK record. XclImpStringRef mxString; /// Text data (CHSTRING record). - - // Tokens representing data ranges. This must be ref-counted to allow the - // parent class to be stored in a STL container. - ::boost::shared_ptr<ScTokenArray> mpTokenArray; + ScfRef< ScTokenArray> mxTokenArray; /// Token array representing the data ranges. }; typedef ScfRef< XclImpChSourceLink > XclImpChSourceLinkRef; diff --git a/sc/source/filter/inc/xicontent.hxx b/sc/source/filter/inc/xicontent.hxx index 2b777e57600c..53ed10583249 100644 --- a/sc/source/filter/inc/xicontent.hxx +++ b/sc/source/filter/inc/xicontent.hxx @@ -37,6 +37,8 @@ #include "xistring.hxx" #include "xiroot.hxx" +#include <map> + /* ============================================================================ Classes to import the big Excel document contents (related to several cells or globals for the document). @@ -249,5 +251,64 @@ public: // ============================================================================ +// Document protection ======================================================== + +class XclImpDocProtectBuffer : protected XclImpRoot +{ +public: + explicit XclImpDocProtectBuffer( const XclImpRoot& rRoot ); + + /** document structure protection flag */ + void ReadDocProtect( XclImpStream& rStrm ); + + /** document windows properties protection flag */ + void ReadWinProtect( XclImpStream& rStrm ); + + void ReadPasswordHash( XclImpStream& rStrm ); + + void Apply() const; + +private: + sal_uInt16 mnPassHash; + bool mbDocProtect:1; + bool mbWinProtect:1; +}; + +// Sheet protection =========================================================== + +class XclImpSheetProtectBuffer : protected XclImpRoot +{ +public: + explicit XclImpSheetProtectBuffer( const XclImpRoot& rRoot ); + + void ReadProtect( XclImpStream& rStrm, SCTAB nTab ); + + void ReadOptions( XclImpStream& rStrm, SCTAB nTab ); + + void ReadPasswordHash( XclImpStream& rStrm, SCTAB nTab ); + + void Apply() const; + +private: + struct Sheet + { + bool mbProtected; + sal_uInt16 mnPasswordHash; + sal_uInt16 mnOptions; + + Sheet(); + Sheet(const Sheet& r); + }; + + Sheet* GetSheetItem( SCTAB nTab ); + +private: + typedef ::std::map<SCTAB, Sheet> ProtectedSheetMap; + ProtectedSheetMap maProtectedSheets; +}; + + +// ============================================================================ + #endif diff --git a/sc/source/filter/inc/xiroot.hxx b/sc/source/filter/inc/xiroot.hxx index ea3edb342907..ac0be294f8e8 100644 --- a/sc/source/filter/inc/xiroot.hxx +++ b/sc/source/filter/inc/xiroot.hxx @@ -62,6 +62,8 @@ class XclImpPivotTableManager; class XclImpPageSettings; class XclImpDocViewSettings; class XclImpTabViewSettings; +class XclImpSheetProtectBuffer; +class XclImpDocProtectBuffer; class _ScRangeListTabs; class ExcelToSc; @@ -88,6 +90,8 @@ struct XclImpRootData : public XclRootData typedef ScfRef< XclImpPageSettings > XclImpPageSettRef; typedef ScfRef< XclImpDocViewSettings > XclImpDocViewSettRef; typedef ScfRef< XclImpTabViewSettings > XclImpTabViewSettRef; + typedef ScfRef< XclImpSheetProtectBuffer > XclImpTabProtectRef; + typedef ScfRef< XclImpDocProtectBuffer > XclImpDocProtectRef; XclImpAddrConvRef mxAddrConv; /// The address converter. XclImpFmlaCompRef mxFmlaComp; /// The formula compiler. @@ -111,6 +115,11 @@ struct XclImpRootData : public XclRootData XclImpPageSettRef mxPageSett; /// Page settings for current sheet. XclImpDocViewSettRef mxDocViewSett; /// View settings for entire document. XclImpTabViewSettRef mxTabViewSett; /// View settings for current sheet. + XclImpTabProtectRef mxTabProtect; /// Sheet protection options for current sheet. + XclImpDocProtectRef mxDocProtect; /// Document protection options. + + String maPassw; /// Entered password for stream decryption. + bool mbPassQueried; /// true = Password already querried. bool mbHasCodePage; /// true = CODEPAGE record exists. @@ -184,6 +193,10 @@ public: XclImpWebQueryBuffer& GetWebQueryBuffer() const; /** Returns the pivot table manager. */ XclImpPivotTableManager& GetPivotTableManager() const; + /** Returns the sheet protection options of the current sheet. */ + XclImpSheetProtectBuffer& GetSheetProtectBuffer() const; + /** Returns the document protection options. */ + XclImpDocProtectBuffer& GetDocProtectBuffer() const; /** Returns the page settings of the current sheet. */ XclImpPageSettings& GetPageSettings() const; @@ -195,6 +208,9 @@ public: /** Returns the Calc add-in function name for an Excel function name. */ String GetScAddInName( const String& rXclName ) const; + /** Queries a password from the user and returns it (empty string -> input cancelled). */ + const String& QueryPassword() const; + private: mutable XclImpRootData& mrImpData; /// Reference to the global import data struct. }; diff --git a/sc/source/filter/inc/xistream.hxx b/sc/source/filter/inc/xistream.hxx index aa1cae84d8f6..ccaaccdc0357 100644 --- a/sc/source/filter/inc/xistream.hxx +++ b/sc/source/filter/inc/xistream.hxx @@ -73,6 +73,8 @@ public: @return Count of bytes really read. */ sal_uInt16 Read( SvStream& rStrm, void* pData, sal_uInt16 nBytes ); + const String GetPassword() const; + protected: /** Protected copy c'tor for OnClone(). */ explicit XclImpDecrypter( const XclImpDecrypter& rSrc ); @@ -80,6 +82,8 @@ protected: /** Sets the decrypter to a state showing whether the password was correct. */ void SetHasValidPassword( bool bValid ); + void SetPassword( const String& rPass ); + private: /** Implementation of cloning this object. */ virtual XclImpDecrypter* OnClone() const = 0; @@ -89,6 +93,7 @@ private: virtual sal_uInt16 OnRead( SvStream& rStrm, sal_uInt8* pnData, sal_uInt16 nBytes ) = 0; private: + String maPass; /// Stored password (needed for export) ErrCode mnError; /// Decrypter error code. sal_Size mnOldPos; /// Last known stream position. sal_uInt16 mnRecSize; /// Current record size. diff --git a/sc/source/filter/inc/xlchart.hxx b/sc/source/filter/inc/xlchart.hxx index 92a3b60ce970..1666ecc49ba1 100644 --- a/sc/source/filter/inc/xlchart.hxx +++ b/sc/source/filter/inc/xlchart.hxx @@ -157,6 +157,7 @@ namespace com { namespace sun { namespace star { #define EXC_CHPROP_ROLE_CLOSEVALUES CREATE_OUSTRING( "values-last" ) #define EXC_CHPROP_ROLE_LOWVALUES CREATE_OUSTRING( "values-min" ) #define EXC_CHPROP_ROLE_HIGHVALUES CREATE_OUSTRING( "values-max" ) +#define EXC_CHPROP_ROLE_SIZEVALUES CREATE_OUSTRING( "values-size" ) // Constants and Enumerations ================================================= diff --git a/sc/source/filter/inc/xlroot.hxx b/sc/source/filter/inc/xlroot.hxx index 12ab2808a1ab..36056ead2fe2 100644 --- a/sc/source/filter/inc/xlroot.hxx +++ b/sc/source/filter/inc/xlroot.hxx @@ -92,7 +92,6 @@ struct XclRootData ScDocument& mrDoc; /// The source or destination document. String maDocUrl; /// Document URL of imported/exported file. String maBasePath; /// Base path of imported/exported file (path of maDocUrl). - String maPassw; /// Entered password for stream encryption/decryption. rtl_TextEncoding meTextEnc; /// Text encoding to import/export byte strings. LanguageType meSysLang; /// System language. LanguageType meDocLang; /// Document language (import: from file, export: from system). @@ -116,7 +115,6 @@ struct XclRootData long mnCharWidth; /// Width of '0' in default font (twips). SCTAB mnScTab; /// Current Calc sheet index. const bool mbExport; /// false = Import, true = Export. - bool mbHasPassw; /// true = Password already querried. explicit XclRootData( XclBiff eBiff, SfxMedium& rMedium, SotStorageRef xRootStrg, ScDocument& rDoc, @@ -184,8 +182,6 @@ public: inline const String& GetDocUrl() const { return mrData.maDocUrl; } /** Returns the base path of the imported/exported file. */ inline const String& GetBasePath() const { return mrData.maBasePath; } - /** Queries a password from the user and returns it (empty string -> input cancelled). */ - const String& QueryPassword() const; /** Returns the OLE2 root storage of the imported/exported file. @return Pointer to root storage or 0, if the file is a simple stream. */ diff --git a/sc/source/filter/lotus/op.cxx b/sc/source/filter/lotus/op.cxx index dab66815947e..92cb49e786eb 100644 --- a/sc/source/filter/lotus/op.cxx +++ b/sc/source/filter/lotus/op.cxx @@ -466,7 +466,7 @@ void OP_Note123( SvStream& r, UINT16 n) delete [] pText; ScAddress aPos( static_cast<SCCOL>(nCol), static_cast<SCROW>(nRow), static_cast<SCTAB>(nTab) ); - ScNoteUtil::CreateNoteFromString( *pDoc, aPos, aNoteText, false ); + ScNoteUtil::CreateNoteFromString( *pDoc, aPos, aNoteText, false, false ); } void OP_HorAlign123( BYTE nAlignPattern, SfxItemSet& rPatternItemSet ) diff --git a/sc/source/filter/starcalc/scflt.cxx b/sc/source/filter/starcalc/scflt.cxx index 511c706abdfb..e2a7d9e4d538 100644 --- a/sc/source/filter/starcalc/scflt.cxx +++ b/sc/source/filter/starcalc/scflt.cxx @@ -81,6 +81,7 @@ #include "postit.hxx" #include "globstr.hrc" #include "ftools.hxx" +#include "tabprotection.hxx" #include "fprogressbar.hxx" @@ -1087,9 +1088,11 @@ void Sc10Import::LoadProtect() //rStream.Read(&SheetProtect, sizeof(SheetProtect)); lcl_ReadSheetProtect(rStream, SheetProtect); nError = rStream.GetError(); - uno::Sequence<sal_Int8> aPass; - SvPasswordHelper::GetHashPassword(aPass, SC10TOSTRING( SheetProtect.PassWord )); - pDoc->SetDocProtection( SheetProtect.Protect, aPass); + + ScDocProtection aProtection; + aProtection.setProtected(static_cast<bool>(SheetProtect.Protect)); + aProtection.setPassword(SC10TOSTRING(SheetProtect.PassWord)); + pDoc->SetDocProtection(&aProtection); } @@ -1441,10 +1444,11 @@ void Sc10Import::LoadTables() //rStream.Read(&TabProtect, sizeof(TabProtect)); lcl_ReadTabProtect(rStream, TabProtect); - uno::Sequence<sal_Int8> aPass; - SvPasswordHelper::GetHashPassword(aPass, SC10TOSTRING( TabProtect.PassWord )); - pDoc->SetTabProtection( static_cast<SCTAB>(Tab), TabProtect.Protect, aPass); + ScTableProtection aProtection; + aProtection.setProtected(static_cast<bool>(TabProtect.Protect)); + aProtection.setPassword(SC10TOSTRING(TabProtect.PassWord)); + pDoc->SetTabProtection(static_cast<SCTAB>(Tab), &aProtection); rStream >> TabNo; @@ -1710,7 +1714,7 @@ void Sc10Import::LoadCol(SCCOL Col, SCTAB Tab) String aNoteText( SC10TOSTRING(pNote)); delete [] pNote; ScAddress aPos( Col, static_cast<SCROW>(Row), Tab ); - ScNoteUtil::CreateNoteFromString( *pDoc, aPos, aNoteText, false ); + ScNoteUtil::CreateNoteFromString( *pDoc, aPos, aNoteText, false, false ); } } pPrgrsBar->Progress(); diff --git a/sc/source/filter/xcl97/XclExpChangeTrack.cxx b/sc/source/filter/xcl97/XclExpChangeTrack.cxx index 760599ff594b..a38b023d4f55 100644 --- a/sc/source/filter/xcl97/XclExpChangeTrack.cxx +++ b/sc/source/filter/xcl97/XclExpChangeTrack.cxx @@ -491,6 +491,7 @@ void XclExpChTrTabId::Copy( const XclExpChTrTabIdBuffer& rBuffer ) void XclExpChTrTabId::SaveCont( XclExpStream& rStrm ) { + rStrm.EnableEncryption(); if( pBuffer ) for( sal_uInt16* pElem = pBuffer; pElem < (pBuffer + nTabCount); pElem++ ) rStrm << *pElem; diff --git a/sc/source/filter/xcl97/makefile.mk b/sc/source/filter/xcl97/makefile.mk index c40209d40819..58e2b8cb3074 100644 --- a/sc/source/filter/xcl97/makefile.mk +++ b/sc/source/filter/xcl97/makefile.mk @@ -51,7 +51,6 @@ VISIBILITY_HIDDEN=TRUE # --- Files -------------------------------------------------------- SLOFILES = \ - $(SLO)$/xcl97dum.obj \ $(SLO)$/xcl97esc.obj \ $(SLO)$/xcl97rec.obj \ $(SLO)$/XclImpChangeTrack.obj \ diff --git a/sc/source/filter/xcl97/xcl97rec.cxx b/sc/source/filter/xcl97/xcl97rec.cxx index 3d878243b2c2..bd40e98a02f4 100644 --- a/sc/source/filter/xcl97/xcl97rec.cxx +++ b/sc/source/filter/xcl97/xcl97rec.cxx @@ -79,6 +79,7 @@ #include "scextopt.hxx" #include "docoptio.hxx" #include "patattr.hxx" +#include "tabprotection.hxx" #include <oox/core/tokens.hxx> @@ -716,6 +717,7 @@ ExcBof8_Base::ExcBof8_Base() void ExcBof8_Base::SaveCont( XclExpStream& rStrm ) { + rStrm.DisableEncryption(); rStrm << nVers << nDocType << nRupBuild << nRupYear << nFileHistory << nLowestBiffVer; } @@ -775,7 +777,10 @@ void ExcBundlesheet8::SaveCont( XclExpStream& rStrm ) { nOwnPos = rStrm.GetSvStreamPos(); // write dummy position, real position comes later - rStrm << sal_uInt32( 0 ) << nGrbit << GetName(); + rStrm.DisableEncryption(); + rStrm << sal_uInt32(0); + rStrm.EnableEncryption(); + rStrm << nGrbit << GetName(); } @@ -1083,33 +1088,73 @@ sal_Size ExcEScenarioManager::GetLen() const return 8; } +// ============================================================================ - -// ---- class XclProtection ------------------------------------------ - -const BYTE XclProtection::pMyData[] = +struct XclExpTabProtectOption { - 0x12, 0x00, 0x02, 0x00, 0x01, 0x00, // PROTECT - 0xDD, 0x00, 0x02, 0x00, 0x01, 0x00, // SCENPROTECT - 0x63, 0x00, 0x02, 0x00, 0x01, 0x00 // OBJPROTECT + ScTableProtection::Option eOption; + sal_uInt16 nMask; }; -const sal_Size XclProtection::nMyLen = sizeof( XclProtection::pMyData ); -sal_Size XclProtection::GetLen( void ) const +XclExpSheetProtectOptions::XclExpSheetProtectOptions( const XclExpRoot& rRoot, SCTAB nTab ) : + XclExpRecord( 0x0867, 23 ) { - return nMyLen; -} - + static const XclExpTabProtectOption aTable[] = + { + { ScTableProtection::OBJECTS, 0x0001 }, + { ScTableProtection::SCENARIOS, 0x0002 }, + { ScTableProtection::FORMAT_CELLS, 0x0004 }, + { ScTableProtection::FORMAT_COLUMNS, 0x0008 }, + { ScTableProtection::FORMAT_ROWS, 0x0010 }, + { ScTableProtection::INSERT_COLUMNS, 0x0020 }, + { ScTableProtection::INSERT_ROWS, 0x0040 }, + { ScTableProtection::INSERT_HYPERLINKS, 0x0080 }, + + { ScTableProtection::DELETE_COLUMNS, 0x0100 }, + { ScTableProtection::DELETE_ROWS, 0x0200 }, + { ScTableProtection::SELECT_LOCKED_CELLS, 0x0400 }, + { ScTableProtection::SORT, 0x0800 }, + { ScTableProtection::AUTOFILTER, 0x1000 }, + { ScTableProtection::PIVOT_TABLES, 0x2000 }, + { ScTableProtection::SELECT_UNLOCKED_CELLS, 0x4000 }, + + { ScTableProtection::NONE, 0x0000 } + }; + + mnOptions = 0x0000; + ScTableProtection* pProtect = rRoot.GetDoc().GetTabProtection(nTab); + if (!pProtect) + return; -const BYTE* XclProtection::GetData( void ) const -{ - return pMyData; + for (int i = 0; aTable[i].nMask != 0x0000; ++i) + { + if ( pProtect->isOptionEnabled(aTable[i].eOption) ) + mnOptions |= aTable[i].nMask; + } } +void XclExpSheetProtectOptions::WriteBody( XclExpStream& rStrm ) +{ + sal_uInt16 nBytes = 0x0867; + rStrm << nBytes; + sal_uChar nZero = 0x00; + for (int i = 0; i < 9; ++i) + rStrm << nZero; + nBytes = 0x0200; + rStrm << nBytes; + nBytes = 0x0100; + rStrm << nBytes; + nBytes = 0xFFFF; + rStrm << nBytes << nBytes; + rStrm << mnOptions; + nBytes = 0; + rStrm << nBytes; +} +// ============================================================================ @@ -1214,8 +1259,253 @@ void XclDelta::SaveXml( XclExpXmlStream& rStrm ) FSEND ); } +// ============================================================================ + +XclExpFilePass::XclExpFilePass( const XclExpRoot& rRoot ) : + XclExpRecord(0x002F, 54), + mrRoot(rRoot) +{ +} + +XclExpFilePass::~XclExpFilePass() +{ +} + +void XclExpFilePass::WriteBody( XclExpStream& rStrm ) +{ + static const sal_uInt8 nDocId[] = { + 0x17, 0xf7, 0x01, 0x08, 0xea, 0xad, 0x30, 0x5c, + 0x1a, 0x95, 0xa5, 0x75, 0xd6, 0x79, 0xcd, 0x8d }; + + + static const sal_uInt8 nSalt[] = { + 0xa4, 0x5b, 0xf7, 0xe9, 0x9f, 0x55, 0x21, 0xc5, + 0xc5, 0x56, 0xa8, 0x0d, 0x39, 0x05, 0x3a, 0xb4 }; + + // 0x0000 - neither standard nor strong encryption + // 0x0001 - standard or strong encryption + rStrm << static_cast<sal_uInt16>(0x0001); + + // 0x0000 - non standard encryption + // 0x0001 - standard encryption + sal_uInt16 nStdEnc = 0x0001; + rStrm << nStdEnc << nStdEnc; + + sal_uInt8 nSaltHash[16]; + XclExpEncrypterRef xEnc( new XclExpBiff8Encrypter(mrRoot, nDocId, nSalt) ); + xEnc->GetSaltDigest(nSaltHash); + + rStrm.Write(nDocId, 16); + rStrm.Write(nSalt, 16); + rStrm.Write(nSaltHash, 16); + + rStrm.SetEncrypter(xEnc); +} + +// ============================================================================ + +XclExpFnGroupCount::XclExpFnGroupCount() : + XclExpRecord(0x009C, 2) +{ +} + +XclExpFnGroupCount::~XclExpFnGroupCount() +{ +} + +void XclExpFnGroupCount::WriteBody( XclExpStream& rStrm ) +{ + rStrm << static_cast<sal_uInt16>(14); +} + +// ============================================================================ + +XclExpInterfaceHdr::XclExpInterfaceHdr() : + XclExpRecord(0x00E1, 2) +{ +} + +XclExpInterfaceHdr::~XclExpInterfaceHdr() +{ +} +void XclExpInterfaceHdr::WriteBody( XclExpStream& rStrm ) +{ + // The value must be the same value as the CODEPAGE record. + rStrm.DisableEncryption(); + rStrm << static_cast<sal_uInt16>(0x04B0); +} + +// ============================================================================ + +XclExpInterfaceEnd::XclExpInterfaceEnd() : + XclExpRecord(0x00E2, 0) +{ +} + +XclExpInterfaceEnd::~XclExpInterfaceEnd() +{ +} + +void XclExpInterfaceEnd::WriteBody( XclExpStream& /*rStrm*/ ) +{ +} + +// ============================================================================ + +XclExpMMS::XclExpMMS() : + XclExpRecord(0x00C1, 2) +{ +} + +XclExpMMS::~XclExpMMS() +{ +} + +void XclExpMMS::WriteBody( XclExpStream& rStrm ) +{ + rStrm << static_cast<sal_uInt16>(0x0000); +} + +// ============================================================================ + +XclExpWriteAccess::XclExpWriteAccess() : + XclExpRecord(0x005C, 112) +{ +} +XclExpWriteAccess::~XclExpWriteAccess() +{ +} + +void XclExpWriteAccess::WriteBody( XclExpStream& rStrm ) +{ + static const sal_uInt8 aData[] = { + 0x04, 0x00, 0x00, 'C', 'a', 'l', 'c', 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, + 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20 }; + + sal_Size nDataSize = sizeof(aData); + for (sal_Size i = 0; i < nDataSize; ++i) + rStrm << aData[i]; +} + +// ============================================================================ + +XclExpCodePage::XclExpCodePage() : + XclExpRecord(0x0042, 2) +{ +} + +XclExpCodePage::~XclExpCodePage() +{ +} + +void XclExpCodePage::WriteBody( XclExpStream& rStrm ) +{ + // 0x04B0 : UTF-16 (BIFF8) + rStrm << static_cast<sal_uInt16>(0x04B0); +} + +// ============================================================================ + +XclExpDSF::XclExpDSF() : + XclExpRecord(0x0161, 2) +{ +} + +XclExpDSF::~XclExpDSF() +{ +} + +void XclExpDSF::WriteBody( XclExpStream& rStrm ) +{ + rStrm << static_cast<sal_uInt16>(0x0000); +} + +// ============================================================================ + +XclExpProt4Rev::XclExpProt4Rev() : + XclExpRecord(0x01AF, 2) +{ +} + +XclExpProt4Rev::~XclExpProt4Rev() +{ +} + +void XclExpProt4Rev::WriteBody( XclExpStream& rStrm ) +{ + rStrm << static_cast<sal_uInt16>(0x0000); +} + +// ============================================================================ + +XclExpProt4RevPass::XclExpProt4RevPass() : + XclExpRecord(0x01BC, 2) +{ +} + +XclExpProt4RevPass::~XclExpProt4RevPass() +{ +} + +void XclExpProt4RevPass::WriteBody( XclExpStream& rStrm ) +{ + rStrm << static_cast<sal_uInt16>(0x0000); +} + +// ============================================================================ + +XclExpExcel9File::XclExpExcel9File() : + XclExpRecord(0x01C0, 0) +{ +} + +XclExpExcel9File::~XclExpExcel9File() +{ +} + +void XclExpExcel9File::WriteBody( XclExpStream& /*rStrm*/ ) +{ +} + +// ============================================================================ + +static const sal_uInt8 nDataRecalcId[] = { + 0xC1, 0x01, 0x00, 0x00, 0x54, 0x8D, 0x01, 0x00 +}; + +XclExpRecalcId::XclExpRecalcId() : + XclExpDummyRecord(0x01C1, nDataRecalcId, sizeof(nDataRecalcId)) +{ +} + +// ============================================================================ + +static const sal_uInt8 nDataBookExt[] = { + 0x63, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x02 +}; + +XclExpBookExt::XclExpBookExt() : + XclExpDummyRecord(0x0863, nDataBookExt, sizeof(nDataBookExt)) +{ +} + +// ============================================================================ XclRefmode::XclRefmode( const ScDocument& rDoc ) : XclExpBoolRecord( 0x000F, rDoc.GetAddressConvention() != formula::FormulaGrammar::CONV_XL_R1C1 ) diff --git a/sc/source/filter/xml/XMLConverter.cxx b/sc/source/filter/xml/XMLConverter.cxx index e0a20ad4353e..84fdba343630 100644 --- a/sc/source/filter/xml/XMLConverter.cxx +++ b/sc/source/filter/xml/XMLConverter.cxx @@ -31,20 +31,17 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sc.hxx" - - - -//___________________________________________________________________ #include "XMLConverter.hxx" +#include <com/sun/star/util/DateTime.hpp> +#include <tools/datetime.hxx> +#include <xmloff/xmltoken.hxx> +#include <xmloff/xmluconv.hxx> #include "rangelst.hxx" #include "rangeutl.hxx" #include "docuno.hxx" #include "convuno.hxx" #include "document.hxx" -#include <tools/datetime.hxx> -#include <xmloff/xmltoken.hxx> -#include <xmloff/xmluconv.hxx> -#include <com/sun/star/util/DateTime.hpp> +#include "ftools.hxx" using ::rtl::OUString; using ::rtl::OUStringBuffer; @@ -385,3 +382,292 @@ void ScXMLConverter::ConvertAPIToCoreDateTime(const util::DateTime& aDateTime, D rDateTime = aTempDateTime; } +// ============================================================================ + +namespace { + +/** Enumerates different types of condition tokens. */ +enum ScXMLConditionTokenType +{ + XML_COND_TYPE_KEYWORD, /// Simple keyword without parentheses, e.g. 'and'. + XML_COND_TYPE_COMPARISON, /// Comparison rule, e.g. 'cell-content()<=2'. + XML_COND_TYPE_FUNCTION0, /// Function without parameters, e.g. 'cell-content-is-whole-number()'. + XML_COND_TYPE_FUNCTION1, /// Function with 1 parameter, e.g. 'is-true-formula(1+1=2)'. + XML_COND_TYPE_FUNCTION2 /// Function with 2 parameters, e.g. 'cell-content-is-between(1,2)'. +}; + +struct ScXMLConditionInfo +{ + ScXMLConditionToken meToken; + ScXMLConditionTokenType meType; + sheet::ValidationType meValidation; + sheet::ConditionOperator meOperator; + const sal_Char* mpcIdentifier; + sal_Int32 mnIdentLength; +}; + +static const ScXMLConditionInfo spConditionInfos[] = +{ + { XML_COND_AND, XML_COND_TYPE_KEYWORD, sheet::ValidationType_ANY, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "and" ) }, + { XML_COND_CELLCONTENT, XML_COND_TYPE_COMPARISON, sheet::ValidationType_ANY, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content" ) }, + { XML_COND_ISBETWEEN, XML_COND_TYPE_FUNCTION2, sheet::ValidationType_ANY, sheet::ConditionOperator_BETWEEN, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-between" ) }, + { XML_COND_ISNOTBETWEEN, XML_COND_TYPE_FUNCTION2, sheet::ValidationType_ANY, sheet::ConditionOperator_NOT_BETWEEN, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-not-between" ) }, + { XML_COND_ISWHOLENUMBER, XML_COND_TYPE_FUNCTION0, sheet::ValidationType_WHOLE, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-whole-number" ) }, + { XML_COND_ISDECIMALNUMBER, XML_COND_TYPE_FUNCTION0, sheet::ValidationType_DECIMAL, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-decimal-number" ) }, + { XML_COND_ISDATE, XML_COND_TYPE_FUNCTION0, sheet::ValidationType_DATE, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-date" ) }, + { XML_COND_ISTIME, XML_COND_TYPE_FUNCTION0, sheet::ValidationType_TIME, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-time" ) }, + { XML_COND_ISINLIST, XML_COND_TYPE_FUNCTION1, sheet::ValidationType_LIST, sheet::ConditionOperator_EQUAL, RTL_CONSTASCII_STRINGPARAM( "cell-content-is-in-list" ) }, + { XML_COND_TEXTLENGTH, XML_COND_TYPE_COMPARISON, sheet::ValidationType_TEXT_LEN, sheet::ConditionOperator_NONE, RTL_CONSTASCII_STRINGPARAM( "cell-content-text-length" ) }, + { XML_COND_TEXTLENGTH_ISBETWEEN, XML_COND_TYPE_FUNCTION2, sheet::ValidationType_TEXT_LEN, sheet::ConditionOperator_BETWEEN, RTL_CONSTASCII_STRINGPARAM( "cell-content-text-length-is-between" ) }, + { XML_COND_TEXTLENGTH_ISNOTBETWEEN, XML_COND_TYPE_FUNCTION2, sheet::ValidationType_TEXT_LEN, sheet::ConditionOperator_NOT_BETWEEN, RTL_CONSTASCII_STRINGPARAM( "cell-content-text-length-is-not-between" ) }, + { XML_COND_ISTRUEFORMULA, XML_COND_TYPE_FUNCTION1, sheet::ValidationType_CUSTOM, sheet::ConditionOperator_FORMULA, RTL_CONSTASCII_STRINGPARAM( "is-true-formula" ) } +}; + +void lclSkipWhitespace( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd ) +{ + while( (rpcString < pcEnd) && (*rpcString <= ' ') ) ++rpcString; +} + +const ScXMLConditionInfo* lclGetConditionInfo( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd ) +{ + lclSkipWhitespace( rpcString, pcEnd ); + /* Search the end of an identifier name; assuming that valid identifiers + consist of [a-z-] only. */ + const sal_Unicode* pcIdStart = rpcString; + while( (rpcString < pcEnd) && (((*rpcString >= 'a') && (*rpcString <= 'z')) || (*rpcString == '-')) ) ++rpcString; + sal_Int32 nLength = static_cast< sal_Int32 >( rpcString - pcIdStart ); + + // search the table for an entry + if( nLength > 0 ) + for( const ScXMLConditionInfo* pInfo = spConditionInfos; pInfo < STATIC_TABLE_END( spConditionInfos ); ++pInfo ) + if( (nLength == pInfo->mnIdentLength) && (::rtl_ustr_ascii_shortenedCompare_WithLength( pcIdStart, nLength, pInfo->mpcIdentifier, nLength ) == 0) ) + return pInfo; + + return 0; +} + +sheet::ConditionOperator lclGetConditionOperator( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd ) +{ + // check for double-char operators + if( (rpcString + 1 < pcEnd) && (rpcString[ 1 ] == '=') ) + { + sheet::ConditionOperator eOperator = sheet::ConditionOperator_NONE; + switch( *rpcString ) + { + case '!': eOperator = sheet::ConditionOperator_NOT_EQUAL; break; + case '<': eOperator = sheet::ConditionOperator_LESS_EQUAL; break; + case '>': eOperator = sheet::ConditionOperator_GREATER_EQUAL; break; + } + if( eOperator != sheet::ConditionOperator_NONE ) + { + rpcString += 2; + return eOperator; + } + } + + // check for single-char operators + if( rpcString < pcEnd ) + { + sheet::ConditionOperator eOperator = sheet::ConditionOperator_NONE; + switch( *rpcString ) + { + case '=': eOperator = sheet::ConditionOperator_EQUAL; break; + case '<': eOperator = sheet::ConditionOperator_LESS; break; + case '>': eOperator = sheet::ConditionOperator_GREATER; break; + } + if( eOperator != sheet::ConditionOperator_NONE ) + { + ++rpcString; + return eOperator; + } + } + + return sheet::ConditionOperator_NONE; +} + +/** Skips a literal string in a formula expression. + + @param rpcString + (in-out) On call, must point to the first character of the string + following the leading string delimiter character. On return, points to + the trailing string delimiter character if existing, otherwise to + pcEnd. + + @param pcEnd + The end of the string to parse. + + @param cQuoteChar + The string delimiter character enclosing the string. + */ +void lclSkipExpressionString( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd, sal_Unicode cQuoteChar ) +{ + if( rpcString < pcEnd ) + { + sal_Int32 nLength = static_cast< sal_Int32 >( pcEnd - rpcString ); + sal_Int32 nNextQuote = ::rtl_ustr_indexOfChar_WithLength( rpcString, nLength, cQuoteChar ); + if( nNextQuote >= 0 ) + rpcString += nNextQuote; + else + rpcString = pcEnd; + } +} + +/** Skips a formula expression. Processes embedded parentheses, braces, and + literal strings. + + @param rpcString + (in-out) On call, must point to the first character of the expression. + On return, points to the passed end character if existing, otherwise to + pcEnd. + + @param pcEnd + The end of the string to parse. + + @param cEndChar + The termination character following the expression. + */ +void lclSkipExpression( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd, sal_Unicode cEndChar ) +{ + while( rpcString < pcEnd ) + { + if( *rpcString == cEndChar ) + return; + switch( *rpcString ) + { + case '(': lclSkipExpression( ++rpcString, pcEnd, ')' ); break; + case '{': lclSkipExpression( ++rpcString, pcEnd, '}' ); break; + case '"': lclSkipExpressionString( ++rpcString, pcEnd, '"' ); break; + case '\'': lclSkipExpressionString( ++rpcString, pcEnd, '\'' ); break; + } + if( rpcString < pcEnd ) ++rpcString; + } +} + +/** Extracts a formula expression. Processes embedded parentheses, braces, and + literal strings. + + @param rpcString + (in-out) On call, must point to the first character of the expression. + On return, points *behind* the passed end character if existing, + otherwise to pcEnd. + + @param pcEnd + The end of the string to parse. + + @param cEndChar + The termination character following the expression. + */ +OUString lclGetExpression( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd, sal_Unicode cEndChar ) +{ + OUString aExp; + const sal_Unicode* pcExpStart = rpcString; + lclSkipExpression( rpcString, pcEnd, cEndChar ); + if( rpcString < pcEnd ) + { + aExp = OUString( pcExpStart, static_cast< sal_Int32 >( rpcString - pcExpStart ) ).trim(); + ++rpcString; + } + return aExp; +} + +/** Tries to skip an empty pair of parentheses (which may contain whitespace + characters). + + @return + True on success, rpcString points behind the closing parentheses then. + */ +bool lclSkipEmptyParentheses( const sal_Unicode*& rpcString, const sal_Unicode* pcEnd ) +{ + if( (rpcString < pcEnd) && (*rpcString == '(') ) + { + lclSkipWhitespace( ++rpcString, pcEnd ); + if( (rpcString < pcEnd) && (*rpcString == ')') ) + { + ++rpcString; + return true; + } + } + return false; +} + +} // namespace + +// ---------------------------------------------------------------------------- + +/*static*/ void ScXMLConditionHelper::parseCondition( + ScXMLConditionParseResult& rParseResult, const OUString& rAttribute, sal_Int32 nStartIndex ) +{ + rParseResult.meToken = XML_COND_INVALID; + if( (nStartIndex < 0) || (nStartIndex >= rAttribute.getLength()) ) return; + + // try to find an identifier + const sal_Unicode* pcBegin = rAttribute.getStr(); + const sal_Unicode* pcString = pcBegin + nStartIndex; + const sal_Unicode* pcEnd = pcBegin + rAttribute.getLength(); + if( const ScXMLConditionInfo* pCondInfo = lclGetConditionInfo( pcString, pcEnd ) ) + { + // insert default values into parse result (may be changed below) + rParseResult.meValidation = pCondInfo->meValidation; + rParseResult.meOperator = pCondInfo->meOperator; + // continue parsing dependent on token type + switch( pCondInfo->meType ) + { + case XML_COND_TYPE_KEYWORD: + // nothing specific has to follow, success + rParseResult.meToken = pCondInfo->meToken; + break; + + case XML_COND_TYPE_COMPARISON: + // format is <condition>()<operator><expression> + if( lclSkipEmptyParentheses( pcString, pcEnd ) ) + { + rParseResult.meOperator = lclGetConditionOperator( pcString, pcEnd ); + if( rParseResult.meOperator != sheet::ConditionOperator_NONE ) + { + lclSkipWhitespace( pcString, pcEnd ); + if( pcString < pcEnd ) + { + rParseResult.meToken = pCondInfo->meToken; + // comparison must be at end of attribute, remaining text is the formula + rParseResult.maOperand1 = OUString( pcString, static_cast< sal_Int32 >( pcEnd - pcString ) ); + } + } + } + break; + + case XML_COND_TYPE_FUNCTION0: + // format is <condition>() + if( lclSkipEmptyParentheses( pcString, pcEnd ) ) + rParseResult.meToken = pCondInfo->meToken; + break; + + case XML_COND_TYPE_FUNCTION1: + // format is <condition>(<expression>) + if( (pcString < pcEnd) && (*pcString == '(') ) + { + rParseResult.maOperand1 = lclGetExpression( ++pcString, pcEnd, ')' ); + if( rParseResult.maOperand1.getLength() > 0 ) + rParseResult.meToken = pCondInfo->meToken; + } + break; + + case XML_COND_TYPE_FUNCTION2: + // format is <condition>(<expression1>,<expression2>) + if( (pcString < pcEnd) && (*pcString == '(') ) + { + rParseResult.maOperand1 = lclGetExpression( ++pcString, pcEnd, ',' ); + if( rParseResult.maOperand1.getLength() > 0 ) + { + rParseResult.maOperand2 = lclGetExpression( pcString, pcEnd, ')' ); + if( rParseResult.maOperand2.getLength() > 0 ) + rParseResult.meToken = pCondInfo->meToken; + } + } + break; + } + rParseResult.mnEndIndex = static_cast< sal_Int32 >( pcString - pcBegin ); + } +} + +// ============================================================================ + diff --git a/sc/source/filter/xml/XMLConverter.hxx b/sc/source/filter/xml/XMLConverter.hxx index 75254a7b3300..090a3553aa91 100644 --- a/sc/source/filter/xml/XMLConverter.hxx +++ b/sc/source/filter/xml/XMLConverter.hxx @@ -36,8 +36,10 @@ #include "detdata.hxx" #include <rtl/ustrbuf.hxx> #include <com/sun/star/frame/XModel.hpp> +#include <com/sun/star/sheet/ConditionOperator.hpp> #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp> #include <com/sun/star/sheet/GeneralFunction.hpp> +#include <com/sun/star/sheet/ValidationType.hpp> #include <com/sun/star/util/DateTime.hpp> class ScDocument; @@ -117,6 +119,62 @@ public: static void ConvertAPIToCoreDateTime(const com::sun::star::util::DateTime& aDateTime, DateTime& rDateTime); }; +// ============================================================================ + +enum ScXMLConditionToken +{ + XML_COND_INVALID, /// Token not recognized. + XML_COND_AND, /// The 'and' token. + XML_COND_CELLCONTENT, /// The 'cell-content' token. + XML_COND_ISBETWEEN, /// The 'cell-content-is-between' token. + XML_COND_ISNOTBETWEEN, /// The 'cell-content-is-not-between' token. + XML_COND_ISWHOLENUMBER, /// The 'cell-content-is-whole-number' token. + XML_COND_ISDECIMALNUMBER, /// The 'cell-content-is-decimal-number' token. + XML_COND_ISDATE, /// The 'cell-content-is-date' token. + XML_COND_ISTIME, /// The 'cell-content-is-time' token. + XML_COND_ISINLIST, /// The 'cell-content-is-in-list' token. + XML_COND_TEXTLENGTH, /// The 'cell-content-text-length' token. + XML_COND_TEXTLENGTH_ISBETWEEN, /// The 'cell-content-text-length-is-between' token. + XML_COND_TEXTLENGTH_ISNOTBETWEEN, /// The 'cell-content-text-length-is-not-between' token. + XML_COND_ISTRUEFORMULA /// The 'is-true-formula' token. +}; + +// ---------------------------------------------------------------------------- + +/** Result of an attempt to parse a single condition in a 'condition' attribute + value of e.g. conditional formatting or data validation. + */ +struct ScXMLConditionParseResult +{ + ScXMLConditionToken meToken; /// The leading condition token. + ::com::sun::star::sheet::ValidationType + meValidation; /// A data validation type if existing. + ::com::sun::star::sheet::ConditionOperator + meOperator; /// A comparison operator if existing. + ::rtl::OUString maOperand1; /// First operand of the token or comparison value. + ::rtl::OUString maOperand2; /// Second operand of 'between' conditions. + sal_Int32 mnEndIndex; /// Index of first character following the condition. +}; + +// ---------------------------------------------------------------------------- + +class ScXMLConditionHelper +{ +public: + /** Parses the next condition in a 'condition' attribute value of e.g. + conditional formatting or data validation. + */ + static void parseCondition( + ScXMLConditionParseResult& rParseResult, + const ::rtl::OUString& rAttribute, + sal_Int32 nStartIndex ); + +private: + ScXMLConditionHelper(); + ~ScXMLConditionHelper(); +}; + +// ============================================================================ #endif diff --git a/sc/source/filter/xml/XMLExportDatabaseRanges.cxx b/sc/source/filter/xml/XMLExportDatabaseRanges.cxx index 4ca83809843d..b9d9b4936961 100644 --- a/sc/source/filter/xml/XMLExportDatabaseRanges.cxx +++ b/sc/source/filter/xml/XMLExportDatabaseRanges.cxx @@ -203,44 +203,56 @@ void ScXMLExportDatabaseRanges::WriteImportDescriptor(const uno::Sequence <beans } } -rtl::OUString ScXMLExportDatabaseRanges::getOperatorXML(const sheet::FilterOperator aFilterOperator, const sal_Bool bUseRegularExpressions) const +rtl::OUString ScXMLExportDatabaseRanges::getOperatorXML(const long aFilterOperator, const sal_Bool bUseRegularExpressions) const { switch (aFilterOperator) { - case sheet::FilterOperator_EQUAL : + case sheet::FilterOperator2::EQUAL : { if (bUseRegularExpressions) return GetXMLToken(XML_MATCH); else return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("=")); } - case sheet::FilterOperator_NOT_EQUAL : + case sheet::FilterOperator2::NOT_EQUAL : { if (bUseRegularExpressions) return GetXMLToken(XML_NOMATCH); else return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("!=")); } - case sheet::FilterOperator_BOTTOM_PERCENT : + case sheet::FilterOperator2::BOTTOM_PERCENT : return GetXMLToken(XML_BOTTOM_PERCENT); - case sheet::FilterOperator_BOTTOM_VALUES : + case sheet::FilterOperator2::BOTTOM_VALUES : return GetXMLToken(XML_BOTTOM_VALUES); - case sheet::FilterOperator_EMPTY : + case sheet::FilterOperator2::EMPTY : return GetXMLToken(XML_EMPTY); - case sheet::FilterOperator_GREATER : + case sheet::FilterOperator2::GREATER : return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">")); - case sheet::FilterOperator_GREATER_EQUAL : + case sheet::FilterOperator2::GREATER_EQUAL : return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(">=")); - case sheet::FilterOperator_LESS : + case sheet::FilterOperator2::LESS : return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<")); - case sheet::FilterOperator_LESS_EQUAL : + case sheet::FilterOperator2::LESS_EQUAL : return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("<=")); - case sheet::FilterOperator_NOT_EMPTY : + case sheet::FilterOperator2::NOT_EMPTY : return GetXMLToken(XML_NOEMPTY); - case sheet::FilterOperator_TOP_PERCENT : + case sheet::FilterOperator2::TOP_PERCENT : return GetXMLToken(XML_TOP_PERCENT); - case sheet::FilterOperator_TOP_VALUES : + case sheet::FilterOperator2::TOP_VALUES : return GetXMLToken(XML_TOP_VALUES); + case sheet::FilterOperator2::CONTAINS : + return GetXMLToken(XML_CONTAINS); + case sheet::FilterOperator2::DOES_NOT_CONTAIN : + return GetXMLToken(XML_DOES_NOT_CONTAIN); + case sheet::FilterOperator2::BEGINS_WITH : + return GetXMLToken(XML_BEGINS_WITH); + case sheet::FilterOperator2::DOES_NOT_BEGIN_WITH : + return GetXMLToken(XML_DOES_NOT_BEGIN_WITH); + case sheet::FilterOperator2::ENDS_WITH : + return GetXMLToken(XML_ENDS_WITH); + case sheet::FilterOperator2::DOES_NOT_END_WITH : + return GetXMLToken(XML_DOES_NOT_END_WITH); default: { // added to avoid warnings @@ -249,7 +261,7 @@ rtl::OUString ScXMLExportDatabaseRanges::getOperatorXML(const sheet::FilterOpera return rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("=")); } -void ScXMLExportDatabaseRanges::WriteCondition(const sheet::TableFilterField& aFilterField, sal_Bool bIsCaseSensitive, sal_Bool bUseRegularExpressions) +void ScXMLExportDatabaseRanges::WriteCondition(const sheet::TableFilterField2& aFilterField, sal_Bool bIsCaseSensitive, sal_Bool bUseRegularExpressions) { rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_FIELD_NUMBER, rtl::OUString::valueOf(aFilterField.Field)); if (bIsCaseSensitive) @@ -267,9 +279,9 @@ void ScXMLExportDatabaseRanges::WriteCondition(const sheet::TableFilterField& aF SvXMLElementExport aElemC(rExport, XML_NAMESPACE_TABLE, XML_FILTER_CONDITION, sal_True, sal_True); } -void ScXMLExportDatabaseRanges::WriteFilterDescriptor(const uno::Reference <sheet::XSheetFilterDescriptor>& xSheetFilterDescriptor, const rtl::OUString sDatabaseRangeName) +void ScXMLExportDatabaseRanges::WriteFilterDescriptor(const uno::Reference <sheet::XSheetFilterDescriptor2>& xSheetFilterDescriptor, const rtl::OUString sDatabaseRangeName) { - uno::Sequence <sheet::TableFilterField> aTableFilterFields(xSheetFilterDescriptor->getFilterFields()); + uno::Sequence< sheet::TableFilterField2 > aTableFilterFields( xSheetFilterDescriptor->getFilterFields2() ); sal_Int32 nTableFilterFields = aTableFilterFields.getLength(); if (nTableFilterFields > 0) { @@ -336,7 +348,7 @@ void ScXMLExportDatabaseRanges::WriteFilterDescriptor(const uno::Reference <shee else { SvXMLElementExport aElemC(rExport, XML_NAMESPACE_TABLE, XML_FILTER_OR, sal_True, sal_True); - sheet::TableFilterField aPrevFilterField = aTableFilterFields[0]; + sheet::TableFilterField2 aPrevFilterField = aTableFilterFields[0]; sheet::FilterConnection aConnection = aTableFilterFields[1].Connection; sal_Bool bOpenAndElement; rtl::OUString aName = rExport.GetNamespaceMap().GetQNameByKey(XML_NAMESPACE_TABLE, GetXMLToken(XML_FILTER_AND)); @@ -632,7 +644,9 @@ void ScXMLExportDatabaseRanges::WriteDatabaseRanges(const com::sun::star::uno::R if (::cppu::any2bool(xPropertySetDatabaseRange->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_STRIPDAT))))) rExport.AddAttribute(XML_NAMESPACE_TABLE, XML_HAS_PERSISTENT_DATA, XML_FALSE); } - uno::Reference <sheet::XSheetFilterDescriptor> xSheetFilterDescriptor(xDatabaseRange->getFilterDescriptor()); + + uno::Reference< sheet::XSheetFilterDescriptor2 > xSheetFilterDescriptor( + xDatabaseRange->getFilterDescriptor(), uno::UNO_QUERY ); uno::Sequence <beans::PropertyValue> aSortProperties(xDatabaseRange->getSortDescriptor()); if (xSheetFilterDescriptor.is()) { diff --git a/sc/source/filter/xml/XMLExportDatabaseRanges.hxx b/sc/source/filter/xml/XMLExportDatabaseRanges.hxx index c4829ffd3fdd..81d1399e16b3 100644 --- a/sc/source/filter/xml/XMLExportDatabaseRanges.hxx +++ b/sc/source/filter/xml/XMLExportDatabaseRanges.hxx @@ -33,9 +33,9 @@ #include <com/sun/star/uno/Sequence.h> #include <com/sun/star/beans/PropertyValue.hpp> -#include <com/sun/star/sheet/FilterOperator.hpp> -#include <com/sun/star/sheet/TableFilterField.hpp> -#include <com/sun/star/sheet/XSheetFilterDescriptor.hpp> +#include <com/sun/star/sheet/FilterOperator2.hpp> +#include <com/sun/star/sheet/TableFilterField2.hpp> +#include <com/sun/star/sheet/XSheetFilterDescriptor2.hpp> #include <com/sun/star/sheet/XSubTotalDescriptor.hpp> #include <com/sun/star/sheet/XSpreadsheetDocument.hpp> @@ -49,9 +49,9 @@ class ScXMLExportDatabaseRanges ScDocument* pDoc; void WriteImportDescriptor(const com::sun::star::uno::Sequence <com::sun::star::beans::PropertyValue> aImportDescriptor); - rtl::OUString getOperatorXML(const com::sun::star::sheet::FilterOperator aFilterOperator, const sal_Bool bUseRegularExpressions) const; - void WriteCondition(const com::sun::star::sheet::TableFilterField& aFilterField, sal_Bool bIsCaseSensitive, sal_Bool bUseRegularExpressions); - void WriteFilterDescriptor(const com::sun::star::uno::Reference <com::sun::star::sheet::XSheetFilterDescriptor>& xSheetFilterDescriptor, const rtl::OUString sDatabaseRangeName); + rtl::OUString getOperatorXML(const long aFilterOperator, const sal_Bool bUseRegularExpressions) const; + void WriteCondition(const com::sun::star::sheet::TableFilterField2& aFilterField, sal_Bool bIsCaseSensitive, sal_Bool bUseRegularExpressions); + void WriteFilterDescriptor(const com::sun::star::uno::Reference <com::sun::star::sheet::XSheetFilterDescriptor2>& xSheetFilterDescriptor, const rtl::OUString sDatabaseRangeName); void WriteSortDescriptor(const com::sun::star::uno::Sequence <com::sun::star::beans::PropertyValue> aSortProperties); void WriteSubTotalDescriptor(const com::sun::star::uno::Reference <com::sun::star::sheet::XSubTotalDescriptor> xSubTotalDescriptor, const rtl::OUString sDatabaseRangeName); public: diff --git a/sc/source/filter/xml/XMLTrackedChangesContext.cxx b/sc/source/filter/xml/XMLTrackedChangesContext.cxx index d1320a8c737f..2d8eac1dfc76 100644 --- a/sc/source/filter/xml/XMLTrackedChangesContext.cxx +++ b/sc/source/filter/xml/XMLTrackedChangesContext.cxx @@ -109,6 +109,7 @@ class ScXMLCellContentDeletionContext : public SvXMLImportContext { rtl::OUString sFormulaAddress; rtl::OUString sFormula; + rtl::OUString sFormulaNmsp; rtl::OUString sInputString; ScBigRange aBigRange; double fValue; @@ -298,7 +299,8 @@ public: ScXMLChangeCellContext( ScXMLImport& rImport, USHORT nPrfx, const ::rtl::OUString& rLName, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList>& xAttrList, - ScBaseCell*& rOldCell, rtl::OUString& sAddress, rtl::OUString& sFormula, + ScBaseCell*& rOldCell, rtl::OUString& sAddress, + rtl::OUString& rFormula, rtl::OUString& rFormulaNmsp, formula::FormulaGrammar::Grammar& rGrammar, rtl::OUString& rInputString, double& fValue, sal_uInt16& nType, sal_uInt8& nMatrixFlag, sal_Int32& nMatrixCols, sal_Int32& nMatrixRows); @@ -322,6 +324,7 @@ class ScXMLPreviousContext : public SvXMLImportContext { rtl::OUString sFormulaAddress; rtl::OUString sFormula; + rtl::OUString sFormulaNmsp; rtl::OUString sInputString; double fValue; ScXMLChangeTrackingImportHelper* pChangeTrackingImportHelper; @@ -329,7 +332,7 @@ class ScXMLPreviousContext : public SvXMLImportContext sal_uInt32 nID; sal_Int32 nMatrixCols; sal_Int32 nMatrixRows; - formula::FormulaGrammar::Grammar eGrammar; + formula::FormulaGrammar::Grammar eGrammar; sal_uInt16 nType; sal_uInt8 nMatrixFlag; @@ -831,7 +834,7 @@ SvXMLImportContext *ScXMLCellContentDeletionContext::CreateChildContext( USHORT { bContainsCell = sal_True; pContext = new ScXMLChangeCellContext(GetScImport(), nPrefix, rLocalName, xAttrList, - pCell, sFormulaAddress, sFormula, eGrammar, sInputString, fValue, nType, nMatrixFlag, nMatrixCols, nMatrixRows ); + pCell, sFormulaAddress, sFormula, sFormulaNmsp, eGrammar, sInputString, fValue, nType, nMatrixFlag, nMatrixCols, nMatrixRows ); } else if (IsXMLToken(rLocalName, XML_CELL_ADDRESS)) { @@ -1115,7 +1118,8 @@ ScXMLChangeCellContext::ScXMLChangeCellContext( ScXMLImport& rImport, USHORT nPrfx, const ::rtl::OUString& rLName, const uno::Reference<xml::sax::XAttributeList>& xAttrList, - ScBaseCell*& rTempOldCell, rtl::OUString& rAddress, rtl::OUString& rFormula, + ScBaseCell*& rTempOldCell, rtl::OUString& rAddress, + rtl::OUString& rFormula, rtl::OUString& rFormulaNmsp, formula::FormulaGrammar::Grammar& rGrammar, rtl::OUString& rTempInputString, double& fDateTimeValue, sal_uInt16& nType, sal_uInt8& nMatrixFlag, sal_Int32& nMatrixCols, sal_Int32& nMatrixRows ) : @@ -1130,7 +1134,6 @@ ScXMLChangeCellContext::ScXMLChangeCellContext( ScXMLImport& rImport, bString(sal_True), bFormula(sal_False) { - const formula::FormulaGrammar::Grammar eStorageGrammar = rGrammar = GetScImport().GetDocument()->GetStorageGrammar(); sal_Bool bIsMatrix(sal_False); sal_Bool bIsCoveredMatrix(sal_False); sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0); @@ -1147,12 +1150,7 @@ ScXMLChangeCellContext::ScXMLChangeCellContext( ScXMLImport& rImport, if (IsXMLToken(aLocalName, XML_FORMULA)) { bEmpty = sal_False; - sal_uInt16 nFormulaPrefix = GetImport().GetNamespaceMap(). - _GetKeyByAttrName( sValue, &rFormula, sal_False ); - - if (!ScXMLImport::IsAcceptedFormulaNamespace( nFormulaPrefix, - sValue, rGrammar, eStorageGrammar)) - rFormula = sValue; + GetScImport().ExtractFormulaNamespaceGrammar( rFormula, rFormulaNmsp, rGrammar, sValue ); bFormula = sal_True; } else if (IsXMLToken(aLocalName, XML_CELL_ADDRESS)) @@ -1339,8 +1337,6 @@ ScXMLPreviousContext::ScXMLPreviousContext( ScXMLImport& rImport, const uno::Reference<xml::sax::XAttributeList>& xAttrList, ScXMLChangeTrackingImportHelper* pTempChangeTrackingImportHelper ) : SvXMLImportContext( rImport, nPrfx, rLName ), - sFormulaAddress(), - sFormula(), pChangeTrackingImportHelper(pTempChangeTrackingImportHelper), pOldCell(NULL), nID(0), @@ -1380,7 +1376,7 @@ SvXMLImportContext *ScXMLPreviousContext::CreateChildContext( USHORT nPrefix, if ((nPrefix == XML_NAMESPACE_TABLE) && (IsXMLToken(rLocalName, XML_CHANGE_TRACK_TABLE_CELL))) pContext = new ScXMLChangeCellContext(GetScImport(), nPrefix, rLocalName, xAttrList, - pOldCell, sFormulaAddress, sFormula, eGrammar, sInputString, fValue, nType, nMatrixFlag, nMatrixCols, nMatrixRows); + pOldCell, sFormulaAddress, sFormula, sFormulaNmsp, eGrammar, sInputString, fValue, nType, nMatrixFlag, nMatrixCols, nMatrixRows); if( !pContext ) pContext = new SvXMLImportContext( GetImport(), nPrefix, rLocalName ); diff --git a/sc/source/filter/xml/xmlannoi.cxx b/sc/source/filter/xml/xmlannoi.cxx index 5160b17a1a9d..f8081b7b8f48 100644 --- a/sc/source/filter/xml/xmlannoi.cxx +++ b/sc/source/filter/xml/xmlannoi.cxx @@ -31,13 +31,10 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_sc.hxx" - - // INCLUDE --------------------------------------------------------------- #include "xmlannoi.hxx" #include "xmlimprt.hxx" -#include "xmlcelli.hxx" #include "xmlconti.hxx" #include "XMLTableShapeImportHelper.hxx" @@ -45,25 +42,34 @@ #include <xmloff/nmspmap.hxx> #include <xmloff/xmlnmspe.hxx> #include <xmloff/xmltoken.hxx> -#include <svx/unoshape.hxx> -#include <svx/svdobj.hxx> -#include <svx/outlobj.hxx> using namespace com::sun::star; using namespace xmloff::token; //------------------------------------------------------------------ +ScXMLAnnotationData::ScXMLAnnotationData() : + mbUseShapePos( false ), + mbShown( false ) +{ +} + +ScXMLAnnotationData::~ScXMLAnnotationData() +{ +} + +//------------------------------------------------------------------ + ScXMLAnnotationContext::ScXMLAnnotationContext( ScXMLImport& rImport, USHORT nPrfx, const ::rtl::OUString& rLName, const uno::Reference<xml::sax::XAttributeList>& xAttrList, + ScXMLAnnotationData& rAnnotationData, ScXMLTableRowCellContext* pTempCellContext) : SvXMLImportContext( rImport, nPrfx, rLName ), + mrAnnotationData( rAnnotationData ), nParagraphCount(0), - bDisplay(sal_False), bHasTextP(sal_False), - bHasPos(sal_False), pCellContext(pTempCellContext), pShapeContext(NULL) { @@ -91,32 +97,32 @@ ScXMLAnnotationContext::ScXMLAnnotationContext( ScXMLImport& rImport, { case XML_TOK_TABLE_ANNOTATION_ATTR_AUTHOR: { - sAuthorBuffer = sValue; + maAuthorBuffer = sValue; } break; case XML_TOK_TABLE_ANNOTATION_ATTR_CREATE_DATE: { - sCreateDateBuffer = sValue; + maCreateDateBuffer = sValue; } break; case XML_TOK_TABLE_ANNOTATION_ATTR_CREATE_DATE_STRING: { - sCreateDateStringBuffer = sValue; + maCreateDateStringBuffer = sValue; } break; case XML_TOK_TABLE_ANNOTATION_ATTR_DISPLAY: { - bDisplay = IsXMLToken(sValue, XML_TRUE); + mrAnnotationData.mbShown = IsXMLToken(sValue, XML_TRUE); } break; case XML_TOK_TABLE_ANNOTATION_ATTR_X: { - bHasPos = sal_True; + mrAnnotationData.mbUseShapePos = true; } break; case XML_TOK_TABLE_ANNOTATION_ATTR_Y: { - bHasPos = sal_True; + mrAnnotationData.mbUseShapePos = true; } break; } @@ -144,28 +150,28 @@ SvXMLImportContext *ScXMLAnnotationContext::CreateChildContext( USHORT nPrefix, { if( IsXMLToken( rLName, XML_CREATOR ) ) pContext = new ScXMLContentContext(GetScImport(), nPrefix, - rLName, xAttrList, sAuthorBuffer); + rLName, xAttrList, maAuthorBuffer); else if( IsXMLToken( rLName, XML_DATE ) ) pContext = new ScXMLContentContext(GetScImport(), nPrefix, - rLName, xAttrList, sCreateDateBuffer); + rLName, xAttrList, maCreateDateBuffer); } else if( XML_NAMESPACE_META == nPrefix ) { if( IsXMLToken( rLName, XML_DATE_STRING ) ) pContext = new ScXMLContentContext(GetScImport(), nPrefix, - rLName, xAttrList, sCreateDateStringBuffer); + rLName, xAttrList, maCreateDateStringBuffer); } /* else if ((nPrefix == XML_NAMESPACE_TEXT) && IsXMLToken(rLName, XML_P) ) { if (!bHasTextP) { bHasTextP = sal_True; - sOUText.setLength(0); + maTextBuffer.setLength(0); } if(nParagraphCount) - sOUText.append(static_cast<sal_Unicode>('\n')); + maTextBuffer.append(static_cast<sal_Unicode>('\n')); ++nParagraphCount; - pContext = new ScXMLContentContext( GetScImport(), nPrefix, rLName, xAttrList, sOUText); + pContext = new ScXMLContentContext( GetScImport(), nPrefix, rLName, xAttrList, maTextBuffer); }*/ if( !pContext && pShapeContext ) @@ -180,7 +186,7 @@ SvXMLImportContext *ScXMLAnnotationContext::CreateChildContext( USHORT nPrefix, void ScXMLAnnotationContext::Characters( const ::rtl::OUString& rChars ) { if (!bHasTextP) - sOUText.append(rChars); + maTextBuffer.append(rChars); } void ScXMLAnnotationContext::EndElement() @@ -191,41 +197,19 @@ void ScXMLAnnotationContext::EndElement() delete pShapeContext; } - ScMyImportAnnotation* pMyAnnotation = new ScMyImportAnnotation(); - pMyAnnotation->sAuthor = sAuthorBuffer.makeStringAndClear(); - pMyAnnotation->sCreateDate = sCreateDateBuffer.makeStringAndClear(); - if (!pMyAnnotation->sCreateDate.getLength()) - pMyAnnotation->sCreateDate = sCreateDateStringBuffer.makeStringAndClear(); - pMyAnnotation->sText = sOUText.makeStringAndClear(); - pMyAnnotation->bDisplay = bDisplay; - - if (xShape.is() && xShapes.is()) - { - SvxShape* pShapeImp = SvxShape::getImplementation(xShape); - if (pShapeImp) - { - SdrObject *pSdrObj = pShapeImp->GetSdrObject(); - if (pSdrObj) - { - if (bHasPos) - { - pMyAnnotation->pItemSet = pSdrObj->GetMergedItemSet().Clone(); - awt::Point aPos = xShape->getPosition(); - awt::Size aSize = xShape->getSize(); - Rectangle aRect(Point(aPos.X, aPos.Y), Size(aSize.Width, aSize.Height)); - pMyAnnotation->pRect = new Rectangle(aRect); - } - - if( OutlinerParaObject* pOPO = pSdrObj->GetOutlinerParaObject() ) - pMyAnnotation->pOPO = new OutlinerParaObject( *pOPO ); - - xShapes->remove(xShape); - } - } - } + mrAnnotationData.maAuthor = maAuthorBuffer.makeStringAndClear(); + mrAnnotationData.maCreateDate = maCreateDateBuffer.makeStringAndClear(); + if (!mrAnnotationData.maCreateDate.getLength()) + mrAnnotationData.maCreateDate = maCreateDateStringBuffer.makeStringAndClear(); + mrAnnotationData.maSimpleText = maTextBuffer.makeStringAndClear(); XMLTableShapeImportHelper* pTableShapeImport = (XMLTableShapeImportHelper*)GetScImport().GetShapeImport().get(); pTableShapeImport->SetAnnotation(NULL); +} - pCellContext->AddAnnotation(pMyAnnotation); +void ScXMLAnnotationContext::SetShape( const uno::Reference< drawing::XShape >& rxShape, const uno::Reference< drawing::XShapes >& rxShapes ) +{ + mrAnnotationData.mxShape = rxShape; + mrAnnotationData.mxShapes = rxShapes; } + diff --git a/sc/source/filter/xml/xmlannoi.hxx b/sc/source/filter/xml/xmlannoi.hxx index 3a65d5b444ff..c509b72124ed 100644 --- a/sc/source/filter/xml/xmlannoi.hxx +++ b/sc/source/filter/xml/xmlannoi.hxx @@ -30,6 +30,7 @@ #ifndef SC_XMLANNOI_HXX #define SC_XMLANNOI_HXX +#include <memory> #include <xmloff/xmlictxt.hxx> #include <xmloff/xmlimp.hxx> #include <rtl/ustrbuf.hxx> @@ -39,30 +40,31 @@ class ScXMLImport; class ScXMLTableRowCellContext; -class ScXMLAnnotationContext : public SvXMLImportContext +struct ScXMLAnnotationData { - rtl::OUStringBuffer sOUText; - rtl::OUStringBuffer sAuthorBuffer; - rtl::OUStringBuffer sCreateDateBuffer; - rtl::OUStringBuffer sCreateDateStringBuffer; - sal_Int32 nParagraphCount; - sal_Bool bDisplay; - sal_Bool bHasTextP; - sal_Bool bHasPos; - ScXMLTableRowCellContext* pCellContext; - SvXMLImportContext* pShapeContext; - com::sun::star::uno::Reference< com::sun::star::drawing::XShape > xShape; - com::sun::star::uno::Reference< com::sun::star::drawing::XShapes > xShapes; + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape > + mxShape; + ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes > + mxShapes; + ::rtl::OUString maAuthor; + ::rtl::OUString maCreateDate; + ::rtl::OUString maSimpleText; + bool mbUseShapePos; + bool mbShown; - const ScXMLImport& GetScImport() const { return (const ScXMLImport&)GetImport(); } - ScXMLImport& GetScImport() { return (ScXMLImport&)GetImport(); } + explicit ScXMLAnnotationData(); + ~ScXMLAnnotationData(); +}; +class ScXMLAnnotationContext : public SvXMLImportContext +{ public: ScXMLAnnotationContext( ScXMLImport& rImport, USHORT nPrfx, const ::rtl::OUString& rLName, const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList>& xAttrList, + ScXMLAnnotationData& rAnnotationData, ScXMLTableRowCellContext* pCellContext); virtual ~ScXMLAnnotationContext(); @@ -78,8 +80,23 @@ public: virtual void EndElement(); - void SetShape(const com::sun::star::uno::Reference< com::sun::star::drawing::XShape >& xTempShape, - const com::sun::star::uno::Reference< com::sun::star::drawing::XShapes >& xTempShapes) { xShape.set(xTempShape); xShapes.set(xTempShapes); } + void SetShape( + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& rxShape, + const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShapes >& rxShapes ); + +private: + ScXMLAnnotationData& mrAnnotationData; + rtl::OUStringBuffer maTextBuffer; + rtl::OUStringBuffer maAuthorBuffer; + rtl::OUStringBuffer maCreateDateBuffer; + rtl::OUStringBuffer maCreateDateStringBuffer; + sal_Int32 nParagraphCount; + sal_Bool bHasTextP; + ScXMLTableRowCellContext* pCellContext; + SvXMLImportContext* pShapeContext; + + const ScXMLImport& GetScImport() const { return (const ScXMLImport&)GetImport(); } + ScXMLImport& GetScImport() { return (ScXMLImport&)GetImport(); } }; diff --git a/sc/source/filter/xml/xmlbodyi.cxx b/sc/source/filter/xml/xmlbodyi.cxx index fd9562a9b1fb..048f1ec0c549 100644 --- a/sc/source/filter/xml/xmlbodyi.cxx +++ b/sc/source/filter/xml/xmlbodyi.cxx @@ -52,6 +52,7 @@ #include "XMLTrackedChangesContext.hxx" #include "XMLEmptyContext.hxx" #include "scerrors.hxx" +#include "tabprotection.hxx" #include <xmloff/xmltkmap.hxx> #include <xmloff/xmltoken.hxx> @@ -62,7 +63,10 @@ #include <sal/types.h> #include <tools/debug.hxx> +#include <memory> + using rtl::OUString; + using namespace com::sun::star; using namespace xmloff::token; @@ -281,10 +285,17 @@ void ScXMLBodyContext::EndElement() // #i37959# handle document protection after the sheet settings if (bProtected) { + ::std::auto_ptr<ScDocProtection> pProtection(new ScDocProtection); + pProtection->setProtected(true); + uno::Sequence<sal_Int8> aPass; if (sPassword.getLength()) + { SvXMLUnitConverter::decodeBase64(aPass, sPassword); - pDoc->SetDocProtection(bProtected, aPass); + pProtection->setPasswordHash(aPass, PASSHASH_OOO); + } + + pDoc->SetDocProtection(pProtection.get()); } } GetScImport().UnlockSolarMutex(); diff --git a/sc/source/filter/xml/xmlcelli.cxx b/sc/source/filter/xml/xmlcelli.cxx index 06c84ac83366..f0a4569cc86e 100644 --- a/sc/source/filter/xml/xmlcelli.cxx +++ b/sc/source/filter/xml/xmlcelli.cxx @@ -68,6 +68,7 @@ #include <svx/svdocapt.hxx> #include <svx/outlobj.hxx> #include <svx/editobj.hxx> +#include <svx/unoapi.hxx> #include <svtools/languageoptions.hxx> #include <com/sun/star/frame/XModel.hpp> @@ -99,15 +100,6 @@ using namespace xmloff::token; //------------------------------------------------------------------ -ScMyImportAnnotation::~ScMyImportAnnotation() -{ - delete pRect; - delete pItemSet; - delete pOPO; -} - -//------------------------------------------------------------------ - ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport& rImport, USHORT nPrfx, const ::rtl::OUString& rLName, @@ -117,7 +109,6 @@ ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport& rImport, const sal_Int32 nTempRepeatedRows ) : SvXMLImportContext( rImport, nPrfx, rLName ), pContentValidationName(NULL), - pMyAnnotation(NULL), pDetectiveObjVec(NULL), pCellRangeSource(NULL), fValue(0.0), @@ -138,7 +129,6 @@ ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport& rImport, bSolarMutexLocked(sal_False), bFormulaTextResult(sal_False) { - formula::FormulaGrammar::Grammar eStorageGrammar = eGrammar = GetScImport().GetDocument()->GetStorageGrammar(); rXMLImport.SetRemoveLastChar(sal_False); rXMLImport.GetTables().AddColumn(bTempIsCovered); const sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; @@ -241,25 +231,9 @@ ScXMLTableRowCellContext::ScXMLTableRowCellContext( ScXMLImport& rImport, if (sValue.getLength()) { DBG_ASSERT(!pOUFormula, "here should be only one formula"); - rtl::OUString sFormula; - sal_uInt16 nFormulaPrefix = GetImport().GetNamespaceMap(). - _GetKeyByAttrName( sValue, &sFormula, sal_False ); - - if (ScXMLImport::IsAcceptedFormulaNamespace( - nFormulaPrefix, sValue, eGrammar, - eStorageGrammar)) - { - // Namespaces we accept. - pOUFormula.reset( sFormula); - } - else - { - // No namespace => entire string. - // Also unknown namespace included in formula, - // so hopefully will result in string or - // compile error. - pOUFormula.reset( sValue); - } + rtl::OUString aFormula, aFormulaNmsp; + rXMLImport.ExtractFormulaNamespaceGrammar( aFormula, aFormulaNmsp, eGrammar, sValue ); + pOUFormula.reset( FormulaWithNamespace( aFormula, aFormulaNmsp ) ); } } break; @@ -283,8 +257,6 @@ ScXMLTableRowCellContext::~ScXMLTableRowCellContext() { if (pContentValidationName) delete pContentValidationName; - if (pMyAnnotation) - delete pMyAnnotation; if (pDetectiveObjVec) delete pDetectiveObjVec; if (pCellRangeSource) @@ -425,8 +397,10 @@ SvXMLImportContext *ScXMLTableRowCellContext::CreateChildContext( USHORT nPrefix case XML_TOK_TABLE_ROW_CELL_ANNOTATION: { bIsEmpty = sal_False; + DBG_ASSERT( !mxAnnotationData.get(), "ScXMLTableRowCellContext::CreateChildContext - multiple annotations in one cell" ); + mxAnnotationData.reset( new ScXMLAnnotationData ); pContext = new ScXMLAnnotationContext( rXMLImport, nPrefix, rLName, - xAttrList, this); + xAttrList, *mxAnnotationData, this); } break; case XML_TOK_TABLE_ROW_CELL_DETECTIVE: @@ -539,7 +513,7 @@ void ScXMLTableRowCellContext::SetContentValidation(com::sun::star::uno::Referen if (pContentValidationName) { ScMyImportValidation aValidation; - aValidation.eGrammar = GetScImport().GetDocument()->GetStorageGrammar(); + aValidation.eGrammar1 = aValidation.eGrammar2 = GetScImport().GetDocument()->GetStorageGrammar(); if (rXMLImport.GetValidation(*pContentValidationName, aValidation)) { uno::Reference<beans::XPropertySet> xPropertySet(xPropSet->getPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_VALIXML))), uno::UNO_QUERY); @@ -568,8 +542,11 @@ void ScXMLTableRowCellContext::SetContentValidation(com::sun::star::uno::Referen // #b4974740# source position must be set as string, because it may // refer to a sheet that hasn't been loaded yet. xPropertySet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_SOURCESTR)), uno::makeAny(aValidation.sBaseCellAddress)); - // Transport grammar. - xPropertySet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_GRAMMAR)), uno::makeAny(static_cast<sal_Int32>(aValidation.eGrammar))); + // Transport grammar and formula namespace + xPropertySet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_FORMULANMSP1)), uno::makeAny(aValidation.sFormulaNmsp1)); + xPropertySet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_FORMULANMSP2)), uno::makeAny(aValidation.sFormulaNmsp2)); + xPropertySet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_GRAMMAR1)), uno::makeAny(static_cast<sal_Int32>(aValidation.eGrammar1))); + xPropertySet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_GRAMMAR2)), uno::makeAny(static_cast<sal_Int32>(aValidation.eGrammar2))); } } xPropSet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_VALIXML)), uno::makeAny(xPropertySet)); @@ -607,71 +584,98 @@ void ScXMLTableRowCellContext::SetCellProperties(const uno::Reference<table::XCe void ScXMLTableRowCellContext::SetAnnotation(const table::CellAddress& aCellAddress) { - /*uno::Reference<sheet::XSheetAnnotationAnchor> xSheetAnnotationAnchor(xCell, uno::UNO_QUERY); - if (xSheetAnnotationAnchor.is()) + ScDocument* pDoc = rXMLImport.GetDocument(); + if( !pDoc || !mxAnnotationData.get() ) + return; + + LockSolarMutex(); + + ScAddress aPos; + ScUnoConversion::FillScAddress( aPos, aCellAddress ); + ScPostIt* pNote = 0; + + uno::Reference< drawing::XShapes > xShapes = rXMLImport.GetTables().GetCurrentXShapes(); + uno::Reference< container::XIndexAccess > xShapesIA( xShapes, uno::UNO_QUERY ); + sal_Int32 nOldShapeCount = xShapesIA.is() ? xShapesIA->getCount() : 0; + + DBG_ASSERT( !mxAnnotationData->mxShape.is() || mxAnnotationData->mxShapes.is(), + "ScXMLTableRowCellContext::SetAnnotation - shape without drawing page" ); + if( mxAnnotationData->mxShape.is() && mxAnnotationData->mxShapes.is() ) { - uno::Reference <sheet::XSheetAnnotation> xSheetAnnotation (xSheetAnnotationAnchor->getAnnotation()); - uno::Reference<text::XSimpleText> xSimpleText(xSheetAnnotation, uno::UNO_QUERY); - if (xSheetAnnotation.is() && xSimpleText.is()) + DBG_ASSERT( mxAnnotationData->mxShapes.get() == xShapes.get(), "ScXMLTableRowCellContext::SetAnnotation - diffenet drawing pages" ); + SdrObject* pObject = ::GetSdrObjectFromXShape( mxAnnotationData->mxShape ); + DBG_ASSERT( pObject, "ScXMLTableRowCellContext::SetAnnotation - cannot get SdrObject from shape" ); + + /* Try to reuse the drawing object already created (but only if the + note is visible, and the object is a caption object). */ + if( mxAnnotationData->mbShown && mxAnnotationData->mbUseShapePos ) { - xSimpleText->setString(aMyAnnotation.sText); - //xSheetAnnotation->setAuthor(aMyAnnotation.sAuthor); - //xSheetAnnotation->setDate(); - xSheetAnnotation->setIsVisible(aMyAnnotation.bDisplay); + if( SdrCaptionObj* pCaption = dynamic_cast< SdrCaptionObj* >( pObject ) ) + { + OSL_ENSURE( !pCaption->GetLogicRect().IsEmpty(), "ScXMLTableRowCellContext::SetAnnotation - invalid caption rectangle" ); + // create the cell note with the caption object + pNote = ScNoteUtil::CreateNoteFromCaption( *pDoc, aPos, *pCaption, true ); + // forget pointer to object (do not create note again below) + pObject = 0; + } } - }*/ - if( pMyAnnotation ) - { - double fDate; - rXMLImport.GetMM100UnitConverter().convertDateTime(fDate, pMyAnnotation->sCreateDate); - ScDocument* pDoc = rXMLImport.GetDocument(); - if (pDoc) + + // drawing object has not been used to create a note -> use shape data + if( pObject ) { - LockSolarMutex(); - SvNumberFormatter* pNumForm = pDoc->GetFormatTable(); - sal_uInt32 nfIndex = pNumForm->GetFormatIndex(NF_DATE_SYS_DDMMYYYY, LANGUAGE_SYSTEM); - String sDate; - Color* pColor = NULL; - Color** ppColor = &pColor; - pNumForm->GetOutputString(fDate, nfIndex, sDate, ppColor); + // rescue settings from drawing object before the shape is removed + ::std::auto_ptr< SfxItemSet > xItemSet( new SfxItemSet( pObject->GetMergedItemSet() ) ); + ::std::auto_ptr< OutlinerParaObject > xOutlinerObj; + if( OutlinerParaObject* pOutlinerObj = pObject->GetOutlinerParaObject() ) + xOutlinerObj.reset( new OutlinerParaObject( *pOutlinerObj ) ); + Rectangle aCaptionRect; + if( mxAnnotationData->mbUseShapePos ) + aCaptionRect = pObject->GetLogicRect(); + // remove the shape from the drawing page, this invalidates pObject + mxAnnotationData->mxShapes->remove( mxAnnotationData->mxShape ); + pObject = 0; + // update current number of existing objects + if( xShapesIA.is() ) + nOldShapeCount = xShapesIA->getCount(); - ScAddress aPos; - ScUnoConversion::FillScAddress( aPos, aCellAddress ); - if( ScPostIt* pNote = pDoc->GetOrCreateNote( aPos ) ) + // an outliner object is required (empty note captions not allowed) + if( xOutlinerObj.get() ) { - pNote->SetDate( sDate ); - pNote->SetAuthor( pMyAnnotation->sAuthor ); - if( SdrCaptionObj* pCaption = pNote->GetCaption() ) - { - if( pMyAnnotation->pOPO ) - { - // transfer outliner object to caption - pCaption->SetOutlinerParaObject( pMyAnnotation->pOPO ); - // do not delete the object in ScMyImportAnnotation d'tor - pMyAnnotation->pOPO = 0; - } - else - pCaption->SetText( pMyAnnotation->sText ); - // copy all items and reset shadow items - if( pMyAnnotation->pItemSet ) - pNote->SetCaptionItems( *pMyAnnotation->pItemSet ); - else - pNote->SetCaptionDefaultItems(); // default items need to be applied to text - if( pMyAnnotation->pRect ) - pCaption->SetLogicRect( *pMyAnnotation->pRect ); - - uno::Reference<container::XIndexAccess> xShapesIndex (rXMLImport.GetTables().GetCurrentXShapes(), uno::UNO_QUERY); // make draw page - if (xShapesIndex.is()) - { - sal_Int32 nShapes = xShapesIndex->getCount(); - uno::Reference < drawing::XShape > xShape; - rXMLImport.GetShapeImport()->shapeWithZIndexAdded(xShape, nShapes); - } - } - pNote->ShowCaption( pMyAnnotation->bDisplay ); + // create cell note with all data from drawing object + pNote = ScNoteUtil::CreateNoteFromObjectData( *pDoc, aPos, + xItemSet.release(), xOutlinerObj.release(), + aCaptionRect, mxAnnotationData->mbShown, false ); } } } + else if( mxAnnotationData->maSimpleText.getLength() > 0 ) + { + // create note from simple text + pNote = ScNoteUtil::CreateNoteFromString( *pDoc, aPos, + mxAnnotationData->maSimpleText, mxAnnotationData->mbShown, false ); + } + + // set author and date + if( pNote ) + { + double fDate; + rXMLImport.GetMM100UnitConverter().convertDateTime( fDate, mxAnnotationData->maCreateDate ); + SvNumberFormatter* pNumForm = pDoc->GetFormatTable(); + sal_uInt32 nfIndex = pNumForm->GetFormatIndex( NF_DATE_SYS_DDMMYYYY, LANGUAGE_SYSTEM ); + String aDate; + Color* pColor = 0; + Color** ppColor = &pColor; + pNumForm->GetOutputString( fDate, nfIndex, aDate, ppColor ); + pNote->SetDate( aDate ); + pNote->SetAuthor( mxAnnotationData->maAuthor ); + } + + // register a shape that has been newly created in the ScNoteUtil functions + if( xShapesIA.is() && (nOldShapeCount < xShapesIA->getCount()) ) + { + uno::Reference< drawing::XShape > xShape; + rXMLImport.GetShapeImport()->shapeWithZIndexAdded( xShape, xShapesIA->getCount() ); + } } // core implementation @@ -798,7 +802,7 @@ void ScXMLTableRowCellContext::EndElement() // uno::Reference <table::XCell> xCell; table::CellAddress aCurrentPos( aCellPos ); if ((pContentValidationName && pContentValidationName->getLength()) || - pMyAnnotation || pDetectiveObjVec || pCellRangeSource) + mxAnnotationData.get() || pDetectiveObjVec || pCellRangeSource) bIsEmpty = sal_False; ScMyTables& rTables = rXMLImport.GetTables(); @@ -980,7 +984,7 @@ void ScXMLTableRowCellContext::EndElement() } else { - if (!bWasEmpty || (pMyAnnotation)) + if (!bWasEmpty || mxAnnotationData.get()) { if (aCurrentPos.Row > MAXROW) rXMLImport.SetRangeOverflowType(SCWARN_IMPORT_ROW_OVERFLOW); @@ -1028,7 +1032,7 @@ void ScXMLTableRowCellContext::EndElement() //SetType(xTempCell); } } - else + else // if ( !pOUFormula ) { if (CellExists(aCellPos)) { @@ -1041,7 +1045,7 @@ void ScXMLTableRowCellContext::EndElement() { DBG_ERRORFILE("It seems here are to many columns or rows"); } - if (xCell.is() && pOUFormula) + if (xCell.is()) { SetCellProperties(xCell); // set now only the validation DBG_ASSERT(((nCellsRepeated == 1) && (nRepeatedRows == 1)), "repeated cells with formula not possible now"); @@ -1054,7 +1058,7 @@ void ScXMLTableRowCellContext::EndElement() xCell)); if (pCellObj) { - pCellObj->SetFormulaWithGrammar( *pOUFormula, eGrammar); + pCellObj->SetFormulaWithGrammar( pOUFormula->first, pOUFormula->second, eGrammar); if (bFormulaTextResult && pOUTextValue && pOUTextValue->getLength()) pCellObj->SetFormulaResultString( *pOUTextValue); else if (fValue != 0.0) @@ -1069,7 +1073,7 @@ void ScXMLTableRowCellContext::EndElement() aCellPos.Column, aCellPos.Row, aCellPos.Column + nMatrixCols - 1, aCellPos.Row + nMatrixRows - 1, - *pOUFormula, eGrammar); + pOUFormula->first, pOUFormula->second, eGrammar); } } SetAnnotation( aCellPos ); @@ -1086,7 +1090,7 @@ void ScXMLTableRowCellContext::EndElement() rXMLImport.SetRangeOverflowType(SCWARN_IMPORT_COLUMN_OVERFLOW); } - } + } // if ( !pOUFormula ) } UnlockSolarMutex(); } diff --git a/sc/source/filter/xml/xmlcelli.hxx b/sc/source/filter/xml/xmlcelli.hxx index 67b619a15ed3..fe2bfd116348 100644 --- a/sc/source/filter/xml/xmlcelli.hxx +++ b/sc/source/filter/xml/xmlcelli.hxx @@ -30,6 +30,7 @@ #ifndef SC_XMLCELLI_HXX #define SC_XMLCELLI_HXX +#include <memory> #include "XMLDetectiveContext.hxx" #include "XMLCellRangeSourceContext.hxx" #include <xmloff/xmlictxt.hxx> @@ -37,7 +38,6 @@ #include <com/sun/star/table/XCell.hpp> #include <tools/time.hxx> #include <com/sun/star/util/DateTime.hpp> -#include <sal/types.h> #include <com/sun/star/table/XCellRange.hpp> #include <com/sun/star/table/CellRangeAddress.hpp> #include <com/sun/star/table/CellAddress.hpp> @@ -48,31 +48,18 @@ #include <boost/optional.hpp> class ScXMLImport; -class OutlinerParaObject; - -struct ScMyImportAnnotation -{ - rtl::OUString sAuthor; - rtl::OUString sCreateDate; - rtl::OUString sText; - sal_Bool bDisplay; - Rectangle* pRect; - SfxItemSet* pItemSet; - OutlinerParaObject* pOPO; - - ScMyImportAnnotation() : bDisplay(sal_False), pRect(NULL), pItemSet(NULL), pOPO(NULL) {} - ~ScMyImportAnnotation(); -}; +struct ScXMLAnnotationData; class ScXMLTableRowCellContext : public SvXMLImportContext { + typedef ::std::pair< ::rtl::OUString, ::rtl::OUString > FormulaWithNamespace; com::sun::star::uno::Reference<com::sun::star::table::XCell> xBaseCell; com::sun::star::uno::Reference<com::sun::star::document::XActionLockable> xLockable; ::boost::optional< rtl::OUString > pOUTextValue; ::boost::optional< rtl::OUString > pOUTextContent; - ::boost::optional< rtl::OUString > pOUFormula; + ::boost::optional< FormulaWithNamespace > pOUFormula; rtl::OUString* pContentValidationName; - ScMyImportAnnotation* pMyAnnotation; + ::std::auto_ptr< ScXMLAnnotationData > mxAnnotationData; ScMyImpDetectiveObjVec* pDetectiveObjVec; ScMyImpCellRangeSource* pCellRangeSource; double fValue; @@ -140,8 +127,6 @@ public: void SetCellRangeSource( const ::com::sun::star::table::CellAddress& rPosition ); virtual void EndElement(); - - void AddAnnotation(ScMyImportAnnotation* pValue) { pMyAnnotation = pValue; } }; #endif diff --git a/sc/source/filter/xml/xmlcvali.cxx b/sc/source/filter/xml/xmlcvali.cxx index d8d8eb0d7cc2..aeff28f3eed6 100644 --- a/sc/source/filter/xml/xmlcvali.cxx +++ b/sc/source/filter/xml/xmlcvali.cxx @@ -51,6 +51,8 @@ using namespace com::sun::star; using namespace xmloff::token; +using namespace ::formula; +using ::rtl::OUString; class ScXMLContentValidationContext : public SvXMLImportContext { @@ -62,7 +64,6 @@ class ScXMLContentValidationContext : public SvXMLImportContext rtl::OUString sErrorMessageType; rtl::OUString sBaseCellAddress; rtl::OUString sCondition; - formula::FormulaGrammar::Grammar eGrammar; sal_Int16 nShowList; sal_Bool bAllowEmptyCell; sal_Bool bDisplayHelp; @@ -73,11 +74,10 @@ class ScXMLContentValidationContext : public SvXMLImportContext const ScXMLImport& GetScImport() const { return (const ScXMLImport&)GetImport(); } ScXMLImport& GetScImport() { return (ScXMLImport&)GetImport(); } - void GetAlertStyle(const rtl::OUString& sMessageType, com::sun::star::sheet::ValidationAlertStyle& aAlertStyle); - void SetFormulas(const rtl::OUString& sFormulas, rtl::OUString& sFormula1, rtl::OUString& sFormula2) const; - void GetCondition(const rtl::OUString& sCondition, rtl::OUString& sFormula1, rtl::OUString& sFormula2, - com::sun::star::sheet::ValidationType& aValidationType, - com::sun::star::sheet::ConditionOperator& aOperator); + com::sun::star::sheet::ValidationAlertStyle GetAlertStyle() const; + void SetFormula( OUString& rFormula, OUString& rFormulaNmsp, FormulaGrammar::Grammar& reGrammar, + const OUString& rCondition, const OUString& rGlobNmsp, FormulaGrammar::Grammar eGlobGrammar, bool bHasNmsp ) const; + void GetCondition( ScMyImportValidation& rValidation ) const; public: @@ -235,20 +235,11 @@ ScXMLContentValidationContext::ScXMLContentValidationContext( ScXMLImport& rImpo const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList>& xAttrList) : SvXMLImportContext( rImport, nPrfx, rLName ), - sName(), - sHelpTitle(), - sHelpMessage(), - sErrorTitle(), - sErrorMessage(), - sErrorMessageType(), - sBaseCellAddress(), - sCondition(), nShowList(sheet::TableValidationVisibility::UNSORTED), bAllowEmptyCell(sal_True), bDisplayHelp(sal_False), bDisplayError(sal_False) { - const formula::FormulaGrammar::Grammar eStorageGrammar = eGrammar = GetScImport().GetDocument()->GetStorageGrammar(); sal_Int16 nAttrCount = xAttrList.is() ? xAttrList->getLength() : 0; const SvXMLTokenMap& rAttrTokenMap = GetScImport().GetContentValidationAttrTokenMap(); for( sal_Int16 i=0; i < nAttrCount; ++i ) @@ -265,14 +256,7 @@ ScXMLContentValidationContext::ScXMLContentValidationContext( ScXMLImport& rImpo sName = sValue; break; case XML_TOK_CONTENT_VALIDATION_CONDITION: - { - sal_uInt16 nCondPrefix = GetImport().GetNamespaceMap(). - _GetKeyByAttrName( sValue, &sCondition, sal_False ); - - if (!ScXMLImport::IsAcceptedFormulaNamespace( nCondPrefix, - sValue, eGrammar, eStorageGrammar)) - sCondition = sValue; - } + sCondition = sValue; break; case XML_TOK_CONTENT_VALIDATION_BASE_CELL_ADDRESS: sBaseCellAddress = sValue; @@ -336,189 +320,116 @@ SvXMLImportContext *ScXMLContentValidationContext::CreateChildContext( USHORT nP return pContext; } -void ScXMLContentValidationContext::GetAlertStyle(const rtl::OUString& sMessageType, com::sun::star::sheet::ValidationAlertStyle& aAlertStyle) +sheet::ValidationAlertStyle ScXMLContentValidationContext::GetAlertStyle() const { - if (IsXMLToken(sMessageType, XML_MACRO)) - aAlertStyle = sheet::ValidationAlertStyle_MACRO; - else if (IsXMLToken(sMessageType, XML_STOP)) - aAlertStyle = sheet::ValidationAlertStyle_STOP; - else if (IsXMLToken(sMessageType, XML_WARNING)) - aAlertStyle = sheet::ValidationAlertStyle_WARNING; - else if (IsXMLToken(sMessageType, XML_INFORMATION)) - aAlertStyle = sheet::ValidationAlertStyle_INFO; - else // don't leave uninitialized - aAlertStyle = sheet::ValidationAlertStyle_STOP; + if (IsXMLToken(sErrorMessageType, XML_MACRO)) + return sheet::ValidationAlertStyle_MACRO; + if (IsXMLToken(sErrorMessageType, XML_STOP)) + return sheet::ValidationAlertStyle_STOP; + if (IsXMLToken(sErrorMessageType, XML_WARNING)) + return sheet::ValidationAlertStyle_WARNING; + if (IsXMLToken(sErrorMessageType, XML_INFORMATION)) + return sheet::ValidationAlertStyle_INFO; + // default for unknown + return sheet::ValidationAlertStyle_STOP; } -void ScXMLContentValidationContext::SetFormulas(const rtl::OUString& sFormulas, rtl::OUString& sFormula1, rtl::OUString& sFormula2) const +void ScXMLContentValidationContext::SetFormula( OUString& rFormula, OUString& rFormulaNmsp, FormulaGrammar::Grammar& reGrammar, + const OUString& rCondition, const OUString& rGlobNmsp, FormulaGrammar::Grammar eGlobGrammar, bool bHasNmsp ) const { - sal_Int32 i = 0; - sal_Bool bString = sal_False; - sal_Int32 nBrakes = 0; - while ((sFormulas[i] != ',' || nBrakes > 0 || bString) && i < sFormulas.getLength()) + reGrammar = FormulaGrammar::GRAM_UNSPECIFIED; + if( bHasNmsp ) { - if (sFormulas[i] == '(') - ++nBrakes; - if (sFormulas[i] == ')') - --nBrakes; - if (sFormulas[i] == '"') - bString = !bString; - ++i; + // the entire attribute contains a namespace: internal namespace not allowed + rFormula = rCondition; + rFormulaNmsp = rGlobNmsp; + reGrammar = eGlobGrammar; } - if (sFormulas[i] == ',') + else { - sFormula1 = sFormulas.copy(0, i); - sFormula2 = sFormulas.copy(i + 1); + // the attribute does not contain a namespace: try to find a namespace of an external grammar + GetScImport().ExtractFormulaNamespaceGrammar( rFormula, rFormulaNmsp, reGrammar, rCondition, true ); + if( reGrammar != FormulaGrammar::GRAM_EXTERNAL ) + reGrammar = eGlobGrammar; } } -void ScXMLContentValidationContext::GetCondition(const rtl::OUString& sTempCondition, rtl::OUString& sFormula1, rtl::OUString& sFormula2, - com::sun::star::sheet::ValidationType& aValidationType, - com::sun::star::sheet::ConditionOperator& aOperator) +void ScXMLContentValidationContext::GetCondition( ScMyImportValidation& rValidation ) const { - aValidationType = sheet::ValidationType_ANY; // #b6343997# default if no condition is given - aOperator = sheet::ConditionOperator_NONE; + rValidation.aValidationType = sheet::ValidationType_ANY; // #b6343997# default if no condition is given + rValidation.aOperator = sheet::ConditionOperator_NONE; - rtl::OUString sLocalCondition(sTempCondition); - if (sLocalCondition.getLength()) + if( sCondition.getLength() > 0 ) { - // ToDo: erase all blanks in the condition, but not in formulas or strings - rtl::OUString scell_content(RTL_CONSTASCII_USTRINGPARAM("cell_content")); - rtl::OUString scell_content_is_date(RTL_CONSTASCII_USTRINGPARAM("cell-content-is-date")); - rtl::OUString scell_content_is_time(RTL_CONSTASCII_USTRINGPARAM("cell-content-is-time")); - rtl::OUString scell_content_is_between(RTL_CONSTASCII_USTRINGPARAM("cell-content-is-between")); - rtl::OUString scell_content_is_in_list(RTL_CONSTASCII_USTRINGPARAM("cell-content-is-in-list")); - rtl::OUString scell_content_text_length(RTL_CONSTASCII_USTRINGPARAM("cell-content-text-length")); - rtl::OUString scell_content_is_not_between(RTL_CONSTASCII_USTRINGPARAM("cell-content-is-not-between")); - rtl::OUString scell_content_is_whole_number(RTL_CONSTASCII_USTRINGPARAM("cell-content-is-whole-number")); - rtl::OUString scell_content_is_decimal_number(RTL_CONSTASCII_USTRINGPARAM("cell-content-is-decimal-number")); - rtl::OUString scell_content_text_length_is_between(RTL_CONSTASCII_USTRINGPARAM("cell-content-text-length-is-between")); - rtl::OUString scell_content_text_length_is_not_between(RTL_CONSTASCII_USTRINGPARAM("cell-content-text-length-is-not-between")); - sal_Int32 i = 0; - sal_Bool bAnd(sal_True); - while (sLocalCondition[i] != '(' && i < sLocalCondition.getLength()) - ++i; - if (sLocalCondition[i] == '(') + // extract leading namespace from condition string + OUString aCondition, aConditionNmsp; + FormulaGrammar::Grammar eGrammar = FormulaGrammar::GRAM_UNSPECIFIED; + GetScImport().ExtractFormulaNamespaceGrammar( aCondition, aConditionNmsp, eGrammar, sCondition ); + bool bHasNmsp = aCondition.getLength() < sCondition.getLength(); + + // parse a condition from the attribute string + ScXMLConditionParseResult aParseResult; + ScXMLConditionHelper::parseCondition( aParseResult, aCondition, 0 ); + + /* Check the result. A valid value in aParseResult.meToken implies + that the other members of aParseResult are filled with valid data + for that token. */ + bool bSecondaryPart = false; + switch( aParseResult.meToken ) { - if (i != scell_content_text_length.getLength() && - i != scell_content_text_length_is_between.getLength() && - i != scell_content_text_length_is_not_between.getLength() && - i != scell_content_is_in_list.getLength()) - { - if (i == scell_content_is_time.getLength()) - { - rtl::OUString sTemp = sLocalCondition.copy(0, i); - if (sTemp == scell_content_is_time) - aValidationType = sheet::ValidationType_TIME; - else - aValidationType = sheet::ValidationType_DATE; - } - else if (i == scell_content_is_whole_number.getLength()) - aValidationType = sheet::ValidationType_WHOLE; - else if (i == scell_content_is_decimal_number.getLength()) - aValidationType = sheet::ValidationType_DECIMAL; - sLocalCondition = sLocalCondition.copy(i + 2); - rtl::OUString sTemp = sLocalCondition.copy(0, 5); - if (sTemp.compareToAscii(" and ") == 0) - sLocalCondition = sLocalCondition.copy(5); - else - bAnd = sal_False; - } - if (sLocalCondition.getLength() && bAnd) + case XML_COND_TEXTLENGTH: // condition is 'cell-content-text-length()<operator><expression>' + case XML_COND_TEXTLENGTH_ISBETWEEN: // condition is 'cell-content-text-length-is-between(<expression1>,<expression2>)' + case XML_COND_TEXTLENGTH_ISNOTBETWEEN: // condition is 'cell-content-text-length-is-not-between(<expression1>,<expression2>)' + case XML_COND_ISINLIST: // condition is 'cell-content-is-in-list(<expression>)' + rValidation.aValidationType = aParseResult.meValidation; + rValidation.aOperator = aParseResult.meOperator; + break; + + case XML_COND_ISWHOLENUMBER: // condition is 'cell-content-is-whole-number() and <condition>' + case XML_COND_ISDECIMALNUMBER: // condition is 'cell-content-is-decimal-number() and <condition>' + case XML_COND_ISDATE: // condition is 'cell-content-is-date() and <condition>' + case XML_COND_ISTIME: // condition is 'cell-content-is-time() and <condition>' + rValidation.aValidationType = aParseResult.meValidation; + bSecondaryPart = true; + break; + + default:; // unacceptable or unknown condition + } + + /* Parse the following 'and <condition>' part of some conditions. This + updates the members of aParseResult that will contain the operands + and comparison operator then. */ + if( bSecondaryPart ) + { + ScXMLConditionHelper::parseCondition( aParseResult, aCondition, aParseResult.mnEndIndex ); + if( aParseResult.meToken == XML_COND_AND ) { - i = 0; - while (sLocalCondition[i] != '(' && i < sLocalCondition.getLength()) - ++i; - if (sLocalCondition[i] == '(') + ScXMLConditionHelper::parseCondition( aParseResult, aCondition, aParseResult.mnEndIndex ); + switch( aParseResult.meToken ) { - rtl::OUString sTemp = sLocalCondition.copy(0, i); - sLocalCondition = sLocalCondition.copy(i + 1); - if (i == scell_content_is_between.getLength() || - i == scell_content_text_length_is_between.getLength()) - { - if (sTemp == scell_content_is_in_list) - { - aValidationType = sheet::ValidationType_LIST; - sFormula1 = sLocalCondition.copy(0, sLocalCondition.getLength() - 1); - aOperator = sheet::ConditionOperator_EQUAL; - } - else - { - if (i == scell_content_text_length_is_between.getLength()) - aValidationType = sheet::ValidationType_TEXT_LEN; - aOperator = sheet::ConditionOperator_BETWEEN; - sLocalCondition = sLocalCondition.copy(0, sLocalCondition.getLength() - 1); - SetFormulas(sLocalCondition, sFormula1, sFormula2); - } - } - else if (i == scell_content_is_not_between.getLength() || - i == scell_content_text_length_is_not_between.getLength()) - { - if (i == scell_content_text_length_is_not_between.getLength()) - aValidationType = sheet::ValidationType_TEXT_LEN; - aOperator = sheet::ConditionOperator_NOT_BETWEEN; - sLocalCondition = sLocalCondition.copy(0, sLocalCondition.getLength() - 1); - SetFormulas(sLocalCondition, sFormula1, sFormula2); - } - else if (i == scell_content.getLength() || - i == scell_content_text_length.getLength()) - { - if (i == scell_content_text_length.getLength()) - aValidationType = sheet::ValidationType_TEXT_LEN; - sLocalCondition = sLocalCondition.copy(1); - switch (sLocalCondition[0]) - { - case '<' : - { - if (sLocalCondition[1] == '=') - { - aOperator = sheet::ConditionOperator_LESS_EQUAL; - sLocalCondition = sLocalCondition.copy(2); - } - else - { - aOperator = sheet::ConditionOperator_LESS; - sLocalCondition = sLocalCondition.copy(1); - } - } - break; - case '>' : - { - if (sLocalCondition[1] == '=') - { - aOperator = sheet::ConditionOperator_GREATER_EQUAL; - sLocalCondition = sLocalCondition.copy(2); - } - else - { - aOperator = sheet::ConditionOperator_GREATER; - sLocalCondition = sLocalCondition.copy(1); - } - } - break; - case '=' : - { - aOperator = sheet::ConditionOperator_EQUAL; - sLocalCondition = sLocalCondition.copy(1); - } - break; - case '!' : - { - aOperator = sheet::ConditionOperator_NOT_EQUAL; - sLocalCondition = sLocalCondition.copy(1); - } - break; - } - sFormula1 = sLocalCondition; - } + case XML_COND_CELLCONTENT: // condition is 'and cell-content()<operator><expression>' + case XML_COND_ISBETWEEN: // condition is 'and cell-content-is-between(<expression1>,<expression2>)' + case XML_COND_ISNOTBETWEEN: // condition is 'and cell-content-is-not-between(<expression1>,<expression2>)' + rValidation.aOperator = aParseResult.meOperator; + break; + default:; // unacceptable or unknown condition } } } - } - // a validation type (date, integer) without a condition isn't possible - if ( aOperator == sheet::ConditionOperator_NONE ) - aValidationType = sheet::ValidationType_ANY; + // a validation type (date, integer) without a condition isn't possible + if( rValidation.aOperator == sheet::ConditionOperator_NONE ) + rValidation.aValidationType = sheet::ValidationType_ANY; + + // parse the formulas + if( rValidation.aValidationType != sheet::ValidationType_ANY ) + { + SetFormula( rValidation.sFormula1, rValidation.sFormulaNmsp1, rValidation.eGrammar1, + aParseResult.maOperand1, aConditionNmsp, eGrammar, bHasNmsp ); + SetFormula( rValidation.sFormula2, rValidation.sFormulaNmsp2, rValidation.eGrammar2, + aParseResult.maOperand2, aConditionNmsp, eGrammar, bHasNmsp ); + } + } } void ScXMLContentValidationContext::EndElement() @@ -546,15 +457,15 @@ void ScXMLContentValidationContext::EndElement() } ScMyImportValidation aValidation; - aValidation.eGrammar = eGrammar; + aValidation.eGrammar1 = aValidation.eGrammar2 = GetScImport().GetDocument()->GetStorageGrammar(); aValidation.sName = sName; aValidation.sBaseCellAddress = sBaseCellAddress; aValidation.sImputTitle = sHelpTitle; aValidation.sImputMessage = sHelpMessage; aValidation.sErrorTitle = sErrorTitle; aValidation.sErrorMessage = sErrorMessage; - GetCondition(sCondition, aValidation.sFormula1, aValidation.sFormula2, aValidation.aValidationType, aValidation.aOperator); - GetAlertStyle(sErrorMessageType, aValidation.aAlertStyle); + GetCondition( aValidation ); + aValidation.aAlertStyle = GetAlertStyle(); aValidation.bShowErrorMessage = bDisplayError; aValidation.bShowImputMessage = bDisplayHelp; aValidation.bIgnoreBlanks = bAllowEmptyCell; diff --git a/sc/source/filter/xml/xmldrani.cxx b/sc/source/filter/xml/xmldrani.cxx index e2aa6fcd7504..55a1859211d0 100644 --- a/sc/source/filter/xml/xmldrani.cxx +++ b/sc/source/filter/xml/xmldrani.cxx @@ -381,7 +381,8 @@ void ScXMLDatabaseRangeContext::EndElement() pDBData->SetSortParam(aSortParam); } - uno::Reference <sheet::XSheetFilterDescriptor> xSheetFilterDescriptor(xDatabaseRange->getFilterDescriptor()); + uno::Reference< sheet::XSheetFilterDescriptor2 > xSheetFilterDescriptor( + xDatabaseRange->getFilterDescriptor(), uno::UNO_QUERY ); if (xSheetFilterDescriptor.is()) { uno::Reference <beans::XPropertySet> xFilterPropertySet (xSheetFilterDescriptor, uno::UNO_QUERY); @@ -396,7 +397,7 @@ void ScXMLDatabaseRangeContext::EndElement() xFilterPropertySet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_USEREGEX)), uno::makeAny(bFilterUseRegularExpressions)); xFilterPropertySet->setPropertyValue(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_OUTPOS)), uno::makeAny(aFilterOutputPosition)); } - xSheetFilterDescriptor->setFilterFields(aFilterFields); + xSheetFilterDescriptor->setFilterFields2(aFilterFields); if (bFilterConditionSourceRange) { ScRange aAdvSource; diff --git a/sc/source/filter/xml/xmldrani.hxx b/sc/source/filter/xml/xmldrani.hxx index 36c668b0f77f..be55e5b143cc 100644 --- a/sc/source/filter/xml/xmldrani.hxx +++ b/sc/source/filter/xml/xmldrani.hxx @@ -36,7 +36,7 @@ #include <com/sun/star/sheet/SubTotalColumn.hpp> #include <com/sun/star/beans/XPropertySet.hpp> #include <com/sun/star/beans/PropertyValue.hpp> -#include <com/sun/star/sheet/TableFilterField.hpp> +#include <com/sun/star/sheet/TableFilterField2.hpp> #include <com/sun/star/table/CellAddress.hpp> #include <com/sun/star/table/CellRangeAddress.hpp> #include <com/sun/star/table/TableOrientation.hpp> @@ -79,7 +79,7 @@ class ScXMLDatabaseRangeContext : public SvXMLImportContext rtl::OUString sDatabaseName; rtl::OUString sSourceObject; com::sun::star::uno::Sequence <com::sun::star::beans::PropertyValue> aSortSequence; - com::sun::star::uno::Sequence <com::sun::star::sheet::TableFilterField> aFilterFields; + com::sun::star::uno::Sequence <com::sun::star::sheet::TableFilterField2> aFilterFields; std::vector < ScSubTotalRule > aSubTotalRules; com::sun::star::table::CellAddress aFilterOutputPosition; com::sun::star::table::CellRangeAddress aFilterConditionSourceRangeAddress; @@ -146,7 +146,7 @@ public: void SetFilterIsCaseSensitive(const sal_Bool bTemp) { bFilterIsCaseSensitive = bTemp; } void SetFilterSkipDuplicates(const sal_Bool bTemp) { bFilterSkipDuplicates = bTemp; } void SetFilterUseRegularExpressions(const sal_Bool bTemp) { bFilterUseRegularExpressions = bTemp; } - void SetFilterFields(const com::sun::star::uno::Sequence <com::sun::star::sheet::TableFilterField>& aTemp) { aFilterFields = aTemp; } + void SetFilterFields(const com::sun::star::uno::Sequence <com::sun::star::sheet::TableFilterField2>& aTemp) { aFilterFields = aTemp; } void SetFilterOutputPosition(const com::sun::star::table::CellAddress& aTemp) { aFilterOutputPosition = aTemp; } void SetFilterConditionSourceRangeAddress(const com::sun::star::table::CellRangeAddress& aTemp) { aFilterConditionSourceRangeAddress = aTemp; bFilterConditionSourceRange = sal_True; } diff --git a/sc/source/filter/xml/xmlexprt.cxx b/sc/source/filter/xml/xmlexprt.cxx index 7d95e92c2891..98965cba07bc 100644 --- a/sc/source/filter/xml/xmlexprt.cxx +++ b/sc/source/filter/xml/xmlexprt.cxx @@ -69,6 +69,7 @@ #include "postit.hxx" #include "externalrefmgr.hxx" #include "editutil.hxx" +#include "tabprotection.hxx" #include <xmloff/xmltoken.hxx> #include <xmloff/xmlnmspe.hxx> @@ -595,6 +596,7 @@ void ScXMLExport::CollectSharedData(sal_Int32& nTableCount, sal_Int32& nShapesCo if (!pSharedData) CreateSharedData(nTableCount); pCellStyles->AddNewTable(nTableCount - 1); + pDoc->InitializeAllNoteCaptions( true ); if (HasDrawPages(xSpreadDoc)) { rtl::OUString sCaptionPoint( RTL_CONSTASCII_USTRINGPARAM( "CaptionPoint" )); @@ -1469,7 +1471,11 @@ void ScXMLExport::SetBodyAttributes() { AddAttribute(XML_NAMESPACE_TABLE, XML_STRUCTURE_PROTECTED, XML_TRUE); rtl::OUStringBuffer aBuffer; - SvXMLUnitConverter::encodeBase64(aBuffer, pDoc->GetDocPassword()); + uno::Sequence<sal_Int8> aPassHash; + const ScDocProtection* p = pDoc->GetDocProtection(); + if (p) + aPassHash = p->getPasswordHash(PASSHASH_OOO); + SvXMLUnitConverter::encodeBase64(aBuffer, aPassHash); if (aBuffer.getLength()) AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear()); } @@ -1543,7 +1549,11 @@ void ScXMLExport::_ExportContent() AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTED, XML_TRUE); rtl::OUStringBuffer aBuffer; if (pDoc) - SvXMLUnitConverter::encodeBase64(aBuffer, pDoc->GetTabPassword(static_cast<SCTAB>(nTable))); + { + ScTableProtection* pProtect = pDoc->GetTabProtection(static_cast<SCTAB>(nTable)); + if (pProtect) + SvXMLUnitConverter::encodeBase64(aBuffer, pProtect->getPasswordHash(PASSHASH_OOO)); + } if (aBuffer.getLength()) AddAttribute(XML_NAMESPACE_TABLE, XML_PROTECTION_KEY, aBuffer.makeStringAndClear()); } diff --git a/sc/source/filter/xml/xmlfilti.cxx b/sc/source/filter/xml/xmlfilti.cxx index 59d53542535a..87bdc748906c 100644 --- a/sc/source/filter/xml/xmlfilti.cxx +++ b/sc/source/filter/xml/xmlfilti.cxx @@ -335,48 +335,60 @@ SvXMLImportContext *ScXMLConditionContext::CreateChildContext( USHORT nPrefix, return new SvXMLImportContext( GetImport(), nPrefix, rLName ); } -void ScXMLConditionContext::getOperatorXML(const rtl::OUString sTempOperator, sheet::FilterOperator& aFilterOperator, sal_Bool& bUseRegularExpressions) const +void ScXMLConditionContext::getOperatorXML(const rtl::OUString sTempOperator, sal_Int32& aFilterOperator, sal_Bool& bUseRegularExpressions) const { bUseRegularExpressions = sal_False; if (IsXMLToken(sTempOperator, XML_MATCH)) { bUseRegularExpressions = sal_True; - aFilterOperator = sheet::FilterOperator_EQUAL; + aFilterOperator = sheet::FilterOperator2::EQUAL; } else if (IsXMLToken(sTempOperator, XML_NOMATCH)) { bUseRegularExpressions = sal_True; - aFilterOperator = sheet::FilterOperator_NOT_EQUAL; + aFilterOperator = sheet::FilterOperator2::NOT_EQUAL; } else if (sTempOperator.compareToAscii("=") == 0) - aFilterOperator = sheet::FilterOperator_EQUAL; + aFilterOperator = sheet::FilterOperator2::EQUAL; else if (sTempOperator.compareToAscii("!=") == 0) - aFilterOperator = sheet::FilterOperator_NOT_EQUAL; + aFilterOperator = sheet::FilterOperator2::NOT_EQUAL; else if (IsXMLToken(sTempOperator, XML_BOTTOM_PERCENT)) - aFilterOperator = sheet::FilterOperator_BOTTOM_PERCENT; + aFilterOperator = sheet::FilterOperator2::BOTTOM_PERCENT; else if (IsXMLToken(sTempOperator, XML_BOTTOM_VALUES)) - aFilterOperator = sheet::FilterOperator_BOTTOM_VALUES; + aFilterOperator = sheet::FilterOperator2::BOTTOM_VALUES; else if (IsXMLToken(sTempOperator, XML_EMPTY)) - aFilterOperator = sheet::FilterOperator_EMPTY; + aFilterOperator = sheet::FilterOperator2::EMPTY; else if (sTempOperator.compareToAscii(">") == 0) - aFilterOperator = sheet::FilterOperator_GREATER; + aFilterOperator = sheet::FilterOperator2::GREATER; else if (sTempOperator.compareToAscii(">=") == 0) - aFilterOperator = sheet::FilterOperator_GREATER_EQUAL; + aFilterOperator = sheet::FilterOperator2::GREATER_EQUAL; else if (sTempOperator.compareToAscii("<") == 0) - aFilterOperator = sheet::FilterOperator_LESS; + aFilterOperator = sheet::FilterOperator2::LESS; else if (sTempOperator.compareToAscii("<=") == 0) - aFilterOperator = sheet::FilterOperator_LESS_EQUAL; + aFilterOperator = sheet::FilterOperator2::LESS_EQUAL; else if (IsXMLToken(sTempOperator, XML_NOEMPTY)) - aFilterOperator = sheet::FilterOperator_NOT_EMPTY; + aFilterOperator = sheet::FilterOperator2::NOT_EMPTY; else if (IsXMLToken(sTempOperator, XML_TOP_PERCENT)) - aFilterOperator = sheet::FilterOperator_TOP_PERCENT; + aFilterOperator = sheet::FilterOperator2::TOP_PERCENT; else if (IsXMLToken(sTempOperator, XML_TOP_VALUES)) - aFilterOperator = sheet::FilterOperator_TOP_VALUES; + aFilterOperator = sheet::FilterOperator2::TOP_VALUES; + else if (IsXMLToken(sTempOperator, XML_CONTAINS)) + aFilterOperator = sheet::FilterOperator2::CONTAINS; + else if (IsXMLToken(sTempOperator, XML_DOES_NOT_CONTAIN)) + aFilterOperator = sheet::FilterOperator2::DOES_NOT_CONTAIN; + else if (IsXMLToken(sTempOperator, XML_BEGINS_WITH)) + aFilterOperator = sheet::FilterOperator2::BEGINS_WITH; + else if (IsXMLToken(sTempOperator, XML_DOES_NOT_BEGIN_WITH)) + aFilterOperator = sheet::FilterOperator2::DOES_NOT_BEGIN_WITH; + else if (IsXMLToken(sTempOperator, XML_ENDS_WITH)) + aFilterOperator = sheet::FilterOperator2::ENDS_WITH; + else if (IsXMLToken(sTempOperator, XML_DOES_NOT_END_WITH)) + aFilterOperator = sheet::FilterOperator2::DOES_NOT_END_WITH; } void ScXMLConditionContext::EndElement() { - sheet::TableFilterField aFilterField; + sheet::TableFilterField2 aFilterField; if (pFilterContext->GetConnection()) aFilterField.Connection = sheet::FilterConnection_OR; else diff --git a/sc/source/filter/xml/xmlfilti.hxx b/sc/source/filter/xml/xmlfilti.hxx index f0021e9dda1b..b2b45175c138 100644 --- a/sc/source/filter/xml/xmlfilti.hxx +++ b/sc/source/filter/xml/xmlfilti.hxx @@ -36,7 +36,8 @@ #include <com/sun/star/table/CellAddress.hpp> #include <com/sun/star/table/CellRangeAddress.hpp> #include <com/sun/star/sheet/FilterOperator.hpp> -#include <com/sun/star/sheet/TableFilterField.hpp> +#include <com/sun/star/sheet/FilterOperator2.hpp> +#include <com/sun/star/sheet/TableFilterField2.hpp> #include <tools/stack.hxx> #include "xmldrani.hxx" @@ -48,7 +49,7 @@ class ScXMLFilterContext : public SvXMLImportContext { ScXMLDatabaseRangeContext* pDatabaseRangeContext; - com::sun::star::uno::Sequence <com::sun::star::sheet::TableFilterField> aFilterFields; + com::sun::star::uno::Sequence <com::sun::star::sheet::TableFilterField2> aFilterFields; com::sun::star::table::CellAddress aOutputPosition; com::sun::star::table::CellRangeAddress aConditionSourceRangeAddress; sal_Int16 nUserListIndex; @@ -89,7 +90,7 @@ public: aConnectionOrStack.Push(pTemp);} void CloseConnection() { sal_Bool* pTemp = static_cast <sal_Bool*> (aConnectionOrStack.Pop()); bConnectionOr = *pTemp; bNextConnectionOr = *pTemp; delete pTemp;} sal_Bool GetConnection() { sal_Bool bTemp = bConnectionOr; bConnectionOr = bNextConnectionOr; return bTemp; } - void AddFilterField (const com::sun::star::sheet::TableFilterField aFilterField) { aFilterFields.realloc(aFilterFields.getLength() + 1); + void AddFilterField(const com::sun::star::sheet::TableFilterField2 aFilterField) { aFilterFields.realloc(aFilterFields.getLength() + 1); aFilterFields[aFilterFields.getLength() - 1] = aFilterField; } }; @@ -171,7 +172,7 @@ public: const ::com::sun::star::uno::Reference< ::com::sun::star::xml::sax::XAttributeList>& xAttrList ); - void getOperatorXML(const rtl::OUString sTempOperator, com::sun::star::sheet::FilterOperator& aFilterOperator, sal_Bool& bUseRegularExpressions) const; + void getOperatorXML(const rtl::OUString sTempOperator, sal_Int32& aFilterOperator, sal_Bool& bUseRegularExpressions) const; virtual void EndElement(); }; diff --git a/sc/source/filter/xml/xmlimprt.cxx b/sc/source/filter/xml/xmlimprt.cxx index 873e95168088..200e33743020 100644 --- a/sc/source/filter/xml/xmlimprt.cxx +++ b/sc/source/filter/xml/xmlimprt.cxx @@ -74,6 +74,7 @@ #include "unonames.hxx" #include "rangeutl.hxx" #include "postit.hxx" +#include "formulaparserpool.hxx" #include <comphelper/extract.hxx> #include <com/sun/star/document/XDocumentPropertiesSupplier.hpp> @@ -2850,36 +2851,99 @@ void ScXMLImport::ProgressBarIncrement(sal_Bool bEditCell, sal_Int32 nInc) } } -// static -bool ScXMLImport::IsAcceptedFormulaNamespace( const sal_uInt16 nFormulaPrefix, - const rtl::OUString & rValue, formula::FormulaGrammar::Grammar& rGrammar, - const formula::FormulaGrammar::Grammar eStorageGrammar ) +sal_Int32 ScXMLImport::GetVisibleSheet() { - switch (nFormulaPrefix) + // Get the visible sheet number from model's view data (after settings were loaded), + // or 0 (default: first sheet) if no settings available. + + uno::Reference<document::XViewDataSupplier> xSupp(GetModel(), uno::UNO_QUERY); + if (xSupp.is()) { - case XML_NAMESPACE_OF: - rGrammar = formula::FormulaGrammar::GRAM_ODFF; - return true; - case XML_NAMESPACE_OOOC: - rGrammar = formula::FormulaGrammar::GRAM_PODF; - return true; + uno::Reference<container::XIndexAccess> xIndex = xSupp->getViewData(); + if ( xIndex.is() && xIndex->getCount() > 0 ) + { + uno::Any aAny( xIndex->getByIndex(0) ); + uno::Sequence<beans::PropertyValue> aViewSettings; // settings for (first) view + if ( aAny >>= aViewSettings ) + { + sal_Int32 nCount = aViewSettings.getLength(); + for (sal_Int32 i = 0; i < nCount; ++i) + { + if ( aViewSettings[i].Name.compareToAscii(SC_ACTIVETABLE) == 0 ) + { + rtl::OUString sValue; + if(aViewSettings[i].Value >>= sValue) + { + String sTabName(sValue); + SCTAB nTab = 0; + if (pDoc->GetTable(sTabName, nTab)) + return nTab; + } + } + } + } + } } - // An invalid namespace can occur from a colon in the formula text if no - // namespace tag was added. First character in string has to be '=' in that - // case. - bool bNoNamespace = (nFormulaPrefix == XML_NAMESPACE_NONE || - (nFormulaPrefix == XML_NAMESPACE_UNKNOWN && rValue.toChar() == '=')); - - if (bNoNamespace && eStorageGrammar == formula::FormulaGrammar::GRAM_PODF) - // There may be documents in the wild that stored no namespace in ODF 1.x - rGrammar = formula::FormulaGrammar::GRAM_PODF; - else if (bNoNamespace) - // The default for ODF 1.2 and later without namespace is 'of:' ODFF - rGrammar = formula::FormulaGrammar::GRAM_ODFF; - else - // Whatever ... - rGrammar = eStorageGrammar; + return 0; +} - return false; +void ScXMLImport::ExtractFormulaNamespaceGrammar( + OUString& rFormula, OUString& rFormulaNmsp, FormulaGrammar::Grammar& reGrammar, + const OUString& rAttrValue, bool bRestrictToExternalNmsp ) const +{ + // parse the attribute value, extract namespace ID, literal namespace, and formula string + rFormulaNmsp = OUString(); + sal_uInt16 nNsId = GetNamespaceMap()._GetKeyByAttrName( rAttrValue, 0, &rFormula, &rFormulaNmsp, sal_False ); + + // check if we have an ODF formula namespace + if( !bRestrictToExternalNmsp ) switch( nNsId ) + { + case XML_NAMESPACE_OOOC: + rFormulaNmsp = OUString(); // remove namespace string for built-in grammar + reGrammar = FormulaGrammar::GRAM_PODF; + return; + case XML_NAMESPACE_OF: + rFormulaNmsp = OUString(); // remove namespace string for built-in grammar + reGrammar = FormulaGrammar::GRAM_ODFF; + return; + } + + /* Find default grammar for formulas without namespace. There may be + documents in the wild that stored no namespace in ODF 1.0/1.1. Use + GRAM_PODF then (old style ODF 1.0/1.1 formulas). The default for ODF + 1.2 and later without namespace is GRAM_ODFF (OpenFormula). */ + FormulaGrammar::Grammar eDefaultGrammar = + (GetDocument()->GetStorageGrammar() == FormulaGrammar::GRAM_PODF) ? + FormulaGrammar::GRAM_PODF : FormulaGrammar::GRAM_ODFF; + + /* Check if we have no namespace at all. The value XML_NAMESPACE_NONE + indicates that there is no colon. If the first character of the + attribute value is the equality sign, the value XML_NAMESPACE_UNKNOWN + indicates that there is a colon somewhere in the formula string. */ + if( (nNsId == XML_NAMESPACE_NONE) || ((nNsId == XML_NAMESPACE_UNKNOWN) && (rAttrValue.toChar() == '=')) ) + { + rFormula = rAttrValue; // return entire string as formula + reGrammar = eDefaultGrammar; + return; + } + + /* Check if a namespace URL could be resolved from the attribute value. + Use that namespace only, if the Calc document knows an associated + external formula parser. This prevents that the range operator in + conjunction with defined names is confused as namespaces prefix, e.g. + in the expression 'table:A1' where 'table' is a named reference. */ + if( ((nNsId & XML_NAMESPACE_UNKNOWN_FLAG) != 0) && (rFormulaNmsp.getLength() > 0) && + GetDocument()->GetFormulaParserPool().hasFormulaParser( rFormulaNmsp ) ) + { + reGrammar = FormulaGrammar::GRAM_EXTERNAL; + return; + } + + /* All attempts failed (e.g. no namespace and no leading equality sign, or + an invalid namespace prefix), continue with the entire attribute value. */ + rFormula = rAttrValue; + rFormulaNmsp = OUString(); // remove any namespace string + reGrammar = eDefaultGrammar; } + diff --git a/sc/source/filter/xml/xmlimprt.hxx b/sc/source/filter/xml/xmlimprt.hxx index 052ef20c6022..f96d34c40ca5 100644 --- a/sc/source/filter/xml/xmlimprt.hxx +++ b/sc/source/filter/xml/xmlimprt.hxx @@ -598,6 +598,7 @@ struct ScMyNamedExpression { rtl::OUString sName; rtl::OUString sContent; + rtl::OUString sContentNmsp; rtl::OUString sBaseCellAddress; rtl::OUString sRangeType; formula::FormulaGrammar::Grammar eGrammar; @@ -624,11 +625,14 @@ struct ScMyImportValidation rtl::OUString sErrorMessage; rtl::OUString sFormula1; rtl::OUString sFormula2; + rtl::OUString sFormulaNmsp1; + rtl::OUString sFormulaNmsp2; rtl::OUString sBaseCellAddress; // #b4974740# string is used directly com::sun::star::sheet::ValidationAlertStyle aAlertStyle; com::sun::star::sheet::ValidationType aValidationType; com::sun::star::sheet::ConditionOperator aOperator; - formula::FormulaGrammar::Grammar eGrammar; + formula::FormulaGrammar::Grammar eGrammar1; + formula::FormulaGrammar::Grammar eGrammar2; sal_Int16 nShowList; sal_Bool bShowErrorMessage; sal_Bool bShowImputMessage; @@ -983,46 +987,43 @@ public: void SetLabelRanges(); void AddDefaultNote( const com::sun::star::table::CellAddress& aCell ); - - /** If namespace prefix is an accepted formula namespace. - - For an accepted namespace (return <TRUE/>), the formula text is the - part without the namespace tag (aFormula of the _GetKeyByAttrName() - example below). - - For an invalid namespace (not defined in the file, - XML_NAMESPACE_UNKNOWN; may also be the result of no namespace with - colon in the formula text, in that case text has to start with - character '=') or no namespace tag (XML_NAMESPACE_NONE) the full text - (rValue) should be used (return <FALSE/>). - - @param nFormulaPrefix - The result of a _GetKeyByAttrName( rValue, aFormula, sal_False) - call. - - @param rValue - The attribute's string (formula text) including the namespace, if - any. - - @param rGrammar - Return value set toformula::FormulaGrammar::GRAM_ODFF orformula::FormulaGrammar::GRAM_PODF or - eStorageGrammar, according to the namespace or absence thereof - encountered. - - @param eStorageGrammar - Default storage grammar of the document,formula::FormulaGrammar::GRAM_ODFF for - ODF 1.2 and later documents,formula::FormulaGrammar::GRAM_PODF for ODF 1.x - documents. - - @return - <TRUE/> if an accepted namespace (XML_NAMESPACE_OF or - XML_NAMESPACE_OOOC), else <FALSE/>. + sal_Int32 GetVisibleSheet(); + /** Extracts the formula string, the formula grammar namespace URL, and a + grammar enum value from the passed formula attribute value. + + @param rFormula + (out-parameter) Returns the plain formula string with the leading + equality sign if existing. + + @param rFormulaNmsp + (out-parameter) Returns the URL of the formula grammar namespace if + the attribute value contains the prefix of an unknown namespace. + + @param reGrammar + (out-parameter) Returns the exact formula grammar if the formula + is in a supported ODF format (e.g. FormulaGrammar::GRAM_PODF for + ODF 1.0/1.1 formulas, or FormulaGrammar::GRAM_ODFF for ODF 1.2 + formulas a.k.a. OpenFormula). Returns the default storage grammar, + if the attribute value does not contain a namespace prefix. Returns + the special value FormulaGrammar::GRAM_EXTERNAL, if an unknown + namespace could be extracted from the formula which will be + contained in the parameter rFormulaNmsp then. + + @param rAttrValue + The value of the processed formula attribute. + + @param bRestrictToExternalNmsp + If set to TRUE, only namespaces of external formula grammars will + be recognized. Internal namespace prefixes (e.g. 'oooc:' or 'of:' + will be considered to be part of the formula, e.g. an expression + with range operator. */ - - static bool IsAcceptedFormulaNamespace( const sal_uInt16 nFormulaPrefix, - const rtl::OUString & rValue, formula::FormulaGrammar::Grammar& rGrammar, - const formula::FormulaGrammar::Grammar eStorageGrammar ); - + void ExtractFormulaNamespaceGrammar( + ::rtl::OUString& rFormula, + ::rtl::OUString& rFormulaNmsp, + ::formula::FormulaGrammar::Grammar& reGrammar, + const ::rtl::OUString& rAttrValue, + bool bRestrictToExternalNmsp = false ) const; }; #endif diff --git a/sc/source/filter/xml/xmlnexpi.cxx b/sc/source/filter/xml/xmlnexpi.cxx index 3f822d5274c6..9a2a49f0b021 100644 --- a/sc/source/filter/xml/xmlnexpi.cxx +++ b/sc/source/filter/xml/xmlnexpi.cxx @@ -196,8 +196,6 @@ ScXMLNamedExpressionContext::ScXMLNamedExpressionContext( ScXMLImport& rImport, SvXMLImportContext( rImport, nPrfx, rLName ) { ScMyNamedExpression* pNamedExpression(new ScMyNamedExpression); - const formula::FormulaGrammar::Grammar eStorageGrammar = pNamedExpression->eGrammar = - GetScImport().GetDocument()->GetStorageGrammar(); sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0); const SvXMLTokenMap& rAttrTokenMap(GetScImport().GetNamedExpressionAttrTokenMap()); for( sal_Int16 i=0; i < nAttrCount; ++i ) @@ -217,16 +215,9 @@ ScXMLNamedExpressionContext::ScXMLNamedExpressionContext( ScXMLImport& rImport, break; case XML_TOK_NAMED_EXPRESSION_ATTR_EXPRESSION : { - rtl::OUString sFormula; - sal_uInt16 nFormulaPrefix = GetImport().GetNamespaceMap(). - _GetKeyByAttrName( sValue, &sFormula, sal_False ); - - if (ScXMLImport::IsAcceptedFormulaNamespace( nFormulaPrefix, - sValue, pNamedExpression->eGrammar, - eStorageGrammar)) - pNamedExpression->sContent = sFormula; - else - pNamedExpression->sContent = sValue; + GetScImport().ExtractFormulaNamespaceGrammar( + pNamedExpression->sContent, pNamedExpression->sContentNmsp, + pNamedExpression->eGrammar, sValue ); } break; case XML_TOK_NAMED_EXPRESSION_ATTR_BASE_CELL_ADDRESS : diff --git a/sc/source/filter/xml/xmlstyli.cxx b/sc/source/filter/xml/xmlstyli.cxx index ac6cef7e54ec..79ba79f0e689 100644 --- a/sc/source/filter/xml/xmlstyli.cxx +++ b/sc/source/filter/xml/xmlstyli.cxx @@ -73,6 +73,7 @@ using namespace ::com::sun::star::beans; using namespace ::com::sun::star::container; using namespace xmloff::token; //using namespace ::com::sun::star::text; +using namespace ::formula; ScXMLCellImportPropertyMapper::ScXMLCellImportPropertyMapper( const UniReference< XMLPropertySetMapper >& rMapper, @@ -248,8 +249,14 @@ void ScXMLRowImportPropertyMapper::finished(::std::vector< XMLPropertyState >& r if (::cppu::any2bool(pOptimalHeight->maValue)) { if (pHeight) + { + // set the stored height, but keep "optimal" flag: + // pass the height value as OptimalHeight property (only allowed while loading!) + pOptimalHeight->maValue = pHeight->maValue; pHeight->mnIndex = -1; - pOptimalHeight->mnIndex = -1; + } + else + pOptimalHeight->mnIndex = -1; } } else if (pHeight) @@ -279,10 +286,7 @@ public: ScXMLMapContext::ScXMLMapContext(SvXMLImport& rImport, sal_uInt16 nPrfx, const OUString& rLName, const uno::Reference< xml::sax::XAttributeList > & xAttrList ) - : SvXMLImportContext( rImport, nPrfx, rLName ), - sApplyStyle(), - sCondition(), - sBaseCell() + : SvXMLImportContext( rImport, nPrfx, rLName ) { sal_Int16 nAttrCount(xAttrList.is() ? xAttrList->getLength() : 0); for( sal_Int16 i=0; i < nAttrCount; ++i ) @@ -309,200 +313,118 @@ ScXMLMapContext::~ScXMLMapContext() { } -void XMLTableStyleContext::SetOperator(com::sun::star::uno::Sequence<beans::PropertyValue>& aProps, - const com::sun::star::sheet::ConditionOperator aOp) const -{ - sal_Int32 nLength(aProps.getLength()); - aProps.realloc(nLength + 1); - aProps[nLength].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_OPERATOR)); - aProps[nLength].Value <<= aOp; -} +namespace { -void XMLTableStyleContext::SetBaseCellAddress(com::sun::star::uno::Sequence<beans::PropertyValue>& aProps, - const rtl::OUString& sBaseCell) const +template< typename Type > +inline void lclAppendProperty( uno::Sequence< beans::PropertyValue >& rProps, const OUString& rPropName, const Type& rValue ) { - sal_Int32 nLength(aProps.getLength()); - aProps.realloc(nLength + 1); - - // #b4974740# source position must be set as string, because it may - // refer to a sheet that hasn't been loaded yet. - - aProps[nLength].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_SOURCESTR)); - aProps[nLength].Value <<= sBaseCell; + sal_Int32 nLength = rProps.getLength(); + rProps.realloc( nLength + 1 ); + rProps[ nLength ].Name = rPropName; + rProps[ nLength ].Value <<= rValue; } -void XMLTableStyleContext::SetStyle(com::sun::star::uno::Sequence<beans::PropertyValue>& aProps, - const rtl::OUString& sApplyStyle) const +} // namespace + +void XMLTableStyleContext::SetOperator( uno::Sequence< beans::PropertyValue >& rProps, sheet::ConditionOperator eOp ) const { - sal_Int32 nLength(aProps.getLength()); - aProps.realloc(nLength + 1); - aProps[nLength].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_STYLENAME)); - aProps[nLength].Value <<= sApplyStyle; + lclAppendProperty( rProps, OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_OPERATOR ) ), eOp ); } -void XMLTableStyleContext::SetFormula1(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps, - const rtl::OUString& sFormula, bool bPreParse) const +void XMLTableStyleContext::SetBaseCellAddress( uno::Sequence< beans::PropertyValue >& rProps, const OUString& rBaseCell ) const { - sal_Int32 nLength(aProps.getLength()); - aProps.realloc(nLength + 1); - aProps[nLength].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_FORMULA1)); - if (bPreParse) - { - rtl::OUString sRealFormula(sFormula); - ScXMLConverter::ParseFormula(sRealFormula); - aProps[nLength].Value <<= sRealFormula; - } - else - aProps[nLength].Value <<= sFormula; + /* #b4974740# Source position must be set as string, because it may refer + to a sheet that hasn't been loaded yet. */ + lclAppendProperty( rProps, OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_SOURCESTR ) ), rBaseCell ); } -void XMLTableStyleContext::SetFormula2(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps, - const rtl::OUString& sFormula) const +void XMLTableStyleContext::SetStyle( uno::Sequence<beans::PropertyValue>& rProps, const OUString& rApplyStyle ) const { - sal_Int32 nLength(aProps.getLength()); - aProps.realloc(nLength + 1); - aProps[nLength].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_FORMULA2)); - rtl::OUString sRealFormula(sFormula); - ScXMLConverter::ParseFormula(sRealFormula); - aProps[nLength].Value <<= sRealFormula; + lclAppendProperty( rProps, OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_STYLENAME ) ), rApplyStyle ); } -void XMLTableStyleContext::SetFormulas(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps, - const rtl::OUString& sFormulas) const +void XMLTableStyleContext::SetFormula( uno::Sequence< beans::PropertyValue >& rProps, + sal_Int32 nFormulaIdx, const OUString& rFormula, const OUString& rFormulaNmsp, + FormulaGrammar::Grammar eGrammar, bool bHasNmsp ) const { - sal_Int32 i(0); - sal_Bool bString(sal_False); - sal_Int32 nBrakes(0); - while ((sFormulas[i] != ',' || nBrakes > 0 || bString) && i < sFormulas.getLength()) + OUString aFormula, aFormulaNmsp; + FormulaGrammar::Grammar eNewGrammar = FormulaGrammar::GRAM_UNSPECIFIED; + if( bHasNmsp ) { - if (sFormulas[i] == '(') - ++nBrakes; - if (sFormulas[i] == ')') - --nBrakes; - if (sFormulas[i] == '"') - bString = !bString; - ++i; + // the entire attribute contains a namespace: internal namespace not allowed + aFormula = rFormula; + aFormulaNmsp = rFormulaNmsp; + eNewGrammar = eGrammar; } - if (sFormulas[i] == ',') + else { - rtl::OUString sFormula1(sFormulas.copy(0, i)); - rtl::OUString sFormula2(sFormulas.copy(i + 1)); - SetFormula1(aProps, sFormula1); - SetFormula2(aProps, sFormula2); + // the attribute does not contain a namespace: try to find a namespace of an external grammar + GetScImport().ExtractFormulaNamespaceGrammar( aFormula, aFormulaNmsp, eNewGrammar, rFormula, true ); + if( eNewGrammar != FormulaGrammar::GRAM_EXTERNAL ) + eNewGrammar = eGrammar; } -} -void XMLTableStyleContext::SetGrammar(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps, - const formula::FormulaGrammar::Grammar eGrammar) const -{ - sal_Int32 nLength(aProps.getLength()); - aProps.realloc(nLength + 1); - aProps[nLength].Name = rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNONAME_GRAMMAR)); - aProps[nLength].Value <<= static_cast<sal_Int32>(eGrammar); + // add formula, formula namespace, and grammar with appropriate property names + sal_Int32 nGrammar = static_cast< sal_Int32 >( eNewGrammar ); + switch( nFormulaIdx ) + { + case 1: + lclAppendProperty( rProps, OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_FORMULA1 ) ), aFormula ); + lclAppendProperty( rProps, OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_FORMULANMSP1 ) ), aFormulaNmsp ); + lclAppendProperty( rProps, OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_GRAMMAR1 ) ), nGrammar ); + break; + case 2: + lclAppendProperty( rProps, OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_FORMULA2 ) ), aFormula ); + lclAppendProperty( rProps, OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_FORMULANMSP2 ) ), aFormulaNmsp ); + lclAppendProperty( rProps, OUString( RTL_CONSTASCII_USTRINGPARAM( SC_UNONAME_GRAMMAR2 ) ), nGrammar ); + break; + default: + OSL_ENSURE( false, "XMLTableStyleContext::SetFormula - invalid formula index" ); + } } void XMLTableStyleContext::GetConditionalFormat(uno::Any& aAny, const rtl::OUString& sTempCondition, const rtl::OUString& sApplyStyle, const rtl::OUString& sBaseCell) const { - rtl::OUString sCondition(sTempCondition); - if (sCondition.getLength() && sApplyStyle.getLength()) + if (sTempCondition.getLength() && sApplyStyle.getLength()) { uno::Reference<sheet::XSheetConditionalEntries> xConditionalEntries(aAny, uno::UNO_QUERY); if (xConditionalEntries.is()) { - const formula::FormulaGrammar::Grammar eStorageGrammar = GetScImport().GetDocument()->GetStorageGrammar(); - formula::FormulaGrammar::Grammar eGrammar = eStorageGrammar; - // ToDo: erase all blanks in the condition, but not in formulas or strings - rtl::OUString scell_content(RTL_CONSTASCII_USTRINGPARAM("cell_content")); - rtl::OUString scell_content_is_between(RTL_CONSTASCII_USTRINGPARAM("cell_content_is_between")); - rtl::OUString scell_content_is_not_between(RTL_CONSTASCII_USTRINGPARAM("cell_content_is_not_between")); - rtl::OUString sis_true_formula(RTL_CONSTASCII_USTRINGPARAM("is_true_formula")); uno::Sequence<beans::PropertyValue> aProps; if (sBaseCell.getLength()) SetBaseCellAddress(aProps, sBaseCell); SetStyle(aProps, sApplyStyle); - sal_Int32 i = 0; - while (sCondition[i] != '(' && i < sCondition.getLength()) - ++i; - if (sCondition[i] == '(') + + // extract leading namespace from condition string + OUString aCondition, aConditionNmsp; + FormulaGrammar::Grammar eGrammar = FormulaGrammar::GRAM_UNSPECIFIED; + GetScImport().ExtractFormulaNamespaceGrammar( aCondition, aConditionNmsp, eGrammar, sTempCondition ); + bool bHasNmsp = aCondition.getLength() < sTempCondition.getLength(); + + // parse a condition from the attribute string + ScXMLConditionParseResult aParseResult; + ScXMLConditionHelper::parseCondition( aParseResult, aCondition, 0 ); + + /* Check the result. A valid value in aParseResult.meToken implies + that the other members of aParseResult are filled with valid + data for that token. */ + switch( aParseResult.meToken ) { - sCondition = sCondition.copy(i + 1); - if (i == scell_content.getLength()) - { - sCondition = sCondition.copy(1); - switch (sCondition[0]) - { - case '<' : - { - if (sCondition[1] == '=') - { - SetOperator(aProps, sheet::ConditionOperator_LESS_EQUAL); - sCondition = sCondition.copy(2); - } - else - { - SetOperator(aProps, sheet::ConditionOperator_LESS); - sCondition = sCondition.copy(1); - } - } - break; - case '>' : - { - if (sCondition[1] == '=') - { - SetOperator(aProps, sheet::ConditionOperator_GREATER_EQUAL); - sCondition = sCondition.copy(2); - } - else - { - SetOperator(aProps, sheet::ConditionOperator_GREATER); - sCondition = sCondition.copy(1); - } - } - break; - case '=' : - { - SetOperator(aProps, sheet::ConditionOperator_EQUAL); - sCondition = sCondition.copy(1); - } - break; - case '!' : - { - SetOperator(aProps, sheet::ConditionOperator_NOT_EQUAL); - sCondition = sCondition.copy(1); - } - break; - } - SetFormula1(aProps, sCondition); - } - else if (i == scell_content_is_between.getLength()) - { - SetOperator(aProps, sheet::ConditionOperator_BETWEEN); - sCondition = sCondition.copy(0, sCondition.getLength() - 1); - SetFormulas(aProps, sCondition); - } - else if (i == scell_content_is_not_between.getLength()) - { - SetOperator(aProps, sheet::ConditionOperator_NOT_BETWEEN); - sCondition = sCondition.copy(0, sCondition.getLength() - 1); - SetFormulas(aProps, sCondition); - } - else if (i == sis_true_formula.getLength()) - { - SetOperator(aProps, sheet::ConditionOperator_FORMULA); - sCondition = sCondition.copy(0, sCondition.getLength() - 1); - rtl::OUString sFormula; - sal_uInt16 nFormulaPrefix = GetImport().GetNamespaceMap(). - _GetKeyByAttrName( sCondition, &sFormula, sal_False ); - if (ScXMLImport::IsAcceptedFormulaNamespace( nFormulaPrefix, - sCondition, eGrammar, eStorageGrammar)) - sCondition = sFormula; - SetFormula1(aProps, sCondition, false); - } + case XML_COND_CELLCONTENT: // condition is 'cell-content()<operator><expression>' + case XML_COND_ISTRUEFORMULA: // condition is 'is-true-formula(<expression>)' + case XML_COND_ISBETWEEN: // condition is 'cell-content-is-between(<expression1>,<expression2>)' + case XML_COND_ISNOTBETWEEN: // condition is 'cell-content-is-not-between(<expression1>,<expression2>)' + SetOperator( aProps, aParseResult.meOperator ); + SetFormula( aProps, 1, aParseResult.maOperand1, aConditionNmsp, eGrammar, bHasNmsp ); + SetFormula( aProps, 2, aParseResult.maOperand2, aConditionNmsp, eGrammar, bHasNmsp ); + break; + + default:; // unacceptable or unknown condition } - SetGrammar( aProps, eGrammar); - xConditionalEntries->addNew(aProps); + + xConditionalEntries->addNew( aProps ); aAny <<= xConditionalEntries; } } diff --git a/sc/source/filter/xml/xmlstyli.hxx b/sc/source/filter/xml/xmlstyli.hxx index 4d80f5710ac9..272ec0151134 100644 --- a/sc/source/filter/xml/xmlstyli.hxx +++ b/sc/source/filter/xml/xmlstyli.hxx @@ -107,20 +107,22 @@ class XMLTableStyleContext : public XMLPropStyleContext const ScXMLImport& GetScImport() const { return (const ScXMLImport&)GetImport(); } ScXMLImport& GetScImport() { return (ScXMLImport&)GetImport(); } - void SetOperator(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps, - const com::sun::star::sheet::ConditionOperator aOp) const; - void SetBaseCellAddress(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps, - const rtl::OUString& sBaseCell) const; - void SetStyle(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps, - const rtl::OUString& sApplyStyle) const; - void SetFormula1(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps, - const rtl::OUString& sFormula, bool bPreParse = true) const; - void SetFormula2(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps, - const rtl::OUString& sFormula) const; - void SetFormulas(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps, - const rtl::OUString& sFormulas) const; - void SetGrammar(com::sun::star::uno::Sequence<com::sun::star::beans::PropertyValue>& aProps, - const formula::FormulaGrammar::Grammar eGrammar) const; + void SetOperator( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rProps, + ::com::sun::star::sheet::ConditionOperator eOp ) const; + + void SetBaseCellAddress( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rProps, + const ::rtl::OUString& rBaseCell ) const; + + void SetStyle( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rProps, + const ::rtl::OUString& rApplyStyle ) const; + + void SetFormula( + ::com::sun::star::uno::Sequence< ::com::sun::star::beans::PropertyValue >& rProps, + sal_Int32 nFormulaIdx, const ::rtl::OUString& rFormula, + const ::rtl::OUString& rFormulaNmsp, ::formula::FormulaGrammar::Grammar eGrammar, bool bHasNmsp ) const; void GetConditionalFormat( ::com::sun::star::uno::Any& aAny, const rtl::OUString& sCondition, diff --git a/sc/source/filter/xml/xmlsubti.cxx b/sc/source/filter/xml/xmlsubti.cxx index 03437449ec61..231839b9f946 100644 --- a/sc/source/filter/xml/xmlsubti.cxx +++ b/sc/source/filter/xml/xmlsubti.cxx @@ -38,10 +38,13 @@ #include "xmlstyli.hxx" #include "xmlimprt.hxx" #include "document.hxx" +#include "markdata.hxx" #include "XMLConverter.hxx" #include "docuno.hxx" #include "cellsuno.hxx" #include "XMLStylesImportHelper.hxx" +#include "tabprotection.hxx" +#include <svx/svdpage.hxx> #include <xmloff/xmltkmap.hxx> #include <xmloff/nmspmap.hxx> @@ -58,6 +61,10 @@ #include <com/sun/star/util/XProtectable.hpp> #include <com/sun/star/sheet/XArrayFormulaRange.hpp> +#include <memory> + +using ::std::auto_ptr; + //------------------------------------------------------------------ using namespace com::sun::star; @@ -576,7 +583,35 @@ void ScMyTables::UpdateRowHeights() { rImport.LockSolarMutex(); // update automatic row heights - ScModelObj::getImplementation(rImport.GetModel())->UpdateAllRowHeights(); + + // For sheets with any kind of shapes (including notes), + // update row heights immediately (before setting the positions). + // For sheets without shapes, set "pending" flag + // and update row heights when a sheet is shown. + // The current sheet (from view settings) is always updated immediately. + + ScDocument* pDoc = ScXMLConverter::GetScDocument(rImport.GetModel()); + if (pDoc) + { + SCTAB nCount = pDoc->GetTableCount(); + ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer(); + + SCTAB nVisible = static_cast<SCTAB>( rImport.GetVisibleSheet() ); + + ScMarkData aUpdateSheets; + for (SCTAB nTab=0; nTab<nCount; ++nTab) + { + const SdrPage* pPage = pDrawLayer ? pDrawLayer->GetPage(nTab) : NULL; + if ( nTab == nVisible || ( pPage && pPage->GetObjCount() != 0 ) ) + aUpdateSheets.SelectTable( nTab, TRUE ); + else + pDoc->SetPendingRowHeights( nTab, TRUE ); + } + + if (aUpdateSheets.GetSelectCount()) + ScModelObj::getImplementation(rImport.GetModel())->UpdateAllRowHeights(&aUpdateSheets); + } + rImport.UnlockSolarMutex(); } } @@ -606,7 +641,7 @@ void ScMyTables::DeleteTable() ScMyMatrixRangeList::iterator aEndItr = aMatrixRangeList.end(); while(aItr != aEndItr) { - SetMatrix(aItr->aRange, aItr->sFormula, aItr->eGrammar); + SetMatrix(aItr->aRange, aItr->sFormula, aItr->sFormulaNmsp, aItr->eGrammar); ++aItr; } aMatrixRangeList.clear(); @@ -616,13 +651,10 @@ void ScMyTables::DeleteTable() { uno::Sequence<sal_Int8> aPass; SvXMLUnitConverter::decodeBase64(aPass, sPassword); - rImport.GetDocument()->SetTabProtection(static_cast<SCTAB>(nCurrentSheet), bProtection, aPass); - /*uno::Reference <util::XProtectable> xProtectable(xCurrentSheet, uno::UNO_QUERY); - if (xProtectable.is()) - { - rtl::OUString sKey; - xProtectable->protect(sKey); - }*/ + auto_ptr<ScTableProtection> pProtect(new ScTableProtection); + pProtect->setProtected(bProtection); + pProtect->setPasswordHash(aPass, PASSHASH_OOO); + rImport.GetDocument()->SetTabProtection(static_cast<SCTAB>(nCurrentSheet), pProtect.get()); } rImport.UnlockSolarMutex(); @@ -723,7 +755,9 @@ void ScMyTables::AddShape(uno::Reference <drawing::XShape>& rShape, aResizeShapes.AddShape(rShape, pRangeList, rStartAddress, rEndAddress, nEndX, nEndY); } -void ScMyTables::AddMatrixRange(sal_Int32 nStartColumn, sal_Int32 nStartRow, sal_Int32 nEndColumn, sal_Int32 nEndRow, const rtl::OUString& rFormula, const formula::FormulaGrammar::Grammar eGrammar) +void ScMyTables::AddMatrixRange( + sal_Int32 nStartColumn, sal_Int32 nStartRow, sal_Int32 nEndColumn, sal_Int32 nEndRow, + const rtl::OUString& rFormula, const rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar) { DBG_ASSERT(nEndRow >= nStartRow, "wrong row order"); DBG_ASSERT(nEndColumn >= nStartColumn, "wrong column order"); @@ -733,7 +767,7 @@ void ScMyTables::AddMatrixRange(sal_Int32 nStartColumn, sal_Int32 nStartRow, sal aRange.EndColumn = nEndColumn; aRange.EndRow = nEndRow; aRange.Sheet = sal::static_int_cast<sal_Int16>(nCurrentSheet); - ScMatrixRange aMRange(aRange, rFormula, eGrammar); + ScMatrixRange aMRange(aRange, rFormula, rFormulaNmsp, eGrammar); aMatrixRangeList.push_back(aMRange); } @@ -754,7 +788,7 @@ sal_Bool ScMyTables::IsPartOfMatrix(sal_Int32 nColumn, sal_Int32 nRow) } else if ((nRow > aItr->aRange.EndRow) && (nColumn > aItr->aRange.EndColumn)) { - SetMatrix(aItr->aRange, aItr->sFormula, aItr->eGrammar); + SetMatrix(aItr->aRange, aItr->sFormula, aItr->sFormulaNmsp, aItr->eGrammar); aItr = aMatrixRangeList.erase(aItr); } else if (nColumn < aItr->aRange.StartColumn) @@ -771,7 +805,8 @@ sal_Bool ScMyTables::IsPartOfMatrix(sal_Int32 nColumn, sal_Int32 nRow) return bResult; } -void ScMyTables::SetMatrix(const table::CellRangeAddress& rRange, const rtl::OUString& rFormula, const formula::FormulaGrammar::Grammar eGrammar) +void ScMyTables::SetMatrix(const table::CellRangeAddress& rRange, const rtl::OUString& rFormula, + const rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar) { uno::Reference <table::XCellRange> xMatrixCellRange( GetCurrentXCellRange()->getCellRangeByPosition(rRange.StartColumn, rRange.StartRow, @@ -785,7 +820,7 @@ void ScMyTables::SetMatrix(const table::CellRangeAddress& rRange, const rtl::OUS static_cast<ScCellRangeObj*>(ScCellRangesBase::getImplementation( xMatrixCellRange)); if (pCellRangeObj) - pCellRangeObj->SetArrayFormulaWithGrammar( rFormula, eGrammar); + pCellRangeObj->SetArrayFormulaWithGrammar( rFormula, rFormulaNmsp, eGrammar); } } } diff --git a/sc/source/filter/xml/xmlsubti.hxx b/sc/source/filter/xml/xmlsubti.hxx index 84a07ff90449..c5a16e2c3ef4 100644 --- a/sc/source/filter/xml/xmlsubti.hxx +++ b/sc/source/filter/xml/xmlsubti.hxx @@ -97,10 +97,12 @@ public: struct ScMatrixRange { rtl::OUString sFormula; + rtl::OUString sFormulaNmsp; formula::FormulaGrammar::Grammar eGrammar; com::sun::star::table::CellRangeAddress aRange; - ScMatrixRange(const com::sun::star::table::CellRangeAddress& rRange, const rtl::OUString& rFormula, const formula::FormulaGrammar::Grammar eGrammarP) : + ScMatrixRange(const com::sun::star::table::CellRangeAddress& rRange, const rtl::OUString& rFormula, const rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammarP) : sFormula(rFormula), + sFormulaNmsp(rFormulaNmsp), eGrammar(eGrammarP), aRange(rRange) { @@ -181,11 +183,13 @@ public: sal_Int32 nEndColumn, sal_Int32 nEndRow, const rtl::OUString& rFormula, + const rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar ); sal_Bool IsPartOfMatrix(sal_Int32 nColumn, sal_Int32 nRow); void SetMatrix( const com::sun::star::table::CellRangeAddress& rRange, const rtl::OUString& rFormula, + const rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar ); }; diff --git a/sc/source/ui/Accessibility/AccessibleDocument.cxx b/sc/source/ui/Accessibility/AccessibleDocument.cxx index 616071be52d4..3ed9b4062a9d 100644 --- a/sc/source/ui/Accessibility/AccessibleDocument.cxx +++ b/sc/source/ui/Accessibility/AccessibleDocument.cxx @@ -563,31 +563,6 @@ uno::Reference< XAccessible > ScChildrenShapes::GetAt(const awt::Point& rPoint) --i; } -/* Window* pWindow = mpViewShell->GetWindowByPos(meSplitPos); - if (pWindow) - { - Point aPnt( rPoint.X, rPoint.Y ); - aPnt = pWindow->PixelToLogic( aPnt ); - SdrPage* pDrawPage = GetDrawPage(); - if (pDrawPage) - { - SdrObject * pObj = GetDrawPage()->CheckHit(aPnt, 1, NULL, false); - if (pObj) - { - uno::Reference<drawing::XShape> xShape (pObj->getUnoShape(), uno::UNO_QUERY); - SortedShapes::iterator aItr;; - if (FindShape(xShape, aItr)) - { - if ((*aItr) && (*aItr)->pAccShape) - xAccessible = (*aItr)->pAccShape; - else - xAccessible = Get(aItr - maZOrderedShapes.begin()); - } - else - DBG_ERRORFILE("a shape is not in the list"); - } - } - }*/ } return xAccessible; } diff --git a/sc/source/ui/app/inputhdl.cxx b/sc/source/ui/app/inputhdl.cxx index 3e069b6c9e59..46987c88636f 100644 --- a/sc/source/ui/app/inputhdl.cxx +++ b/sc/source/ui/app/inputhdl.cxx @@ -113,14 +113,22 @@ extern USHORT nEditAdjust; //! Member an ViewData //================================================================== +static sal_Unicode lcl_getSheetSeparator(ScDocument* pDoc) +{ + ScCompiler aComp(pDoc, ScAddress()); + aComp.SetGrammar(pDoc->GetGrammar()); + return aComp.GetNativeAddressSymbol(ScCompiler::Convention::SHEET_SEPARATOR); +} + void ScInputHandler::InitRangeFinder( const String& rFormula ) { DeleteRangeFinder(); + ScDocShell* pDocSh = pActiveViewSh->GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + const sal_Unicode cSheetSep = lcl_getSheetSeparator(pDoc); if ( !pActiveViewSh || !SC_MOD()->GetInputOptions().GetRangeFinder() ) return; - ScDocShell* pDocSh = pActiveViewSh->GetViewData()->GetDocShell(); - ScDocument* pDoc = pDocSh->GetDocument(); // String aDelimiters = pEngine->GetWordDelimiters(); String aDelimiters = ScEditUtil::ModifyDelimiters( @@ -129,7 +137,7 @@ void ScInputHandler::InitRangeFinder( const String& rFormula ) xub_StrLen nColon = aDelimiters.Search(':'); if ( nColon != STRING_NOTFOUND ) aDelimiters.Erase( nColon, 1 ); // Delimiter ohne Doppelpunkt - xub_StrLen nDot = aDelimiters.Search('.'); + xub_StrLen nDot = aDelimiters.Search(cSheetSep); if ( nDot != STRING_NOTFOUND ) aDelimiters.Erase( nDot, 1 ); // Delimiter ohne Punkt @@ -702,6 +710,9 @@ void ScInputHandler::ShowTipCursor() HideTip(); HideTipBelow(); EditView* pActiveView = pTopView ? pTopView : pTableView; + ScDocShell* pDocSh = pActiveViewSh->GetViewData()->GetDocShell(); + const sal_Unicode cSep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0); + const sal_Unicode cSheetSep = lcl_getSheetSeparator(pDocSh->GetDocument()); if ( bFormulaMode && pActiveView && pFormulaDataPara && pEngine->GetParagraphCount() == 1 ) { @@ -730,7 +741,7 @@ void ScInputHandler::ShowTipCursor() nLeftParentPos = lcl_MatchParenthesis( aSelText, aSelText.Len()-1 ); if( nLeftParentPos != STRING_NOTFOUND ) { - sal_Unicode c = aSelText.GetChar( nLeftParentPos-1 ); + sal_Unicode c = ( nLeftParentPos > 0 ) ? aSelText.GetChar( nLeftParentPos-1 ) : 0; if( !((c >= 'A' && c<= 'Z') || (c>= 'a' && c<= 'z' )) ) continue; nNextFStart = aHelper.GetFunctionStart( aSelText, nLeftParentPos, TRUE); @@ -764,8 +775,8 @@ void ScInputHandler::ShowTipCursor() } if( bFlag ) { - nCountSemicolon = aNew.GetTokenCount(';')-1; - nCountDot = aNew.GetTokenCount('.')-1; + nCountSemicolon = aNew.GetTokenCount(cSep)-1; + nCountDot = aNew.GetTokenCount(cSheetSep)-1; if( !nCountSemicolon ) { @@ -787,7 +798,7 @@ void ScInputHandler::ShowTipCursor() { nStartPosition = i+1; } - else if( cNext == ';' ) + else if( cNext == cSep ) { nCount ++; nEndPosition = i; @@ -808,7 +819,7 @@ void ScInputHandler::ShowTipCursor() { nStartPosition = i+1; } - else if( cNext == ';' ) + else if( cNext == cSep ) { nCount ++; nEndPosition = i; @@ -818,7 +829,7 @@ void ScInputHandler::ShowTipCursor() } nStartPosition = nEndPosition+1; } - else if( cNext == '.' ) + else if( cNext == cSheetSep ) { continue; } @@ -919,6 +930,9 @@ void ScInputHandler::ShowTipBelow( const String& rText ) void ScInputHandler::UseFormulaData() { EditView* pActiveView = pTopView ? pTopView : pTableView; + ScDocShell* pDocSh = pActiveViewSh->GetViewData()->GetDocShell(); + const sal_Unicode cSep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0); + const sal_Unicode cSheetSep = lcl_getSheetSeparator(pDocSh->GetDocument()); // Formeln duerfen nur 1 Absatz haben if ( pActiveView && pFormulaData && pEngine->GetParagraphCount() == 1 ) @@ -969,7 +983,8 @@ void ScInputHandler::UseFormulaData() if( nLeftParentPos == STRING_NOTFOUND ) break; - sal_Unicode c = aFormula.GetChar( nLeftParentPos-1 ); + // #160063# nLeftParentPos can be 0 if a parenthesis is inserted before the formula + sal_Unicode c = ( nLeftParentPos > 0 ) ? aFormula.GetChar( nLeftParentPos-1 ) : 0; if( !((c >= 'A' && c<= 'Z') || (c>= 'a' && c<= 'z') ) ) continue; nNextFStart = aHelper.GetFunctionStart( aFormula, nLeftParentPos, TRUE); @@ -1003,8 +1018,8 @@ void ScInputHandler::UseFormulaData() } if( bFlag ) { - nCountSemicolon = aNew.GetTokenCount(';')-1; - nCountDot = aNew.GetTokenCount('.')-1; + nCountSemicolon = aNew.GetTokenCount(cSep)-1; + nCountDot = aNew.GetTokenCount(cSheetSep)-1; if( !nCountSemicolon ) { @@ -1026,7 +1041,7 @@ void ScInputHandler::UseFormulaData() { nStartPosition = i+1; } - else if( cNext == ';' ) + else if( cNext == cSep ) { nCount ++; nEndPosition = i; @@ -1047,7 +1062,7 @@ void ScInputHandler::UseFormulaData() { nStartPosition = i+1; } - else if( cNext == ';' ) + else if( cNext == cSep ) { nCount ++; nEndPosition = i; @@ -1057,7 +1072,7 @@ void ScInputHandler::UseFormulaData() } nStartPosition = nEndPosition+1; } - else if( cNext == '.' ) + else if( cNext == cSheetSep ) { continue; } @@ -2740,6 +2755,7 @@ BOOL ScInputHandler::IsModalMode( SfxObjectShell* pDocSh ) void ScInputHandler::AddRefEntry() { + const sal_Unicode cSep = ScCompiler::GetNativeSymbol(ocSep).GetChar(0); UpdateActiveView(); if (!pTableView && !pTopView) return; // z.B. FillMode @@ -2748,9 +2764,9 @@ void ScInputHandler::AddRefEntry() RemoveSelection(); if (pTableView) - pTableView->InsertText( ';', FALSE ); + pTableView->InsertText( cSep, FALSE ); if (pTopView) - pTopView->InsertText( ';', FALSE ); + pTopView->InsertText( cSep, FALSE ); DataChanged(); } diff --git a/sc/source/ui/app/inputwin.cxx b/sc/source/ui/app/inputwin.cxx index 8fd3c1f8ac0b..5a3fd605b08f 100644 --- a/sc/source/ui/app/inputwin.cxx +++ b/sc/source/ui/app/inputwin.cxx @@ -1699,7 +1699,7 @@ void ScPosWnd::DoEnter() ScRangeName aNewRanges( *pNames ); ScAddress aCursor( pViewData->GetCurX(), pViewData->GetCurY(), pViewData->GetTabNo() ); String aContent; - aSelection.Format( aContent, SCR_ABS_3D, pDoc ); + aSelection.Format( aContent, SCR_ABS_3D, pDoc, pDoc->GetAddressConvention() ); ScRangeData* pNew = new ScRangeData( pDoc, aText, aContent, aCursor ); if ( aNewRanges.Insert(pNew) ) { diff --git a/sc/source/ui/app/transobj.cxx b/sc/source/ui/app/transobj.cxx index 076cd3581d26..94a2cdfc3324 100644 --- a/sc/source/ui/app/transobj.cxx +++ b/sc/source/ui/app/transobj.cxx @@ -658,7 +658,7 @@ void ScTransferObj::InitDocShell() // page format (grid etc) and page size (maximum size for ole object) - Size aPaperSize = SvxPaperInfo::GetPaperSize( SVX_PAPER_A4 ); // Twips + Size aPaperSize = SvxPaperInfo::GetPaperSize( PAPER_A4 ); // Twips ScStyleSheetPool* pStylePool = pDoc->GetStyleSheetPool(); String aStyleName = pDoc->GetPageStyle( aBlock.aStart.Tab() ); SfxStyleSheetBase* pStyleSheet = pStylePool->Find( aStyleName, SFX_STYLE_FAMILY_PAGE ); diff --git a/sc/source/ui/attrdlg/scdlgfact.cxx b/sc/source/ui/attrdlg/scdlgfact.cxx index 84d274580aa0..60b101d482c0 100644 --- a/sc/source/ui/attrdlg/scdlgfact.cxx +++ b/sc/source/ui/attrdlg/scdlgfact.cxx @@ -714,6 +714,24 @@ VclAbstractDialog * ScAbstractDialogFactory_Impl::CreateScColOrRowDlg(Window* } //add for ScColOrRowDlg end +//add for ScSortWarningDlg begin +VclAbstractDialog * ScAbstractDialogFactory_Impl::CreateScSortWarningDlg( Window* pParent, const String& rExtendText, + const String& rCurrentText, int nId ) +{ + Dialog * pDlg=NULL; + switch ( nId ) + { + case RID_SCDLG_SORT_WARNING: + pDlg = new ScSortWarningDlg( pParent, rExtendText, rCurrentText ); + break; + default: + break; + } + if( pDlg ) + return new VclAbstractDialog_Impl( pDlg ); + return 0; +} +//add for ScSortWarningDlg end //add for ScDataPilotDatabaseDlg begin diff --git a/sc/source/ui/attrdlg/scdlgfact.hxx b/sc/source/ui/attrdlg/scdlgfact.hxx index 2bec64c31e13..40f6d3bee976 100644 --- a/sc/source/ui/attrdlg/scdlgfact.hxx +++ b/sc/source/ui/attrdlg/scdlgfact.hxx @@ -63,6 +63,7 @@ class ScShowTabDlg; class ScStringInputDlg; class ScImportOptionsDlg; class SfxTabDialog; +class ScSortWarningDlg; #define DECL_ABSTDLG_BASE(Class,DialogClass) \ DialogClass* pDlg; \ @@ -398,6 +399,9 @@ public: const String& rStrLabel, int nId, BOOL bColDefault = TRUE ); + + virtual VclAbstractDialog * CreateScSortWarningDlg( Window* pParent, const String& rExtendText, const String& rCurrentText, int nId ); + virtual AbstractScDataPilotDatabaseDlg * CreateScDataPilotDatabaseDlg (Window* pParent ,int nId ); //add for ScDataPilotDatabaseDlg virtual AbstractScDataPilotSourceTypeDlg * CreateScDataPilotSourceTypeDlg ( Window* pParent, BOOL bEnableExternal, int nId ) ; //add for ScDataPilotSourceTypeDlg diff --git a/sc/source/ui/dbgui/sortdlg.cxx b/sc/source/ui/dbgui/sortdlg.cxx index 00931de58924..7d1462f62f27 100644 --- a/sc/source/ui/dbgui/sortdlg.cxx +++ b/sc/source/ui/dbgui/sortdlg.cxx @@ -34,7 +34,7 @@ #undef SC_DLLIMPLEMENTATION - +#include <vcl/msgbox.hxx> #include "tpsort.hxx" #include "sortdlg.hxx" #include "scresid.hxx" @@ -69,3 +69,42 @@ __EXPORT ScSortDlg::~ScSortDlg() { } +//================================================================== +ScSortWarningDlg::ScSortWarningDlg( Window* pParent, + const String& rExtendText, + const String& rCurrentText ): + ModalDialog ( pParent, ScResId( RID_SCDLG_SORT_WARNING ) ), + aFtText ( this, ScResId( FT_TEXT ) ), + aFtTip ( this, ScResId( FT_TIP ) ), + aBtnExtSort ( this, ScResId( BTN_EXTSORT ) ), + aBtnCurSort ( this, ScResId( BTN_CURSORT ) ), + aBtnCancel ( this, ScResId( BTN_CANCEL ) ) +{ + String sTextName = aFtText.GetText(); + sTextName.SearchAndReplaceAscii("%1", rExtendText); + sTextName.SearchAndReplaceAscii("%2", rCurrentText); + aFtText.SetText( sTextName ); + + aBtnExtSort .SetClickHdl( LINK( this, ScSortWarningDlg, BtnHdl ) ); + aBtnCurSort .SetClickHdl( LINK( this, ScSortWarningDlg, BtnHdl ) ); + + FreeResource(); +} + +ScSortWarningDlg::~ScSortWarningDlg() +{ +} + +IMPL_LINK( ScSortWarningDlg, BtnHdl, PushButton*, pBtn ) +{ + if ( pBtn == &aBtnExtSort ) + { + EndDialog( BTN_EXTEND_RANGE ); + } + else if( pBtn == &aBtnCurSort ) + { + EndDialog( BTN_CURRENT_SELECTION ); + } + return 0; +} +//========================================================================// diff --git a/sc/source/ui/docshell/dbdocfun.cxx b/sc/source/ui/docshell/dbdocfun.cxx index 1e85f3c01f3e..33caccaed815 100644 --- a/sc/source/ui/docshell/dbdocfun.cxx +++ b/sc/source/ui/docshell/dbdocfun.cxx @@ -58,6 +58,7 @@ #include "editable.hxx" #include "attrib.hxx" #include "drwlayer.hxx" +#include "dpshttab.hxx" // ----------------------------------------------------------------- @@ -1299,6 +1300,22 @@ BOOL ScDBDocFunc::DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pNewOb BOOL bOverflow = FALSE; ScRange aNewOut = pDestObj->GetNewOutputRange( bOverflow ); + + //! test for overlap with other data pilot tables + if( pOldObj ) + { + const ScSheetSourceDesc* pSheetDesc = pOldObj->GetSheetDesc(); + if( pSheetDesc && pSheetDesc->aSourceRange.Intersects( aNewOut ) ) + { + ScRange aOldRange = pOldObj->GetOutRange(); + SCsROW nDiff = aOldRange.aStart.Row()-aNewOut.aStart.Row(); + aNewOut.aStart.SetRow( aOldRange.aStart.Row() ); + aNewOut.aEnd.SetRow( aNewOut.aEnd.Row()+nDiff ); + if( !ValidRow( aNewOut.aStart.Row() ) || !ValidRow( aNewOut.aEnd.Row() ) ) + bOverflow = TRUE; + } + } + if ( bOverflow ) { // like with STR_PROTECTIONERR, use undo to reverse everything @@ -1354,9 +1371,7 @@ BOOL ScDBDocFunc::DataPilotUpdate( ScDPObject* pOldObj, const ScDPObject* pNewOb pDoc->CopyToDocument( aNewOut, IDF_ALL, FALSE, pNewUndoDoc ); } - //! test for overlap with other data pilot tables - - pDestObj->Output(); + pDestObj->Output( aNewOut.aStart ); rDocShell.PostPaintGridAll(); //! only necessary parts bDone = TRUE; diff --git a/sc/source/ui/docshell/docfunc.cxx b/sc/source/ui/docshell/docfunc.cxx index 0383d6758767..ebb080a89cfa 100644 --- a/sc/source/ui/docshell/docfunc.cxx +++ b/sc/source/ui/docshell/docfunc.cxx @@ -93,7 +93,12 @@ #include "editable.hxx" #include "compiler.hxx" #include "scui_def.hxx" //CHINA001 +#include "tabprotection.hxx" + +#include <memory> + using namespace com::sun::star; +using ::com::sun::star::uno::Sequence; // STATIC DATA ----------------------------------------------------------- @@ -955,16 +960,18 @@ BOOL ScDocFunc::PutData( const ScAddress& rPos, ScEditEngineDefaulter& rEngine, } -ScTokenArray* lcl_ScDocFunc_CreateTokenArrayXML( const String& rText ) +ScTokenArray* lcl_ScDocFunc_CreateTokenArrayXML( const String& rText, const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar ) { ScTokenArray* pCode = new ScTokenArray; pCode->AddString( rText ); + if( (eGrammar == formula::FormulaGrammar::GRAM_EXTERNAL) && (rFormulaNmsp.Len() > 0) ) + pCode->AddString( rFormulaNmsp ); return pCode; } ScBaseCell* ScDocFunc::InterpretEnglishString( const ScAddress& rPos, - const String& rText, const formula::FormulaGrammar::Grammar eGrammar ) + const String& rText, const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar ) { ScDocument* pDoc = rDocShell.GetDocument(); ScBaseCell* pNewCell = NULL; @@ -974,7 +981,7 @@ ScBaseCell* ScDocFunc::InterpretEnglishString( const ScAddress& rPos, ScTokenArray* pCode; if ( pDoc->IsImportingXML() ) { // temporary formula string as string tokens - pCode = lcl_ScDocFunc_CreateTokenArrayXML( rText ); + pCode = lcl_ScDocFunc_CreateTokenArrayXML( rText, rFormulaNmsp, eGrammar ); pDoc->IncXMLImportedFormulaCount( rText.Len() ); } else @@ -1011,8 +1018,8 @@ ScBaseCell* ScDocFunc::InterpretEnglishString( const ScAddress& rPos, BOOL ScDocFunc::SetCellText( const ScAddress& rPos, const String& rText, - BOOL bInterpret, BOOL bEnglish, BOOL bApi, - const formula::FormulaGrammar::Grammar eGrammar ) + BOOL bInterpret, BOOL bEnglish, BOOL bApi, + const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar ) { // SetCellText ruft PutCell oder SetNormalString @@ -1025,12 +1032,15 @@ BOOL ScDocFunc::SetCellText( const ScAddress& rPos, const String& rText, // code moved to own method InterpretEnglishString because it is also used in // ScCellRangeObj::setFormulaArray - pNewCell = InterpretEnglishString( rPos, rText, eGrammar ); + pNewCell = InterpretEnglishString( rPos, rText, rFormulaNmsp, eGrammar ); } // sonst Null behalten -> SetString mit lokalen Formeln/Zahlformat } else if ( rText.Len() ) + { + OSL_ENSURE( rFormulaNmsp.Len() == 0, "ScDocFunc::SetCellText - formula namespace, but do not interpret?" ); pNewCell = ScBaseCell::CreateTextCell( rText, pDoc ); // immer Text + } if (pNewCell) return PutCell( rPos, pNewCell, bApi ); @@ -1047,7 +1057,7 @@ bool ScDocFunc::ShowNote( const ScAddress& rPos, bool bShow ) if( !pNote || (bShow == pNote->IsCaptionShown()) ) return false; // move the caption to internal or hidden layer and create undo action - pNote->ShowCaption( bShow ); + pNote->ShowCaption( rPos, bShow ); if( rDoc.IsUndoEnabled() ) rDocShell.GetUndoManager()->AddUndoAction( new ScUndoShowHideNote( rDocShell, rPos, bShow ) ); @@ -1075,7 +1085,7 @@ bool ScDocFunc::SetNoteText( const ScAddress& rPos, const String& rText, BOOL bA aNewText.ConvertLineEnd(); //! ist das noetig ??? if( ScPostIt* pNote = (aNewText.Len() > 0) ? pDoc->GetOrCreateNote( rPos ) : pDoc->GetNote( rPos ) ) - pNote->SetText( aNewText ); + pNote->SetText( rPos, aNewText ); //! Undo !!! @@ -1099,23 +1109,26 @@ bool ScDocFunc::ReplaceNote( const ScAddress& rPos, const String& rNoteText, con ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer(); SfxUndoManager* pUndoMgr = (pDrawLayer && rDoc.IsUndoEnabled()) ? rDocShell.GetUndoManager() : 0; - // collect drawing undo actions for deleting/inserting caption obejcts - if( pUndoMgr ) - pDrawLayer->BeginCalcUndo(); - - // delete old note ScNoteData aOldData; - if( ScPostIt* pOldNote = rDoc.ReleaseNote( rPos ) ) + ScPostIt* pOldNote = rDoc.ReleaseNote( rPos ); + if( pOldNote ) { + // ensure existing caption object before draw undo tracking starts + pOldNote->GetOrCreateCaption( rPos ); // rescue note data for undo aOldData = pOldNote->GetNoteData(); - // delete the note (creates drawing undo action for the caption object) - delete pOldNote; } + // collect drawing undo actions for deleting/inserting caption obejcts + if( pUndoMgr ) + pDrawLayer->BeginCalcUndo(); + + // delete the note (creates drawing undo action for the caption object) + delete pOldNote; + // create new note (creates drawing undo action for the new caption object) ScNoteData aNewData; - if( ScPostIt* pNewNote = ScNoteUtil::CreateNoteFromString( rDoc, rPos, rNoteText, false ) ) + if( ScPostIt* pNewNote = ScNoteUtil::CreateNoteFromString( rDoc, rPos, rNoteText, false, true ) ) { if( pAuthor ) pNewNote->SetAuthor( *pAuthor ); if( pDate ) pNewNote->SetDate( *pDate ); @@ -1340,6 +1353,14 @@ BOOL ScDocFunc::InsertCells( const ScRange& rRange, const ScMarkData* pTabMark, } } + ScMarkData aFullMark( aMark ); // including scenario sheets + for( i=0; i<nTabCount; i++ ) + if( aMark.GetTableSelect( i ) ) + { + for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) + aFullMark.SelectTable( j, TRUE ); + } + SCTAB nSelCount = aMark.GetSelectCount(); // zugehoerige Szenarien auch anpassen @@ -1430,8 +1451,8 @@ BOOL ScDocFunc::InsertCells( const ScRange& rRange, const ScMarkData* pTabMark, pDoc->ExtendMerge( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i ); pDoc->ExtendOverlapped( nMergeStartX, nMergeStartY, nMergeEndX, nMergeEndY, i ); - if(( eCmd == INS_CELLSDOWN && ( nMergeStartX != nMergeTestStartX || nMergeEndX != nMergeTestEndX ))|| - eCmd == INS_CELLSRIGHT && ( nMergeStartY != nMergeTestStartY || nMergeEndY != nMergeTestEndY ) ) + if(( eCmd == INS_CELLSDOWN && ( nMergeStartX != nMergeTestStartX || nMergeEndX != nMergeTestEndX )) || + (eCmd == INS_CELLSRIGHT && ( nMergeStartY != nMergeTestStartY || nMergeEndY != nMergeTestEndY )) ) { if (!bApi) rDocShell.ErrorMessage(STR_MSSG_INSERTCELLS_0); @@ -1543,66 +1564,22 @@ BOOL ScDocFunc::InsertCells( const ScRange& rRange, const ScMarkData* pTabMark, switch (eCmd) { case INS_CELLSDOWN: - bSuccess = TRUE; - for( i=0; i<nTabCount; i++ ) - { - if( aMark.GetTableSelect( i ) ) - { - SCTAB nScenarioCount = 0; - for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) - nScenarioCount ++; - - bSuccess &= pDoc->InsertRow( nStartCol, i, nEndCol, i+nScenarioCount, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc ); - } - } + bSuccess = pDoc->InsertRow( nStartCol, 0, nEndCol, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &aFullMark ); nPaintEndY = MAXROW; break; case INS_INSROWS: - bSuccess = TRUE; - for( i=0; i<nTabCount; i++ ) - { - if( aMark.GetTableSelect( i ) ) - { - SCTAB nScenarioCount = 0; - for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) - nScenarioCount ++; - - bSuccess &= pDoc->InsertRow( 0, i, MAXCOL, i+nScenarioCount, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc ); - } - } + bSuccess = pDoc->InsertRow( 0, 0, MAXCOL, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &aFullMark ); nPaintStartX = 0; nPaintEndX = MAXCOL; nPaintEndY = MAXROW; nPaintFlags |= PAINT_LEFT; break; case INS_CELLSRIGHT: - bSuccess = TRUE; - for( i=0; i<nTabCount; i++ ) - { - if( aMark.GetTableSelect( i ) ) - { - SCTAB nScenarioCount = 0; - for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) - nScenarioCount ++; - - bSuccess &= pDoc->InsertCol( nStartRow, i, nEndRow, i+nScenarioCount, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc ); - } - } + bSuccess = pDoc->InsertCol( nStartRow, 0, nEndRow, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &aFullMark ); nPaintEndX = MAXCOL; break; case INS_INSCOLS: - bSuccess = TRUE; - for( i=0; i<nTabCount; i++ ) - { - if( aMark.GetTableSelect( i ) ) - { - SCTAB nScenarioCount = 0; - for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) - nScenarioCount ++; - - bSuccess &= pDoc->InsertCol( 0, i, MAXROW, i+nScenarioCount, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc ); - } - } + bSuccess = pDoc->InsertCol( 0, 0, MAXROW, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &aFullMark ); nPaintStartY = 0; nPaintEndY = MAXROW; nPaintEndX = MAXCOL; @@ -1795,6 +1772,14 @@ BOOL ScDocFunc::DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark, } } + ScMarkData aFullMark( aMark ); // including scenario sheets + for( i=0; i<nTabCount; i++ ) + if( aMark.GetTableSelect( i ) ) + { + for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) + aFullMark.SelectTable( j, TRUE ); + } + SCTAB nSelCount = aMark.GetSelectCount(); SCCOL nUndoStartX = nStartCol; @@ -2035,66 +2020,22 @@ BOOL ScDocFunc::DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark, switch (eCmd) { case DEL_CELLSUP: - for( i=0; i<nTabCount; i++ ) - { - if( aMark.GetTableSelect( i ) ) - { - SCTAB nScenarioCount = 0; - - for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) - nScenarioCount ++; - - pDoc->DeleteRow( nStartCol, i, nEndCol, i+nScenarioCount, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc ); - } - } + pDoc->DeleteRow( nStartCol, 0, nEndCol, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, NULL, &aFullMark ); nPaintEndY = MAXROW; break; case DEL_DELROWS: - for( i=0; i<nTabCount; i++ ) - { - if( aMark.GetTableSelect( i ) ) - { - SCTAB nScenarioCount = 0; - - for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) - nScenarioCount ++; - - pDoc->DeleteRow( 0, i, MAXCOL, i+nScenarioCount, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &bUndoOutline ); - } - } + pDoc->DeleteRow( 0, 0, MAXCOL, MAXTAB, nStartRow, static_cast<SCSIZE>(nEndRow-nStartRow+1), pRefUndoDoc, &bUndoOutline, &aFullMark ); nPaintStartX = 0; nPaintEndX = MAXCOL; nPaintEndY = MAXROW; nPaintFlags |= PAINT_LEFT; break; case DEL_CELLSLEFT: - for( i=0; i<nTabCount; i++ ) - { - if( aMark.GetTableSelect( i ) ) - { - SCTAB nScenarioCount = 0; - - for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) - nScenarioCount ++; - - pDoc->DeleteCol( nStartRow, i, nEndRow, i+nScenarioCount, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc ); - } - } + pDoc->DeleteCol( nStartRow, 0, nEndRow, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, NULL, &aFullMark ); nPaintEndX = MAXCOL; break; case DEL_DELCOLS: - for( i=0; i<nTabCount; i++ ) - { - if( aMark.GetTableSelect( i ) ) - { - SCTAB nScenarioCount = 0; - - for( SCTAB j = i+1; j<nTabCount && pDoc->IsScenario(j); j++ ) - nScenarioCount ++; - - pDoc->DeleteCol( 0, i, MAXROW, i+nScenarioCount, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &bUndoOutline ); - } - } + pDoc->DeleteCol( 0, 0, MAXROW, MAXTAB, nStartCol, static_cast<SCSIZE>(nEndCol-nStartCol+1), pRefUndoDoc, &bUndoOutline, &aFullMark ); nPaintStartY = 0; nPaintEndY = MAXROW; nPaintEndX = MAXCOL; @@ -2109,8 +2050,9 @@ BOOL ScDocFunc::DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark, if ( bRecord ) { - for ( i=nStartTab; i<=nTabCount; i++) - pRefUndoDoc->DeleteAreaTab(nUndoStartX,nUndoStartY,nUndoEndX,nUndoEndY, i, IDF_ALL); + for( i=0; i<nTabCount; i++ ) + if( aFullMark.GetTableSelect( i ) ) + pRefUndoDoc->DeleteAreaTab(nUndoStartX,nUndoStartY,nUndoEndX,nUndoEndY, i, IDF_ALL); // alle Tabellen anlegen, damit Formeln kopiert werden koennen: pUndoDoc->AddUndoTab( 0, nTabCount-1, FALSE, FALSE ); @@ -2136,6 +2078,12 @@ BOOL ScDocFunc::DeleteCells( const ScRange& rRange, const ScMarkData* pTabMark, nUndoPos ++; } } + + if( !bDeletingMerge ) + { + rDocShell.GetUndoManager()->LeaveListAction(); + } + rDocShell.GetUndoManager()->AddUndoAction( new ScUndoDeleteCells( &rDocShell, ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ),nUndoPos, pTabs, pScenarios, eCmd, pUndoDoc, pUndoData ) ); @@ -2492,9 +2440,13 @@ BOOL ScDocFunc::MoveBlock( const ScRange& rSource, const ScAddress& rDestPos, /* Paste cell notes and drawing objects after adjusting formula references and row heights. There are no cell notes or drawing objects, if the - clipdoc does not contain a drawing layer. */ + clipdoc does not contain a drawing layer. + #i102056# Passing IDF_NOTE only would overwrite cell contents with + empty note cells, therefore the special modifier IDF_ADDNOTES is passed + here too which changes the behaviour of ScColumn::CopyFromClip() to not + touch existing cells. */ if ( pClipDoc->GetDrawLayer() ) - pDoc->CopyFromClip( aPasteDest, aDestMark, IDF_NOTE | IDF_OBJECTS, + pDoc->CopyFromClip( aPasteDest, aDestMark, IDF_NOTE | IDF_ADDNOTES | IDF_OBJECTS, pRefUndoDoc, pClipDoc, TRUE, FALSE, bIncludeFiltered ); if (bRecord) @@ -3193,103 +3145,156 @@ BOOL ScDocFunc::RemovePageBreak( BOOL bColumn, const ScAddress& rPos, //------------------------------------------------------------------------ -BOOL lcl_ValidPassword( ScDocument* pDoc, SCTAB nTab, - const String& rPassword, - uno::Sequence<sal_Int8>* pReturnOld = NULL ) +void ScDocFunc::ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect ) { - uno::Sequence<sal_Int8> aOldPassword; - if ( nTab == TABLEID_DOC ) - { - if (pDoc->IsDocProtected()) - aOldPassword = pDoc->GetDocPassword(); - } - else + ScDocument* pDoc = rDocShell.GetDocument(); + + pDoc->SetTabProtection(nTab, &rProtect); + if (pDoc->IsUndoEnabled()) { - if (pDoc->IsTabProtected(nTab)) - aOldPassword = pDoc->GetTabPassword(nTab); - } + ScTableProtection* pProtect = pDoc->GetTabProtection(nTab); + DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!"); + if (pProtect) + { + ::std::auto_ptr<ScTableProtection> p(new ScTableProtection(*pProtect)); + p->setProtected(true); // just in case ... + rDocShell.GetUndoManager()->AddUndoAction( + new ScUndoTabProtect(&rDocShell, nTab, p) ); - if (pReturnOld) - *pReturnOld = aOldPassword; + // ownership of auto_ptr now transferred to ScUndoTabProtect. + } + } - return ((aOldPassword.getLength() == 0) || SvPasswordHelper::CompareHashPassword(aOldPassword, rPassword)); + rDocShell.PostPaintGridAll(); + ScDocShellModificator aModificator(rDocShell); + aModificator.SetDocumentModified(); } -BOOL ScDocFunc::Protect( SCTAB nTab, const String& rPassword, BOOL bApi ) +BOOL ScDocFunc::Protect( SCTAB nTab, const String& rPassword, BOOL /*bApi*/ ) { - ScDocShellModificator aModificator( rDocShell ); - ScDocument* pDoc = rDocShell.GetDocument(); - BOOL bUndo(pDoc->IsUndoEnabled()); - BOOL bOk = lcl_ValidPassword( pDoc, nTab, rPassword); - if ( bOk ) - { - uno::Sequence<sal_Int8> aPass; - if (rPassword.Len()) - SvPasswordHelper::GetHashPassword(aPass, rPassword); - - if (bUndo) + if (nTab == TABLEID_DOC) + { + // document protection + ScDocProtection aProtection; + aProtection.setProtected(true); + aProtection.setPassword(rPassword); + pDoc->SetDocProtection(&aProtection); + if (pDoc->IsUndoEnabled()) { - rDocShell.GetUndoManager()->AddUndoAction( - new ScUndoProtect( &rDocShell, nTab, TRUE, aPass ) ); + ScDocProtection* pProtect = pDoc->GetDocProtection(); + DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScDocProtection pointer is NULL!"); + if (pProtect) + { + ::std::auto_ptr<ScDocProtection> p(new ScDocProtection(*pProtect)); + p->setProtected(true); // just in case ... + rDocShell.GetUndoManager()->AddUndoAction( + new ScUndoDocProtect(&rDocShell, p) ); + // ownership of auto_ptr is transferred to ScUndoDocProtect. + } } - - if ( nTab == TABLEID_DOC ) - pDoc->SetDocProtection( TRUE, aPass ); - else - pDoc->SetTabProtection( nTab, TRUE, aPass ); - - rDocShell.PostPaintGridAll(); - aModificator.SetDocumentModified(); } - else if (!bApi) + else { - // different password was set before + // sheet protection -//! rDocShell.ErrorMessage(...); - - InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) ); - aBox.Execute(); + ScTableProtection aProtection; + aProtection.setProtected(true); + aProtection.setPassword(rPassword); + pDoc->SetTabProtection(nTab, &aProtection); + if (pDoc->IsUndoEnabled()) + { + ScTableProtection* pProtect = pDoc->GetTabProtection(nTab); + DBG_ASSERT(pProtect, "ScDocFunc::Unprotect: ScTableProtection pointer is NULL!"); + if (pProtect) + { + ::std::auto_ptr<ScTableProtection> p(new ScTableProtection(*pProtect)); + p->setProtected(true); // just in case ... + rDocShell.GetUndoManager()->AddUndoAction( + new ScUndoTabProtect(&rDocShell, nTab, p) ); + // ownership of auto_ptr now transferred to ScUndoTabProtect. + } + } } - return bOk; + rDocShell.PostPaintGridAll(); + ScDocShellModificator aModificator( rDocShell ); + aModificator.SetDocumentModified(); + + return true; } BOOL ScDocFunc::Unprotect( SCTAB nTab, const String& rPassword, BOOL bApi ) { - ScDocShellModificator aModificator( rDocShell ); - ScDocument* pDoc = rDocShell.GetDocument(); - BOOL bUndo(pDoc->IsUndoEnabled()); - uno::Sequence<sal_Int8> aOldPassword; - uno::Sequence<sal_Int8> aPass; - BOOL bOk = lcl_ValidPassword( pDoc, nTab, rPassword, &aOldPassword ); - if ( bOk ) - { - uno::Sequence<sal_Int8> aEmptyPass; - if ( nTab == TABLEID_DOC ) - pDoc->SetDocProtection( FALSE, aEmptyPass ); - else - pDoc->SetTabProtection( nTab, FALSE, aEmptyPass ); - if (bUndo) + if (nTab == TABLEID_DOC) + { + // document protection + + ScDocProtection* pDocProtect = pDoc->GetDocProtection(); + if (!pDocProtect || !pDocProtect->isProtected()) + // already unprotected (should not happen)! + return true; + + // save the protection state before unprotect (for undo). + ::std::auto_ptr<ScDocProtection> pProtectCopy(new ScDocProtection(*pDocProtect)); + + if (!pDocProtect->verifyPassword(rPassword)) { - rDocShell.GetUndoManager()->AddUndoAction( - new ScUndoProtect( &rDocShell, nTab, FALSE, aOldPassword ) ); + if (!bApi) + { + InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) ); + aBox.Execute(); + } + return false; } - rDocShell.PostPaintGridAll(); - aModificator.SetDocumentModified(); + pDoc->SetDocProtection(NULL); + if (pDoc->IsUndoEnabled()) + { + pProtectCopy->setProtected(false); + rDocShell.GetUndoManager()->AddUndoAction( + new ScUndoDocProtect(&rDocShell, pProtectCopy) ); + // ownership of auto_ptr now transferred to ScUndoDocProtect. + } } - else if (!bApi) + else { -//! rDocShell.ErrorMessage(...); + // sheet protection + + ScTableProtection* pTabProtect = pDoc->GetTabProtection(nTab); + if (!pTabProtect || !pTabProtect->isProtected()) + // already unprotected (should not happen)! + return true; + + // save the protection state before unprotect (for undo). + ::std::auto_ptr<ScTableProtection> pProtectCopy(new ScTableProtection(*pTabProtect)); + if (!pTabProtect->verifyPassword(rPassword)) + { + if (!bApi) + { + InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) ); + aBox.Execute(); + } + return false; + } - InfoBox aBox( rDocShell.GetActiveDialogParent(), String( ScResId( SCSTR_WRONGPASSWORD ) ) ); - aBox.Execute(); + pDoc->SetTabProtection(nTab, NULL); + if (pDoc->IsUndoEnabled()) + { + pProtectCopy->setProtected(false); + rDocShell.GetUndoManager()->AddUndoAction( + new ScUndoTabProtect(&rDocShell, nTab, pProtectCopy) ); + // ownership of auto_ptr now transferred to ScUndoTabProtect. + } } - return bOk; + rDocShell.PostPaintGridAll(); + ScDocShellModificator aModificator( rDocShell ); + aModificator.SetDocumentModified(); + + return true; } //------------------------------------------------------------------------ @@ -3516,9 +3521,8 @@ BOOL ScDocFunc::AutoFormat( const ScRange& rRange, const ScMarkData* pTabMark, //------------------------------------------------------------------------ BOOL ScDocFunc::EnterMatrix( const ScRange& rRange, const ScMarkData* pTabMark, - const ScTokenArray* pTokenArray, - const String& rString, BOOL bApi, BOOL bEnglish, - const formula::FormulaGrammar::Grammar eGrammar ) + const ScTokenArray* pTokenArray, const String& rString, BOOL bApi, BOOL bEnglish, + const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar ) { ScDocShellModificator aModificator( rDocShell ); @@ -3565,7 +3569,7 @@ BOOL ScDocFunc::EnterMatrix( const ScRange& rRange, const ScMarkData* pTabMark, } else if ( pDoc->IsImportingXML() ) { - ScTokenArray* pCode = lcl_ScDocFunc_CreateTokenArrayXML( rString ); + ScTokenArray* pCode = lcl_ScDocFunc_CreateTokenArrayXML( rString, rFormulaNmsp, eGrammar ); pDoc->InsertMatrixFormula( nStartCol, nStartRow, nEndCol, nEndRow, aMark, EMPTY_STRING, pCode, eGrammar); delete pCode; @@ -4495,11 +4499,11 @@ BOOL ScDocFunc::ResizeMatrix( const ScRange& rOldRange, const ScAddress& rNewEnd if ( DeleteContents( aMark, IDF_CONTENTS, TRUE, bApi ) ) { // GRAM_PODF_A1 for API compatibility. - bRet = EnterMatrix( aNewRange, &aMark, NULL, aFormula, bApi, FALSE,formula::FormulaGrammar::GRAM_PODF_A1 ); + bRet = EnterMatrix( aNewRange, &aMark, NULL, aFormula, bApi, FALSE, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 ); if (!bRet) { // versuchen, alten Zustand wiederherzustellen - EnterMatrix( rOldRange, &aMark, NULL, aFormula, bApi, FALSE,formula::FormulaGrammar::GRAM_PODF_A1 ); + EnterMatrix( rOldRange, &aMark, NULL, aFormula, bApi, FALSE, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 ); } } diff --git a/sc/source/ui/docshell/docsh.cxx b/sc/source/ui/docshell/docsh.cxx index e360e93bae5d..c62c2dc41fdf 100644 --- a/sc/source/ui/docshell/docsh.cxx +++ b/sc/source/ui/docshell/docsh.cxx @@ -79,11 +79,6 @@ #include <sot/formats.hxx> #define SOT_FORMATSTR_ID_STARCALC_30 SOT_FORMATSTR_ID_STARCALC -//REMOVE #ifndef SO2_DECL_SVSTORAGESTREAM_DEFINED -//REMOVE #define SO2_DECL_SVSTORAGESTREAM_DEFINED -//REMOVE SO2_DECL_REF(SotStorageStream) -//REMOVE #endif - // INCLUDE --------------------------------------------------------------- #include "cell.hxx" @@ -97,7 +92,6 @@ #include "scresid.hxx" #include "sc.hrc" #include "globstr.hrc" -//CHINA001 #include "tpstat.hxx" #include "scerrors.hxx" #include "brdcst.hxx" #include "stlpool.hxx" @@ -126,6 +120,7 @@ #include "cfgids.hxx" #include "warnpassword.hxx" #include "optsolver.hxx" +#include "tabprotection.hxx" #include "docsh.hxx" #include "docshimp.hxx" @@ -406,7 +401,7 @@ BOOL ScDocShell::LoadXML( SfxMedium* pLoadMedium, const ::com::sun::star::uno::R bRet = aImport.Import(sal_True, nError); if ( nError ) - pLoadMedium->SetError( nError ); + pLoadMedium->SetError( nError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); aDocument.SetXMLFromWrapper( FALSE ); AfterXMLLoading(bRet); @@ -467,10 +462,10 @@ BOOL __EXPORT ScDocShell::Load( SfxMedium& rMedium ) } if (!bRet && !rMedium.GetError()) - rMedium.SetError( SVSTREAM_FILEFORMAT_ERROR ); + rMedium.SetError( SVSTREAM_FILEFORMAT_ERROR, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); if (rMedium.GetError()) - SetError( rMedium.GetError() ); + SetError( rMedium.GetError(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); InitItems(); CalcOutputFactor(); @@ -751,7 +746,7 @@ void __EXPORT ScDocShell::Notify( SfxBroadcaster&, const SfxHint& rHint ) } if ( !bSuccess ) - SetError( ERRCODE_IO_ABORT ); // this error code will produce no error message, but will break the further saving process + SetError( ERRCODE_IO_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); // this error code will produce no error message, but will break the further saving process } } break; @@ -853,7 +848,7 @@ BOOL __EXPORT ScDocShell::ConvertFrom( SfxMedium& rMedium ) if (eError != eERR_OK) { if (!GetError()) - SetError(eError); + SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) )); } else bRet = TRUE; @@ -884,7 +879,7 @@ BOOL __EXPORT ScDocShell::ConvertFrom( SfxMedium& rMedium ) if (eError != eERR_OK) { if (!GetError()) - SetError(eError); + SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) )); if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK ) bRet = TRUE; @@ -923,13 +918,13 @@ BOOL __EXPORT ScDocShell::ConvertFrom( SfxMedium& rMedium ) if (eError == SCWARN_IMPORT_RANGE_OVERFLOW) { if (!GetError()) - SetError(eError); + SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) )); bRet = TRUE; } else if (eError != eERR_OK) { if (!GetError()) - SetError(eError); + SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) )); } else bRet = TRUE; @@ -989,12 +984,12 @@ BOOL __EXPORT ScDocShell::ConvertFrom( SfxMedium& rMedium ) if (eError != eERR_OK) { if (!GetError()) - SetError(eError); + SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) )); } else if ( bOverflow ) { if (!GetError()) - SetError(SCWARN_IMPORT_RANGE_OVERFLOW); + SetError(SCWARN_IMPORT_RANGE_OVERFLOW, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) )); } bSetColWidths = TRUE; bSetSimpleTextColWidths = TRUE; @@ -1024,7 +1019,7 @@ BOOL __EXPORT ScDocShell::ConvertFrom( SfxMedium& rMedium ) if (eError != eERR_OK) { if (!GetError()) - SetError(eError); + SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) )); bRet = ( eError == SCWARN_IMPORT_RANGE_OVERFLOW ); } else @@ -1068,7 +1063,7 @@ BOOL __EXPORT ScDocShell::ConvertFrom( SfxMedium& rMedium ) if (eError != eERR_OK) { if (!GetError()) - SetError(eError); + SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) )); if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK ) bRet = TRUE; @@ -1103,7 +1098,7 @@ BOOL __EXPORT ScDocShell::ConvertFrom( SfxMedium& rMedium ) } if ( eError != eERR_OK && !GetError() ) - SetError(eError); + SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) )); bSetColWidths = TRUE; bSetSimpleTextColWidths = TRUE; bSetRowHeights = TRUE; @@ -1116,7 +1111,7 @@ BOOL __EXPORT ScDocShell::ConvertFrom( SfxMedium& rMedium ) if (eError != eERR_OK) { if (!GetError()) - SetError( eError ); + SetError( eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK ) bRet = TRUE; } @@ -1142,7 +1137,7 @@ BOOL __EXPORT ScDocShell::ConvertFrom( SfxMedium& rMedium ) if (eError != eERR_OK) { if (!GetError()) - SetError(eError); + SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) )); if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK ) bRet = TRUE; @@ -1161,7 +1156,7 @@ BOOL __EXPORT ScDocShell::ConvertFrom( SfxMedium& rMedium ) } if ( eError != eERR_OK && !GetError() ) - SetError(eError); + SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) )); } else if (aFltName.EqualsAscii(pFilterHtml) || aFltName.EqualsAscii(pFilterHtmlWebQ)) { @@ -1181,7 +1176,7 @@ BOOL __EXPORT ScDocShell::ConvertFrom( SfxMedium& rMedium ) if (eError != eERR_OK) { if (!GetError()) - SetError(eError); + SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) )); if( ( eError & ERRCODE_WARNING_MASK ) == ERRCODE_WARNING_MASK ) bRet = TRUE; @@ -1198,12 +1193,12 @@ BOOL __EXPORT ScDocShell::ConvertFrom( SfxMedium& rMedium ) } if ( eError != eERR_OK && !GetError() ) - SetError(eError); + SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) )); } else { if (!GetError()) - SetError(SCERR_IMPORT_NI); + SetError(SCERR_IMPORT_NI, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) )); } if (!bCalc3) @@ -1327,6 +1322,16 @@ BOOL __EXPORT ScDocShell::SaveAs( SfxMedium& rMedium ) { RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::SaveAs" ); +#if ENABLE_SHEET_PROTECTION + ScTabViewShell* pViewShell = GetBestViewShell(); + if (pViewShell && ScPassHashHelper::needsPassHashRegen(aDocument, PASSHASH_OOO)) + { + if (!pViewShell->ExecuteRetypePassDlg(PASSHASH_OOO)) + // password re-type cancelled. Don't save the document. + return false; + } +#endif + ScRefreshTimerProtector( aDocument.GetRefreshTimerControlAddress() ); PrepareSaveGuard aPrepareGuard( *this); @@ -1792,7 +1797,6 @@ void ScDocShell::AsciiSave( SvStream& rStream, const ScImportOptions& rAsciiOpt rStream.SetNumberFormatInt( nOldNumberFormatInt ); } - BOOL __EXPORT ScDocShell::ConvertTo( SfxMedium &rMed ) { RTL_LOGFILE_CONTEXT_AUTHOR ( aLog, "sc", "nn93723", "ScDocShell::ConvertTo" ); @@ -1846,15 +1850,39 @@ BOOL __EXPORT ScDocShell::ConvertTo( SfxMedium &rMed ) aDocument.SetExtDocOptions( pExtDocOpt = new ScExtDocOptions ); pViewShell->GetViewData()->WriteExtOptions( *pExtDocOpt ); - /* #115980 #If the imported document contained an encrypted password - - determine if we should save without it. */ - ScExtDocSettings& rDocSett = pExtDocOpt->GetDocSettings(); - if( rDocSett.mbEncrypted ) +#if ENABLE_SHEET_PROTECTION + bool bNeedRetypePassDlg = ScPassHashHelper::needsPassHashRegen(aDocument, PASSHASH_XL); + if (bNeedRetypePassDlg && !pViewShell->ExecuteRetypePassDlg(PASSHASH_XL)) + { + SetError( ERRCODE_ABORT ); + return false; + } +#else + + do { + SfxItemSet* pSet = rMed.GetItemSet(); + if (!pSet) + break; + + const SfxPoolItem* pItem = NULL; + if (SFX_ITEM_SET != pSet->GetItemState(SID_PASSWORD, sal_True, &pItem)) + // password is not set. + break; + + /* #115980 #If the imported document contained an encrypted password - + determine if we should save without it. */ bDoSave = ScWarnPassword::WarningOnPassword( rMed ); - // #i42858# warn only on time - rDocSett.mbEncrypted = false; + + if (bDoSave) + { + // #i42858# warn only one time + pSet->ClearItem(SID_PASSWORD); + } } + while (false); + +#endif } if( bDoSave ) @@ -1867,7 +1895,7 @@ BOOL __EXPORT ScDocShell::ConvertTo( SfxMedium &rMed ) FltError eError = ScFormatFilter::Get().ScExportExcel5( rMed, &aDocument, eFormat, RTL_TEXTENCODING_MS_1252 ); if( eError && !GetError() ) - SetError( eError ); + SetError( eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); // don't return false for warnings bRet = ((eError & ERRCODE_WARNING_MASK) == ERRCODE_WARNING_MASK) || (eError == eERR_OK); @@ -1875,7 +1903,7 @@ BOOL __EXPORT ScDocShell::ConvertTo( SfxMedium &rMed ) else { // export aborted, i.e. "Save without password" warning - SetError( ERRCODE_ABORT ); + SetError( ERRCODE_ABORT, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); } } else if (aFltName.EqualsAscii(pFilterAscii)) @@ -1908,7 +1936,7 @@ BOOL __EXPORT ScDocShell::ConvertTo( SfxMedium &rMed ) if (aDocument.GetTableCount() > 1) if (!rMed.GetError()) - rMed.SetError(SCWARN_EXPORT_ASCII); + rMed.SetError(SCWARN_EXPORT_ASCII, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) )); } } else if (aFltName.EqualsAscii(pFilterDBase)) @@ -1941,11 +1969,11 @@ BOOL __EXPORT ScDocShell::ConvertTo( SfxMedium &rMed ) if ( eError != eERR_OK && (eError & ERRCODE_WARNING_MASK) ) { //! if ( !rMed.GetError() ) -//! rMed.SetError( eError ); +//! rMed.SetError( eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); eError = eERR_OK; } //! else if ( aDocument.GetTableCount() > 1 && !rMed.GetError() ) -//! rMed.SetError( SCWARN_EXPORT_ASCII ); +//! rMed.SetError( SCWARN_EXPORT_ASCII, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); INetURLObject aTmpFile( rMed.GetPhysicalName(), INET_PROT_FILE ); if ( bHasMemo ) @@ -1953,7 +1981,7 @@ BOOL __EXPORT ScDocShell::ConvertTo( SfxMedium &rMed ) if ( eError != eERR_OK ) { if (!GetError()) - SetError(eError); + SetError(eError, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) )); if ( bHasMemo && IsDocument( aTmpFile ) ) KillFile( aTmpFile ); } @@ -1974,7 +2002,7 @@ BOOL __EXPORT ScDocShell::ConvertTo( SfxMedium &rMed ) { KillFile( aTmpFile ); if ( !GetError() ) - SetError( SCERR_EXPORT_DATA ); + SetError( SCERR_EXPORT_DATA, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); } } } @@ -2008,7 +2036,7 @@ BOOL __EXPORT ScDocShell::ConvertTo( SfxMedium &rMed ) if (aDocument.GetTableCount() > 1) if (!rMed.GetError()) - rMed.SetError(SCWARN_EXPORT_ASCII); + rMed.SetError(SCWARN_EXPORT_ASCII, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) )); } } else if (aFltName.EqualsAscii(pFilterSylk)) @@ -2041,13 +2069,13 @@ BOOL __EXPORT ScDocShell::ConvertTo( SfxMedium &rMed ) SetError( *new StringErrorInfo( SCWARN_EXPORT_NONCONVERTIBLE_CHARS, aImExport.GetNonConvertibleChars(), - ERRCODE_BUTTON_OK | ERRCODE_MSG_INFO ) ); + ERRCODE_BUTTON_OK | ERRCODE_MSG_INFO ), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); } } else { if (GetError()) - SetError(SCERR_IMPORT_NI); + SetError(SCERR_IMPORT_NI, ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); } return bRet; } diff --git a/sc/source/ui/docshell/docsh3.cxx b/sc/source/ui/docshell/docsh3.cxx index fcdfa8612a02..fcbfb648ae14 100644 --- a/sc/source/ui/docshell/docsh3.cxx +++ b/sc/source/ui/docshell/docsh3.cxx @@ -1051,8 +1051,8 @@ void ScDocShell::MergeDocument( ScDocument& rOtherDoc, bool bShared, bool bCheck aValue.Erase( 0, 1 ); aValue.Erase( aValue.Len()-1, 1 ); GetDocFunc().EnterMatrix( aSourceRange, - NULL, NULL, aValue, FALSE, FALSE, - formula::FormulaGrammar::GRAM_DEFAULT ); + NULL, NULL, aValue, FALSE, FALSE, + EMPTY_STRING, formula::FormulaGrammar::GRAM_DEFAULT ); } break; case MM_REFERENCE : // do nothing diff --git a/sc/source/ui/docshell/docsh4.cxx b/sc/source/ui/docshell/docsh4.cxx index f73389cb866f..d4df2863eec5 100644 --- a/sc/source/ui/docshell/docsh4.cxx +++ b/sc/source/ui/docshell/docsh4.cxx @@ -1842,6 +1842,10 @@ void lcl_GetPrintData( ScDocShell* pDocShell /*in*/, rOptions = SC_MOD()->GetPrintOptions(); } + // update all pending row heights with a single progress bar, + // instead of a separate progress for each sheet from ScPrintFunc + pDocShell->UpdatePendingRowHeights( MAXTAB, true ); + // get number of total pages rnTotalPages = 0; SCTAB nTabCount = pDocument->GetTableCount(); @@ -2501,10 +2505,14 @@ long __EXPORT ScDocShell::DdeSetData( const String& rItem, pData->GetSymbol( aPos ); // continue with the name's contents } } + + // Address in DDE function must be always parsed as CONV_OOO so that it + // would always work regardless of current address convension. We do this + // because the address item in a DDE entry is *not* normalized when saved + // into ODF. ScRange aRange; - formula::FormulaGrammar::AddressConvention eConv = aDocument.GetAddressConvention(); - BOOL bValid = ( ( aRange.Parse( aPos, &aDocument, eConv ) & SCA_VALID ) || - ( aRange.aStart.Parse( aPos, &aDocument, eConv ) & SCA_VALID ) ); + bool bValid = ( (aRange.Parse(aPos, &aDocument, formula::FormulaGrammar::CONV_OOO ) & SCA_VALID) || + (aRange.aStart.Parse(aPos, &aDocument, formula::FormulaGrammar::CONV_OOO) & SCA_VALID) ); ScServerObject* pObj = NULL; // NULL = error if ( bValid ) diff --git a/sc/source/ui/docshell/docsh5.cxx b/sc/source/ui/docshell/docsh5.cxx index d3b6bb55dcdd..281f03ff3622 100644 --- a/sc/source/ui/docshell/docsh5.cxx +++ b/sc/source/ui/docshell/docsh5.cxx @@ -393,13 +393,51 @@ BOOL ScDocShell::AdjustRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab ) return bChange; } -void ScDocShell::UpdateAllRowHeights() +void ScDocShell::UpdateAllRowHeights( const ScMarkData* pTabMark ) { // update automatic row heights ScSizeDeviceProvider aProv(this); Fraction aZoom(1,1); - aDocument.UpdateAllRowHeights( aProv.GetDevice(), aProv.GetPPTX(), aProv.GetPPTY(), aZoom, aZoom ); + aDocument.UpdateAllRowHeights( aProv.GetDevice(), aProv.GetPPTX(), aProv.GetPPTY(), aZoom, aZoom, pTabMark ); +} + +void ScDocShell::UpdatePendingRowHeights( SCTAB nUpdateTab, bool bBefore ) +{ + BOOL bIsUndoEnabled = aDocument.IsUndoEnabled(); + aDocument.EnableUndo( FALSE ); + if ( bBefore ) // check all sheets up to nUpdateTab + { + SCTAB nTabCount = aDocument.GetTableCount(); + if ( nUpdateTab >= nTabCount ) + nUpdateTab = nTabCount-1; // nUpdateTab is inclusive + + ScMarkData aUpdateSheets; + SCTAB nTab; + for (nTab=0; nTab<=nUpdateTab; ++nTab) + if ( aDocument.IsPendingRowHeights( nTab ) ) + aUpdateSheets.SelectTable( nTab, TRUE ); + + if (aUpdateSheets.GetSelectCount()) + UpdateAllRowHeights(&aUpdateSheets); // update with a single progress bar + + for (nTab=0; nTab<=nUpdateTab; ++nTab) + if ( aUpdateSheets.GetTableSelect( nTab ) ) + { + aDocument.UpdatePageBreaks( nTab ); + aDocument.SetPendingRowHeights( nTab, FALSE ); + } + } + else // only nUpdateTab + { + if ( aDocument.IsPendingRowHeights( nUpdateTab ) ) + { + AdjustRowHeight( 0, MAXROW, nUpdateTab ); + aDocument.UpdatePageBreaks( nUpdateTab ); + aDocument.SetPendingRowHeights( nUpdateTab, FALSE ); + } + } + aDocument.EnableUndo( bIsUndoEnabled ); } #if OLD_PIVOT_IMPLEMENTATION @@ -827,7 +865,7 @@ BOOL ScDocShell::MoveTable( SCTAB nSrcTab, SCTAB nDestTab, BOOL bCopy, BOOL bRec ++nAdjSource; // new position of source table after CopyTab if ( aDocument.IsTabProtected( nAdjSource ) ) - aDocument.SetTabProtection( nDestTab, TRUE, aDocument.GetTabPassword( nAdjSource ) ); + aDocument.CopyTabProtection(nAdjSource, nDestTab); if (bRecord) { diff --git a/sc/source/ui/docshell/externalrefmgr.cxx b/sc/source/ui/docshell/externalrefmgr.cxx index 637093275bad..9cc0b274028e 100644 --- a/sc/source/ui/docshell/externalrefmgr.cxx +++ b/sc/source/ui/docshell/externalrefmgr.cxx @@ -143,7 +143,8 @@ private: // ============================================================================ ScExternalRefCache::Table::Table() - : mbReferenced( true) // Prevent accidental data loss due to lack of knowledge. + : meReferenced( REFERENCED_MARKED ) + // Prevent accidental data loss due to lack of knowledge. { } @@ -151,14 +152,25 @@ ScExternalRefCache::Table::~Table() { } +void ScExternalRefCache::Table::setReferencedFlag( ScExternalRefCache::Table::ReferencedFlag eFlag ) +{ + meReferenced = eFlag; +} + void ScExternalRefCache::Table::setReferenced( bool bReferenced ) { - mbReferenced = bReferenced; + if (meReferenced != REFERENCED_PERMANENT) + meReferenced = (bReferenced ? REFERENCED_MARKED : UNREFERENCED); +} + +ScExternalRefCache::Table::ReferencedFlag ScExternalRefCache::Table::getReferencedFlag() const +{ + return meReferenced; } bool ScExternalRefCache::Table::isReferenced() const { - return mbReferenced; + return meReferenced != UNREFERENCED; } void ScExternalRefCache::Table::setCell(SCCOL nCol, SCROW nRow, TokenRef pToken, sal_uInt32 nFmtIndex) @@ -737,21 +749,57 @@ bool ScExternalRefCache::setCacheDocReferenced( sal_uInt16 nFileId ) return areAllCacheTablesReferenced(); } -bool ScExternalRefCache::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName ) +bool ScExternalRefCache::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets, bool bPermanent ) { - size_t nIndex = 0; - TableTypeRef pTab = getCacheTable( nFileId, rTabName, false, &nIndex); - if (pTab.get()) + DocItem* pDoc = getDocItem(nFileId); + if (pDoc) { - if (!pTab->isReferenced()) + size_t nIndex = 0; + String aTabNameUpper = ScGlobal::pCharClass->upper( rTabName); + if (lcl_getTableDataIndex( pDoc->maTableNameIndex, aTabNameUpper, nIndex)) { - pTab->setReferenced( true); - addCacheTableToReferenced( nFileId, nIndex); + size_t nStop = ::std::min( nIndex + nSheets, pDoc->maTables.size()); + for (size_t i = nIndex; i < nStop; ++i) + { + TableTypeRef pTab = pDoc->maTables[i]; + if (pTab.get()) + { + Table::ReferencedFlag eNewFlag = (bPermanent ? + Table::REFERENCED_PERMANENT : + Table::REFERENCED_MARKED); + Table::ReferencedFlag eOldFlag = pTab->getReferencedFlag(); + if (eOldFlag != Table::REFERENCED_PERMANENT && eNewFlag != eOldFlag) + { + pTab->setReferencedFlag( eNewFlag); + addCacheTableToReferenced( nFileId, i); + } + } + } } } return areAllCacheTablesReferenced(); } +void ScExternalRefCache::setCacheTableReferencedPermanently( sal_uInt16 nFileId, const String& rTabName, size_t nSheets ) +{ + DocItem* pDoc = getDocItem(nFileId); + if (pDoc) + { + size_t nIndex = 0; + String aTabNameUpper = ScGlobal::pCharClass->upper( rTabName); + if (lcl_getTableDataIndex( pDoc->maTableNameIndex, aTabNameUpper, nIndex)) + { + size_t nStop = ::std::min( nIndex + nSheets, pDoc->maTables.size()); + for (size_t i = nIndex; i < nStop; ++i) + { + TableTypeRef pTab = pDoc->maTables[i]; + if (pTab.get()) + pTab->setReferencedFlag( Table::REFERENCED_PERMANENT); + } + } + } +} + void ScExternalRefCache::setAllCacheTableReferencedStati( bool bReferenced ) { if (bReferenced) @@ -791,9 +839,17 @@ void ScExternalRefCache::setAllCacheTableReferencedStati( bool bReferenced ) TableTypeRef & xTab = rDocItem.maTables[i]; if (xTab.get()) { - xTab->setReferenced( false); - rDocReferenced.maTables[i] = false; - rDocReferenced.mbAllTablesReferenced = false; + if (xTab->getReferencedFlag() == Table::REFERENCED_PERMANENT) + addCacheTableToReferenced( nFileId, i); + else + { + xTab->setReferencedFlag( Table::UNREFERENCED); + rDocReferenced.maTables[i] = false; + rDocReferenced.mbAllTablesReferenced = false; + // An addCacheTableToReferenced() actually may have + // resulted in mbAllReferenced been set. Clear it. + maReferenced.mbAllReferenced = false; + } } } } @@ -1317,8 +1373,9 @@ void ScExternalRefManager::RefCells::moveTable(SCTAB nOldTab, SCTAB nNewTab, boo xNewTab->mnIndex = nNewTab; maTables.insert(itrNew, xNewTab); list<TabItemRef>::iterator itr = itrNew, itrEnd = maTables.end(); - for (++itr; itr != itrEnd; ++itr) - (*itr)->mnIndex += 1; + if (itr != itrEnd) // #i99807# check that itr is not at end already + for (++itr; itr != itrEnd; ++itr) + (*itr)->mnIndex += 1; } else { @@ -1480,9 +1537,19 @@ bool ScExternalRefManager::setCacheDocReferenced( sal_uInt16 nFileId ) return maRefCache.setCacheDocReferenced( nFileId); } -bool ScExternalRefManager::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName ) +bool ScExternalRefManager::setCacheTableReferenced( sal_uInt16 nFileId, const String& rTabName, size_t nSheets ) { - return maRefCache.setCacheTableReferenced( nFileId, rTabName); + return maRefCache.setCacheTableReferenced( nFileId, rTabName, nSheets, false); +} + +void ScExternalRefManager::setCacheTableReferencedPermanently( sal_uInt16 nFileId, const String& rTabName, size_t nSheets ) +{ + if (isInReferenceMarking()) + // Do all maintenance work. + maRefCache.setCacheTableReferenced( nFileId, rTabName, nSheets, true); + else + // Set only the permanent flag. + maRefCache.setCacheTableReferencedPermanently( nFileId, rTabName, nSheets); } void ScExternalRefManager::setAllCacheTableReferencedStati( bool bReferenced ) diff --git a/sc/source/ui/drawfunc/drawsh.cxx b/sc/source/ui/drawfunc/drawsh.cxx index 8b86e0d886ef..63f958763479 100644 --- a/sc/source/ui/drawfunc/drawsh.cxx +++ b/sc/source/ui/drawfunc/drawsh.cxx @@ -230,7 +230,7 @@ void ScDrawShell::ExecDrawAttr( SfxRequest& rReq ) { SdrPageView* pPV = 0; SdrObject* pHit = 0; - if ( pView->PickObj( pWin->PixelToLogic( pViewData->GetMousePosPixel() ), pHit, pPV, SDRSEARCH_DEEP ) ) + if ( pView->PickObj( pWin->PixelToLogic( pViewData->GetMousePosPixel() ), pView->getHitTolLog(), pHit, pPV, SDRSEARCH_DEEP ) ) pObj = pHit; } diff --git a/sc/source/ui/drawfunc/fudraw.cxx b/sc/source/ui/drawfunc/fudraw.cxx index 2dccd6edbfe0..fadb8270b6a6 100644 --- a/sc/source/ui/drawfunc/fudraw.cxx +++ b/sc/source/ui/drawfunc/fudraw.cxx @@ -795,12 +795,12 @@ void FuDraw::ForcePointer(const MouseEvent* pMEvt) SdrPageView* pPV; ScMacroInfo* pInfo = 0; - if ( pView->PickObj(aPnt, pObj, pPV, SDRSEARCH_ALSOONMASTER) ) + if ( pView->PickObj(aPnt, pView->getHitTolLog(), pObj, pPV, SDRSEARCH_ALSOONMASTER) ) { if ( pObj->IsGroupObject() ) { SdrObject* pHit = 0; - if ( pView->PickObj(aMDPos, pHit, pPV, SDRSEARCH_DEEP ) ) + if ( pView->PickObj(aMDPos, pView->getHitTolLog(), pHit, pPV, SDRSEARCH_DEEP ) ) pObj = pHit; } pInfo = ScDrawLayer::GetMacroInfo( pObj ); @@ -825,7 +825,7 @@ void FuDraw::ForcePointer(const MouseEvent* pMEvt) // kann mit ALT unterdrueckt werden pWindow->SetPointer( Pointer( POINTER_REFHAND ) ); // Text-URL / ImageMap } - else if ( !bAlt && pView->PickObj(aPnt, pObj, pPV, SDRSEARCH_PICKMACRO) ) + else if ( !bAlt && pView->PickObj(aPnt, pView->getHitTolLog(), pObj, pPV, SDRSEARCH_PICKMACRO) ) { // kann mit ALT unterdrueckt werden SdrObjMacroHitRec aHitRec; //! muss da noch irgendwas gesetzt werden ???? diff --git a/sc/source/ui/drawfunc/fuins2.cxx b/sc/source/ui/drawfunc/fuins2.cxx index 5dff4041bd22..93abbd48c9e7 100644 --- a/sc/source/ui/drawfunc/fuins2.cxx +++ b/sc/source/ui/drawfunc/fuins2.cxx @@ -167,8 +167,10 @@ void lcl_ChartInit( const uno::Reference < embed::XEmbeddedObject >& xObj, ScVie if ( aRangeListRef->Count() ) { pScDoc->LimitChartIfAll( aRangeListRef ); // limit whole columns/rows to used area + + // update string from modified ranges. The ranges must be in the current formula syntax. String aTmpStr; - aRangeListRef->Format( aTmpStr, SCR_ABS_3D, pScDoc, pScDoc->GetAddressConvention() ); // update string from changed ranges + aRangeListRef->Format( aTmpStr, SCR_ABS_3D, pScDoc, pScDoc->GetAddressConvention() ); aRangeString = aTmpStr; ScChartPositioner aChartPositioner( pScDoc, aRangeListRef ); diff --git a/sc/source/ui/drawfunc/fupoor.cxx b/sc/source/ui/drawfunc/fupoor.cxx index c26d3fdcb5fc..23aefe17c71b 100644 --- a/sc/source/ui/drawfunc/fupoor.cxx +++ b/sc/source/ui/drawfunc/fupoor.cxx @@ -42,6 +42,7 @@ #include "detfunc.hxx" #include "document.hxx" #include <vcl/svapp.hxx> +#include <svx/sdrhittesthelper.hxx> /************************************************************************* |* @@ -333,8 +334,10 @@ BOOL FuPoor::IsDetectiveHit( const Point& rLogicPos ) { USHORT nHitLog = (USHORT) pWindow->PixelToLogic( Size(pView->GetHitTolerancePixel(),0)).Width(); - if ( pObject->IsHit( rLogicPos, nHitLog ) ) + if(SdrObjectPrimitiveHit(*pObject, rLogicPos, nHitLog, *pPV, 0, false)) + { bFound = TRUE; + } } pObject = aIter.Next(); diff --git a/sc/source/ui/drawfunc/fusel.cxx b/sc/source/ui/drawfunc/fusel.cxx index 02fc2e38b0f6..79c466f9f2c3 100644 --- a/sc/source/ui/drawfunc/fusel.cxx +++ b/sc/source/ui/drawfunc/fusel.cxx @@ -171,7 +171,7 @@ BOOL __EXPORT FuSelection::MouseButtonDown(const MouseEvent& rMEvt) else { BOOL bAlt = rMEvt.IsMod2(); - if ( !bAlt && pView->PickObj(aMDPos, pObj, pPV, SDRSEARCH_PICKMACRO) ) + if ( !bAlt && pView->PickObj(aMDPos, pView->getHitTolLog(), pObj, pPV, SDRSEARCH_PICKMACRO) ) { pView->BegMacroObj(aMDPos, pObj, pPV, pWindow); bReturn = TRUE; @@ -179,7 +179,7 @@ BOOL __EXPORT FuSelection::MouseButtonDown(const MouseEvent& rMEvt) else { String sURL, sTarget; - if ( !bAlt && pView->PickObj(aMDPos, pObj, pPV, SDRSEARCH_ALSOONMASTER)) + if ( !bAlt && pView->PickObj(aMDPos, pView->getHitTolLog(), pObj, pPV, SDRSEARCH_ALSOONMASTER)) { // Support for imported Excel docs // Excel is of course not consistent and allows @@ -200,7 +200,7 @@ BOOL __EXPORT FuSelection::MouseButtonDown(const MouseEvent& rMEvt) if ( pObj->IsGroupObject() ) { SdrObject* pHit = NULL; - if ( pView->PickObj(aMDPos, pHit, pPV, SDRSEARCH_DEEP ) ) + if ( pView->PickObj(aMDPos, pView->getHitTolLog(), pHit, pPV, SDRSEARCH_DEEP ) ) pObj = pHit; } diff --git a/sc/source/ui/drawfunc/fusel2.cxx b/sc/source/ui/drawfunc/fusel2.cxx index aa518ee42a81..7c096fd51d71 100644 --- a/sc/source/ui/drawfunc/fusel2.cxx +++ b/sc/source/ui/drawfunc/fusel2.cxx @@ -53,6 +53,7 @@ #include "drwlayer.hxx" #include "docsh.hxx" #include "drawview.hxx" +#include <svx/sdrhittesthelper.hxx> // ----------------------------------------------------------------------- @@ -79,7 +80,7 @@ BOOL FuSelection::TestDetective( SdrPageView* pPV, const Point& rPos ) { USHORT nHitLog = (USHORT) pWindow->PixelToLogic( Size(pView->GetHitTolerancePixel(),0)).Width(); - if ( pObject->IsHit( rPos, nHitLog ) ) + if (SdrObjectPrimitiveHit(*pObject, rPos, nHitLog, *pPV, 0, false)) { ScViewData* pViewData = pViewShell->GetViewData(); ScSplitPos ePos = pViewShell->FindWindow( pWindow ); diff --git a/sc/source/ui/drawfunc/futext.cxx b/sc/source/ui/drawfunc/futext.cxx index 302d1c825a2a..ebcb2ad30802 100644 --- a/sc/source/ui/drawfunc/futext.cxx +++ b/sc/source/ui/drawfunc/futext.cxx @@ -193,7 +193,7 @@ BOOL __EXPORT FuText::MouseButtonDown(const MouseEvent& rMEvt) { if (pHdl == NULL && // pView->TakeTextEditObject(aMDPos, pObj, pPV) ) - pView->PickObj(aMDPos, pObj, pPV, SDRSEARCH_PICKTEXTEDIT) ) + pView->PickObj(aMDPos, pView->getHitTolLog(), pObj, pPV, SDRSEARCH_PICKTEXTEDIT) ) { SdrOutliner* pO = MakeOutliner(); lcl_UpdateHyphenator( *pO, pObj ); @@ -250,7 +250,7 @@ BOOL __EXPORT FuText::MouseButtonDown(const MouseEvent& rMEvt) BOOL bMacro = FALSE; // if (bMacro && pView->TakeMacroObject(aMDPos,pObj,pPV)) - if (bMacro && pView->PickObj(aMDPos, pObj, pPV, SDRSEARCH_PICKMACRO) ) + if (bMacro && pView->PickObj(aMDPos, pView->getHitTolLog(), pObj, pPV, SDRSEARCH_PICKMACRO) ) { pView->BegMacroObj(aMDPos,pObj,pPV,pWindow); diff --git a/sc/source/ui/drawfunc/futext3.cxx b/sc/source/ui/drawfunc/futext3.cxx index 3fc99568e173..701a53aecfcc 100644 --- a/sc/source/ui/drawfunc/futext3.cxx +++ b/sc/source/ui/drawfunc/futext3.cxx @@ -130,7 +130,7 @@ void FuText::StopEditMode(BOOL /*bTextDirection*/) if( pNote ) { // hide the caption object if it is in hidden state - pNote->HideCaptionTemp(); + pNote->ShowCaptionTemp( aNotePos, false ); // update author and date pNote->AutoStamp(); diff --git a/sc/source/ui/formdlg/formula.cxx b/sc/source/ui/formdlg/formula.cxx index 4544c1ca0792..8d631a9f0609 100644 --- a/sc/source/ui/formdlg/formula.cxx +++ b/sc/source/ui/formdlg/formula.cxx @@ -126,7 +126,6 @@ ScFormulaDlg::ScFormulaDlg( SfxBindings* pB, SfxChildWindow* pCW, m_xParser.set(ScServiceProvider::MakeInstance(SC_SERVICE_FORMULAPARS,(ScDocShell*)pDoc->GetDocumentShell()),uno::UNO_QUERY); uno::Reference< beans::XPropertySet> xSet(m_xParser,uno::UNO_QUERY); xSet->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_COMPILEFAP)),uno::makeAny(sal_True)); - xSet->setPropertyValue(::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(SC_UNO_REFERENCEPOS)),uno::makeAny(table::CellAddress(aCursorPos.Tab(),aCursorPos.Col(),aCursorPos.Row()))); m_xOpCodeMapper.set(ScServiceProvider::MakeInstance(SC_SERVICE_OPCODEMAPPER,(ScDocShell*)pDoc->GetDocumentShell()),uno::UNO_QUERY); @@ -657,6 +656,12 @@ uno::Reference< sheet::XFormulaOpCodeMapper> ScFormulaDlg::getFormulaOpCodeMappe { return m_xOpCodeMapper; } + +table::CellAddress ScFormulaDlg::getReferencePosition() const +{ + return table::CellAddress(aCursorPos.Tab(),aCursorPos.Col(),aCursorPos.Row()); +} + ::std::auto_ptr<formula::FormulaTokenArray> ScFormulaDlg::convertToTokenArray(const uno::Sequence< sheet::FormulaToken >& _aTokenList) { ::std::auto_ptr<formula::FormulaTokenArray> pArray(new ScTokenArray()); diff --git a/sc/source/ui/inc/docfunc.hxx b/sc/source/ui/inc/docfunc.hxx index ecdaceb55294..21e295a58fa4 100644 --- a/sc/source/ui/inc/docfunc.hxx +++ b/sc/source/ui/inc/docfunc.hxx @@ -33,7 +33,6 @@ #include <tools/link.hxx> #include "global.hxx" -#include "postit.hxx" #include "formula/grammar.hxx" class ScEditEngineDefaulter; @@ -47,7 +46,7 @@ class ScRangeName; class ScBaseCell; class ScTokenArray; struct ScTabOpParam; - +class ScTableProtection; // --------------------------------------------------------------------------- @@ -90,11 +89,12 @@ public: BOOL bInterpret, BOOL bApi ); BOOL SetCellText( const ScAddress& rPos, const String& rText, BOOL bInterpret, BOOL bEnglish, BOOL bApi, + const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar ); // creates a new cell for use with PutCell ScBaseCell* InterpretEnglishString( const ScAddress& rPos, const String& rText, - const formula::FormulaGrammar::Grammar eGrammar ); + const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar ); bool ShowNote( const ScAddress& rPos, bool bShow = true ); inline bool HideNote( const ScAddress& rPos ) { return ShowNote( rPos, false ); } @@ -135,6 +135,8 @@ public: BOOL RemovePageBreak( BOOL bColumn, const ScAddress& rPos, BOOL bRecord, BOOL bSetModified, BOOL bApi ); + void ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect ); + BOOL Protect( SCTAB nTab, const String& rPassword, BOOL bApi ); BOOL Unprotect( SCTAB nTab, const String& rPassword, BOOL bApi ); @@ -146,6 +148,7 @@ public: BOOL EnterMatrix( const ScRange& rRange, const ScMarkData* pTabMark, const ScTokenArray* pTokenArray, const String& rString, BOOL bApi, BOOL bEnglish, + const String& rFormulaNmsp, const formula::FormulaGrammar::Grammar ); BOOL TabOp( const ScRange& rRange, const ScMarkData* pTabMark, diff --git a/sc/source/ui/inc/docsh.hxx b/sc/source/ui/inc/docsh.hxx index df102a54f355..b8b8d10f0c6e 100644 --- a/sc/source/ui/inc/docsh.hxx +++ b/sc/source/ui/inc/docsh.hxx @@ -290,7 +290,8 @@ public: BOOL IsEditable() const; BOOL AdjustRowHeight( SCROW nStartRow, SCROW nEndRow, SCTAB nTab ); - void UpdateAllRowHeights(); + void UpdateAllRowHeights( const ScMarkData* pTabMark = NULL ); + void UpdatePendingRowHeights( SCTAB nUpdateTab, bool bBefore = false ); #if OLD_PIVOT_IMPLEMENTATION void PivotUpdate( ScPivot* pOldPivot, ScPivot* pNewPivot, diff --git a/sc/source/ui/inc/formula.hxx b/sc/source/ui/inc/formula.hxx index a40a6092fe26..b25811eb9220 100644 --- a/sc/source/ui/inc/formula.hxx +++ b/sc/source/ui/inc/formula.hxx @@ -105,6 +105,7 @@ public: virtual ::std::auto_ptr<formula::FormulaTokenArray> convertToTokenArray(const ::com::sun::star::uno::Sequence< ::com::sun::star::sheet::FormulaToken >& _aTokenList); virtual ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XFormulaParser> getFormulaParser() const; virtual ::com::sun::star::uno::Reference< ::com::sun::star::sheet::XFormulaOpCodeMapper> getFormulaOpCodeMapper() const; + virtual ::com::sun::star::table::CellAddress getReferencePosition() const; virtual BOOL Close(); diff --git a/sc/source/ui/inc/gridwin.hxx b/sc/source/ui/inc/gridwin.hxx index 9b31289d13d0..844d88055578 100644 --- a/sc/source/ui/inc/gridwin.hxx +++ b/sc/source/ui/inc/gridwin.hxx @@ -116,18 +116,19 @@ namespace sdr public: typedef ::std::vector< basegfx::B2DRange > RangeVector; + protected: + basegfx::B2DPolyPolygon impGetOverlayPolyPolygon() const; + private: ScOverlayType mePaintType; RangeVector maRectangles; - virtual void drawGeometry(OutputDevice& rOutputDevice); - virtual void createBaseRange(OutputDevice& rOutputDevice); + // geometry creation for OverlayObject + virtual drawinglayer::primitive2d::Primitive2DSequence createOverlayObjectPrimitive2DSequence(); public: OverlayObjectCell( ScOverlayType eType, const Color& rColor, const RangeVector& rRects); virtual ~OverlayObjectCell(); - - virtual void transform(const basegfx::B2DHomMatrix& rMatrix); }; } // end of namespace overlay diff --git a/sc/source/ui/inc/printfun.hxx b/sc/source/ui/inc/printfun.hxx index 6a8e43fb2e7c..fd607975ff47 100644 --- a/sc/source/ui/inc/printfun.hxx +++ b/sc/source/ui/inc/printfun.hxx @@ -92,7 +92,7 @@ public: Size aUserSize; MapMode aUserMapMode; - Paper ePaper; + Paper ePaper; Orientation eOrientation; USHORT nPaperBin; }; diff --git a/sc/source/ui/inc/protectiondlg.hrc b/sc/source/ui/inc/protectiondlg.hrc new file mode 100644 index 000000000000..79285d3ce125 --- /dev/null +++ b/sc/source/ui/inc/protectiondlg.hrc @@ -0,0 +1,47 @@ +/************************************************************************* + * + * 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: protectiondlg.hrc,v $ + * $Revision: 1.1.2.1 $ + * + * 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. + * + ************************************************************************/ + +#include <sc.hrc> + +#define BTN_OK 1 +#define BTN_CANCEL 2 +#define BTN_HELP 3 + +#define BTN_PROTECT 4 +#define FT_PASSWORD1 5 +#define ED_PASSWORD1 6 +#define FT_PASSWORD2 7 +#define ED_PASSWORD2 8 +#define FL_OPTIONS 9 +#define FT_OPTIONS 10 +#define CLB_OPTIONS 11 + +#define ST_SELECT_LOCKED_CELLS 50 +#define ST_SELECT_UNLOCKED_CELLS 51 diff --git a/sc/source/ui/inc/protectiondlg.hxx b/sc/source/ui/inc/protectiondlg.hxx new file mode 100644 index 000000000000..36330498c941 --- /dev/null +++ b/sc/source/ui/inc/protectiondlg.hxx @@ -0,0 +1,85 @@ +/************************************************************************* + * + * 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: protectiondlg.hxx,v $ + * $Revision: 1.1.2.4 $ + * + * 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_UI_PROTECTION_DLG_HXX +#define SC_UI_PROTECTION_DLG_HXX + +#include <vcl/dialog.hxx> +#include <vcl/button.hxx> +#include <vcl/fixed.hxx> +#include <vcl/edit.hxx> +#include <svx/checklbx.hxx> + +class Window; +class ScTableProtection; + +class ScTableProtectionDlg : public ModalDialog +{ +public: + explicit ScTableProtectionDlg(Window* pParent); + virtual ~ScTableProtectionDlg(); + + virtual short Execute(); + + void SetDialogData(const ScTableProtection& rData); + + void WriteData(ScTableProtection& rData) const; + +private: + ScTableProtectionDlg(); // disabled + + void Init(); + + void EnableOptionalWidgets(bool bEnable = true); + + CheckBox maBtnProtect; + + FixedText maPassword1Text; + Edit maPassword1Edit; + FixedText maPassword2Text; + Edit maPassword2Edit; + + FixedLine maOptionsLine; + FixedText maOptionsText; + SvxCheckListBox maOptionsListBox; + + OKButton maBtnOk; + CancelButton maBtnCancel; + HelpButton maBtnHelp; + + String maSelectLockedCells; + String maSelectUnlockedCells; + + DECL_LINK( OKHdl, OKButton* ); + DECL_LINK( CheckBoxHdl, CheckBox* ); + DECL_LINK( PasswordModifyHdl, Edit* ); +}; + +#endif diff --git a/sc/source/ui/inc/retypepassdlg.hrc b/sc/source/ui/inc/retypepassdlg.hrc new file mode 100644 index 000000000000..fe0f7e8a760a --- /dev/null +++ b/sc/source/ui/inc/retypepassdlg.hrc @@ -0,0 +1,74 @@ +/************************************************************************* + * + * 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: retypepassdlg.hrc,v $ + * $Revision: 1.1.2.2 $ + * + * 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. + * + ************************************************************************/ + +#include <sc.hrc> + +#define BTN_OK 1 +#define BTN_CANCEL 2 +#define BTN_HELP 3 + +#define FT_DESC 10 +#define FL_DOCUMENT 11 +#define FT_DOCSTATUS 12 +#define BTN_RETYPE_DOC 13 + +#define FL_SHEET 112 + +#define FT_SHEETNAME1 113 +#define FT_SHEETSTATUS1 114 +#define BTN_RETYPE_SHEET1 115 + +#define FT_SHEETNAME2 116 +#define FT_SHEETSTATUS2 117 +#define BTN_RETYPE_SHEET2 118 + +#define FT_SHEETNAME3 119 +#define FT_SHEETSTATUS3 120 +#define BTN_RETYPE_SHEET3 121 + +#define FT_SHEETNAME4 122 +#define FT_SHEETSTATUS4 123 +#define BTN_RETYPE_SHEET4 124 + +#define SB_SCROLL 190 + +#define STR_NOT_PROTECTED 200 +#define STR_NOT_PASS_PROTECTED 201 +#define STR_HASH_BAD 202 +#define STR_HASH_GOOD 203 +#define STR_HASH_REGENERATED 204 + +#define FT_PASSWORD1 301 +#define ED_PASSWORD1 302 +#define FT_PASSWORD2 303 +#define ED_PASSWORD2 304 +#define BTN_MATCH_OLD_PASSWORD 305 +#define BTN_RETYPE_PASSWORD 306 +#define BTN_REMOVE_PASSWORD 307 diff --git a/sc/source/ui/inc/retypepassdlg.hxx b/sc/source/ui/inc/retypepassdlg.hxx new file mode 100644 index 000000000000..657773d112f7 --- /dev/null +++ b/sc/source/ui/inc/retypepassdlg.hxx @@ -0,0 +1,177 @@ +/************************************************************************* + * + * 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: retypepassdlg.hxx,v $ + * $Revision: 1.1.2.7 $ + * + * 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_UI_RETYPEPASS_DLG_HXX +#define SC_UI_RETYPEPASS_DLG_HXX + +#include <vcl/dialog.hxx> +#include <vcl/button.hxx> +#include <vcl/fixed.hxx> +#include <vcl/edit.hxx> +#include <vcl/scrbar.hxx> +#include <svx/checklbx.hxx> +#include <svtools/stdctrl.hxx> + +#include "tabprotection.hxx" + +#include <boost/shared_ptr.hpp> + +class Window; +class ScDocProtection; +class ScTableProtection; +class ScDocument; + +class ScRetypePassDlg : public ModalDialog +{ +public: + typedef ::boost::shared_ptr<ScDocProtection> DocProtectionPtr; + typedef ::boost::shared_ptr<ScTableProtection> TabProtectionPtr; + + explicit ScRetypePassDlg(Window* pParent); + virtual ~ScRetypePassDlg(); + + virtual short Execute(); + + void SetDataFromDocument(const ScDocument& rDoc); + void SetDesiredHash(ScPasswordHash eHash); + + /** Write the new set of password data to the document instance to + overwrite the current ones. */ + void WriteNewDataToDocument(ScDocument& rDoc) const; + +private: + ScRetypePassDlg(); // disabled + + void Init(); + void PopulateDialog(); + void SetDocData(); + void SetTableData(size_t nRowPos, SCTAB nTab); + void ResetTableRows(); + + /** Check the status of all hash values to see if it's okay to enable + the OK button. */ + void CheckHashStatus(); + +private: + OKButton maBtnOk; + CancelButton maBtnCancel; + HelpButton maBtnHelp; + + FixedInfo maTextDescription; + + FixedLine maLineDocument; + FixedText maTextDocStatus; + PushButton maBtnRetypeDoc; + + FixedLine maLineSheet; + FixedText maTextSheetName1; + FixedText maTextSheetStatus1; + PushButton maBtnRetypeSheet1; + + FixedText maTextSheetName2; + FixedText maTextSheetStatus2; + PushButton maBtnRetypeSheet2; + + FixedText maTextSheetName3; + FixedText maTextSheetStatus3; + PushButton maBtnRetypeSheet3; + + FixedText maTextSheetName4; + FixedText maTextSheetStatus4; + PushButton maBtnRetypeSheet4; + + ScrollBar maScrollBar; + + String maTextNotProtected; + String maTextNotPassProtected; + String maTextHashBad; + String maTextHashGood; + String maTextHashRegen; + + DECL_LINK( OKHdl, OKButton* ); + DECL_LINK( RetypeBtnHdl, PushButton* ); + DECL_LINK( ScrollHdl, ScrollBar* ); + + struct TableItem + { + String maName; + TabProtectionPtr mpProtect; + }; + ::std::vector<TableItem> maTableItems; + + DocProtectionPtr mpDocItem; + size_t mnCurScrollPos; + ScPasswordHash meDesiredHash; +}; + +// ============================================================================ + +class ScRetypePassInputDlg : public ModalDialog +{ +public: + explicit ScRetypePassInputDlg(Window* pParent, ScPassHashProtectable* pProtected); + virtual ~ScRetypePassInputDlg(); + + virtual short Execute(); + + bool IsRemovePassword() const; + String GetNewPassword() const; + +private: + ScRetypePassInputDlg(); // disabled + + void Init(); + void CheckPasswordInput(); + +private: + OKButton maBtnOk; + CancelButton maBtnCancel; + HelpButton maBtnHelp; + + RadioButton maBtnRetypePassword; + + FixedText maPassword1Text; + Edit maPassword1Edit; + FixedText maPassword2Text; + Edit maPassword2Edit; + + CheckBox maBtnMatchOldPass; + + RadioButton maBtnRemovePassword; + + DECL_LINK( OKHdl, OKButton* ); + DECL_LINK( RadioBtnHdl, RadioButton* ); + DECL_LINK( CheckBoxHdl, CheckBox* ); + DECL_LINK( PasswordModifyHdl, Edit* ); + + ScPassHashProtectable* mpProtected; +}; + +#endif diff --git a/sc/source/ui/inc/scui_def.hxx b/sc/source/ui/inc/scui_def.hxx index 231c983db69a..e2a11bb3204c 100644 --- a/sc/source/ui/inc/scui_def.hxx +++ b/sc/source/ui/inc/scui_def.hxx @@ -53,6 +53,8 @@ #define BTN_PASTE_NAME 100 // from namepast.hxx #define BTN_PASTE_LIST 101 // from namepast.hxx +#define BTN_EXTEND_RANGE 150 +#define BTN_CURRENT_SELECTION 151 #define SCRET_REMOVE 0x42 //from subtdlg.hxx #endif diff --git a/sc/source/ui/inc/sortdlg.hrc b/sc/source/ui/inc/sortdlg.hrc index 902606429596..8f2f641e7574 100644 --- a/sc/source/ui/inc/sortdlg.hrc +++ b/sc/source/ui/inc/sortdlg.hrc @@ -32,6 +32,7 @@ #include "sc.hrc" // -> RID_SCDLG_SORT // -> RID_SCPAGE_SORT_FIELDS // -> RID_SCPAGE_SORT_OPTIONS + // -> RID_SCDLG_SORT_WARNING // -> SCSTR_NONAME // -> SCSTR_UNDEFINED // -> SCSTR_FIELD @@ -40,6 +41,7 @@ #define RID_SCDLG_SORT 256 #define RID_SCPAGE_SORT_FIELDS 257 #define RID_SCPAGE_SORT_OPTIONS 258 +#define RID_SCDLG_SORT_WARNING */ #define TP_FIELDS 1 @@ -80,6 +82,12 @@ #define FT_ALGORITHM 18 #define LB_ALGORITHM 19 +//#define RID_SCDLG_SORT_WARNING +#define FT_TEXT 1 +#define FT_TIP 2 +#define BTN_EXTSORT 3 +#define BTN_CURSORT 4 +#define BTN_CANCEL 5 diff --git a/sc/source/ui/inc/sortdlg.hxx b/sc/source/ui/inc/sortdlg.hxx index 3dcb3a08191d..d1ffb8aac0ed 100644 --- a/sc/source/ui/inc/sortdlg.hxx +++ b/sc/source/ui/inc/sortdlg.hxx @@ -32,6 +32,10 @@ #define SC_SORTDLG_HXX #include <sfx2/tabdlg.hxx> +#include <vcl/button.hxx> +#include <vcl/dialog.hxx> +#include <vcl/fixed.hxx> +#include "scui_def.hxx" //CHINA001 #ifndef LAYOUT_SFX_TABDIALOG_BROKEN #define LAYOUT_SFX_TABDIALOG_BROKEN 1 @@ -65,6 +69,20 @@ inline void ScSortDlg::SetByRows ( BOOL bByRows ) { bIsByRows = bByRows; } inline BOOL ScSortDlg::GetHeaders() const { return bIsHeaders; } inline BOOL ScSortDlg::GetByRows () const { return bIsByRows; } +class ScSortWarningDlg : public ModalDialog +{ +public: + ScSortWarningDlg( Window* pParent, const String& rExtendText,const String& rCurrentText ); + ~ScSortWarningDlg(); + DECL_LINK( BtnHdl, PushButton* ); +private: + FixedText aFtText; + FixedText aFtTip; + PushButton aBtnExtSort; + PushButton aBtnCurSort; + CancelButton aBtnCancel; +}; + #if !LAYOUT_SFX_TABDIALOG_BROKEN #include <layout/layout-post.hxx> #endif diff --git a/sc/source/ui/inc/tabvwsh.hxx b/sc/source/ui/inc/tabvwsh.hxx index 13cd49df6879..10224536bf0b 100644 --- a/sc/source/ui/inc/tabvwsh.hxx +++ b/sc/source/ui/inc/tabvwsh.hxx @@ -39,6 +39,7 @@ #include "target.hxx" #include "rangelst.hxx" // ScRangeListRef #include "shellids.hxx" +#include "tabprotection.hxx" // for ScPasswordHash class FmFormShell; class SbxObject; @@ -430,6 +431,8 @@ public: void BroadcastAccessibility( const SfxHint &rHint ); BOOL HasAccessibilityObjects(); + bool ExecuteRetypePassDlg(ScPasswordHash eDesiredHash); + using ScTabView::ShowCursor; }; diff --git a/sc/source/ui/inc/undoblk.hxx b/sc/source/ui/inc/undoblk.hxx index d357461d0f5e..281f44f4fe82 100644 --- a/sc/source/ui/inc/undoblk.hxx +++ b/sc/source/ui/inc/undoblk.hxx @@ -36,6 +36,7 @@ #include "spellparam.hxx" class ScDocShell; +class ScBaseCell; class ScDocument; class ScOutlineTable; class ScRangeName; @@ -592,6 +593,35 @@ private: void SetChangeTrack(); }; +class ScUndoRefConversion: public ScSimpleUndo +{ +public: + TYPEINFO(); + ScUndoRefConversion( ScDocShell* pNewDocShell, + const ScRange& aMarkRange, const ScMarkData& rMark, + ScDocument* pNewUndoDoc, ScDocument* pNewRedoDoc, BOOL bNewMulti, USHORT nNewFlag); + virtual ~ScUndoRefConversion(); + + virtual void Undo(); + virtual void Redo(); + virtual void Repeat(SfxRepeatTarget& rTarget); + virtual BOOL CanRepeat(SfxRepeatTarget& rTarget) const; + + virtual String GetComment() const; + +private: + ScMarkData aMarkData; + ScDocument* pUndoDoc; + ScDocument* pRedoDoc; + ScRange aRange; + BOOL bMulti; + USHORT nFlags; + ULONG nStartChangeAction; + ULONG nEndChangeAction; + + void DoChange( ScDocument* pRefDoc); + void SetChangeTrack(); +}; class ScUndoListNames: public ScBlockUndo { diff --git a/sc/source/ui/inc/undotab.hxx b/sc/source/ui/inc/undotab.hxx index ff76ebd16702..1eadf24041db 100644 --- a/sc/source/ui/inc/undotab.hxx +++ b/sc/source/ui/inc/undotab.hxx @@ -52,11 +52,15 @@ #include <com/sun/star/uno/Sequence.hxx> +#include <memory> + class ScDocShell; class ScDocument; class SdrUndoAction; class ScPrintRangeSaver; class SdrObject; +class ScDocProtection; +class ScTableProtection; //---------------------------------------------------------------------------- @@ -335,14 +339,15 @@ private: void DoChange( BOOL bShow ) const; }; +// ============================================================================ -class ScUndoProtect : public ScSimpleUndo +/** This class implements undo & redo of document protect & unprotect + operations. */ +class ScUndoDocProtect : public ScSimpleUndo { public: - TYPEINFO(); - ScUndoProtect( ScDocShell* pShell, SCTAB nNewTab, - BOOL bNewProtect, const com::sun::star::uno::Sequence<sal_Int8>& rNewPassword ); - virtual ~ScUndoProtect(); + ScUndoDocProtect(ScDocShell* pShell, ::std::auto_ptr<ScDocProtection> pProtectSettings); + virtual ~ScUndoDocProtect(); virtual void Undo(); virtual void Redo(); @@ -352,11 +357,34 @@ public: virtual String GetComment() const; private: - SCTAB nTab; - BOOL bProtect; - com::sun::star::uno::Sequence<sal_Int8> aPassword; + ::std::auto_ptr<ScDocProtection> mpProtectSettings; + + void DoProtect(bool bProtect); +}; + +// ============================================================================ + +/** This class implements undo & redo of both protect and unprotect of + sheet. */ +class ScUndoTabProtect : public ScSimpleUndo +{ +public: + ScUndoTabProtect(ScDocShell* pShell, SCTAB nTab, + ::std::auto_ptr<ScTableProtection> pProtectSettings); + virtual ~ScUndoTabProtect(); + + virtual void Undo(); + virtual void Redo(); + virtual void Repeat(SfxRepeatTarget& rTarget); + virtual BOOL CanRepeat(SfxRepeatTarget& rTarget) const; + + virtual String GetComment() const; + +private: + SCTAB mnTab; + ::std::auto_ptr<ScTableProtection> mpProtectSettings; - void DoProtect( BOOL bDo ); + void DoProtect(bool bProtect); }; diff --git a/sc/source/ui/inc/viewfunc.hxx b/sc/source/ui/inc/viewfunc.hxx index 0759d1fe2893..228c4b4c1489 100644 --- a/sc/source/ui/inc/viewfunc.hxx +++ b/sc/source/ui/inc/viewfunc.hxx @@ -69,6 +69,7 @@ class Exchange; class ScRangeList; class SvxHyperlinkItem; class ScTransferObj; +class ScTableProtection; namespace com { namespace sun { namespace star { namespace datatransfer { class XTransferable; } } } } @@ -199,6 +200,8 @@ public: void ChangeIndent( BOOL bIncrement ); + void ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect ); + void Protect( SCTAB nTab, const String& rPassword ); BOOL Unprotect( SCTAB nTab, const String& rPassword ); @@ -300,6 +303,7 @@ public: void SetNoteText( const ScAddress& rPos, const String& rNoteText ); void ReplaceNote( const ScAddress& rPos, const String& rNoteText, const String* pAuthor, const String* pDate ); + void DoRefConversion( BOOL bRecord = TRUE ); //UNUSED2008-05 void DoSpellingChecker( BOOL bRecord = TRUE ); void DoHangulHanjaConversion( BOOL bRecord = TRUE ); diff --git a/sc/source/ui/miscdlgs/makefile.mk b/sc/source/ui/miscdlgs/makefile.mk index 988b288da625..66e1f33618e2 100644 --- a/sc/source/ui/miscdlgs/makefile.mk +++ b/sc/source/ui/miscdlgs/makefile.mk @@ -78,7 +78,9 @@ SLOFILES = \ $(SLO)$/warnbox.obj \ $(SLO)$/scuiautofmt.obj \ $(SLO)$/conflictsdlg.obj \ - $(SLO)$/sharedocdlg.obj + $(SLO)$/sharedocdlg.obj \ + $(SLO)$/protectiondlg.obj \ + $(SLO)$/retypepassdlg.obj EXCEPTIONSFILES = \ $(SLO)$/acredlin.obj \ @@ -87,7 +89,9 @@ EXCEPTIONSFILES = \ $(SLO)$/optsolver.obj \ $(SLO)$/solveroptions.obj \ $(SLO)$/crnrdlg.obj \ - $(SLO)$/solverutil.obj + $(SLO)$/solverutil.obj \ + $(SLO)$/protectiondlg.obj \ + $(SLO)$/retypepassdlg.obj SRS1NAME=$(TARGET) SRC1FILES = \ @@ -96,7 +100,9 @@ SRC1FILES = \ highred.src \ linkarea.src \ conflictsdlg.src \ - sharedocdlg.src + sharedocdlg.src \ + protectiondlg.src \ + retypepassdlg.src LIB1TARGET = $(SLB)$/$(TARGET).lib @@ -116,7 +122,9 @@ LIB1OBJFILES = \ $(SLO)$/redcom.obj \ $(SLO)$/warnbox.obj \ $(SLO)$/conflictsdlg.obj \ - $(SLO)$/sharedocdlg.obj + $(SLO)$/sharedocdlg.obj \ + $(SLO)$/protectiondlg.obj \ + $(SLO)$/retypepassdlg.obj # --- Tagets ------------------------------------------------------- diff --git a/sc/source/ui/miscdlgs/protectiondlg.cxx b/sc/source/ui/miscdlgs/protectiondlg.cxx new file mode 100644 index 000000000000..a5116ef61d66 --- /dev/null +++ b/sc/source/ui/miscdlgs/protectiondlg.cxx @@ -0,0 +1,164 @@ +/************************************************************************* + * + * 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: protectiondlg.cxx,v $ + * $Revision: 1.1.2.6 $ + * + * 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 "protectiondlg.hxx" +#include "protectiondlg.hrc" +#include "scresid.hxx" +#include "tabprotection.hxx" + +#include <vcl/msgbox.hxx> + + +// The order must match that of the list box. +static const ScTableProtection::Option aOptions[] = { + ScTableProtection::SELECT_LOCKED_CELLS, + ScTableProtection::SELECT_UNLOCKED_CELLS, +}; +static const USHORT nOptionCount = sizeof(aOptions)/sizeof(aOptions[0]); + + +ScTableProtectionDlg::ScTableProtectionDlg(Window* pParent) : + ModalDialog(pParent, ScResId(RID_SCDLG_TABPROTECTION)), + + maBtnProtect (this, ScResId(BTN_PROTECT)), + maPassword1Text (this, ScResId(FT_PASSWORD1)), + maPassword1Edit (this, ScResId(ED_PASSWORD1)), + maPassword2Text (this, ScResId(FT_PASSWORD2)), + maPassword2Edit (this, ScResId(ED_PASSWORD2)), + maOptionsLine (this, ScResId(FL_OPTIONS)), + maOptionsText (this, ScResId(FT_OPTIONS)), + maOptionsListBox(this, ScResId(CLB_OPTIONS)), + + maBtnOk (this, ScResId(BTN_OK)), + maBtnCancel (this, ScResId(BTN_CANCEL)), + maBtnHelp (this, ScResId(BTN_HELP)), + + maSelectLockedCells(ScResId(ST_SELECT_LOCKED_CELLS)), + maSelectUnlockedCells(ScResId(ST_SELECT_UNLOCKED_CELLS)) +{ + Init(); + FreeResource(); +} + +ScTableProtectionDlg::~ScTableProtectionDlg() +{ +} + +short ScTableProtectionDlg::Execute() +{ + return ModalDialog::Execute(); +} + +void ScTableProtectionDlg::SetDialogData(const ScTableProtection& rData) +{ + for (USHORT i = 0; i < nOptionCount; ++i) + maOptionsListBox.CheckEntryPos(i, rData.isOptionEnabled(aOptions[i])); +} + +void ScTableProtectionDlg::WriteData(ScTableProtection& rData) const +{ + rData.setProtected(maBtnProtect.IsChecked()); + + // We assume that the two password texts match. + rData.setPassword(maPassword1Edit.GetText()); + + for (USHORT i = 0; i < nOptionCount; ++i) + rData.setOption(aOptions[i], maOptionsListBox.IsChecked(i)); +} + +void ScTableProtectionDlg::Init() +{ + Link aLink = LINK( this, ScTableProtectionDlg, CheckBoxHdl ); + maBtnProtect.SetClickHdl(aLink); + + aLink = LINK( this, ScTableProtectionDlg, OKHdl ); + maBtnOk.SetClickHdl(aLink); + + aLink = LINK( this, ScTableProtectionDlg, PasswordModifyHdl ); + maPassword1Edit.SetModifyHdl(aLink); + maPassword2Edit.SetModifyHdl(aLink); + + maOptionsListBox.SetUpdateMode(false); + maOptionsListBox.Clear(); + + maOptionsListBox.InsertEntry(maSelectLockedCells); + maOptionsListBox.InsertEntry(maSelectUnlockedCells); + + maOptionsListBox.CheckEntryPos(0, true); + maOptionsListBox.CheckEntryPos(1, true); + + maOptionsListBox.SetUpdateMode(true); + + // Set the default state of the dialog. + maBtnProtect.Check(true); + maPassword1Edit.GrabFocus(); +} + +void ScTableProtectionDlg::EnableOptionalWidgets(bool bEnable) +{ + maPassword1Text.Enable(bEnable); + maPassword1Edit.Enable(bEnable); + maPassword2Text.Enable(bEnable); + maPassword2Edit.Enable(bEnable); + maOptionsLine.Enable(bEnable); + maOptionsText.Enable(bEnable); + + maOptionsListBox.Enable(bEnable); + maOptionsListBox.Invalidate(); +} + +IMPL_LINK( ScTableProtectionDlg, CheckBoxHdl, CheckBox*, pBtn ) +{ + if (pBtn == &maBtnProtect) + { + bool bChecked = maBtnProtect.IsChecked(); + EnableOptionalWidgets(bChecked); + maBtnOk.Enable(bChecked); + } + + return 0; +} + +IMPL_LINK( ScTableProtectionDlg, OKHdl, OKButton*, EMPTYARG ) +{ + EndDialog(RET_OK); + return 0; +} + +IMPL_LINK( ScTableProtectionDlg, PasswordModifyHdl, Edit*, EMPTYARG ) +{ + String aPass1 = maPassword1Edit.GetText(); + String aPass2 = maPassword2Edit.GetText(); + maBtnOk.Enable(aPass1.Equals(aPass2)); + return 0; +} diff --git a/sc/source/ui/miscdlgs/protectiondlg.src b/sc/source/ui/miscdlgs/protectiondlg.src new file mode 100644 index 000000000000..4919f93ca6f4 --- /dev/null +++ b/sc/source/ui/miscdlgs/protectiondlg.src @@ -0,0 +1,130 @@ +/************************************************************************* + * + * 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: protectiondlg.src,v $ + * $Revision: 1.1.2.6 $ + * + * 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. + * + ************************************************************************/ + +#include "protectiondlg.hrc" + +ModalDialog RID_SCDLG_TABPROTECTION +{ + Text [ en-US ] = "Protect Sheet" ; + Size = MAP_APPFONT ( 220 , 135 ) ; + Moveable = TRUE ; + Closeable = TRUE ; + + OKButton BTN_OK + { + Pos = MAP_APPFONT ( 164 , 6 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + DefButton = TRUE ; + }; + CancelButton BTN_CANCEL + { + Pos = MAP_APPFONT ( 164 , 23 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + }; + HelpButton BTN_HELP + { + Pos = MAP_APPFONT ( 164 , 43 ) ; + Size = MAP_APPFONT ( 50 , 14 ) ; + }; + + CheckBox BTN_PROTECT + { + Pos = MAP_APPFONT ( 6 , 6 ) ; + Size = MAP_APPFONT ( 150 , 10 ); + + Text [ en-US ] = "P~rotect this sheet and the contents of locked cells" ; + }; + + FixedText FT_PASSWORD1 + { + Pos = MAP_APPFONT ( 11, 23 ); + Size = MAP_APPFONT ( 42, 10 ); + + Text [ en-US ] = "~Password" ; + }; + + Edit ED_PASSWORD1 + { + Border = TRUE; + PassWord = TRUE; + Pos = MAP_APPFONT ( 56, 22 ); + Size = MAP_APPFONT ( 75, 12 ); + }; + + FixedText FT_PASSWORD2 + { + Pos = MAP_APPFONT ( 11, 40 ); + Size = MAP_APPFONT ( 42, 10 ); + + Text [ en-US ] = "~Confirm" ; + }; + + Edit ED_PASSWORD2 + { + Border = TRUE; + PassWord = TRUE; + Pos = MAP_APPFONT ( 56, 39 ); + Size = MAP_APPFONT ( 75, 12 ); + }; + + FixedLine FL_OPTIONS + { + Pos = MAP_APPFONT ( 6, 60 ); + Size = MAP_APPFONT ( 150, 8 ); + + Text [ en-US ] = "Options"; + }; + + FixedText FT_OPTIONS + { + Pos = MAP_APPFONT ( 11, 74 ); + Size = MAP_APPFONT ( 140, 8 ); + + Text [ en-US ] = "Allow all users of this sheet to:"; + }; + + Control CLB_OPTIONS + { + Pos = MAP_APPFONT ( 11, 85 ); + Size = MAP_APPFONT ( 140, 40 ); + Border = TRUE ; + TabStop = TRUE ; + }; + + String ST_SELECT_LOCKED_CELLS + { + Text [ en-US ] = "Select locked cells"; + }; + + String ST_SELECT_UNLOCKED_CELLS + { + Text [ en-US ] = "Select unlocked cells"; + }; +}; diff --git a/sc/source/ui/miscdlgs/retypepassdlg.cxx b/sc/source/ui/miscdlgs/retypepassdlg.cxx new file mode 100644 index 000000000000..84a008f68f5f --- /dev/null +++ b/sc/source/ui/miscdlgs/retypepassdlg.cxx @@ -0,0 +1,547 @@ +/************************************************************************* + * + * 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: retypepassdlg.cxx,v $ + * $Revision: 1.1.2.7 $ + * + * 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 "retypepassdlg.hxx" +#include "retypepassdlg.hrc" +#include "scresid.hxx" +#include "document.hxx" +#include "tabprotection.hxx" + +#include <stdio.h> + +#include <vcl/msgbox.hxx> + +ScRetypePassDlg::ScRetypePassDlg(Window* pParent) : + ModalDialog(pParent, ScResId(RID_SCDLG_RETYPEPASS)), + + maBtnOk (this, ScResId(BTN_OK)), + maBtnCancel (this, ScResId(BTN_CANCEL)), + maBtnHelp (this, ScResId(BTN_HELP)), + + maTextDescription(this, ScResId(FT_DESC)), + maLineDocument(this, ScResId(FL_DOCUMENT)), + maTextDocStatus(this, ScResId(FT_DOCSTATUS)), + maBtnRetypeDoc(this, ScResId(BTN_RETYPE_DOC)), + + maLineSheet(this, ScResId(FL_SHEET)), + maTextSheetName1(this, ScResId(FT_SHEETNAME1)), + maTextSheetStatus1(this, ScResId(FT_SHEETSTATUS1)), + maBtnRetypeSheet1(this, ScResId(BTN_RETYPE_SHEET1)), + + maTextSheetName2(this, ScResId(FT_SHEETNAME2)), + maTextSheetStatus2(this, ScResId(FT_SHEETSTATUS2)), + maBtnRetypeSheet2(this, ScResId(BTN_RETYPE_SHEET2)), + + maTextSheetName3(this, ScResId(FT_SHEETNAME3)), + maTextSheetStatus3(this, ScResId(FT_SHEETSTATUS3)), + maBtnRetypeSheet3(this, ScResId(BTN_RETYPE_SHEET3)), + + maTextSheetName4(this, ScResId(FT_SHEETNAME4)), + maTextSheetStatus4(this, ScResId(FT_SHEETSTATUS4)), + maBtnRetypeSheet4(this, ScResId(BTN_RETYPE_SHEET4)), + + maScrollBar (this, ScResId(SB_SCROLL)), + + maTextNotProtected(ScResId(STR_NOT_PROTECTED)), + maTextNotPassProtected(ScResId(STR_NOT_PASS_PROTECTED)), + maTextHashBad(ScResId(STR_HASH_BAD)), + maTextHashGood(ScResId(STR_HASH_GOOD)), + maTextHashRegen(ScResId(STR_HASH_REGENERATED)), + + mpDocItem(static_cast<ScDocProtection*>(NULL)), + mnCurScrollPos(0), + meDesiredHash(PASSHASH_OOO) +{ + Init(); +} + +ScRetypePassDlg::~ScRetypePassDlg() +{ +} + +short ScRetypePassDlg::Execute() +{ + PopulateDialog(); + CheckHashStatus(); + return ModalDialog::Execute(); +} + +void ScRetypePassDlg::SetDataFromDocument(const ScDocument& rDoc) +{ + const ScDocProtection* pDocProtect = rDoc.GetDocProtection(); + if (pDocProtect && pDocProtect->isProtected()) + mpDocItem.reset(new ScDocProtection(*pDocProtect)); + + SCTAB nTabCount = rDoc.GetTableCount(); + maTableItems.reserve(nTabCount); + for (SCTAB i = 0; i < nTabCount; ++i) + { + TableItem aTabItem; + rDoc.GetName(i, aTabItem.maName); + + const ScTableProtection* pTabProtect = rDoc.GetTabProtection(i); + if (pTabProtect && pTabProtect->isProtected()) + aTabItem.mpProtect.reset(new ScTableProtection(*pTabProtect)); + + maTableItems.push_back(aTabItem); + } +} + +void ScRetypePassDlg::SetDesiredHash(ScPasswordHash eHash) +{ + meDesiredHash = eHash; +} + +void ScRetypePassDlg::WriteNewDataToDocument(ScDocument& rDoc) const +{ + if (mpDocItem.get()) + rDoc.SetDocProtection(mpDocItem.get()); + + size_t nTabCount = static_cast<size_t>(rDoc.GetTableCount()); + size_t n = maTableItems.size(); + for (size_t i = 0; i < n; ++i) + { + if (i >= nTabCount) + break; + + ScTableProtection* pTabProtect = maTableItems[i].mpProtect.get(); + if (pTabProtect) + rDoc.SetTabProtection(static_cast<SCTAB>(i), pTabProtect); + } +} + +void ScRetypePassDlg::Init() +{ + Link aLink = LINK( this, ScRetypePassDlg, OKHdl ); + maBtnOk.SetClickHdl(aLink); + + aLink = LINK( this, ScRetypePassDlg, RetypeBtnHdl ); + maBtnRetypeDoc.SetClickHdl(aLink); + maBtnRetypeSheet1.SetClickHdl(aLink); + maBtnRetypeSheet2.SetClickHdl(aLink); + maBtnRetypeSheet3.SetClickHdl(aLink); + maBtnRetypeSheet4.SetClickHdl(aLink); + + maTextDocStatus.SetText(maTextNotProtected); + maTextSheetStatus1.SetText(maTextNotProtected); + maTextSheetStatus2.SetText(maTextNotProtected); + maTextSheetStatus3.SetText(maTextNotProtected); + maTextSheetStatus4.SetText(maTextNotProtected); + maBtnRetypeDoc.Disable(); + + // Make all sheet rows invisible. + + maTextSheetName1.Show(false); + maTextSheetStatus1.Show(false); + maBtnRetypeSheet1.Show(false); + maBtnRetypeSheet1.Disable(); + + maTextSheetName2.Show(false); + maTextSheetStatus2.Show(false); + maBtnRetypeSheet2.Show(false); + maBtnRetypeSheet2.Disable(); + + maTextSheetName3.Show(false); + maTextSheetStatus3.Show(false); + maBtnRetypeSheet3.Show(false); + maBtnRetypeSheet3.Disable(); + + maTextSheetName4.Show(false); + maTextSheetStatus4.Show(false); + maBtnRetypeSheet4.Show(false); + maBtnRetypeSheet4.Disable(); + + maScrollBar.Show(false); + + maScrollBar.SetEndScrollHdl( LINK( this, ScRetypePassDlg, ScrollHdl ) ); + maScrollBar.SetScrollHdl( LINK( this, ScRetypePassDlg, ScrollHdl ) ); + + maScrollBar.SetPageSize(4); + maScrollBar.SetVisibleSize(4); + maScrollBar.SetLineSize(1); +} + +void ScRetypePassDlg::PopulateDialog() +{ + // Document protection first. + SetDocData(); + + // Sheet protection next. We're only interested in the first 4 sheets + // (or less). + size_t n = maTableItems.size(); + for (size_t i = 0; i < n && i < 4; ++i) + SetTableData(i, static_cast< SCTAB >( i )); + + if (n > 4) + { + maScrollBar.Show(true); + maScrollBar.SetRange(Range(0, n)); + } +} + +void ScRetypePassDlg::SetDocData() +{ + bool bBtnEnabled = false; + if (mpDocItem.get() && mpDocItem->isProtected()) + { + if (mpDocItem->isPasswordEmpty()) + maTextDocStatus.SetText(maTextNotPassProtected); + else if (mpDocItem->hasPasswordHash(meDesiredHash)) + maTextDocStatus.SetText(maTextHashGood); + else + { + // incompatible hash + maTextDocStatus.SetText(maTextHashBad); + bBtnEnabled = true; + } + } + maBtnRetypeDoc.Enable(bBtnEnabled); +} + +void ScRetypePassDlg::SetTableData(size_t nRowPos, SCTAB nTab) +{ + if (nRowPos >= 4) + return; + + FixedText* pName = NULL; + FixedText* pStatus = NULL; + PushButton* pBtn = NULL; + switch (nRowPos) + { + case 0: + pName = &maTextSheetName1; + pStatus = &maTextSheetStatus1; + pBtn = &maBtnRetypeSheet1; + break; + case 1: + pName = &maTextSheetName2; + pStatus = &maTextSheetStatus2; + pBtn = &maBtnRetypeSheet2; + break; + case 2: + pName = &maTextSheetName3; + pStatus = &maTextSheetStatus3; + pBtn = &maBtnRetypeSheet3; + break; + case 3: + pName = &maTextSheetName4; + pStatus = &maTextSheetStatus4; + pBtn = &maBtnRetypeSheet4; + break; + default: + return; + } + + bool bBtnEnabled = false; + pName->SetText(maTableItems[nTab].maName); + pName->Show(true); + const ScTableProtection* pTabProtect = maTableItems[nTab].mpProtect.get(); + if (pTabProtect && pTabProtect->isProtected()) + { + if (pTabProtect->isPasswordEmpty()) + pStatus->SetText(maTextNotPassProtected); + else if (pTabProtect->hasPasswordHash(meDesiredHash)) + pStatus->SetText(maTextHashGood); + else + { + // incompatible hash + pStatus->SetText(maTextHashBad); + bBtnEnabled = true; + } + } + else + pStatus->SetText(maTextNotProtected); + + pStatus->Show(true); + pBtn->Show(true); + pBtn->Enable(bBtnEnabled); +} + +void ScRetypePassDlg::ResetTableRows() +{ + long nScrollPos = maScrollBar.GetThumbPos(); + mnCurScrollPos = nScrollPos < 0 ? 0 : nScrollPos; + size_t nRowCount = maTableItems.size() - nScrollPos; + for (size_t i = 0; i < nRowCount; ++i) + SetTableData(i, static_cast< SCTAB >( i + nScrollPos )); +} + +bool lcl_IsInGoodStatus(ScPassHashProtectable* pProtected, ScPasswordHash eDesiredHash) +{ + if (!pProtected || !pProtected->isProtected()) + // Not protected. + return true; + + if (pProtected->isPasswordEmpty()) + return true; + + if (pProtected->hasPasswordHash(eDesiredHash)) + return true; + + return false; +} + +void ScRetypePassDlg::CheckHashStatus() +{ + do + { + if (!lcl_IsInGoodStatus(mpDocItem.get(), meDesiredHash)) + break; + + bool bStatusGood = true; + size_t nTabCount = maTableItems.size(); + for (size_t i = 0; i < nTabCount && bStatusGood; ++i) + { + if (!lcl_IsInGoodStatus(maTableItems[i].mpProtect.get(), meDesiredHash)) + bStatusGood = false; + } + if (!bStatusGood) + break; + + maBtnOk.Enable(); + return; + } + while (false); + + maBtnOk.Disable(); +} + +IMPL_LINK( ScRetypePassDlg, OKHdl, OKButton*, EMPTYARG ) +{ + EndDialog(RET_OK); + return 0; +} + +IMPL_LINK( ScRetypePassDlg, RetypeBtnHdl, PushButton*, pBtn ) +{ + ScPassHashProtectable* pProtected = NULL; + if (pBtn == &maBtnRetypeDoc) + { + // document protection. + pProtected = mpDocItem.get(); + } + else + { + // sheet protection. + size_t nTabPos = mnCurScrollPos; + if (pBtn == &maBtnRetypeSheet2) + nTabPos += 1; + else if (pBtn == &maBtnRetypeSheet3) + nTabPos += 2; + else if (pBtn == &maBtnRetypeSheet4) + nTabPos += 3; + else if (pBtn != &maBtnRetypeSheet1) + // This should never happen ! + return 0; + + if (nTabPos >= maTableItems.size()) + // Likewise, this should never happen ! + return 0; + + pProtected = maTableItems[nTabPos].mpProtect.get(); + } + + if (!pProtected) + // What the ... !? + return 0; + + ScRetypePassInputDlg aDlg(this, pProtected); + if (aDlg.Execute() == RET_OK) + { + // OK is pressed. Update the protected item. + if (aDlg.IsRemovePassword()) + { + // Remove password from this item. + pProtected->setPassword(String()); + } + else + { + // Set a new password. + String aNewPass = aDlg.GetNewPassword(); + pProtected->setPassword(aNewPass); + } + + SetDocData(); + ResetTableRows(); + CheckHashStatus(); + } + return 0; +} + +IMPL_LINK( ScRetypePassDlg, ScrollHdl, ScrollBar*, EMPTYARG ) +{ + ResetTableRows(); + return 0; +} + +// ============================================================================ + +ScRetypePassInputDlg::ScRetypePassInputDlg(Window* pParent, ScPassHashProtectable* pProtected) : + ModalDialog(pParent, ScResId(RID_SCDLG_RETYPEPASS_INPUT)), + + maBtnOk (this, ScResId(BTN_OK)), + maBtnCancel (this, ScResId(BTN_CANCEL)), + maBtnHelp (this, ScResId(BTN_HELP)), + + maBtnRetypePassword(this, ScResId(BTN_RETYPE_PASSWORD)), + + maPassword1Text (this, ScResId(FT_PASSWORD1)), + maPassword1Edit (this, ScResId(ED_PASSWORD1)), + maPassword2Text (this, ScResId(FT_PASSWORD2)), + maPassword2Edit (this, ScResId(ED_PASSWORD2)), + maBtnMatchOldPass(this, ScResId(BTN_MATCH_OLD_PASSWORD)), + + maBtnRemovePassword(this, ScResId(BTN_REMOVE_PASSWORD)), + + mpProtected(pProtected) +{ + Init(); +} + +ScRetypePassInputDlg::~ScRetypePassInputDlg() +{ +} + +short ScRetypePassInputDlg::Execute() +{ + return ModalDialog::Execute(); +} + +bool ScRetypePassInputDlg::IsRemovePassword() const +{ + return maBtnRemovePassword.IsChecked(); +} + +String ScRetypePassInputDlg::GetNewPassword() const +{ + return maPassword1Edit.GetText(); +} + +void ScRetypePassInputDlg::Init() +{ + Link aLink = LINK( this, ScRetypePassInputDlg, OKHdl ); + maBtnOk.SetClickHdl(aLink); + aLink = LINK( this, ScRetypePassInputDlg, RadioBtnHdl ); + maBtnRetypePassword.SetClickHdl(aLink); + maBtnRemovePassword.SetClickHdl(aLink); + aLink = LINK( this, ScRetypePassInputDlg, CheckBoxHdl ); + maBtnMatchOldPass.SetClickHdl(aLink); + aLink = LINK( this, ScRetypePassInputDlg, PasswordModifyHdl ); + maPassword1Edit.SetModifyHdl(aLink); + maPassword2Edit.SetModifyHdl(aLink); + + maBtnOk.Disable(); + maBtnRetypePassword.Check(true); + maBtnMatchOldPass.Check(true); + maPassword1Edit.GrabFocus(); +} + +void ScRetypePassInputDlg::CheckPasswordInput() +{ + String aPass1 = maPassword1Edit.GetText(); + String aPass2 = maPassword2Edit.GetText(); + + if (!aPass1.Len() || !aPass2.Len()) + { + // Empty password is not allowed. + maBtnOk.Disable(); + return; + } + + if (!aPass1.Equals(aPass2)) + { + // The two passwords differ. + maBtnOk.Disable(); + return; + } + + if (!maBtnMatchOldPass.IsChecked()) + { + maBtnOk.Enable(); + return; + } + + if (!mpProtected) + { + // This should never happen! + maBtnOk.Disable(); + return; + } + + bool bPassGood = mpProtected->verifyPassword(aPass1); + maBtnOk.Enable(bPassGood); +} + +IMPL_LINK( ScRetypePassInputDlg, OKHdl, OKButton*, EMPTYARG ) +{ + EndDialog(RET_OK); + return 0; +} + +IMPL_LINK( ScRetypePassInputDlg, RadioBtnHdl, RadioButton*, pBtn ) +{ + if (pBtn == &maBtnRetypePassword) + { + maBtnRemovePassword.Check(false); + maPassword1Text.Enable(); + maPassword1Edit.Enable(); + maPassword2Text.Enable(); + maPassword2Edit.Enable(); + maBtnMatchOldPass.Enable(); + CheckPasswordInput(); + } + else if (pBtn == &maBtnRemovePassword) + { + maBtnRetypePassword.Check(false); + maPassword1Text.Disable(); + maPassword1Edit.Disable(); + maPassword2Text.Disable(); + maPassword2Edit.Disable(); + maBtnMatchOldPass.Disable(); + maBtnOk.Enable(); + } + + return 0; +} + +IMPL_LINK( ScRetypePassInputDlg, CheckBoxHdl, CheckBox*, EMPTYARG ) +{ + CheckPasswordInput(); + return 0; +} + +IMPL_LINK( ScRetypePassInputDlg, PasswordModifyHdl, Edit*, EMPTYARG ) +{ + CheckPasswordInput(); + return 0; +} diff --git a/sc/source/ui/miscdlgs/retypepassdlg.src b/sc/source/ui/miscdlgs/retypepassdlg.src new file mode 100644 index 000000000000..87d436881f69 --- /dev/null +++ b/sc/source/ui/miscdlgs/retypepassdlg.src @@ -0,0 +1,316 @@ +/************************************************************************* + * + * 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: retypepassdlg.src,v $ + * $Revision: 1.1.2.3 $ + * + * 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. + * + ************************************************************************/ + +#include "retypepassdlg.hrc" + + +ModalDialog RID_SCDLG_RETYPEPASS +{ + Text [ en-US ] = "Re-type Password" ; + Size = MAP_APPFONT ( 260 , 165 ) ; + Moveable = TRUE ; + Closeable = TRUE ; + + OKButton BTN_OK + { + Pos = MAP_APPFONT ( 204, 6 ) ; + Size = MAP_APPFONT ( 50, 14 ) ; + DefButton = TRUE ; + }; + + CancelButton BTN_CANCEL + { + Pos = MAP_APPFONT ( 204, 23 ) ; + Size = MAP_APPFONT ( 50, 14 ) ; + }; + + HelpButton BTN_HELP + { + Pos = MAP_APPFONT ( 204, 43 ) ; + Size = MAP_APPFONT ( 50, 14 ) ; + }; + + FixedText FT_DESC + { + Pos = MAP_APPFONT ( 6, 6 ) ; + Size = MAP_APPFONT ( 190, 36 ); + + WordBreak = TRUE ; + + Text [ en-US ] = "The document you are about to export has one or more protected items with password that cannot be exported. Please re-type your password to be able to export your document." ; + }; + + FixedLine FL_DOCUMENT + { + Pos = MAP_APPFONT ( 6, 48 ); + Size = MAP_APPFONT ( 190, 8 ); + + Text [ en-US ] = "Document protection" ; + }; + + FixedText FT_DOCSTATUS + { + Pos = MAP_APPFONT ( 10, 62 ); + Size = MAP_APPFONT ( 140, 8 ); + + Text [ en-US ] = "Status unknown" ; + }; + + PushButton BTN_RETYPE_DOC + { + Pos = MAP_APPFONT ( 158, 59 ); + Size = MAP_APPFONT ( 30, 14 ); + + Text [ en-US ] = "Re-type" ; + }; + + FixedLine FL_SHEET + { + Pos = MAP_APPFONT ( 6, 83 ); + Size = MAP_APPFONT ( 190, 8 ); + + Text [ en-US ] = "Sheet protection" ; + }; + + FixedText FT_SHEETNAME1 + { + Pos = MAP_APPFONT ( 10, 97 ); + Size = MAP_APPFONT ( 68, 8 ); + + Text [ en-US ] = "Sheet1 has a really long name" ; + }; + + FixedText FT_SHEETSTATUS1 + { + Pos = MAP_APPFONT ( 82, 97 ); + Size = MAP_APPFONT ( 72, 8 ); + + Text [ en-US ] = "Status unknown" ; + }; + + PushButton BTN_RETYPE_SHEET1 + { + Pos = MAP_APPFONT ( 158, 94 ); + Size = MAP_APPFONT ( 30, 14 ); + + Text [ en-US ] = "Re-type" ; + }; + + FixedText FT_SHEETNAME2 + { + Pos = MAP_APPFONT ( 10, 113 ); + Size = MAP_APPFONT ( 68, 8 ); + + Text [ en-US ] = "Sheet2" ; + }; + + FixedText FT_SHEETSTATUS2 + { + Pos = MAP_APPFONT ( 82, 113 ); + Size = MAP_APPFONT ( 72, 8 ); + + Text [ en-US ] = "Status unknown" ; + }; + + PushButton BTN_RETYPE_SHEET2 + { + Pos = MAP_APPFONT ( 158, 110 ); + Size = MAP_APPFONT ( 30, 14 ); + + Text [ en-US ] = "Re-type" ; + }; + + FixedText FT_SHEETNAME3 + { + Pos = MAP_APPFONT ( 10, 129 ); + Size = MAP_APPFONT ( 68, 8 ); + + Text [ en-US ] = "Sheet3" ; + }; + + FixedText FT_SHEETSTATUS3 + { + Pos = MAP_APPFONT ( 82, 129 ); + Size = MAP_APPFONT ( 72, 8 ); + + Text [ en-US ] = "Status unknown" ; + }; + + PushButton BTN_RETYPE_SHEET3 + { + Pos = MAP_APPFONT ( 158, 126 ); + Size = MAP_APPFONT ( 30, 14 ); + + Text [ en-US ] = "Re-type" ; + }; + + FixedText FT_SHEETNAME4 + { + Pos = MAP_APPFONT ( 10, 145 ); + Size = MAP_APPFONT ( 68, 8 ); + + Text [ en-US ] = "Sheet4" ; + }; + + FixedText FT_SHEETSTATUS4 + { + Pos = MAP_APPFONT ( 82, 145 ); + Size = MAP_APPFONT ( 72, 8 ); + + Text [ en-US ] = "Status unknown" ; + }; + + PushButton BTN_RETYPE_SHEET4 + { + Pos = MAP_APPFONT ( 158, 142 ); + Size = MAP_APPFONT ( 30, 14 ); + + Text [ en-US ] = "Re-type" ; + }; + + ScrollBar SB_SCROLL + { + Pos = MAP_APPFONT ( 190, 94 ) ; + Size = MAP_APPFONT ( 8, 61 ) ; + VScroll = TRUE ; + }; + + String STR_NOT_PROTECTED + { + Text [ en-US ] = "Not protected" ; + }; + + String STR_NOT_PASS_PROTECTED + { + Text [ en-US ] = "Not password-protected" ; + }; + + String STR_HASH_BAD + { + Text [ en-US ] = "Hash incompatible" ; + }; + + String STR_HASH_GOOD + { + Text [ en-US ] = "Hash compatible" ; + }; + + String STR_HASH_REGENERATED + { + Text [ en-US ] = "Hash re-generated" ; + }; +}; + +// ---------------------------------------------------------------------------- + +ModalDialog RID_SCDLG_RETYPEPASS_INPUT +{ + Text [ en-US ] = "Re-type Password" ; + Size = MAP_APPFONT ( 230 , 110 ) ; + Moveable = TRUE ; + Closeable = TRUE ; + + OKButton BTN_OK + { + Pos = MAP_APPFONT ( 174, 6 ) ; + Size = MAP_APPFONT ( 50, 14 ) ; + DefButton = TRUE ; + }; + + CancelButton BTN_CANCEL + { + Pos = MAP_APPFONT ( 174, 23 ) ; + Size = MAP_APPFONT ( 50, 14 ) ; + }; + + HelpButton BTN_HELP + { + Pos = MAP_APPFONT ( 174, 43 ) ; + Size = MAP_APPFONT ( 50, 14 ) ; + }; + + RadioButton BTN_RETYPE_PASSWORD + { + Pos = MAP_APPFONT ( 11, 10 ); + Size = MAP_APPFONT ( 150, 10 ); + + Text [ en-US ] = "Re-type password" ; + }; + + FixedText FT_PASSWORD1 + { + Pos = MAP_APPFONT ( 20, 30 ); + Size = MAP_APPFONT ( 42, 10 ); + + Text [ en-US ] = "~Password" ; + }; + + Edit ED_PASSWORD1 + { + Border = TRUE; + PassWord = TRUE; + Pos = MAP_APPFONT ( 65, 29 ); + Size = MAP_APPFONT ( 75, 12 ); + }; + + FixedText FT_PASSWORD2 + { + Pos = MAP_APPFONT ( 20, 45 ); + Size = MAP_APPFONT ( 42, 10 ); + + Text [ en-US ] = "~Confirm" ; + }; + + Edit ED_PASSWORD2 + { + Border = TRUE; + PassWord = TRUE; + Pos = MAP_APPFONT ( 65, 44 ); + Size = MAP_APPFONT ( 75, 12 ); + }; + + CheckBox BTN_MATCH_OLD_PASSWORD + { + Pos = MAP_APPFONT ( 20, 65 ); + Size = MAP_APPFONT ( 150, 10 ); + + Text [ en-US ] = "New password must match the original password." ; + }; + + RadioButton BTN_REMOVE_PASSWORD + { + Pos = MAP_APPFONT ( 11, 90 ); + Size = MAP_APPFONT ( 150, 10 ); + + Text [ en-US ] = "Remove password from this protected item." ; + }; +}; + + diff --git a/sc/source/ui/src/filter.src b/sc/source/ui/src/filter.src index 73108b984ebe..2e6a1c330671 100644 --- a/sc/source/ui/src/filter.src +++ b/sc/source/ui/src/filter.src @@ -34,7 +34,7 @@ ModelessDialog RID_SCDLG_FILTER HelpId = SID_FILTER ; Hide = TRUE ; SVLook = TRUE ; - Size = MAP_APPFONT ( 251 , 121 ) ; + Size = MAP_APPFONT ( 279 , 121 ) ; Text [ en-US ] = "Standard Filter" ; Moveable = TRUE ; Closeable = FALSE ; @@ -58,7 +58,7 @@ ModelessDialog RID_SCDLG_FILTER }; FixedText FT_VAL { - Pos = MAP_APPFONT ( 173 , 14 ) ; + Pos = MAP_APPFONT ( 201 , 14 ) ; Size = MAP_APPFONT ( 60 , 8 ) ; Text [ en-US ] = "Value" ; }; @@ -150,7 +150,7 @@ ModelessDialog RID_SCDLG_FILTER { Border = TRUE ; Pos = MAP_APPFONT ( 122 , 25 ) ; - Size = MAP_APPFONT ( 47 , 145 ) ; + Size = MAP_APPFONT ( 75 , 145 ) ; TabStop = TRUE ; DropDown = TRUE ; stringlist [ en-US ] = @@ -165,13 +165,19 @@ ModelessDialog RID_SCDLG_FILTER < "Smallest" ; Default ; > ; < "Largest %" ; Default ; > ; < "Smallest %" ; Default ; > ; + < "Contains" ; Default ; > ; + < "Does not contain" ; Default ; > ; + < "Begins with" ; Default ; > ; + < "Does not begin with" ; Default ; > ; + < "Ends with" ; Default ; > ; + < "Does not end with" ; Default ; > ; }; }; ListBox LB_COND2 { Border = TRUE ; Pos = MAP_APPFONT ( 122 , 41 ) ; - Size = MAP_APPFONT ( 47 , 145 ) ; + Size = MAP_APPFONT ( 75 , 145 ) ; TabStop = TRUE ; DropDown = TRUE ; stringlist [ en-US ] = @@ -186,13 +192,19 @@ ModelessDialog RID_SCDLG_FILTER < "Smallest" ; Default ; > ; < "Largest %" ; Default ; > ; < "Smallest %" ; Default ; > ; + < "Contains" ; Default ; > ; + < "Does not contain" ; Default ; > ; + < "Begins with" ; Default ; > ; + < "Does not begin with" ; Default ; > ; + < "Ends with" ; Default ; > ; + < "Does not end with" ; Default ; > ; }; }; ListBox LB_COND3 { Border = TRUE ; Pos = MAP_APPFONT ( 122 , 57 ) ; - Size = MAP_APPFONT ( 47 , 145 ) ; + Size = MAP_APPFONT ( 75 , 145 ) ; TabStop = TRUE ; DropDown = TRUE ; stringlist [ en-US ] = @@ -207,13 +219,19 @@ ModelessDialog RID_SCDLG_FILTER < "Smallest" ; Default ; > ; < "Largest %" ; Default ; > ; < "Smallest %" ; Default ; > ; + < "Contains" ; Default ; > ; + < "Does not contain" ; Default ; > ; + < "Begins with" ; Default ; > ; + < "Does not begin with" ; Default ; > ; + < "Ends with" ; Default ; > ; + < "Does not end with" ; Default ; > ; }; }; ListBox LB_COND4 { Border = TRUE ; Pos = MAP_APPFONT ( 122 , 73 ) ; - Size = MAP_APPFONT ( 47 , 145 ) ; + Size = MAP_APPFONT ( 75 , 145 ) ; TabStop = TRUE ; DropDown = TRUE ; stringlist [ en-US ] = @@ -228,39 +246,45 @@ ModelessDialog RID_SCDLG_FILTER < "Smallest" ; Default ; > ; < "Largest %" ; Default ; > ; < "Smallest %" ; Default ; > ; + < "Contains" ; Default ; > ; + < "Does not contain" ; Default ; > ; + < "Begins with" ; Default ; > ; + < "Does not begin with" ; Default ; > ; + < "Ends with" ; Default ; > ; + < "Does not end with" ; Default ; > ; }; }; ComboBox ED_VAL1 { - Pos = MAP_APPFONT ( 173 , 25 ) ; + Pos = MAP_APPFONT ( 201 , 25 ) ; Size = MAP_APPFONT ( 60 , 90 ) ; TabStop = TRUE ; DropDown = TRUE ; }; ComboBox ED_VAL2 { - Pos = MAP_APPFONT ( 173 , 41 ) ; + Pos = MAP_APPFONT ( 201 , 41 ) ; Size = MAP_APPFONT ( 60 , 90 ) ; TabStop = TRUE ; DropDown = TRUE ; }; ComboBox ED_VAL3 { - Pos = MAP_APPFONT ( 173 , 57 ) ; + Pos = MAP_APPFONT ( 201 , 57 ) ; Size = MAP_APPFONT ( 60 , 90 ) ; TabStop = TRUE ; DropDown = TRUE ; }; ComboBox ED_VAL4 { - Pos = MAP_APPFONT ( 173 , 73 ) ; + Pos = MAP_APPFONT ( 201 , 73 ) ; Size = MAP_APPFONT ( 60 , 90 ) ; TabStop = TRUE ; DropDown = TRUE ; }; ScrollBar LB_SCROLL { - Pos = MAP_APPFONT ( 237, 25 ) ; + Pos = MAP_APPFONT ( 265, 25 ) ; Size = MAP_APPFONT ( 8 , 60 ) ; TabStop = TRUE ; VScroll = TRUE ; @@ -269,7 +293,7 @@ ModelessDialog RID_SCDLG_FILTER FixedLine FL_CRITERIA { Pos = MAP_APPFONT ( 6 , 3 ) ; - Size = MAP_APPFONT ( 275 , 8 ) ; + Size = MAP_APPFONT ( 267 , 8 ) ; Text [ en-US ] = "Filter criteria"; }; CheckBox BTN_CASE @@ -325,7 +349,7 @@ ModelessDialog RID_SCDLG_FILTER Border = TRUE ; Hide = TRUE ; Pos = MAP_APPFONT ( 21 , 170 ) ; - Size = MAP_APPFONT ( 90 , 90 ) ; + Size = MAP_APPFONT ( 110 , 90 ) ; TabStop = TRUE ; DropDown = TRUE ; }; @@ -333,13 +357,13 @@ ModelessDialog RID_SCDLG_FILTER { Border = TRUE ; Hide = TRUE ; - Pos = MAP_APPFONT ( 115 , 170 ) ; - Size = MAP_APPFONT ( 104 , 12 ) ; + Pos = MAP_APPFONT ( 136 , 170 ) ; + Size = MAP_APPFONT ( 110 , 12 ) ; TabStop = TRUE ; }; ImageButton RB_COPY_AREA { - Pos = MAP_APPFONT ( 221 , 169 ) ; + Pos = MAP_APPFONT ( 248 , 169 ) ; Size = MAP_APPFONT ( 13 , 15 ) ; TabStop = FALSE ; QuickHelpText [ en-US ] = "Shrink" ; @@ -348,7 +372,7 @@ ModelessDialog RID_SCDLG_FILTER { Hide = TRUE ; Pos = MAP_APPFONT ( 6 , 118 ) ; - Size = MAP_APPFONT ( 239 , 8 ) ; + Size = MAP_APPFONT ( 267 , 8 ) ; }; FixedText FT_DBAREA { @@ -367,14 +391,14 @@ ModelessDialog RID_SCDLG_FILTER }; OKButton BTN_OK { - Pos = MAP_APPFONT ( 141 , 101 ) ; + Pos = MAP_APPFONT ( 169 , 101 ) ; Size = MAP_APPFONT ( 50 , 14 ) ; TabStop = TRUE ; DefButton = TRUE ; }; CancelButton BTN_CANCEL { - Pos = MAP_APPFONT ( 195 , 101 ) ; + Pos = MAP_APPFONT ( 223 , 101 ) ; Size = MAP_APPFONT ( 50 , 14 ) ; TabStop = TRUE ; }; @@ -395,7 +419,7 @@ ModelessDialog RID_SCDLG_FILTER FixedLine FL_SEPARATOR { Pos = MAP_APPFONT ( 0 , 91 ) ; - Size = MAP_APPFONT ( 251 , 6 ) ; + Size = MAP_APPFONT ( 279 , 6 ) ; }; }; //============================================================================ diff --git a/sc/source/ui/src/globstr.src b/sc/source/ui/src/globstr.src index 5166340b189e..c5b8cfd1a9e8 100644 --- a/sc/source/ui/src/globstr.src +++ b/sc/source/ui/src/globstr.src @@ -438,10 +438,6 @@ Resource RID_GLOBSTR { Text [ en-US ] = "Cell merge not possible if cells already merged!" ; }; - String STR_MSSG_APPLYPATTLINES_0 - { - Text [ en-US ] = "Cannot apply borders to multiple selection" ; - }; String STR_MSSG_INSERTCELLS_0 { Text [ en-US ] = "Inserting into merged ranges not possible" ; diff --git a/sc/source/ui/src/sortdlg.src b/sc/source/ui/src/sortdlg.src index 2fed10c6f220..71aa7b594575 100644 --- a/sc/source/ui/src/sortdlg.src +++ b/sc/source/ui/src/sortdlg.src @@ -304,4 +304,48 @@ TabDialog RID_SCDLG_SORT }; }; +ModalDialog RID_SCDLG_SORT_WARNING +{ + OutputSize = TRUE ; + SVLook = TRUE ; + Size = MAP_APPFONT ( 180 , 91 ) ; + Text [ en-US ] = "Sort Range" ; + Moveable = TRUE ; + Closeable = FALSE ; + FixedText FT_TEXT + { + Pos = MAP_APPFONT ( 8 , 3 ) ; + Size = MAP_APPFONT ( 170 , 33 ) ; + WordBreak = TRUE; + Text [ en-US ] = "The cells next to the current selection also contain data. Do you want to extend the sort range to %1, or sort the currently selected range, %2?"; + }; + FixedText FT_TIP + { + Pos = MAP_APPFONT ( 8 , 55 ) ; + Size = MAP_APPFONT ( 170 , 33 ) ; + WordBreak = TRUE ; + Text [ en-US ] = "Tip: The sort range can be detected automatically. Place the cell cursor inside a list and execute sort. The whole range of neighboring non-empty cells will then be sorted."; + }; + PushButton BTN_EXTSORT + { + Pos = MAP_APPFONT ( 6 , 39 ) ; + Size = MAP_APPFONT ( 60 , 14 ) ; + TabStop = TRUE ; + DefButton = TRUE ; + Text [ en-US ] = "Extend selection"; + }; + PushButton BTN_CURSORT + { + Pos = MAP_APPFONT ( 70 , 39 ) ; + Size = MAP_APPFONT ( 60 , 14 ) ; + TabStop = TRUE ; + Text [ en-US ] = "Current selection"; + }; + CancelButton BTN_CANCEL + { + Pos = MAP_APPFONT ( 134 , 39 ) ; + Size = MAP_APPFONT ( 40 , 14 ) ; + TabStop = TRUE ; + }; +}; diff --git a/sc/source/ui/undo/undoblk3.cxx b/sc/source/ui/undo/undoblk3.cxx index f12dcda35c8f..ea1e303d6ae3 100644 --- a/sc/source/ui/undo/undoblk3.cxx +++ b/sc/source/ui/undo/undoblk3.cxx @@ -74,6 +74,7 @@ TYPEINIT1(ScUndoAutoFormat, SfxUndoAction); TYPEINIT1(ScUndoReplace, SfxUndoAction); TYPEINIT1(ScUndoTabOp, SfxUndoAction); TYPEINIT1(ScUndoConversion, SfxUndoAction); +TYPEINIT1(ScUndoRefConversion, SfxUndoAction); TYPEINIT1(ScUndoRefreshLink, SfxUndoAction); TYPEINIT1(ScUndoInsertAreaLink, SfxUndoAction); TYPEINIT1(ScUndoRemoveAreaLink, SfxUndoAction); @@ -1197,14 +1198,10 @@ void __EXPORT ScUndoReplace::Undo() } else if (pSearchItem->GetCellType() == SVX_SEARCHIN_NOTE) { - if (ScPostIt* pNote = pDoc->GetNote(aCursorPos)) - { - pNote->SetText( aUndoStr ); - } - else - { - DBG_ERROR("ScUndoReplace: Hier ist keine Notizzelle"); - } + ScPostIt* pNote = pDoc->GetNote( aCursorPos ); + DBG_ASSERT( pNote, "ScUndoReplace::Undo - cell does not contain a note" ); + if (pNote) + pNote->SetText( aCursorPos, aUndoStr ); if (pViewShell) pViewShell->MoveCursorAbs( aCursorPos.Col(), aCursorPos.Row(), SC_FOLLOW_JUMP, FALSE, FALSE ); @@ -1531,6 +1528,98 @@ BOOL ScUndoConversion::CanRepeat(SfxRepeatTarget& rTarget) const //============================================================================ +// class ScUndoRefConversion +// +// cell reference conversion + +//---------------------------------------------------------------------------- + +ScUndoRefConversion::ScUndoRefConversion( ScDocShell* pNewDocShell, + const ScRange& aMarkRange, const ScMarkData& rMark, + ScDocument* pNewUndoDoc, ScDocument* pNewRedoDoc, BOOL bNewMulti, USHORT nNewFlag) : +ScSimpleUndo( pNewDocShell ), +aMarkData ( rMark ), +pUndoDoc ( pNewUndoDoc ), +pRedoDoc ( pNewRedoDoc ), +aRange ( aMarkRange ), +bMulti ( bNewMulti ), +nFlags ( nNewFlag ) +{ + SetChangeTrack(); +} + +__EXPORT ScUndoRefConversion::~ScUndoRefConversion() +{ + delete pUndoDoc; + delete pRedoDoc; +} + +String __EXPORT ScUndoRefConversion::GetComment() const +{ + return ScGlobal::GetRscString( STR_UNDO_ENTERDATA ); // "Eingabe" +} + +void ScUndoRefConversion::SetChangeTrack() +{ + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack && (nFlags & IDF_FORMULA) ) + pChangeTrack->AppendContentsIfInRefDoc( pUndoDoc, + nStartChangeAction, nEndChangeAction ); + else + nStartChangeAction = nEndChangeAction = 0; +} + +void ScUndoRefConversion::DoChange( ScDocument* pRefDoc) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + + ShowTable(aRange); + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + pViewShell->SetMarkData( aMarkData ); + + ScRange aCopyRange = aRange; + SCTAB nTabCount = pDoc->GetTableCount(); + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount-1); + pRefDoc->CopyToDocument( aCopyRange, nFlags, bMulti, pDoc, &aMarkData ); + pDocShell->PostPaint( aRange, PAINT_GRID); + pDocShell->PostDataChanged(); + if (pViewShell) + pViewShell->CellContentChanged(); +} +void __EXPORT ScUndoRefConversion::Undo() +{ + BeginUndo(); + if (pUndoDoc) + DoChange(pUndoDoc); + ScChangeTrack* pChangeTrack = pDocShell->GetDocument()->GetChangeTrack(); + if ( pChangeTrack ) + pChangeTrack->Undo( nStartChangeAction, nEndChangeAction ); + EndUndo(); +} + +void __EXPORT ScUndoRefConversion::Redo() +{ + BeginRedo(); + if (pRedoDoc) + DoChange(pRedoDoc); + SetChangeTrack(); + EndRedo(); +} + +void __EXPORT ScUndoRefConversion::Repeat(SfxRepeatTarget& rTarget) +{ + if (rTarget.ISA(ScTabViewTarget)) + ((ScTabViewTarget&)rTarget).GetViewShell()->DoRefConversion(); +} + +BOOL __EXPORT ScUndoRefConversion::CanRepeat(SfxRepeatTarget& rTarget) const +{ + return (rTarget.ISA(ScTabViewTarget)); +} +//============================================================================ // class ScUndoRefreshLink // // Link aktualisieren / aendern diff --git a/sc/source/ui/undo/undocell.cxx b/sc/source/ui/undo/undocell.cxx index d1a59e65fdb0..eb23516cafeb 100644 --- a/sc/source/ui/undo/undocell.cxx +++ b/sc/source/ui/undo/undocell.cxx @@ -829,6 +829,7 @@ ScUndoReplaceNote::ScUndoReplaceNote( ScDocShell& rDocShell, const ScAddress& rP mpDrawUndo( pDrawUndo ) { DBG_ASSERT( maOldData.mpCaption || maNewData.mpCaption, "ScUndoReplaceNote::ScUndoReplaceNote - missing note captions" ); + DBG_ASSERT( !maOldData.mxInitData.get() && !maNewData.mxInitData.get(), "ScUndoReplaceNote::ScUndoReplaceNote - unexpected unitialized note" ); } ScUndoReplaceNote::~ScUndoReplaceNote() @@ -883,7 +884,7 @@ void ScUndoReplaceNote::DoInsertNote( const ScNoteData& rNoteData ) { ScDocument& rDoc = *pDocShell->GetDocument(); DBG_ASSERT( !rDoc.GetNote( maPos ), "ScUndoReplaceNote::DoInsertNote - unexpected cell note" ); - ScPostIt* pNote = new ScPostIt( rDoc, rNoteData ); + ScPostIt* pNote = new ScPostIt( rDoc, maPos, rNoteData, false ); rDoc.TakeNote( maPos, pNote ); } } @@ -896,7 +897,9 @@ void ScUndoReplaceNote::DoRemoveNote( const ScNoteData& rNoteData ) DBG_ASSERT( rDoc.GetNote( maPos ), "ScUndoReplaceNote::DoRemoveNote - missing cell note" ); if( ScPostIt* pNote = rDoc.ReleaseNote( maPos ) ) { - // forget caption (already handled in drawing undo) + /* Forget pointer to caption object to suppress removing the + caption object from the drawing layer while deleting pNote + (removing the caption is done by a drawing undo action). */ pNote->ForgetCaption(); delete pNote; } @@ -920,7 +923,7 @@ void ScUndoShowHideNote::Undo() { BeginUndo(); if( ScPostIt* pNote = pDocShell->GetDocument()->GetNote( maPos ) ) - pNote->ShowCaption( !mbShown ); + pNote->ShowCaption( maPos, !mbShown ); EndUndo(); } @@ -928,7 +931,7 @@ void ScUndoShowHideNote::Redo() { BeginRedo(); if( ScPostIt* pNote = pDocShell->GetDocument()->GetNote( maPos ) ) - pNote->ShowCaption( mbShown ); + pNote->ShowCaption( maPos, mbShown ); EndRedo(); } diff --git a/sc/source/ui/undo/undotab.cxx b/sc/source/ui/undo/undotab.cxx index d3ff10783c27..abd6f815abf9 100644 --- a/sc/source/ui/undo/undotab.cxx +++ b/sc/source/ui/undo/undotab.cxx @@ -61,6 +61,7 @@ #include "prnsave.hxx" #include "printfun.hxx" #include "chgtrack.hxx" +#include "tabprotection.hxx" // for ScUndoRenameObject - might me moved to another file later #include <svx/svditer.hxx> @@ -72,6 +73,8 @@ extern BOOL bDrawIsInUndo; //! irgendwo als Member !!! using namespace com::sun::star; +using ::com::sun::star::uno::Sequence; +using ::std::auto_ptr; // STATIC DATA ----------------------------------------------------------- @@ -85,7 +88,6 @@ TYPEINIT1(ScUndoMakeScenario, SfxUndoAction); TYPEINIT1(ScUndoImportTab, SfxUndoAction); TYPEINIT1(ScUndoRemoveLink, SfxUndoAction); TYPEINIT1(ScUndoShowHideTab, SfxUndoAction); -TYPEINIT1(ScUndoProtect, SfxUndoAction); TYPEINIT1(ScUndoPrintRange, SfxUndoAction); TYPEINIT1(ScUndoScenarioFlags, SfxUndoAction); TYPEINIT1(ScUndoRenameObject, SfxUndoAction); @@ -112,12 +114,12 @@ ScUndoInsertTab::ScUndoInsertTab( ScDocShell* pNewDocShell, SetChangeTrack(); } -__EXPORT ScUndoInsertTab::~ScUndoInsertTab() +ScUndoInsertTab::~ScUndoInsertTab() { DeleteSdrUndoAction( pDrawUndo ); } -String __EXPORT ScUndoInsertTab::GetComment() const +String ScUndoInsertTab::GetComment() const { if (bAppend) return ScGlobal::GetRscString( STR_UNDO_APPEND_TAB ); @@ -138,7 +140,7 @@ void ScUndoInsertTab::SetChangeTrack() nEndChangeAction = 0; } -void __EXPORT ScUndoInsertTab::Undo() +void ScUndoInsertTab::Undo() { ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); pViewShell->SetTabNo(nTab); @@ -159,7 +161,7 @@ void __EXPORT ScUndoInsertTab::Undo() pDocShell->Broadcast( SfxSimpleHint( SC_HINT_FORCESETTAB ) ); } -void __EXPORT ScUndoInsertTab::Redo() +void ScUndoInsertTab::Redo() { ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); @@ -180,14 +182,14 @@ void __EXPORT ScUndoInsertTab::Redo() SetChangeTrack(); } -void __EXPORT ScUndoInsertTab::Repeat(SfxRepeatTarget& rTarget) +void ScUndoInsertTab::Repeat(SfxRepeatTarget& rTarget) { if (rTarget.ISA(ScTabViewTarget)) ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData()->GetDispatcher(). Execute(FID_INS_TABLE, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD); } -BOOL __EXPORT ScUndoInsertTab::CanRepeat(SfxRepeatTarget& rTarget) const +BOOL ScUndoInsertTab::CanRepeat(SfxRepeatTarget& rTarget) const { return (rTarget.ISA(ScTabViewTarget)); } @@ -211,7 +213,7 @@ ScUndoInsertTables::ScUndoInsertTables( ScDocShell* pNewDocShell, SetChangeTrack(); } -__EXPORT ScUndoInsertTables::~ScUndoInsertTables() +ScUndoInsertTables::~ScUndoInsertTables() { String *pStr=NULL; if(pNameList!=NULL) @@ -227,7 +229,7 @@ __EXPORT ScUndoInsertTables::~ScUndoInsertTables() DeleteSdrUndoAction( pDrawUndo ); } -String __EXPORT ScUndoInsertTables::GetComment() const +String ScUndoInsertTables::GetComment() const { return ScGlobal::GetRscString( STR_UNDO_INSERT_TAB ); } @@ -252,7 +254,7 @@ void ScUndoInsertTables::SetChangeTrack() nStartChangeAction = nEndChangeAction = 0; } -void __EXPORT ScUndoInsertTables::Undo() +void ScUndoInsertTables::Undo() { ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); pViewShell->SetTabNo(nTab); @@ -282,7 +284,7 @@ void __EXPORT ScUndoInsertTables::Undo() pDocShell->Broadcast( SfxSimpleHint( SC_HINT_FORCESETTAB ) ); } -void __EXPORT ScUndoInsertTables::Redo() +void ScUndoInsertTables::Redo() { ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); @@ -299,14 +301,14 @@ void __EXPORT ScUndoInsertTables::Redo() SetChangeTrack(); } -void __EXPORT ScUndoInsertTables::Repeat(SfxRepeatTarget& rTarget) +void ScUndoInsertTables::Repeat(SfxRepeatTarget& rTarget) { if (rTarget.ISA(ScTabViewTarget)) ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData()->GetDispatcher(). Execute(FID_INS_TABLE, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD); } -BOOL __EXPORT ScUndoInsertTables::CanRepeat(SfxRepeatTarget& rTarget) const +BOOL ScUndoInsertTables::CanRepeat(SfxRepeatTarget& rTarget) const { return (rTarget.ISA(ScTabViewTarget)); } @@ -327,12 +329,12 @@ ScUndoDeleteTab::ScUndoDeleteTab( ScDocShell* pNewDocShell,const SvShorts &aTab, SetChangeTrack(); } -__EXPORT ScUndoDeleteTab::~ScUndoDeleteTab() +ScUndoDeleteTab::~ScUndoDeleteTab() { theTabs.Remove(0,theTabs.Count()); } -String __EXPORT ScUndoDeleteTab::GetComment() const +String ScUndoDeleteTab::GetComment() const { return ScGlobal::GetRscString( STR_UNDO_DELETE_TAB ); } @@ -366,7 +368,7 @@ SCTAB lcl_GetVisibleTabBefore( ScDocument& rDoc, SCTAB nTab ) return nTab; } -void __EXPORT ScUndoDeleteTab::Undo() +void ScUndoDeleteTab::Undo() { BeginUndo(); int i=0; @@ -414,7 +416,7 @@ void __EXPORT ScUndoDeleteTab::Undo() pDoc->SetVisible( nTab, pRefUndoDoc->IsVisible( nTab ) ); if ( pRefUndoDoc->IsTabProtected( nTab ) ) - pDoc->SetTabProtection( nTab, TRUE, pRefUndoDoc->GetTabPassword( nTab ) ); + pDoc->SetTabProtection(nTab, pRefUndoDoc->GetTabProtection(nTab)); // Drawing-Layer passiert beim MoveUndo::EndUndo // pDoc->TransferDrawPage(pRefUndoDoc, nTab,nTab); @@ -450,7 +452,7 @@ void __EXPORT ScUndoDeleteTab::Undo() // EndUndo(); } -void __EXPORT ScUndoDeleteTab::Redo() +void ScUndoDeleteTab::Redo() { ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); pViewShell->SetTabNo( lcl_GetVisibleTabBefore( *pDocShell->GetDocument(), theTabs[0] ) ); @@ -469,7 +471,7 @@ void __EXPORT ScUndoDeleteTab::Redo() pDocShell->Broadcast( SfxSimpleHint( SC_HINT_FORCESETTAB ) ); } -void __EXPORT ScUndoDeleteTab::Repeat(SfxRepeatTarget& rTarget) +void ScUndoDeleteTab::Repeat(SfxRepeatTarget& rTarget) { if (rTarget.ISA(ScTabViewTarget)) { @@ -478,7 +480,7 @@ void __EXPORT ScUndoDeleteTab::Repeat(SfxRepeatTarget& rTarget) } } -BOOL __EXPORT ScUndoDeleteTab::CanRepeat(SfxRepeatTarget& rTarget) const +BOOL ScUndoDeleteTab::CanRepeat(SfxRepeatTarget& rTarget) const { return (rTarget.ISA(ScTabViewTarget)); } @@ -500,11 +502,11 @@ ScUndoRenameTab::ScUndoRenameTab( ScDocShell* pNewDocShell, sNewName = rNewName; } -__EXPORT ScUndoRenameTab::~ScUndoRenameTab() +ScUndoRenameTab::~ScUndoRenameTab() { } -String __EXPORT ScUndoRenameTab::GetComment() const +String ScUndoRenameTab::GetComment() const { return ScGlobal::GetRscString( STR_UNDO_RENAME_TAB ); } @@ -526,22 +528,22 @@ void ScUndoRenameTab::DoChange( SCTAB nTabP, const String& rName ) const pViewShell->UpdateInputHandler(); } -void __EXPORT ScUndoRenameTab::Undo() +void ScUndoRenameTab::Undo() { DoChange(nTab, sOldName); } -void __EXPORT ScUndoRenameTab::Redo() +void ScUndoRenameTab::Redo() { DoChange(nTab, sNewName); } -void __EXPORT ScUndoRenameTab::Repeat(SfxRepeatTarget& /* rTarget */) +void ScUndoRenameTab::Repeat(SfxRepeatTarget& /* rTarget */) { // Repeat macht keinen Sinn } -BOOL __EXPORT ScUndoRenameTab::CanRepeat(SfxRepeatTarget& /* rTarget */) const +BOOL ScUndoRenameTab::CanRepeat(SfxRepeatTarget& /* rTarget */) const { return FALSE; } @@ -565,13 +567,13 @@ ScUndoMoveTab::ScUndoMoveTab( ScDocShell* pNewDocShell, theNewTabs.Insert(aNewTab[sal::static_int_cast<USHORT>(i)],theNewTabs.Count()); } -__EXPORT ScUndoMoveTab::~ScUndoMoveTab() +ScUndoMoveTab::~ScUndoMoveTab() { theNewTabs.Remove(0,theNewTabs.Count()); theOldTabs.Remove(0,theOldTabs.Count()); } -String __EXPORT ScUndoMoveTab::GetComment() const +String ScUndoMoveTab::GetComment() const { return ScGlobal::GetRscString( STR_UNDO_MOVE_TAB ); } @@ -618,22 +620,22 @@ void ScUndoMoveTab::DoChange( BOOL bUndo ) const pDocShell->PostDataChanged(); } -void __EXPORT ScUndoMoveTab::Undo() +void ScUndoMoveTab::Undo() { DoChange( TRUE ); } -void __EXPORT ScUndoMoveTab::Redo() +void ScUndoMoveTab::Redo() { DoChange( FALSE ); } -void __EXPORT ScUndoMoveTab::Repeat(SfxRepeatTarget& /* rTarget */) +void ScUndoMoveTab::Repeat(SfxRepeatTarget& /* rTarget */) { // kein Repeat ! ? ! } -BOOL __EXPORT ScUndoMoveTab::CanRepeat(SfxRepeatTarget& /* rTarget */) const +BOOL ScUndoMoveTab::CanRepeat(SfxRepeatTarget& /* rTarget */) const { return FALSE; } @@ -660,12 +662,12 @@ ScUndoCopyTab::ScUndoCopyTab( ScDocShell* pNewDocShell, theNewTabs.Insert(aNewTab[sal::static_int_cast<USHORT>(i)],theNewTabs.Count()); } -__EXPORT ScUndoCopyTab::~ScUndoCopyTab() +ScUndoCopyTab::~ScUndoCopyTab() { DeleteSdrUndoAction( pDrawUndo ); } -String __EXPORT ScUndoCopyTab::GetComment() const +String ScUndoCopyTab::GetComment() const { return ScGlobal::GetRscString( STR_UNDO_COPY_TAB ); } @@ -684,7 +686,7 @@ void ScUndoCopyTab::DoChange() const pDocShell->PostDataChanged(); } -void __EXPORT ScUndoCopyTab::Undo() +void ScUndoCopyTab::Undo() { ScDocument* pDoc = pDocShell->GetDocument(); @@ -717,7 +719,7 @@ void __EXPORT ScUndoCopyTab::Undo() DoChange(); } -void __EXPORT ScUndoCopyTab::Redo() +void ScUndoCopyTab::Redo() { ScDocument* pDoc = pDocShell->GetDocument(); ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); @@ -756,7 +758,7 @@ void __EXPORT ScUndoCopyTab::Redo() } if ( pDoc->IsTabProtected( nAdjSource ) ) - pDoc->SetTabProtection( nNewTab, TRUE, pDoc->GetTabPassword( nAdjSource ) ); + pDoc->CopyTabProtection(nAdjSource, nNewTab); } RedoSdrUndoAction( pDrawUndo ); // after the sheets are inserted @@ -767,12 +769,12 @@ void __EXPORT ScUndoCopyTab::Redo() } -void __EXPORT ScUndoCopyTab::Repeat(SfxRepeatTarget& /* rTarget */) +void ScUndoCopyTab::Repeat(SfxRepeatTarget& /* rTarget */) { // kein Repeat ! ? ! } -BOOL __EXPORT ScUndoCopyTab::CanRepeat(SfxRepeatTarget& /* rTarget */) const +BOOL ScUndoCopyTab::CanRepeat(SfxRepeatTarget& /* rTarget */) const { return FALSE; } @@ -801,17 +803,17 @@ ScUndoMakeScenario::ScUndoMakeScenario( ScDocShell* pNewDocShell, pDrawUndo = GetSdrUndoAction( pDocShell->GetDocument() ); } -__EXPORT ScUndoMakeScenario::~ScUndoMakeScenario() +ScUndoMakeScenario::~ScUndoMakeScenario() { DeleteSdrUndoAction( pDrawUndo ); } -String __EXPORT ScUndoMakeScenario::GetComment() const +String ScUndoMakeScenario::GetComment() const { return ScGlobal::GetRscString( STR_UNDO_MAKESCENARIO ); } -void __EXPORT ScUndoMakeScenario::Undo() +void ScUndoMakeScenario::Undo() { ScDocument* pDoc = pDocShell->GetDocument(); @@ -836,7 +838,7 @@ void __EXPORT ScUndoMakeScenario::Undo() pDocShell->Broadcast( SfxSimpleHint( SC_HINT_FORCESETTAB ) ); } -void __EXPORT ScUndoMakeScenario::Redo() +void ScUndoMakeScenario::Redo() { ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); if (pViewShell) @@ -858,7 +860,7 @@ void __EXPORT ScUndoMakeScenario::Redo() SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); } -void __EXPORT ScUndoMakeScenario::Repeat(SfxRepeatTarget& rTarget) +void ScUndoMakeScenario::Repeat(SfxRepeatTarget& rTarget) { if (rTarget.ISA(ScTabViewTarget)) { @@ -866,7 +868,7 @@ void __EXPORT ScUndoMakeScenario::Repeat(SfxRepeatTarget& rTarget) } } -BOOL __EXPORT ScUndoMakeScenario::CanRepeat(SfxRepeatTarget& rTarget) const +BOOL ScUndoMakeScenario::CanRepeat(SfxRepeatTarget& rTarget) const { return (rTarget.ISA(ScTabViewTarget)); } @@ -889,13 +891,13 @@ ScUndoImportTab::ScUndoImportTab( ScDocShell* pShell, pDrawUndo = GetSdrUndoAction( pDocShell->GetDocument() ); } -__EXPORT ScUndoImportTab::~ScUndoImportTab() +ScUndoImportTab::~ScUndoImportTab() { delete pRedoDoc; DeleteSdrUndoAction( pDrawUndo ); } -String __EXPORT ScUndoImportTab::GetComment() const +String ScUndoImportTab::GetComment() const { return ScGlobal::GetRscString( STR_UNDO_INSERT_TAB ); } @@ -922,7 +924,7 @@ void ScUndoImportTab::DoChange() const PAINT_GRID | PAINT_TOP | PAINT_LEFT | PAINT_EXTRAS ); } -void __EXPORT ScUndoImportTab::Undo() +void ScUndoImportTab::Undo() { //! eingefuegte Bereichsnamen etc. @@ -958,7 +960,7 @@ void __EXPORT ScUndoImportTab::Undo() } if ( pDoc->IsTabProtected( nTabPos ) ) - pRedoDoc->SetTabProtection( nTabPos, TRUE, pDoc->GetTabPassword( nTabPos ) ); + pRedoDoc->SetTabProtection(nTabPos, pDoc->GetTabProtection(nTabPos)); } } @@ -973,7 +975,7 @@ void __EXPORT ScUndoImportTab::Undo() DoChange(); } -void __EXPORT ScUndoImportTab::Redo() +void ScUndoImportTab::Redo() { if (!pRedoDoc) { @@ -1012,7 +1014,7 @@ void __EXPORT ScUndoImportTab::Redo() } if ( pRedoDoc->IsTabProtected( nTabPos ) ) - pDoc->SetTabProtection( nTabPos, TRUE, pRedoDoc->GetTabPassword( nTabPos ) ); + pDoc->SetTabProtection(nTabPos, pRedoDoc->GetTabProtection(nTabPos)); } RedoSdrUndoAction( pDrawUndo ); // after the sheets are inserted @@ -1020,14 +1022,14 @@ void __EXPORT ScUndoImportTab::Redo() DoChange(); } -void __EXPORT ScUndoImportTab::Repeat(SfxRepeatTarget& rTarget) +void ScUndoImportTab::Repeat(SfxRepeatTarget& rTarget) { if (rTarget.ISA(ScTabViewTarget)) ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData()->GetDispatcher(). Execute(FID_INS_TABLE, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD); } -BOOL __EXPORT ScUndoImportTab::CanRepeat(SfxRepeatTarget& rTarget) const +BOOL ScUndoImportTab::CanRepeat(SfxRepeatTarget& rTarget) const { return (rTarget.ISA(ScTabViewTarget)); } @@ -1075,14 +1077,14 @@ ScUndoRemoveLink::ScUndoRemoveLink( ScDocShell* pShell, const String& rDoc ) : } } -__EXPORT ScUndoRemoveLink::~ScUndoRemoveLink() +ScUndoRemoveLink::~ScUndoRemoveLink() { delete pTabs; delete pModes; delete[] pTabNames; } -String __EXPORT ScUndoRemoveLink::GetComment() const +String ScUndoRemoveLink::GetComment() const { return ScGlobal::GetRscString( STR_UNDO_REMOVELINK ); } @@ -1099,22 +1101,22 @@ void ScUndoRemoveLink::DoChange( BOOL bLink ) const pDocShell->UpdateLinks(); } -void __EXPORT ScUndoRemoveLink::Undo() +void ScUndoRemoveLink::Undo() { DoChange( TRUE ); } -void __EXPORT ScUndoRemoveLink::Redo() +void ScUndoRemoveLink::Redo() { DoChange( FALSE ); } -void __EXPORT ScUndoRemoveLink::Repeat(SfxRepeatTarget& /* rTarget */) +void ScUndoRemoveLink::Repeat(SfxRepeatTarget& /* rTarget */) { // gippsnich } -BOOL __EXPORT ScUndoRemoveLink::CanRepeat(SfxRepeatTarget& /* rTarget */) const +BOOL ScUndoRemoveLink::CanRepeat(SfxRepeatTarget& /* rTarget */) const { return FALSE; } @@ -1132,7 +1134,7 @@ ScUndoShowHideTab::ScUndoShowHideTab( ScDocShell* pShell, SCTAB nNewTab, BOOL bN { } -__EXPORT ScUndoShowHideTab::~ScUndoShowHideTab() +ScUndoShowHideTab::~ScUndoShowHideTab() { } @@ -1149,17 +1151,17 @@ void ScUndoShowHideTab::DoChange( BOOL bShowP ) const pDocShell->SetDocumentModified(); } -void __EXPORT ScUndoShowHideTab::Undo() +void ScUndoShowHideTab::Undo() { DoChange(!bShow); } -void __EXPORT ScUndoShowHideTab::Redo() +void ScUndoShowHideTab::Redo() { DoChange(bShow); } -void __EXPORT ScUndoShowHideTab::Repeat(SfxRepeatTarget& rTarget) +void ScUndoShowHideTab::Repeat(SfxRepeatTarget& rTarget) { if (rTarget.ISA(ScTabViewTarget)) ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData()->GetDispatcher(). @@ -1167,53 +1169,44 @@ void __EXPORT ScUndoShowHideTab::Repeat(SfxRepeatTarget& rTarget) SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD); } -BOOL __EXPORT ScUndoShowHideTab::CanRepeat(SfxRepeatTarget& rTarget) const +BOOL ScUndoShowHideTab::CanRepeat(SfxRepeatTarget& rTarget) const { return (rTarget.ISA(ScTabViewTarget)); } -String __EXPORT ScUndoShowHideTab::GetComment() const +String ScUndoShowHideTab::GetComment() const { USHORT nId = bShow ? STR_UNDO_SHOWTAB : STR_UNDO_HIDETAB; return ScGlobal::GetRscString( nId ); } -// ----------------------------------------------------------------------- -// -// Tabelle/Dokument schuetzen oder Schutz aufheben -// +// ============================================================================ -ScUndoProtect::ScUndoProtect( ScDocShell* pShell, SCTAB nNewTab, - BOOL bNewProtect, const uno::Sequence<sal_Int8>& rNewPassword ) : - ScSimpleUndo( pShell ), - nTab( nNewTab ), - bProtect( bNewProtect ), - aPassword( rNewPassword ) +ScUndoDocProtect::ScUndoDocProtect(ScDocShell* pShell, auto_ptr<ScDocProtection> pProtectSettings) : + ScSimpleUndo(pShell), + mpProtectSettings(pProtectSettings) { } -__EXPORT ScUndoProtect::~ScUndoProtect() +ScUndoDocProtect::~ScUndoDocProtect() { } -void ScUndoProtect::DoProtect( BOOL bDo ) +void ScUndoDocProtect::DoProtect(bool bProtect) { ScDocument* pDoc = pDocShell->GetDocument(); - if (bDo) + if (bProtect) { - if ( nTab == TABLEID_DOC ) - pDoc->SetDocProtection( TRUE, aPassword ); - else - pDoc->SetTabProtection( nTab, TRUE, aPassword ); + // set protection. + auto_ptr<ScDocProtection> pCopy(new ScDocProtection(*mpProtectSettings)); + pCopy->setProtected(true); + pDoc->SetDocProtection(pCopy.get()); } else { - uno::Sequence<sal_Int8> aEmptyPass; - if ( nTab == TABLEID_DOC ) - pDoc->SetDocProtection( FALSE, aEmptyPass ); - else - pDoc->SetTabProtection( nTab, FALSE, aEmptyPass ); + // remove protection. + pDoc->SetDocProtection(NULL); } ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); @@ -1226,37 +1219,103 @@ void ScUndoProtect::DoProtect( BOOL bDo ) pDocShell->PostPaintGridAll(); } -void __EXPORT ScUndoProtect::Undo() +void ScUndoDocProtect::Undo() { BeginUndo(); - DoProtect( !bProtect ); + DoProtect(!mpProtectSettings->isProtected()); EndUndo(); } -void __EXPORT ScUndoProtect::Redo() +void ScUndoDocProtect::Redo() { BeginRedo(); - DoProtect( bProtect ); + DoProtect(mpProtectSettings->isProtected()); EndRedo(); } -void __EXPORT ScUndoProtect::Repeat(SfxRepeatTarget& /* rTarget */) +void ScUndoDocProtect::Repeat(SfxRepeatTarget& /* rTarget */) { // gippsnich } -BOOL __EXPORT ScUndoProtect::CanRepeat(SfxRepeatTarget& /* rTarget */) const +BOOL ScUndoDocProtect::CanRepeat(SfxRepeatTarget& /* rTarget */) const { return FALSE; // gippsnich } -String __EXPORT ScUndoProtect::GetComment() const +String ScUndoDocProtect::GetComment() const { - USHORT nId; - if ( nTab == TABLEID_DOC ) - nId = bProtect ? STR_UNDO_PROTECT_DOC : STR_UNDO_UNPROTECT_DOC; + USHORT nId = mpProtectSettings->isProtected() ? STR_UNDO_PROTECT_DOC : STR_UNDO_UNPROTECT_DOC; + return ScGlobal::GetRscString( nId ); +} + +// ============================================================================ + +ScUndoTabProtect::ScUndoTabProtect(ScDocShell* pShell, SCTAB nTab, auto_ptr<ScTableProtection> pProtectSettings) : + ScSimpleUndo(pShell), + mnTab(nTab), + mpProtectSettings(pProtectSettings) +{ +} + +ScUndoTabProtect::~ScUndoTabProtect() +{ +} + +void ScUndoTabProtect::DoProtect(bool bProtect) +{ + ScDocument* pDoc = pDocShell->GetDocument(); + + if (bProtect) + { + // set protection. + auto_ptr<ScTableProtection> pCopy(new ScTableProtection(*mpProtectSettings)); + pCopy->setProtected(true); + pDoc->SetTabProtection(mnTab, pCopy.get()); + } else - nId = bProtect ? STR_UNDO_PROTECT_TAB : STR_UNDO_UNPROTECT_TAB; + { + // remove protection. + pDoc->SetTabProtection(mnTab, NULL); + } + + ScTabViewShell* pViewShell = ScTabViewShell::GetActiveViewShell(); + if (pViewShell) + { + pViewShell->UpdateLayerLocks(); + pViewShell->UpdateInputHandler(TRUE); // damit sofort wieder eingegeben werden kann + } + + pDocShell->PostPaintGridAll(); +} + +void ScUndoTabProtect::Undo() +{ + BeginUndo(); + DoProtect(!mpProtectSettings->isProtected()); + EndUndo(); +} + +void ScUndoTabProtect::Redo() +{ + BeginRedo(); + DoProtect(mpProtectSettings->isProtected()); + EndRedo(); +} + +void ScUndoTabProtect::Repeat(SfxRepeatTarget& /* rTarget */) +{ + // gippsnich +} + +BOOL ScUndoTabProtect::CanRepeat(SfxRepeatTarget& /* rTarget */) const +{ + return FALSE; // gippsnich +} + +String ScUndoTabProtect::GetComment() const +{ + USHORT nId = mpProtectSettings->isProtected() ? STR_UNDO_PROTECT_TAB : STR_UNDO_UNPROTECT_TAB; return ScGlobal::GetRscString( nId ); } @@ -1274,7 +1333,7 @@ ScUndoPrintRange::ScUndoPrintRange( ScDocShell* pShell, SCTAB nNewTab, { } -__EXPORT ScUndoPrintRange::~ScUndoPrintRange() +ScUndoPrintRange::~ScUndoPrintRange() { delete pOldRanges; delete pNewRanges; @@ -1297,31 +1356,31 @@ void ScUndoPrintRange::DoChange(BOOL bUndo) pDocShell->PostPaint( ScRange(0,0,nTab,MAXCOL,MAXROW,nTab), PAINT_GRID ); } -void __EXPORT ScUndoPrintRange::Undo() +void ScUndoPrintRange::Undo() { BeginUndo(); DoChange( TRUE ); EndUndo(); } -void __EXPORT ScUndoPrintRange::Redo() +void ScUndoPrintRange::Redo() { BeginRedo(); DoChange( FALSE ); EndRedo(); } -void __EXPORT ScUndoPrintRange::Repeat(SfxRepeatTarget& /* rTarget */) +void ScUndoPrintRange::Repeat(SfxRepeatTarget& /* rTarget */) { // gippsnich } -BOOL __EXPORT ScUndoPrintRange::CanRepeat(SfxRepeatTarget& /* rTarget */) const +BOOL ScUndoPrintRange::CanRepeat(SfxRepeatTarget& /* rTarget */) const { return FALSE; // gippsnich } -String __EXPORT ScUndoPrintRange::GetComment() const +String ScUndoPrintRange::GetComment() const { return ScGlobal::GetRscString( STR_UNDO_PRINTRANGES ); } @@ -1350,16 +1409,16 @@ ScUndoScenarioFlags::ScUndoScenarioFlags( ScDocShell* pNewDocShell, SCTAB nT, { } -__EXPORT ScUndoScenarioFlags::~ScUndoScenarioFlags() +ScUndoScenarioFlags::~ScUndoScenarioFlags() { } -String __EXPORT ScUndoScenarioFlags::GetComment() const +String ScUndoScenarioFlags::GetComment() const { return ScGlobal::GetRscString( STR_UNDO_EDITSCENARIO ); } -void __EXPORT ScUndoScenarioFlags::Undo() +void ScUndoScenarioFlags::Undo() { ScDocument* pDoc = pDocShell->GetDocument(); @@ -1376,7 +1435,7 @@ void __EXPORT ScUndoScenarioFlags::Undo() SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); } -void __EXPORT ScUndoScenarioFlags::Redo() +void ScUndoScenarioFlags::Redo() { ScDocument* pDoc = pDocShell->GetDocument(); @@ -1393,12 +1452,12 @@ void __EXPORT ScUndoScenarioFlags::Redo() SFX_APP()->Broadcast( SfxSimpleHint( SC_HINT_TABLES_CHANGED ) ); } -void __EXPORT ScUndoScenarioFlags::Repeat(SfxRepeatTarget& /* rTarget */) +void ScUndoScenarioFlags::Repeat(SfxRepeatTarget& /* rTarget */) { // Repeat macht keinen Sinn } -BOOL __EXPORT ScUndoScenarioFlags::CanRepeat(SfxRepeatTarget& /* rTarget */) const +BOOL ScUndoScenarioFlags::CanRepeat(SfxRepeatTarget& /* rTarget */) const { return FALSE; } @@ -1498,7 +1557,7 @@ ScUndoLayoutRTL::ScUndoLayoutRTL( ScDocShell* pShell, SCTAB nNewTab, BOOL bNewRT { } -__EXPORT ScUndoLayoutRTL::~ScUndoLayoutRTL() +ScUndoLayoutRTL::~ScUndoLayoutRTL() { } @@ -1518,29 +1577,29 @@ void ScUndoLayoutRTL::DoChange( BOOL bNew ) pDocShell->SetInUndo( FALSE ); } -void __EXPORT ScUndoLayoutRTL::Undo() +void ScUndoLayoutRTL::Undo() { DoChange(!bRTL); } -void __EXPORT ScUndoLayoutRTL::Redo() +void ScUndoLayoutRTL::Redo() { DoChange(bRTL); } -void __EXPORT ScUndoLayoutRTL::Repeat(SfxRepeatTarget& rTarget) +void ScUndoLayoutRTL::Repeat(SfxRepeatTarget& rTarget) { if (rTarget.ISA(ScTabViewTarget)) ((ScTabViewTarget&)rTarget).GetViewShell()->GetViewData()->GetDispatcher(). Execute( FID_TAB_RTL, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD); } -BOOL __EXPORT ScUndoLayoutRTL::CanRepeat(SfxRepeatTarget& rTarget) const +BOOL ScUndoLayoutRTL::CanRepeat(SfxRepeatTarget& rTarget) const { return (rTarget.ISA(ScTabViewTarget)); } -String __EXPORT ScUndoLayoutRTL::GetComment() const +String ScUndoLayoutRTL::GetComment() const { return ScGlobal::GetRscString( STR_UNDO_TAB_RTL ); } @@ -1560,7 +1619,7 @@ ScUndoSetGrammar::ScUndoSetGrammar( ScDocShell* pShell, meOldGrammar = pDocShell->GetDocument()->GetGrammar(); } -__EXPORT ScUndoSetGrammar::~ScUndoSetGrammar() +ScUndoSetGrammar::~ScUndoSetGrammar() { } @@ -1573,17 +1632,17 @@ void ScUndoSetGrammar::DoChange( formula::FormulaGrammar::Grammar eGrammar ) pDocShell->SetInUndo( FALSE ); } -void __EXPORT ScUndoSetGrammar::Undo() +void ScUndoSetGrammar::Undo() { DoChange( meOldGrammar ); } -void __EXPORT ScUndoSetGrammar::Redo() +void ScUndoSetGrammar::Redo() { DoChange( meNewGrammar ); } -void __EXPORT ScUndoSetGrammar::Repeat(SfxRepeatTarget& /* rTarget */) +void ScUndoSetGrammar::Repeat(SfxRepeatTarget& /* rTarget */) { #if 0 // erAck: 2006-09-07T23:00+0200 commented out in CWS scr1c1 @@ -1593,12 +1652,12 @@ void __EXPORT ScUndoSetGrammar::Repeat(SfxRepeatTarget& /* rTarget */) #endif } -BOOL __EXPORT ScUndoSetGrammar::CanRepeat(SfxRepeatTarget& rTarget) const +BOOL ScUndoSetGrammar::CanRepeat(SfxRepeatTarget& rTarget) const { return (rTarget.ISA(ScTabViewTarget)); } -String __EXPORT ScUndoSetGrammar::GetComment() const +String ScUndoSetGrammar::GetComment() const { return ScGlobal::GetRscString( STR_UNDO_TAB_R1C1 ); } diff --git a/sc/source/ui/unoobj/cellsuno.cxx b/sc/source/ui/unoobj/cellsuno.cxx index c73f56dc55a4..cfe51aed6edc 100644 --- a/sc/source/ui/unoobj/cellsuno.cxx +++ b/sc/source/ui/unoobj/cellsuno.cxx @@ -1170,8 +1170,8 @@ BOOL lcl_PutDataArray( ScDocShell& rDocShell, const ScRange& rRange, } BOOL lcl_PutFormulaArray( ScDocShell& rDocShell, const ScRange& rRange, - const uno::Sequence< uno::Sequence<rtl::OUString> >& aData, - const formula::FormulaGrammar::Grammar eGrammar ) + const uno::Sequence< uno::Sequence<rtl::OUString> >& aData, + const ::rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar ) { // BOOL bApi = TRUE; @@ -1226,7 +1226,7 @@ BOOL lcl_PutFormulaArray( ScDocShell& rDocShell, const ScRange& rRange, { String aText(pColArr[nCol]); ScAddress aPos( nDocCol, nDocRow, nTab ); - ScBaseCell* pNewCell = aFunc.InterpretEnglishString( aPos, aText, eGrammar ); + ScBaseCell* pNewCell = aFunc.InterpretEnglishString( aPos, aText, rFormulaNmsp, eGrammar ); pDoc->PutCell( aPos, pNewCell ); ++nDocCol; @@ -5052,15 +5052,14 @@ rtl::OUString SAL_CALL ScCellRangeObj::getArrayFormula() throw(uno::RuntimeExcep return aFormula; } -void ScCellRangeObj::SetArrayFormula_Impl( const rtl::OUString& aFormula, - const formula::FormulaGrammar::Grammar eGrammar ) throw(uno::RuntimeException) +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) { - String aString(aFormula); ScDocFunc aFunc(*pDocSh); - if ( aString.Len() ) + if ( rFormula.getLength() ) { if ( ScTableSheetObj::getImplementation( (cppu::OWeakObject*)this ) ) { @@ -5068,7 +5067,7 @@ void ScCellRangeObj::SetArrayFormula_Impl( const rtl::OUString& aFormula, throw uno::RuntimeException(); } - aFunc.EnterMatrix( aRange, NULL, NULL, aString, TRUE, TRUE, eGrammar ); + aFunc.EnterMatrix( aRange, NULL, NULL, rFormula, TRUE, TRUE, rFormulaNmsp, eGrammar ); } else { @@ -5086,14 +5085,14 @@ void SAL_CALL ScCellRangeObj::setArrayFormula( const rtl::OUString& aFormula ) { ScUnoGuard aGuard; // GRAM_PODF_A1 for API compatibility. - SetArrayFormula_Impl( aFormula,formula::FormulaGrammar::GRAM_PODF_A1); + SetArrayFormula_Impl( aFormula, ::rtl::OUString(), formula::FormulaGrammar::GRAM_PODF_A1); } -void ScCellRangeObj::SetArrayFormulaWithGrammar( const rtl::OUString& aFormula, - const formula::FormulaGrammar::Grammar eGrammar ) throw(uno::RuntimeException) +void ScCellRangeObj::SetArrayFormulaWithGrammar( const rtl::OUString& rFormula, + const rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar ) throw(uno::RuntimeException) { ScUnoGuard aGuard; - SetArrayFormula_Impl( aFormula, eGrammar); + SetArrayFormula_Impl( rFormula, rFormulaNmsp, eGrammar); } // XArrayFormulaTokens @@ -5153,7 +5152,7 @@ void SAL_CALL ScCellRangeObj::setArrayTokens( const uno::Sequence<sheet::Formula // 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,formula::FormulaGrammar::GRAM_PODF_A1 ); + aFunc.EnterMatrix( aRange, NULL, &aTokenArray, EMPTY_STRING, TRUE, TRUE, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 ); } else { @@ -5269,7 +5268,7 @@ void SAL_CALL ScCellRangeObj::setFormulaArray( if (pDocSh) { // GRAM_PODF_A1 for API compatibility. - bDone = lcl_PutFormulaArray( *pDocSh, aRange, aArray,formula::FormulaGrammar::GRAM_PODF_A1 ); + bDone = lcl_PutFormulaArray( *pDocSh, aRange, aArray, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 ); } if (!bDone) @@ -5439,7 +5438,7 @@ void SAL_CALL ScCellRangeObj::fillAuto( sheet::FillDirection nFillDirection, if ( pDocSh && nSourceCount ) { ScRange aSourceRange(aRange); - SCCOLROW nCount = 0; // "Dest-Count" + SCsCOLROW nCount = 0; // "Dest-Count" FillDir eDir = FILL_TO_BOTTOM; BOOL bError = FALSE; switch (nFillDirection) @@ -5467,7 +5466,7 @@ void SAL_CALL ScCellRangeObj::fillAuto( sheet::FillDirection nFillDirection, default: bError = TRUE; } - if (nCount > MAXROW) // Ueberlauf + if (nCount < 0 || nCount > MAXROW) // overflow bError = TRUE; if (!bError) @@ -5633,7 +5632,15 @@ void SAL_CALL ScCellRangeObj::filter( const uno::Reference<sheet::XSheetFilterDe ScDocShell* pDocSh = GetDocShell(); ScFilterDescriptor aImpl(pDocSh); - aImpl.setFilterFields( xDescriptor->getFilterFields() ); + 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 ); @@ -6198,7 +6205,7 @@ void ScCellObj::SetString_Impl(const String& rString, BOOL bInterpret, BOOL bEng { ScDocFunc aFunc(*pDocSh); // GRAM_PODF_A1 for API compatibility. - (void)aFunc.SetCellText( aCellPos, rString, bInterpret, bEnglish, TRUE,formula::FormulaGrammar::GRAM_PODF_A1 ); + (void)aFunc.SetCellText( aCellPos, rString, bInterpret, bEnglish, TRUE, EMPTY_STRING, formula::FormulaGrammar::GRAM_PODF_A1 ); } } @@ -6246,13 +6253,13 @@ void ScCellObj::SetFormulaResultDouble( double fResult ) } void ScCellObj::SetFormulaWithGrammar( const ::rtl::OUString& rFormula, - const formula::FormulaGrammar::Grammar eGrammar ) + const ::rtl::OUString& rFormulaNmsp, const formula::FormulaGrammar::Grammar eGrammar ) { ScDocShell* pDocSh = GetDocShell(); if ( pDocSh ) { ScDocFunc aFunc(*pDocSh); - aFunc.SetCellText( aCellPos, String( rFormula), TRUE, TRUE, TRUE, eGrammar); + aFunc.SetCellText( aCellPos, rFormula, TRUE, TRUE, TRUE, rFormulaNmsp, eGrammar); } } diff --git a/sc/source/ui/unoobj/chart2uno.cxx b/sc/source/ui/unoobj/chart2uno.cxx index 083dfc3f9374..ccd1b558342b 100644 --- a/sc/source/ui/unoobj/chart2uno.cxx +++ b/sc/source/ui/unoobj/chart2uno.cxx @@ -1051,7 +1051,7 @@ void lcl_SeperateOneRowRange(ScRange aR, const ScAddress& rPos, ScRangeListRef& } vector<ScSharedTokenRef> aTokens; - ScRefTokenHelper::compileRangeRepresentation(aTokens, aRangeRepresentation, m_pDocument); + ScRefTokenHelper::compileRangeRepresentation(aTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar()); return !aTokens.empty(); } @@ -1445,7 +1445,7 @@ ScChart2DataProvider::createDataSource( } vector<ScSharedTokenRef> aRefTokens; - ScRefTokenHelper::compileRangeRepresentation(aRefTokens, aRangeRepresentation, m_pDocument); + ScRefTokenHelper::compileRangeRepresentation(aRefTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar()); if (aRefTokens.empty()) // Invalid range representation. Bail out. throw lang::IllegalArgumentException(); @@ -2180,7 +2180,7 @@ uno::Sequence< beans::PropertyValue > SAL_CALL ScChart2DataProvider::detectArgum return false; vector<ScSharedTokenRef> aTokens; - ScRefTokenHelper::compileRangeRepresentation(aTokens, aRangeRepresentation, m_pDocument); + ScRefTokenHelper::compileRangeRepresentation(aTokens, aRangeRepresentation, m_pDocument, m_pDocument->GetGrammar()); return !aTokens.empty(); } @@ -2197,6 +2197,12 @@ uno::Reference< chart2::data::XDataSequence > SAL_CALL 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()) @@ -2242,7 +2248,7 @@ rtl::OUString SAL_CALL ScChart2DataProvider::convertRangeToXML( const rtl::OUStr return aRet; vector<ScSharedTokenRef> aRefTokens; - ScRefTokenHelper::compileRangeRepresentation(aRefTokens, sRangeRepresentation, m_pDocument); + ScRefTokenHelper::compileRangeRepresentation(aRefTokens, sRangeRepresentation, m_pDocument, m_pDocument->GetGrammar()); if (aRefTokens.empty()) throw lang::IllegalArgumentException(); @@ -2483,7 +2489,7 @@ void ScChart2DataProvider::detectRangesFromDataSource(vector<ScSharedTokenRef>& { const OUString& rRangeRep = *itr; vector<ScSharedTokenRef> aTokens; - ScRefTokenHelper::compileRangeRepresentation(aTokens, rRangeRep, m_pDocument); + ScRefTokenHelper::compileRangeRepresentation(aTokens, rRangeRep, m_pDocument, m_pDocument->GetGrammar()); CollectRefTokens func; func = for_each(aTokens.begin(), aTokens.end(), func); diff --git a/sc/source/ui/unoobj/datauno.cxx b/sc/source/ui/unoobj/datauno.cxx index 98a8a8551d6c..13f2c26c6e47 100644 --- a/sc/source/ui/unoobj/datauno.cxx +++ b/sc/source/ui/unoobj/datauno.cxx @@ -45,6 +45,8 @@ #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" @@ -1106,7 +1108,7 @@ void ScFilterDescriptorBase::Notify( SfxBroadcaster&, const SfxHint& rHint ) } } -// XSheetFilterDescriptor +// XSheetFilterDescriptor and XSheetFilterDescriptor2 uno::Sequence<sheet::TableFilterField> SAL_CALL ScFilterDescriptorBase::getFilterFields() throw(uno::RuntimeException) @@ -1177,6 +1179,80 @@ uno::Sequence<sheet::TableFilterField> SAL_CALL ScFilterDescriptorBase::getFilte 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) @@ -1251,6 +1327,86 @@ void SAL_CALL ScFilterDescriptorBase::setFilterFields( 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 diff --git a/sc/source/ui/unoobj/docuno.cxx b/sc/source/ui/unoobj/docuno.cxx index f25d4a41980a..c924205bdce5 100644 --- a/sc/source/ui/unoobj/docuno.cxx +++ b/sc/source/ui/unoobj/docuno.cxx @@ -271,10 +271,10 @@ SfxObjectShell* ScModelObj::GetEmbeddedObject() const return pDocShell; } -void ScModelObj::UpdateAllRowHeights() +void ScModelObj::UpdateAllRowHeights(const ScMarkData* pTabMark) { if (pDocShell) - pDocShell->UpdateAllRowHeights(); + pDocShell->UpdateAllRowHeights(pTabMark); } ScDrawLayer* ScModelObj::MakeDrawLayer() @@ -2791,7 +2791,26 @@ void SAL_CALL ScTableRowsObj::setPropertyValue( nRowArr[1] = nEndRow; String aNameString(aPropertyName); - if ( aNameString.EqualsAscii( SC_UNONAME_CELLHGT ) ) + 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 + pDoc->SetRowHeightRange( 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 ) @@ -2813,16 +2832,6 @@ void SAL_CALL ScTableRowsObj::setPropertyValue( else pDoc->GetRowFlagsArrayModifiable( nTab).AndValue( nStartRow, nEndRow, sal::static_int_cast<BYTE>(~CR_FILTERED) ); } - else if ( aNameString.EqualsAscii( SC_UNONAME_OHEIGHT ) ) - { - 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_NEWPAGE) || aNameString.EqualsAscii( SC_UNONAME_MANPAGE) ) { //! single function to set/remove all breaks? diff --git a/sc/source/ui/unoobj/editsrc.cxx b/sc/source/ui/unoobj/editsrc.cxx index 80f77998fe44..476409fa5113 100644 --- a/sc/source/ui/unoobj/editsrc.cxx +++ b/sc/source/ui/unoobj/editsrc.cxx @@ -51,6 +51,7 @@ #include "unoguard.hxx" #include "drwlayer.hxx" #include "userdat.hxx" +#include "postit.hxx" #include "AccessibleText.hxx" //------------------------------------------------------------------------ @@ -223,7 +224,7 @@ SvxEditSource* ScAnnotationEditSource::Clone() const SdrObject* ScAnnotationEditSource::GetCaptionObj() { ScPostIt* pNote = pDocShell->GetDocument()->GetNote( aCellPos ); - return pNote ? pNote->GetCaption() : 0; + return pNote ? pNote->GetOrCreateCaption( aCellPos ) : 0; } SvxTextForwarder* ScAnnotationEditSource::GetTextForwarder() diff --git a/sc/source/ui/unoobj/fmtuno.cxx b/sc/source/ui/unoobj/fmtuno.cxx index 14fdb958a180..f9407b544f76 100644 --- a/sc/source/ui/unoobj/fmtuno.cxx +++ b/sc/source/ui/unoobj/fmtuno.cxx @@ -42,7 +42,6 @@ #include "fmtuno.hxx" #include "miscuno.hxx" -#include "conditio.hxx" #include "validat.hxx" #include "document.hxx" #include "unoguard.hxx" @@ -51,7 +50,8 @@ #include "tokenarray.hxx" #include "tokenuno.hxx" -using namespace com::sun::star; +using namespace ::com::sun::star; +using namespace ::formula; //------------------------------------------------------------------------ @@ -130,12 +130,17 @@ ScConditionMode lcl_ConditionOperatorToMode( sheet::ConditionOperator eOper ) //------------------------------------------------------------------------ -//UNUSED2008-05 ScTableConditionalFormat::ScTableConditionalFormat() -//UNUSED2008-05 { -//UNUSED2008-05 } +ScCondFormatEntryItem::ScCondFormatEntryItem() : + meGrammar1( FormulaGrammar::GRAM_UNSPECIFIED ), + meGrammar2( FormulaGrammar::GRAM_UNSPECIFIED ), + meMode( SC_COND_NONE ) +{ +} + +//------------------------------------------------------------------------ -ScTableConditionalFormat::ScTableConditionalFormat(ScDocument* pDoc, ULONG nKey, - const formula::FormulaGrammar::Grammar eGrammar) +ScTableConditionalFormat::ScTableConditionalFormat( + ScDocument* pDoc, ULONG nKey, FormulaGrammar::Grammar eGrammar) { // Eintrag aus dem Dokument lesen... @@ -156,11 +161,11 @@ ScTableConditionalFormat::ScTableConditionalFormat(ScDocument* pDoc, ULONG nKey, { ScCondFormatEntryItem aItem; const ScCondFormatEntry* pFormatEntry = pFormat->GetEntry(i); - aItem.mnMode = sal::static_int_cast<USHORT>(pFormatEntry->GetOperation()); + 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.meGrammar = eGrammar; + aItem.meGrammar1 = aItem.meGrammar2 = eGrammar; aItem.maStyle = pFormatEntry->GetStyle(); AddEntry_Impl(aItem); @@ -170,8 +175,20 @@ ScTableConditionalFormat::ScTableConditionalFormat(ScDocument* pDoc, ULONG nKey, } } +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, formula::FormulaGrammar::Grammar eGrammar ) const + ScDocument* pDoc, FormulaGrammar::Grammar eGrammar) const { // ScConditionalFormat = Core-Struktur, muss leer sein @@ -185,15 +202,12 @@ void ScTableConditionalFormat::FillFormat( ScConditionalFormat& rFormat, ScCondFormatEntryItem aData; pEntry->GetData(aData); - if (eGrammar == formula::FormulaGrammar::GRAM_UNSPECIFIED) - eGrammar = aData.meGrammar; - if (eGrammar == formula::FormulaGrammar::GRAM_UNSPECIFIED) - { - DBG_ERRORFILE("FillFormat: unspecified grammar, using GRAM_PODF_A1"); - eGrammar = formula::FormulaGrammar::GRAM_PODF_A1; - } - ScCondFormatEntry aCoreEntry( static_cast<ScConditionMode>(aData.mnMode), - aData.maExpr1, aData.maExpr2, pDoc, aData.maPos, aData.maStyle, eGrammar ); + + 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 ); @@ -248,69 +262,86 @@ void SAL_CALL ScTableConditionalFormat::addNew( { ScUnoGuard aGuard; ScCondFormatEntryItem aEntry; - aEntry.mnMode = sal::static_int_cast<USHORT>(SC_COND_NONE); + 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]; - String aPropName(rProp.Name); - if ( aPropName.EqualsAscii( SC_UNONAME_OPERATOR ) ) + if ( rProp.Name.equalsAscii( SC_UNONAME_OPERATOR ) ) { sheet::ConditionOperator eOper = (sheet::ConditionOperator) ScUnoHelpFunctions::GetEnumFromAny( rProp.Value ); - aEntry.mnMode = sal::static_int_cast<USHORT>(lcl_ConditionOperatorToMode( eOper )); + aEntry.meMode = lcl_ConditionOperatorToMode( eOper ); } - else if ( aPropName.EqualsAscii( SC_UNONAME_FORMULA1 ) ) + else if ( rProp.Name.equalsAscii( SC_UNONAME_FORMULA1 ) ) { rtl::OUString aStrVal; uno::Sequence<sheet::FormulaToken> aTokens; if ( rProp.Value >>= aStrVal ) - aEntry.maExpr1 = String( aStrVal ); + aEntry.maExpr1 = aStrVal; else if ( rProp.Value >>= aTokens ) { aEntry.maExpr1.Erase(); aEntry.maTokens1 = aTokens; } } - else if ( aPropName.EqualsAscii( SC_UNONAME_FORMULA2 ) ) + else if ( rProp.Name.equalsAscii( SC_UNONAME_FORMULA2 ) ) { rtl::OUString aStrVal; uno::Sequence<sheet::FormulaToken> aTokens; if ( rProp.Value >>= aStrVal ) - aEntry.maExpr2 = String( aStrVal ); + aEntry.maExpr2 = aStrVal; else if ( rProp.Value >>= aTokens ) { aEntry.maExpr2.Erase(); aEntry.maTokens2 = aTokens; } } - else if ( aPropName.EqualsAscii( SC_UNONAME_SOURCEPOS ) ) + 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 ( aPropName.EqualsAscii( SC_UNONAME_SOURCESTR ) ) + else if ( rProp.Name.equalsAscii( SC_UNONAME_SOURCESTR ) ) { rtl::OUString aStrVal; if ( rProp.Value >>= aStrVal ) aEntry.maPosStr = String( aStrVal ); } - else if ( aPropName.EqualsAscii( SC_UNONAME_STYLENAME ) ) + 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 ( aPropName.EqualsAscii( SC_UNONAME_GRAMMAR ) ) + 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.meGrammar = static_cast<formula::FormulaGrammar::Grammar>(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 { @@ -523,14 +554,14 @@ sheet::ConditionOperator SAL_CALL ScTableConditionalEntry::getOperator() throw(uno::RuntimeException) { ScUnoGuard aGuard; - return lcl_ConditionModeToOperator( static_cast<ScConditionMode>(aData.mnMode) ); + return lcl_ConditionModeToOperator( aData.meMode ); } void SAL_CALL ScTableConditionalEntry::setOperator( sheet::ConditionOperator nOperator ) throw(uno::RuntimeException) { ScUnoGuard aGuard; - aData.mnMode = sal::static_int_cast<USHORT>( lcl_ConditionOperatorToMode( nOperator ) ); + aData.meMode = lcl_ConditionOperatorToMode( nOperator ); if (pParent) pParent->DataChanged(); } @@ -619,7 +650,7 @@ ScTableValidationObj::ScTableValidationObj(ScDocument* pDoc, ULONG nKey, aSrcPos = pData->GetValidSrcPos(); // #b4974740# valid pos for expressions aExpr1 = pData->GetExpression( aSrcPos, 0, 0, eGrammar ); aExpr2 = pData->GetExpression( aSrcPos, 1, 0, eGrammar ); - meGrammar = eGrammar; + meGrammar1 = meGrammar2 = eGrammar; nValMode = sal::static_int_cast<USHORT>( pData->GetDataMode() ); bIgnoreBlank = pData->IsIgnoreBlank(); nShowList = pData->GetListType(); @@ -647,18 +678,14 @@ ScValidationData* ScTableValidationObj::CreateValidationData( ScDocument* pDoc, { // ScValidationData = Core-Struktur - if (eGrammar == formula::FormulaGrammar::GRAM_UNSPECIFIED) - eGrammar = meGrammar; - if (eGrammar == formula::FormulaGrammar::GRAM_UNSPECIFIED) - { - DBG_ERRORFILE("CreateValidationData: unspecified grammar, using GRAM_PODF_A1"); - eGrammar = formula::FormulaGrammar::GRAM_PODF_A1; - } + FormulaGrammar::Grammar eGrammar1 = lclResolveGrammar( eGrammar, meGrammar1 ); + FormulaGrammar::Grammar eGrammar2 = lclResolveGrammar( eGrammar, meGrammar2 ); ScValidationData* pRet = new ScValidationData( (ScValidationMode)nValMode, (ScConditionMode)nMode, aExpr1, aExpr2, pDoc, aSrcPos, - eGrammar ); + maExprNmsp1, maExprNmsp2, + eGrammar1, eGrammar2 ); pRet->SetIgnoreBlank(bIgnoreBlank); pRet->SetListType(nShowList); @@ -702,7 +729,9 @@ void ScTableValidationObj::ClearData_Impl() aSrcPos.Set(0,0,0); aExpr1.Erase(); aExpr2.Erase(); - meGrammar = formula::FormulaGrammar::GRAM_UNSPECIFIED; // will be overriden when needed + maExprNmsp1.Erase(); + maExprNmsp2.Erase(); + meGrammar1 = meGrammar2 = FormulaGrammar::GRAM_UNSPECIFIED; // will be overriden when needed aInputTitle.Erase(); aInputMessage.Erase(); aErrorTitle.Erase(); @@ -905,13 +934,37 @@ void SAL_CALL ScTableValidationObj::setPropertyValue( if ( aValue >>= aStrVal ) aPosString = String( aStrVal ); } - else if ( aString.EqualsAscii( SC_UNONAME_GRAMMAR ) ) + 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 ) - meGrammar = static_cast<formula::FormulaGrammar::Grammar>(nVal); + meGrammar2 = static_cast< FormulaGrammar::Grammar >(nVal); } DataChanged(); diff --git a/sc/source/ui/unoobj/notesuno.cxx b/sc/source/ui/unoobj/notesuno.cxx index 4a9cd420f5de..e44dab865d46 100644 --- a/sc/source/ui/unoobj/notesuno.cxx +++ b/sc/source/ui/unoobj/notesuno.cxx @@ -220,14 +220,14 @@ rtl::OUString SAL_CALL ScAnnotationObj::getAuthor() throw(uno::RuntimeException) { ScUnoGuard aGuard; const ScPostIt* pNote = ImplGetNote(); - return pNote ? pNote->GetAuthor() : EMPTY_STRING; + 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() : EMPTY_STRING; + return pNote ? pNote->GetDate() : rtl::OUString(); } sal_Bool SAL_CALL ScAnnotationObj::getIsVisible() throw(uno::RuntimeException) @@ -298,7 +298,7 @@ uno::Reference < drawing::XShape > ScAnnotationShapeObj::GetXShape() { if (!xShape.is()) if( ScPostIt* pNote = pDocShell->GetDocument()->GetNote( aCellPos ) ) - if( SdrObject* pCaption = pNote->GetCaption() ) + if( SdrObject* pCaption = pNote->GetOrCreateCaption( aCellPos ) ) xShape.set( pCaption->getUnoShape(), uno::UNO_QUERY ); return xShape; } diff --git a/sc/source/ui/unoobj/scdetect.cxx b/sc/source/ui/unoobj/scdetect.cxx index 1e735cc77866..1b17c2e130ac 100644 --- a/sc/source/ui/unoobj/scdetect.cxx +++ b/sc/source/ui/unoobj/scdetect.cxx @@ -356,7 +356,7 @@ static BOOL lcl_IsAnyXMLFilter( const SfxFilter* pFilter ) // 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() ); + aMedium.SetError( aMedium.GetLastStorageCreationState(), ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ) ); if ( xInteraction.is() ) { OUString empty; diff --git a/sc/source/ui/unoobj/tokenuno.cxx b/sc/source/ui/unoobj/tokenuno.cxx index dfb0f42702a8..e6e194d7eb75 100644 --- a/sc/source/ui/unoobj/tokenuno.cxx +++ b/sc/source/ui/unoobj/tokenuno.cxx @@ -51,17 +51,16 @@ #include "docsh.hxx" #include "rangeseq.hxx" #include "externalrefmgr.hxx" -using namespace formula; -using namespace com::sun::star; +using namespace ::formula; +using namespace ::com::sun::star; -//------------------------------------------------------------------------ +// ============================================================================ const SfxItemPropertyMapEntry* lcl_GetFormulaParserMap() { static SfxItemPropertyMapEntry aFormulaParserMap_Impl[] = { - {MAP_CHAR_LEN(SC_UNO_REFERENCEPOS), 0, &getCppuType((table::CellAddress*)0), 0, 0 }, {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 }, @@ -74,7 +73,7 @@ const SfxItemPropertyMapEntry* lcl_GetFormulaParserMap() SC_SIMPLE_SERVICE_INFO( ScFormulaParserObj, "ScFormulaParserObj", SC_SERVICENAME_FORMULAPARS ) -//------------------------------------------------------------------------ +// ============================================================================ ScFormulaParserObj::ScFormulaParserObj(ScDocShell* pDocSh) : mpDocShell( pDocSh ), @@ -135,7 +134,8 @@ void ScFormulaParserObj::SetCompilerFlags( ScCompiler& rCompiler ) const rCompiler.SetExternalLinks( maExternalLinks); } -uno::Sequence<sheet::FormulaToken> SAL_CALL ScFormulaParserObj::parseFormula( const rtl::OUString& aFormula ) +uno::Sequence<sheet::FormulaToken> SAL_CALL ScFormulaParserObj::parseFormula( + const rtl::OUString& aFormula, const table::CellAddress& rReferencePos ) throw (uno::RuntimeException) { ScUnoGuard aGuard; @@ -143,8 +143,10 @@ uno::Sequence<sheet::FormulaToken> SAL_CALL ScFormulaParserObj::parseFormula( co if (mpDocShell) { + ScAddress aRefPos( ScAddress::UNINITIALIZED ); + ScUnoConversion::FillScAddress( aRefPos, rReferencePos ); ScDocument* pDoc = mpDocShell->GetDocument(); - ScCompiler aCompiler( pDoc, maRefPos); + ScCompiler aCompiler( pDoc, aRefPos); aCompiler.SetGrammar(pDoc->GetGrammar()); SetCompilerFlags( aCompiler ); @@ -156,7 +158,8 @@ uno::Sequence<sheet::FormulaToken> SAL_CALL ScFormulaParserObj::parseFormula( co return aRet; } -rtl::OUString SAL_CALL ScFormulaParserObj::printFormula( const uno::Sequence<sheet::FormulaToken>& aTokens ) +rtl::OUString SAL_CALL ScFormulaParserObj::printFormula( + const uno::Sequence<sheet::FormulaToken>& aTokens, const table::CellAddress& rReferencePos ) throw (uno::RuntimeException) { ScUnoGuard aGuard; @@ -167,7 +170,9 @@ rtl::OUString SAL_CALL ScFormulaParserObj::printFormula( const uno::Sequence<she ScDocument* pDoc = mpDocShell->GetDocument(); ScTokenArray aCode; (void)ScTokenConversion::ConvertToTokenArray( *pDoc, aCode, aTokens ); - ScCompiler aCompiler( pDoc, maRefPos, aCode); + ScAddress aRefPos( ScAddress::UNINITIALIZED ); + ScUnoConversion::FillScAddress( aRefPos, rReferencePos ); + ScCompiler aCompiler( pDoc, aRefPos, aCode); aCompiler.SetGrammar(pDoc->GetGrammar()); SetCompilerFlags( aCompiler ); @@ -197,13 +202,7 @@ void SAL_CALL ScFormulaParserObj::setPropertyValue( { ScUnoGuard aGuard; String aString(aPropertyName); - if ( aString.EqualsAscii( SC_UNO_REFERENCEPOS ) ) - { - table::CellAddress aAddress; - aValue >>= aAddress; - ScUnoConversion::FillScAddress( maRefPos, aAddress ); - } // if ( aString.EqualsAscii( SC_UNO_REFERENCEPOS ) ) - else if ( aString.EqualsAscii( SC_UNO_COMPILEFAP ) ) + if ( aString.EqualsAscii( SC_UNO_COMPILEFAP ) ) { aValue >>= mbCompileFAP; } @@ -218,7 +217,7 @@ void SAL_CALL ScFormulaParserObj::setPropertyValue( if (mxOpCodeMap.get() && mbEnglish != bOldEnglish) { ScDocument* pDoc = mpDocShell->GetDocument(); - ScCompiler aCompiler( pDoc, maRefPos); + ScCompiler aCompiler( pDoc, ScAddress()); aCompiler.SetGrammar(pDoc->GetGrammar()); mxOpCodeMap = aCompiler.CreateOpCodeMap( maOpCodeMapping, mbEnglish); } @@ -239,7 +238,7 @@ void SAL_CALL ScFormulaParserObj::setPropertyValue( if (aValue >>= maOpCodeMapping) { ScDocument* pDoc = mpDocShell->GetDocument(); - ScCompiler aCompiler( pDoc, maRefPos); + ScCompiler aCompiler( pDoc, ScAddress()); aCompiler.SetGrammar(pDoc->GetGrammar()); mxOpCodeMap = aCompiler.CreateOpCodeMap( maOpCodeMapping, mbEnglish); } @@ -262,13 +261,7 @@ uno::Any SAL_CALL ScFormulaParserObj::getPropertyValue( const rtl::OUString& aPr ScUnoGuard aGuard; uno::Any aRet; String aString(aPropertyName); - if ( aString.EqualsAscii( SC_UNO_REFERENCEPOS ) ) - { - table::CellAddress aAddress; - ScUnoConversion::FillApiAddress( aAddress, maRefPos ); - aRet <<= aAddress; - } - else if ( aString.EqualsAscii( SC_UNO_COMPILEFAP ) ) + if ( aString.EqualsAscii( SC_UNO_COMPILEFAP ) ) { aRet <<= mbCompileFAP; } @@ -299,7 +292,7 @@ uno::Any SAL_CALL ScFormulaParserObj::getPropertyValue( const rtl::OUString& aPr SC_IMPL_DUMMY_PROPERTY_LISTENER( ScFormulaParserObj ) -//------------------------------------------------------------------------ +// ============================================================================ void lcl_ExternalRefToApi( sheet::SingleReference& rAPI, const ScSingleRefData& rRef ) { @@ -345,7 +338,7 @@ void lcl_SingleRefToApi( sheet::SingleReference& rAPI, const ScSingleRefData& rR bool ScTokenConversion::ConvertToTokenArray( ScDocument& rDoc, ScTokenArray& rTokenArray, const uno::Sequence<sheet::FormulaToken>& rSequence ) { - return rTokenArray.Fill(rSequence,rDoc.GetExternalRefManager()); + return !rTokenArray.Fill(rSequence,rDoc.GetExternalRefManager()); } // static @@ -463,9 +456,13 @@ bool ScTokenConversion::ConvertToTokenSequence( ScDocument& rDoc, return !bError; } -// ----------------------------------------------------------------------------- + +// ============================================================================ + ScFormulaOpCodeMapperObj::ScFormulaOpCodeMapperObj(::std::auto_ptr<formula::FormulaCompiler> _pCompiler) : formula::FormulaOpCodeMapperObj(_pCompiler) { } +// ============================================================================ + diff --git a/sc/source/ui/unoobj/viewuno.cxx b/sc/source/ui/unoobj/viewuno.cxx index fa27b94a9956..c1af5ac9bb99 100644 --- a/sc/source/ui/unoobj/viewuno.cxx +++ b/sc/source/ui/unoobj/viewuno.cxx @@ -71,6 +71,7 @@ #include "gridwin.hxx" #include <com/sun/star/view/DocumentZoomType.hpp> #include "AccessibilityHints.hxx" +#include <svx/sdrhittesthelper.hxx> using namespace com::sun::star; @@ -1169,7 +1170,7 @@ uno::Reference< uno::XInterface > ScTabViewObj::GetClickedObject(const Point& rP SdrView* pDrawView = GetViewShell()->GetSdrView(); - if (pDrawPage && pDrawView) + if (pDrawPage && pDrawView && pDrawView->GetSdrPageView()) { Window* pActiveWin = pData->GetActiveWin(); Point aPos = pActiveWin->PixelToLogic(rPoint); @@ -1183,7 +1184,7 @@ uno::Reference< uno::XInterface > ScTabViewObj::GetClickedObject(const Point& rP while (i < nCount && !bFound) { SdrObject* pObj = pDrawPage->GetObj(i); - if (pObj && pObj->IsHit(aPos, nHitLog)) + if (pObj && SdrObjectPrimitiveHit(*pObj, aPos, nHitLog, *pDrawView->GetSdrPageView(), 0, false)) { xTarget.set(pObj->getUnoShape(), uno::UNO_QUERY); bFound = sal_True; diff --git a/sc/source/ui/unoobj/warnpassword.cxx b/sc/source/ui/unoobj/warnpassword.cxx index 6453bcbd0de7..6b11ac7c6641 100644 --- a/sc/source/ui/unoobj/warnpassword.cxx +++ b/sc/source/ui/unoobj/warnpassword.cxx @@ -95,3 +95,4 @@ bool ScWarnPassword::WarningOnPassword( SfxMedium& rMedium ) } return bReturn; } + diff --git a/sc/source/ui/vba/vbacontrol.cxx b/sc/source/ui/vba/vbacontrol.cxx index ddb4b39a91a5..eaf9365016ec 100644 --- a/sc/source/ui/vba/vbacontrol.cxx +++ b/sc/source/ui/vba/vbacontrol.cxx @@ -185,14 +185,15 @@ void SAL_CALL ScVbaControl::setEnabled( sal_Bool bVisible ) throw (uno::RuntimeE sal_Bool SAL_CALL ScVbaControl::getVisible() throw (uno::RuntimeException) { - uno::Reference< awt::XWindow2 > xWindow2( getWindowPeer(), uno::UNO_QUERY_THROW ); - return xWindow2->isVisible(); + sal_Bool bVisible = sal_False; + m_xProps->getPropertyValue(rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "EnableVisible" ) ) ) >>= bVisible; + return bVisible; } void SAL_CALL ScVbaControl::setVisible( sal_Bool bVisible ) throw (uno::RuntimeException) { - uno::Reference< awt::XWindow2 > xWindow2( getWindowPeer(), uno::UNO_QUERY_THROW ); - xWindow2->setVisible( bVisible ); + m_xProps->setPropertyValue + (rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "EnableVisible" ) ), uno::makeAny( bVisible ) ); } double SAL_CALL ScVbaControl::getHeight() throw (uno::RuntimeException) { diff --git a/sc/source/ui/vba/vbarange.cxx b/sc/source/ui/vba/vbarange.cxx index 5019167b4374..d1ac4504ce96 100644 --- a/sc/source/ui/vba/vbarange.cxx +++ b/sc/source/ui/vba/vbarange.cxx @@ -77,7 +77,10 @@ #include <com/sun/star/sheet/XCellRangeMovement.hpp> #include <com/sun/star/sheet/XCellRangeData.hpp> #include <com/sun/star/sheet/FormulaResult.hpp> +#include <com/sun/star/sheet/FilterOperator2.hpp> #include <com/sun/star/sheet/TableFilterField.hpp> +#include <com/sun/star/sheet/TableFilterField2.hpp> +#include <com/sun/star/sheet/XSheetFilterDescriptor2.hpp> #include <com/sun/star/sheet/XSheetFilterable.hpp> #include <com/sun/star/sheet/FilterConnection.hpp> #include <com/sun/star/util/CellProtection.hpp> @@ -4027,7 +4030,7 @@ void lcl_SetAllQueryForField( ScDocShell* pDocShell, SCCOLROW nField, sal_Int16 } // Modifies sCriteria, and nOp depending on the value of sCriteria -void lcl_setTableFieldsFromCriteria( rtl::OUString& sCriteria1, uno::Reference< beans::XPropertySet >& xDescProps, sheet::TableFilterField& rFilterField ) +void lcl_setTableFieldsFromCriteria( rtl::OUString& sCriteria1, uno::Reference< beans::XPropertySet >& xDescProps, sheet::TableFilterField2& rFilterField ) { // #TODO make this more efficient and cycle through // sCriteria1 character by character to pick up <,<>,=, * etc. @@ -4047,10 +4050,10 @@ void lcl_setTableFieldsFromCriteria( rtl::OUString& sCriteria1, uno::Reference< if ( ( nPos = sCriteria1.indexOf( EQUALS ) ) == 0 ) { if ( sCriteria1.getLength() == EQUALS.getLength() ) - rFilterField.Operator = sheet::FilterOperator_EMPTY; + rFilterField.Operator = sheet::FilterOperator2::EMPTY; else { - rFilterField.Operator = sheet::FilterOperator_EQUAL; + rFilterField.Operator = sheet::FilterOperator2::EQUAL; sCriteria1 = sCriteria1.copy( EQUALS.getLength() ); sCriteria1 = VBAToRegexp( sCriteria1 ); // UseRegularExpressions @@ -4062,10 +4065,10 @@ void lcl_setTableFieldsFromCriteria( rtl::OUString& sCriteria1, uno::Reference< else if ( ( nPos = sCriteria1.indexOf( NOTEQUALS ) ) == 0 ) { if ( sCriteria1.getLength() == NOTEQUALS.getLength() ) - rFilterField.Operator = sheet::FilterOperator_NOT_EMPTY; + rFilterField.Operator = sheet::FilterOperator2::NOT_EMPTY; else { - rFilterField.Operator = sheet::FilterOperator_NOT_EQUAL; + rFilterField.Operator = sheet::FilterOperator2::NOT_EQUAL; sCriteria1 = sCriteria1.copy( NOTEQUALS.getLength() ); sCriteria1 = VBAToRegexp( sCriteria1 ); // UseRegularExpressions @@ -4079,12 +4082,12 @@ void lcl_setTableFieldsFromCriteria( rtl::OUString& sCriteria1, uno::Reference< if ( ( nPos = sCriteria1.indexOf( GREATERTHANEQUALS ) ) == 0 ) { sCriteria1 = sCriteria1.copy( GREATERTHANEQUALS.getLength() ); - rFilterField.Operator = sheet::FilterOperator_GREATER_EQUAL; + rFilterField.Operator = sheet::FilterOperator2::GREATER_EQUAL; } else { sCriteria1 = sCriteria1.copy( GREATERTHAN.getLength() ); - rFilterField.Operator = sheet::FilterOperator_GREATER; + rFilterField.Operator = sheet::FilterOperator2::GREATER; } } @@ -4094,17 +4097,17 @@ void lcl_setTableFieldsFromCriteria( rtl::OUString& sCriteria1, uno::Reference< if ( ( nPos = sCriteria1.indexOf( LESSTHANEQUALS ) ) == 0 ) { sCriteria1 = sCriteria1.copy( LESSTHANEQUALS.getLength() ); - rFilterField.Operator = sheet::FilterOperator_LESS_EQUAL; + rFilterField.Operator = sheet::FilterOperator2::LESS_EQUAL; } else { sCriteria1 = sCriteria1.copy( LESSTHAN.getLength() ); - rFilterField.Operator = sheet::FilterOperator_LESS; + rFilterField.Operator = sheet::FilterOperator2::LESS; } } else - rFilterField.Operator = sheet::FilterOperator_EQUAL; + rFilterField.Operator = sheet::FilterOperator2::EQUAL; if ( bIsNumeric ) { @@ -4213,13 +4216,16 @@ ScVbaRange::AutoFilter( const uno::Any& Field, const uno::Any& Criteria1, const bool bAll = false;; if ( ( Field >>= nField ) ) { - uno::Sequence< sheet::TableFilterField > sTabFilts; - uno::Reference< sheet::XSheetFilterDescriptor > xDesc = xDataBaseRange->getFilterDescriptor(); - uno::Reference< beans::XPropertySet > xDescProps( xDesc, uno::UNO_QUERY_THROW ); + uno::Reference< sheet::XSheetFilterDescriptor2 > xDesc( + xDataBaseRange->getFilterDescriptor(), uno::UNO_QUERY ); + if ( xDesc.is() ) + { + uno::Sequence< sheet::TableFilterField2 > sTabFilts; + uno::Reference< beans::XPropertySet > xDescProps( xDesc, uno::UNO_QUERY_THROW ); if ( Criteria1.hasValue() ) { sTabFilts.realloc( 1 ); - sTabFilts[0].Operator = sheet::FilterOperator_EQUAL;// sensible default + sTabFilts[0].Operator = sheet::FilterOperator2::EQUAL;// sensible default if ( !bCritHasNumericValue ) { Criteria1 >>= sCriteria1; @@ -4252,16 +4258,16 @@ ScVbaRange::AutoFilter( const uno::Any& Field, const uno::Any& Criteria1, const switch ( nOperator ) { case excel::XlAutoFilterOperator::xlBottom10Items: - sTabFilts[0].Operator = sheet::FilterOperator_BOTTOM_VALUES; + sTabFilts[0].Operator = sheet::FilterOperator2::BOTTOM_VALUES; break; case excel::XlAutoFilterOperator::xlBottom10Percent: - sTabFilts[0].Operator = sheet::FilterOperator_BOTTOM_PERCENT; + sTabFilts[0].Operator = sheet::FilterOperator2::BOTTOM_PERCENT; break; case excel::XlAutoFilterOperator::xlTop10Items: - sTabFilts[0].Operator = sheet::FilterOperator_TOP_VALUES; + sTabFilts[0].Operator = sheet::FilterOperator2::TOP_VALUES; break; case excel::XlAutoFilterOperator::xlTop10Percent: - sTabFilts[0].Operator = sheet::FilterOperator_TOP_PERCENT; + sTabFilts[0].Operator = sheet::FilterOperator2::TOP_PERCENT; break; case excel::XlAutoFilterOperator::xlOr: nConn = sheet::FilterConnection_OR; @@ -4300,12 +4306,12 @@ ScVbaRange::AutoFilter( const uno::Any& Field, const uno::Any& Criteria1, const { Criteria2 >>= sTabFilts[1].NumericValue; sTabFilts[1].IsNumeric = sal_True; - sTabFilts[1].Operator = sheet::FilterOperator_EQUAL; + sTabFilts[1].Operator = sheet::FilterOperator2::EQUAL; } } } - xDesc->setFilterFields( sTabFilts ); + xDesc->setFilterFields2( sTabFilts ); if ( !bAll ) { xDataBaseRange->refresh(); @@ -4313,6 +4319,7 @@ ScVbaRange::AutoFilter( const uno::Any& Field, const uno::Any& Criteria1, const else // was 0 based now seems to be 1 lcl_SetAllQueryForField( pShell, nField, nSheet ); + } } else { @@ -4333,7 +4340,10 @@ ScVbaRange::AutoFilter( const uno::Any& Field, const uno::Any& Criteria1, const lcl_SetAllQueryForField( pShell, rEntry.nField, nSheet ); } // remove exising filters - xDataBaseRange->getFilterDescriptor()->setFilterFields( uno::Sequence< sheet::TableFilterField >() ); + uno::Reference< sheet::XSheetFilterDescriptor2 > xSheetFilterDescriptor( + xDataBaseRange->getFilterDescriptor(), uno::UNO_QUERY ); + if( xSheetFilterDescriptor.is() ) + xSheetFilterDescriptor->setFilterFields2( uno::Sequence< sheet::TableFilterField2 >() ); } xDBRangeProps->setPropertyValue( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM("AutoFilter") ), uno::Any(!bHasAuto) ); diff --git a/sc/source/ui/view/cellsh1.cxx b/sc/source/ui/view/cellsh1.cxx index 6446d023fe9b..e5bb702402d8 100644 --- a/sc/source/ui/view/cellsh1.cxx +++ b/sc/source/ui/view/cellsh1.cxx @@ -103,6 +103,7 @@ #include "dpsave.hxx" #include "dpgroup.hxx" // for ScDPNumGroupInfo #include "spellparam.hxx" +#include "postit.hxx" #include "globstr.hrc" #include "scui_def.hxx" //CHINA001 @@ -1708,32 +1709,7 @@ void ScCellShell::ExecuteEdit( SfxRequest& rReq ) break; case SID_TOGGLE_REL: - { - BOOL bOk = FALSE; - SCCOL nCol = GetViewData()->GetCurX(); - SCROW nRow = GetViewData()->GetCurY(); - SCTAB nTab = GetViewData()->GetTabNo(); - ScDocument* pDoc = GetViewData()->GetDocument(); - CellType eType; - pDoc->GetCellType( nCol, nRow, nTab, eType ); - if (eType == CELLTYPE_FORMULA) - { - String aOld; - pDoc->GetFormula( nCol, nRow, nTab, aOld ); - xub_StrLen nLen = aOld.Len(); - ScRefFinder aFinder( aOld, pDoc ); - aFinder.ToggleRel( 0, nLen ); - if (aFinder.GetFound()) - { - String aNew = aFinder.GetText(); - pTabViewShell->EnterData( nCol, nRow, nTab, aNew ); - pTabViewShell->UpdateInputHandler(); - bOk = TRUE; - } - } - if (!bOk) - pTabViewShell->ErrorMessage(STR_ERR_NOREF); - } + pTabViewShell->DoRefConversion(); break; case SID_DEC_INDENT: diff --git a/sc/source/ui/view/cellsh2.cxx b/sc/source/ui/view/cellsh2.cxx index 564053a937ef..eabf33f3defc 100644 --- a/sc/source/ui/view/cellsh2.cxx +++ b/sc/source/ui/view/cellsh2.cxx @@ -138,6 +138,77 @@ bool lcl_GetTextToColumnsRange( const ScViewData* pData, ScRange& rRange ) return bRet; } +BOOL lcl_GetSortParam( const ScViewData* pData, ScSortParam& rSortParam ) +{ + ScTabViewShell* pTabViewShell = pData->GetViewShell(); + ScDBData* pDBData = pTabViewShell->GetDBData(); + ScDocument* pDoc = pData->GetDocument(); + SCTAB nTab = pData->GetTabNo(); + ScDirection eFillDir = DIR_TOP; + BOOL bSort = TRUE; + ScRange aExternalRange; + + if( rSortParam.nCol1 != rSortParam.nCol2 ) + eFillDir = DIR_LEFT; + if( rSortParam.nRow1 != rSortParam.nRow2 ) + eFillDir = DIR_TOP; + + SCSIZE nCount = pDoc->GetEmptyLinesInBlock( rSortParam.nCol1, rSortParam.nRow1, nTab, rSortParam.nCol2, rSortParam.nRow2, nTab, eFillDir ); + + if( rSortParam.nRow2 == MAXROW ) + aExternalRange = ScRange( rSortParam.nCol1,sal::static_int_cast<SCROW>( nCount ), nTab ); + else + aExternalRange = ScRange( pData->GetCurX(), pData->GetCurY(), nTab ); + + SCROW nStartRow = aExternalRange.aStart.Row(); + SCCOL nStartCol = aExternalRange.aStart.Col(); + SCROW nEndRow = aExternalRange.aEnd.Row(); + SCCOL nEndCol = aExternalRange.aEnd.Col(); + pDoc->GetDataArea( aExternalRange.aStart.Tab(), nStartCol, nStartRow, nEndCol, nEndRow, FALSE ); + aExternalRange.aStart.SetRow( nStartRow ); + aExternalRange.aStart.SetCol( nStartCol ); + aExternalRange.aEnd.SetRow( nEndRow ); + aExternalRange.aEnd.SetCol( nEndCol ); + + if(( rSortParam.nCol1 == rSortParam.nCol2 && aExternalRange.aStart.Col() != aExternalRange.aEnd.Col() ) || + ( rSortParam.nRow1 == rSortParam.nRow2 && aExternalRange.aStart.Row() != aExternalRange.aEnd.Row() ) ) + { + USHORT nFmt = SCA_VALID; + String aExtendStr,aCurrentStr; + + pTabViewShell->AddHighlightRange( aExternalRange,Color( COL_LIGHTBLUE ) ); + ScRange rExtendRange( aExternalRange.aStart.Col(), aExternalRange.aStart.Row(), nTab, aExternalRange.aEnd.Col(), aExternalRange.aEnd.Row(), nTab ); + rExtendRange.Format( aExtendStr, nFmt, pDoc ); + + ScRange rCurrentRange( rSortParam.nCol1, rSortParam.nRow1, nTab, rSortParam.nCol2, rSortParam.nRow2, nTab ); + rCurrentRange.Format( aCurrentStr, nFmt, pDoc ); + + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + VclAbstractDialog* pWarningDlg = pFact->CreateScSortWarningDlg( pTabViewShell->GetDialogParent(),aExtendStr,aCurrentStr,RID_SCDLG_SORT_WARNING ); + DBG_ASSERT(pWarningDlg, "Dialog create fail!");//CHINA001 + short bResult = pWarningDlg->Execute(); + if( bResult == BTN_EXTEND_RANGE || bResult == BTN_CURRENT_SELECTION ) + { + if( bResult == BTN_EXTEND_RANGE ) + { + pTabViewShell->MarkRange( aExternalRange, FALSE ); + pDBData->SetArea( nTab, aExternalRange.aStart.Col(), aExternalRange.aStart.Row(), aExternalRange.aEnd.Col(), aExternalRange.aEnd.Row() ); + } + } + else + { + bSort = FALSE; + pData->GetDocShell()->CancelAutoDBRange(); + } + + delete pWarningDlg; + pTabViewShell->ClearHighlightRanges(); + } + return bSort; +} + void ScCellShell::ExecuteDB( SfxRequest& rReq ) { ScTabViewShell* pTabViewShell = GetViewData()->GetViewShell(); @@ -332,40 +403,47 @@ void ScCellShell::ExecuteDB( SfxRequest& rReq ) case SID_SORT_DESCENDING: case SID_SORT_ASCENDING: { - SfxItemSet aArgSet( GetPool(), SCITEM_SORTDATA, SCITEM_SORTDATA ); + //#i60401 ux-ctest: Calc does not support all users' strategies regarding sorting data + //the patch comes from maoyg ScSortParam aSortParam; ScDBData* pDBData = pTabViewShell->GetDBData(); - SCCOL nCol = GetViewData()->GetCurX(); - SCCOL nTab = GetViewData()->GetTabNo(); - ScDocument* pDoc = GetViewData()->GetDocument(); - BOOL bHasHeader = FALSE; + ScViewData* pData = GetViewData(); pDBData->GetSortParam( aSortParam ); - bHasHeader = pDoc->HasColHeader( aSortParam.nCol1, aSortParam.nRow1, aSortParam.nCol2, aSortParam.nRow2, nTab ); + if( lcl_GetSortParam( pData, aSortParam ) ) + { + SfxItemSet aArgSet( GetPool(), SCITEM_SORTDATA, SCITEM_SORTDATA ); + SCCOL nCol = GetViewData()->GetCurX(); + SCCOL nTab = GetViewData()->GetTabNo(); + ScDocument* pDoc = GetViewData()->GetDocument(); - if( nCol < aSortParam.nCol1 ) - nCol = aSortParam.nCol1; - else if( nCol > aSortParam.nCol2 ) - nCol = aSortParam.nCol2; + pDBData->GetSortParam( aSortParam ); + BOOL bHasHeader = pDoc->HasColHeader( aSortParam.nCol1, aSortParam.nRow1, aSortParam.nCol2, aSortParam.nRow2, nTab ); - aSortParam.bHasHeader = bHasHeader; - aSortParam.bByRow = TRUE; - aSortParam.bCaseSens = FALSE; - aSortParam.bIncludePattern = TRUE; - aSortParam.bInplace = TRUE; - aSortParam.bDoSort[0] = TRUE; - aSortParam.nField[0] = nCol; - aSortParam.bAscending[0] = (nSlotId == SID_SORT_ASCENDING); + if( nCol < aSortParam.nCol1 ) + nCol = aSortParam.nCol1; + else if( nCol > aSortParam.nCol2 ) + nCol = aSortParam.nCol2; - for ( USHORT i=1; i<MAXSORT; i++ ) - aSortParam.bDoSort[i] = FALSE; + aSortParam.bHasHeader = bHasHeader; + aSortParam.bByRow = TRUE; + aSortParam.bCaseSens = FALSE; + aSortParam.bIncludePattern = TRUE; + aSortParam.bInplace = TRUE; + aSortParam.bDoSort[0] = TRUE; + aSortParam.nField[0] = nCol; + aSortParam.bAscending[0] = (nSlotId == SID_SORT_ASCENDING); - aArgSet.Put( ScSortItem( SCITEM_SORTDATA, GetViewData(), &aSortParam ) ); + for ( USHORT i=1; i<MAXSORT; i++ ) + aSortParam.bDoSort[i] = FALSE; - pTabViewShell->UISort( aSortParam ); // Teilergebnisse bei Bedarf neu + aArgSet.Put( ScSortItem( SCITEM_SORTDATA, GetViewData(), &aSortParam ) ); - rReq.Done(); + pTabViewShell->UISort( aSortParam ); // Teilergebnisse bei Bedarf neu + + rReq.Done(); + } } break; @@ -373,141 +451,155 @@ void ScCellShell::ExecuteDB( SfxRequest& rReq ) { const SfxItemSet* pArgs = rReq.GetArgs(); + //#i60401 ux-ctest: Calc does not support all users' strategies regarding sorting data + //the patch comes from maoyg + if ( pArgs ) // Basic { ScSortParam aSortParam; - ScDBData* pDBData = pTabViewShell->GetDBData(); + ScDBData* pDBData = pTabViewShell->GetDBData(); + ScViewData* pData = GetViewData(); + pDBData->GetSortParam( aSortParam ); - aSortParam.bInplace = TRUE; // von Basic immer - - const SfxPoolItem* pItem; - if ( pArgs->GetItemState( SID_SORT_BYROW, TRUE, &pItem ) == SFX_ITEM_SET ) - aSortParam.bByRow = ((const SfxBoolItem*)pItem)->GetValue(); - if ( pArgs->GetItemState( SID_SORT_HASHEADER, TRUE, &pItem ) == SFX_ITEM_SET ) - aSortParam.bHasHeader = ((const SfxBoolItem*)pItem)->GetValue(); - if ( pArgs->GetItemState( SID_SORT_CASESENS, TRUE, &pItem ) == SFX_ITEM_SET ) - aSortParam.bCaseSens = ((const SfxBoolItem*)pItem)->GetValue(); - if ( pArgs->GetItemState( SID_SORT_ATTRIBS, TRUE, &pItem ) == SFX_ITEM_SET ) - aSortParam.bIncludePattern = ((const SfxBoolItem*)pItem)->GetValue(); - if ( pArgs->GetItemState( SID_SORT_USERDEF, TRUE, &pItem ) == SFX_ITEM_SET ) + + if( lcl_GetSortParam( pData, aSortParam ) ) { - USHORT nUserIndex = ((const SfxUInt16Item*)pItem)->GetValue(); - aSortParam.bUserDef = ( nUserIndex != 0 ); - if ( nUserIndex ) - aSortParam.nUserIndex = nUserIndex - 1; // Basic: 1-basiert - } + ScDocument* pDoc = GetViewData()->GetDocument(); + + pDBData->GetSortParam( aSortParam ); + BOOL bHasHeader = pDoc->HasColHeader( aSortParam.nCol1, aSortParam.nRow1, aSortParam.nCol2, aSortParam.nRow2, pData->GetTabNo() ); + if( bHasHeader ) + aSortParam.bHasHeader = bHasHeader; + + aSortParam.bInplace = TRUE; // von Basic immer + + const SfxPoolItem* pItem; + if ( pArgs->GetItemState( SID_SORT_BYROW, TRUE, &pItem ) == SFX_ITEM_SET ) + aSortParam.bByRow = ((const SfxBoolItem*)pItem)->GetValue(); + if ( pArgs->GetItemState( SID_SORT_HASHEADER, TRUE, &pItem ) == SFX_ITEM_SET ) + aSortParam.bHasHeader = ((const SfxBoolItem*)pItem)->GetValue(); + if ( pArgs->GetItemState( SID_SORT_CASESENS, TRUE, &pItem ) == SFX_ITEM_SET ) + aSortParam.bCaseSens = ((const SfxBoolItem*)pItem)->GetValue(); + if ( pArgs->GetItemState( SID_SORT_ATTRIBS, TRUE, &pItem ) == SFX_ITEM_SET ) + aSortParam.bIncludePattern = ((const SfxBoolItem*)pItem)->GetValue(); + if ( pArgs->GetItemState( SID_SORT_USERDEF, TRUE, &pItem ) == SFX_ITEM_SET ) + { + USHORT nUserIndex = ((const SfxUInt16Item*)pItem)->GetValue(); + aSortParam.bUserDef = ( nUserIndex != 0 ); + if ( nUserIndex ) + aSortParam.nUserIndex = nUserIndex - 1; // Basic: 1-basiert + } - SCCOLROW nField0 = 0; - if ( pArgs->GetItemState( FN_PARAM_1, TRUE, &pItem ) == SFX_ITEM_SET ) - nField0 = ((const SfxInt32Item*)pItem)->GetValue(); - aSortParam.bDoSort[0] = ( nField0 != 0 ); - aSortParam.nField[0] = nField0 > 0 ? (nField0-1) : 0; - if ( pArgs->GetItemState( FN_PARAM_2, TRUE, &pItem ) == SFX_ITEM_SET ) - aSortParam.bAscending[0] = ((const SfxBoolItem*)pItem)->GetValue(); - SCCOLROW nField1 = 0; - if ( pArgs->GetItemState( FN_PARAM_3, TRUE, &pItem ) == SFX_ITEM_SET ) - nField1 = ((const SfxInt32Item*)pItem)->GetValue(); - aSortParam.bDoSort[1] = ( nField1 != 0 ); - aSortParam.nField[1] = nField1 > 0 ? (nField1-1) : 0; - if ( pArgs->GetItemState( FN_PARAM_4, TRUE, &pItem ) == SFX_ITEM_SET ) - aSortParam.bAscending[1] = ((const SfxBoolItem*)pItem)->GetValue(); - SCCOLROW nField2 = 0; - if ( pArgs->GetItemState( FN_PARAM_5, TRUE, &pItem ) == SFX_ITEM_SET ) - nField2 = ((const SfxInt32Item*)pItem)->GetValue(); - aSortParam.bDoSort[2] = ( nField2 != 0 ); - aSortParam.nField[2] = nField2 > 0 ? (nField2-1) : 0; - if ( pArgs->GetItemState( FN_PARAM_6, TRUE, &pItem ) == SFX_ITEM_SET ) - aSortParam.bAscending[2] = ((const SfxBoolItem*)pItem)->GetValue(); - - // Teilergebnisse bei Bedarf neu - pTabViewShell->UISort( aSortParam ); - rReq.Done(); + SCCOLROW nField0 = 0; + if ( pArgs->GetItemState( FN_PARAM_1, TRUE, &pItem ) == SFX_ITEM_SET ) + nField0 = ((const SfxInt32Item*)pItem)->GetValue(); + aSortParam.bDoSort[0] = ( nField0 != 0 ); + aSortParam.nField[0] = nField0 > 0 ? (nField0-1) : 0; + if ( pArgs->GetItemState( FN_PARAM_2, TRUE, &pItem ) == SFX_ITEM_SET ) + aSortParam.bAscending[0] = ((const SfxBoolItem*)pItem)->GetValue(); + SCCOLROW nField1 = 0; + if ( pArgs->GetItemState( FN_PARAM_3, TRUE, &pItem ) == SFX_ITEM_SET ) + nField1 = ((const SfxInt32Item*)pItem)->GetValue(); + aSortParam.bDoSort[1] = ( nField1 != 0 ); + aSortParam.nField[1] = nField1 > 0 ? (nField1-1) : 0; + if ( pArgs->GetItemState( FN_PARAM_4, TRUE, &pItem ) == SFX_ITEM_SET ) + aSortParam.bAscending[1] = ((const SfxBoolItem*)pItem)->GetValue(); + SCCOLROW nField2 = 0; + if ( pArgs->GetItemState( FN_PARAM_5, TRUE, &pItem ) == SFX_ITEM_SET ) + nField2 = ((const SfxInt32Item*)pItem)->GetValue(); + aSortParam.bDoSort[2] = ( nField2 != 0 ); + aSortParam.nField[2] = nField2 > 0 ? (nField2-1) : 0; + if ( pArgs->GetItemState( FN_PARAM_6, TRUE, &pItem ) == SFX_ITEM_SET ) + aSortParam.bAscending[2] = ((const SfxBoolItem*)pItem)->GetValue(); + + // Teilergebnisse bei Bedarf neu + pTabViewShell->UISort( aSortParam ); + rReq.Done(); + } } else { - //CHINA001 ScSortDlg* pDlg = NULL; - SfxAbstractTabDialog* pDlg = NULL; ScSortParam aSortParam; - SfxItemSet aArgSet( GetPool(), SCITEM_SORTDATA, SCITEM_SORTDATA ); + ScDBData* pDBData = pTabViewShell->GetDBData(); + ScViewData* pData = GetViewData(); - ScDBData* pDBData = pTabViewShell->GetDBData(); pDBData->GetSortParam( aSortParam ); - aArgSet.Put( ScSortItem( SCITEM_SORTDATA, GetViewData(), &aSortParam ) ); - //CHINA001 pDlg = new ScSortDlg( pTabViewShell->GetDialogParent(), &aArgSet ); - ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); - DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + if( lcl_GetSortParam( pData, aSortParam ) ) + { + SfxAbstractTabDialog* pDlg = NULL; + ScDocument* pDoc = GetViewData()->GetDocument(); + SfxItemSet aArgSet( GetPool(), SCITEM_SORTDATA, SCITEM_SORTDATA ); - pDlg = pFact->CreateScSortDlg( pTabViewShell->GetDialogParent(), &aArgSet, RID_SCDLG_SORT ); - DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 - pDlg->SetCurPageId(1); + pDBData->GetSortParam( aSortParam ); + BOOL bHasHeader = pDoc->HasColHeader( aSortParam.nCol1, aSortParam.nRow1, aSortParam.nCol2, aSortParam.nRow2, pData->GetTabNo() ); + if( bHasHeader ) + aSortParam.bHasHeader = bHasHeader; - if ( pDlg->Execute() == RET_OK ) - { - const SfxItemSet* pOutSet = pDlg->GetOutputItemSet(); - const ScSortParam& rOutParam = ((const ScSortItem&) - pOutSet->Get( SCITEM_SORTDATA )).GetSortData(); + aArgSet.Put( ScSortItem( SCITEM_SORTDATA, GetViewData(), &aSortParam ) ); - // Teilergebnisse bei Bedarf neu - pTabViewShell->UISort( rOutParam ); + ScAbstractDialogFactory* pFact = ScAbstractDialogFactory::Create(); + DBG_ASSERT(pFact, "ScAbstractFactory create fail!");//CHINA001 + + pDlg = pFact->CreateScSortDlg( pTabViewShell->GetDialogParent(), &aArgSet, RID_SCDLG_SORT ); + DBG_ASSERT(pDlg, "Dialog create fail!");//CHINA001 + pDlg->SetCurPageId(1); - if ( rOutParam.bInplace ) + if ( pDlg->Execute() == RET_OK ) { - rReq.AppendItem( SfxBoolItem( SID_SORT_BYROW, - rOutParam.bByRow ) ); - rReq.AppendItem( SfxBoolItem( SID_SORT_HASHEADER, - rOutParam.bHasHeader ) ); - rReq.AppendItem( SfxBoolItem( SID_SORT_CASESENS, - rOutParam.bCaseSens ) ); - rReq.AppendItem( SfxBoolItem( SID_SORT_ATTRIBS, - rOutParam.bIncludePattern ) ); - USHORT nUser = rOutParam.bUserDef ? ( rOutParam.nUserIndex + 1 ) : 0; - rReq.AppendItem( SfxUInt16Item( SID_SORT_USERDEF, nUser ) ); - if ( rOutParam.bDoSort[0] ) - { - rReq.AppendItem( SfxInt32Item( FN_PARAM_1, - rOutParam.nField[0] + 1 ) ); - rReq.AppendItem( SfxBoolItem( FN_PARAM_2, - rOutParam.bAscending[0] ) ); - } - if ( rOutParam.bDoSort[1] ) - { - rReq.AppendItem( SfxInt32Item( FN_PARAM_3, - rOutParam.nField[1] + 1 ) ); - rReq.AppendItem( SfxBoolItem( FN_PARAM_4, - rOutParam.bAscending[1] ) ); - } - if ( rOutParam.bDoSort[2] ) + const SfxItemSet* pOutSet = pDlg->GetOutputItemSet(); + const ScSortParam& rOutParam = ((const ScSortItem&) + pOutSet->Get( SCITEM_SORTDATA )).GetSortData(); + + // Teilergebnisse bei Bedarf neu + pTabViewShell->UISort( rOutParam ); + + if ( rOutParam.bInplace ) { - rReq.AppendItem( SfxInt32Item( FN_PARAM_5, - rOutParam.nField[2] + 1 ) ); - rReq.AppendItem( SfxBoolItem( FN_PARAM_6, - rOutParam.bAscending[2] ) ); + rReq.AppendItem( SfxBoolItem( SID_SORT_BYROW, + rOutParam.bByRow ) ); + rReq.AppendItem( SfxBoolItem( SID_SORT_HASHEADER, + rOutParam.bHasHeader ) ); + rReq.AppendItem( SfxBoolItem( SID_SORT_CASESENS, + rOutParam.bCaseSens ) ); + rReq.AppendItem( SfxBoolItem( SID_SORT_ATTRIBS, + rOutParam.bIncludePattern ) ); + USHORT nUser = rOutParam.bUserDef ? ( rOutParam.nUserIndex + 1 ) : 0; + rReq.AppendItem( SfxUInt16Item( SID_SORT_USERDEF, nUser ) ); + if ( rOutParam.bDoSort[0] ) + { + rReq.AppendItem( SfxInt32Item( FN_PARAM_1, + rOutParam.nField[0] + 1 ) ); + rReq.AppendItem( SfxBoolItem( FN_PARAM_2, + rOutParam.bAscending[0] ) ); + } + if ( rOutParam.bDoSort[1] ) + { + rReq.AppendItem( SfxInt32Item( FN_PARAM_3, + rOutParam.nField[1] + 1 ) ); + rReq.AppendItem( SfxBoolItem( FN_PARAM_4, + rOutParam.bAscending[1] ) ); + } + if ( rOutParam.bDoSort[2] ) + { + rReq.AppendItem( SfxInt32Item( FN_PARAM_5, + rOutParam.nField[2] + 1 ) ); + rReq.AppendItem( SfxBoolItem( FN_PARAM_6, + rOutParam.bAscending[2] ) ); + } } + + rReq.Done(); } + else + GetViewData()->GetDocShell()->CancelAutoDBRange(); - rReq.Done(); + delete pDlg; } - else - GetViewData()->GetDocShell()->CancelAutoDBRange(); - - delete pDlg; } } break; -/* - { - - USHORT nId = ScPivotLayoutWrapper::GetChildWindowId(); - SfxChildWindow* pWnd = pSfxApp->GetChildWindow( nId ); - - pScMod->SetRefDialog( nId, pWnd ? FALSE : TRUE ); - - } - break; -*/ - case SID_FILTER: { const SfxItemSet* pArgs = rReq.GetArgs(); @@ -1242,6 +1334,10 @@ void __EXPORT ScCellShell::GetDBState( SfxItemSet& rSet ) { rSet.DisableItem( nWhich ); } + else if (pDoc->GetDPAtBlock(aDummy)) + { + rSet.DisableItem( nWhich ); + } else rSet.Put( SfxBoolItem( nWhich, bAutoFilter ) ); } diff --git a/sc/source/ui/view/cellsh3.cxx b/sc/source/ui/view/cellsh3.cxx index 4bb33a4c7855..dd79bb52a112 100644 --- a/sc/source/ui/view/cellsh3.cxx +++ b/sc/source/ui/view/cellsh3.cxx @@ -950,16 +950,12 @@ void ScCellShell::Execute( SfxRequest& rReq ) DBG_ERROR("Execute von InputLine-Status"); break; - case SID_STATUS_DOCPOS: - { - //! Navigator an-/ausschalten (wie im Writer) ??? - //!pViewData->GetDispatcher().Execute( SID_NAVIGATOR, - //! SFX_CALLMODE_SYNCHRON|SFX_CALLMODE_RECORD ); - } + // Launch navigator. + GetViewData()->GetDispatcher().Execute( + SID_NAVIGATOR, SFX_CALLMODE_SYNCHRON|SFX_CALLMODE_RECORD ); break; - case SID_MARKAREA: // called from Basic at the hidden view to select a range in the visible view DBG_ERROR("old slot SID_MARKAREA"); diff --git a/sc/source/ui/view/dbfunc3.cxx b/sc/source/ui/view/dbfunc3.cxx index 8dcb47c927a2..36667ee43c0f 100644 --- a/sc/source/ui/view/dbfunc3.cxx +++ b/sc/source/ui/view/dbfunc3.cxx @@ -1898,7 +1898,13 @@ void ScDBFunc::RepeatDB( BOOL bRecord ) pDBData->GetQueryParam( aQueryParam ); // Bereich kann sich geaendert haben ScRange aAdvSource; if (pDBData->GetAdvancedQuerySource(aAdvSource)) + { + pDoc->CreateQueryParam( + aAdvSource.aStart.Col(), aAdvSource.aStart.Row(), + aAdvSource.aEnd.Col(), aAdvSource.aEnd.Row(), + aAdvSource.aStart.Tab(), aQueryParam ); Query( aQueryParam, &aAdvSource, FALSE ); + } else Query( aQueryParam, NULL, FALSE ); diff --git a/sc/source/ui/view/gridwin.cxx b/sc/source/ui/view/gridwin.cxx index 5591a2a496be..5397377b69cc 100644 --- a/sc/source/ui/view/gridwin.cxx +++ b/sc/source/ui/view/gridwin.cxx @@ -119,6 +119,8 @@ #include "drwlayer.hxx" #include "attrib.hxx" #include "validat.hxx" +#include "tabprotection.hxx" +#include "postit.hxx" // #114409# #include <vcl/salbtype.hxx> // FRound @@ -128,6 +130,11 @@ #include <svx/sdr/overlay/overlaymanager.hxx> #include <vcl/svapp.hxx> +#include <drawinglayer/primitive2d/invertprimitive2d.hxx> +#include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/unifiedalphaprimitive2d.hxx> +#include <basegfx/polygon/b2dpolygontools.hxx> + using namespace com::sun::star; using ::com::sun::star::uno::Sequence; using ::com::sun::star::uno::Any; @@ -1139,6 +1146,13 @@ void ScGridWindow::ExecFilter( ULONG nSel, if (SC_AUTOFILTER_CUSTOM == nSel) { + SCTAB nAreaTab; + SCCOL nStartCol; + SCROW nStartRow; + SCCOL nEndCol; + SCROW nEndRow; + pDBData->GetArea( nAreaTab, nStartCol,nStartRow,nEndCol,nEndRow ); + pViewData->GetView()->MarkRange( ScRange( nStartCol,nStartRow,nAreaTab,nEndCol,nEndRow,nAreaTab)); pViewData->GetView()->SetCursor(nCol,nRow); //! auch ueber Slot ?? pViewData->GetDispatcher().Execute( SID_FILTER, SFX_CALLMODE_SLOT | SFX_CALLMODE_RECORD ); } @@ -2020,8 +2034,9 @@ void __EXPORT ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt ) Point aPos = rMEvt.GetPosPixel(); SCsCOL nPosX; SCsROW nPosY; + SCTAB nTab = pViewData->GetTabNo(); pViewData->GetPosFromPixel( aPos.X(), aPos.Y(), eWhich, nPosX, nPosY ); - ScDPObject* pDPObj = pDoc->GetDPAtCursor( nPosX, nPosY, pViewData->GetTabNo() ); + ScDPObject* pDPObj = pDoc->GetDPAtCursor( nPosX, nPosY, nTab ); if ( pDPObj && pDPObj->GetSaveData()->GetDrillDown() ) { ScAddress aCellPos( nPosX, nPosY, pViewData->GetTabNo() ); @@ -2063,16 +2078,34 @@ void __EXPORT ScGridWindow::MouseButtonUp( const MouseEvent& rMEvt ) return; } - // edit cell contents - pViewData->GetViewShell()->UpdateInputHandler(); - pScMod->SetInputMode( SC_INPUT_TABLE ); - if (pViewData->HasEditView(eWhich)) + // Check for cell protection attribute. + ScTableProtection* pProtect = pDoc->GetTabProtection( nTab ); + bool bEditAllowed = true; + if ( pProtect && pProtect->isProtected() ) + { + bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED); + bool bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS); + bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS); + + if ( bSkipProtected && bSkipUnprotected ) + bEditAllowed = false; + else if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) ) + bEditAllowed = false; + } + + if ( bEditAllowed ) { - // Text-Cursor gleich an die geklickte Stelle setzen - EditView* pEditView = pViewData->GetEditView( eWhich ); - MouseEvent aEditEvt( rMEvt.GetPosPixel(), 1, MOUSE_SYNTHETIC, MOUSE_LEFT, 0 ); - pEditView->MouseButtonDown( aEditEvt ); - pEditView->MouseButtonUp( aEditEvt ); + // edit cell contents + pViewData->GetViewShell()->UpdateInputHandler(); + pScMod->SetInputMode( SC_INPUT_TABLE ); + if (pViewData->HasEditView(eWhich)) + { + // Text-Cursor gleich an die geklickte Stelle setzen + EditView* pEditView = pViewData->GetEditView( eWhich ); + MouseEvent aEditEvt( rMEvt.GetPosPixel(), 1, MOUSE_SYNTHETIC, MOUSE_LEFT, 0 ); + pEditView->MouseButtonDown( aEditEvt ); + pEditView->MouseButtonUp( aEditEvt ); + } } return; } @@ -5662,112 +5695,107 @@ namespace sdr mePaintType( eType ), maRectangles( rRects ) { + // no AA for selection overlays + allowAntiAliase(false); } OverlayObjectCell::~OverlayObjectCell() { } - void OverlayObjectCell::drawGeometry(OutputDevice& rOutputDevice) + drawinglayer::primitive2d::Primitive2DSequence OverlayObjectCell::createOverlayObjectPrimitive2DSequence() { - // safe original AA and switch off for selection - const sal_uInt16 nOriginalAA(rOutputDevice.GetAntialiasing()); - rOutputDevice.SetAntialiasing(0); - - // set colors - rOutputDevice.SetLineColor(); - rOutputDevice.SetFillColor(getBaseColor()); + drawinglayer::primitive2d::Primitive2DSequence aRetval; + const basegfx::BColor aRGBColor(getBaseColor().getBColor()); + const sal_uInt32 nCount(maRectangles.size()); - if ( mePaintType == SC_OVERLAY_BORDER_TRANSPARENT ) - { - // to draw the border, all rectangles have to be collected into a PolyPolygon - - PolyPolygon aPolyPoly; - sal_uInt32 nRectCount = maRectangles.size(); - for(sal_uInt32 nRect=0; nRect < nRectCount; ++nRect) - { - const basegfx::B2DRange& rRange(maRectangles[nRect]); - Rectangle aRectangle(FRound(rRange.getMinX()), FRound(rRange.getMinY()), FRound(rRange.getMaxX()), FRound(rRange.getMaxY())); - if ( nRectCount == 1 || nRect+1 < nRectCount ) - { - // simply add for all except the last rect - aPolyPoly.Insert( Polygon( aRectangle ) ); - } - else - { - PolyPolygon aTemp( aPolyPoly ); - aTemp.GetUnion( PolyPolygon( Polygon( aRectangle ) ), aPolyPoly ); - } - } - - rOutputDevice.DrawTransparent(aPolyPoly, 75); - - rOutputDevice.SetLineColor(getBaseColor()); - rOutputDevice.SetFillColor(); - - rOutputDevice.DrawPolyPolygon(aPolyPoly); - } - else + if(nCount) { - if ( mePaintType == SC_OVERLAY_INVERT ) + // create fill primities for all rectangles + // These ranges are meant as rectangles, so it is not sufficient to replace them + // using the derived polygon. That would leave out the bottom and right lines + // in a discrete width/height due to polygon painting conventions of leaving off those. + // To solve, it is either possible to create a view-dependent rectangle primitive + // handling this internally or to additionally create a hairline primitive to + // cover these areas (which i will do here) + const bool bIsTransparent(SC_OVERLAY_BORDER_TRANSPARENT == mePaintType); + aRetval.realloc(nCount * 2); + + for(sal_uInt32 a(0);a < nCount; a++) { - rOutputDevice.Push(); - rOutputDevice.SetRasterOp( ROP_XOR ); - rOutputDevice.SetFillColor( COL_WHITE ); + const basegfx::B2DRange& rRange(maRectangles[a]); + const basegfx::B2DPolygon aPolygon(basegfx::tools::createPolygonFromRect(rRange)); + + aRetval[a * 2] = drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::PolyPolygonColorPrimitive2D( + basegfx::B2DPolyPolygon(aPolygon), + aRGBColor)); + aRetval[(a * 2) + 1] = drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::PolyPolygonHairlinePrimitive2D( + basegfx::B2DPolyPolygon(aPolygon), + aRGBColor)); } - for(sal_uInt32 a(0L);a < maRectangles.size(); a++) + if(SC_OVERLAY_INVERT == mePaintType) { - const basegfx::B2DRange& rRange(maRectangles[a]); - const Rectangle aRectangle(FRound(rRange.getMinX()), FRound(rRange.getMinY()), FRound(rRange.getMaxX()), FRound(rRange.getMaxY())); + // embed all in invert primitive + const drawinglayer::primitive2d::Primitive2DReference aInvert( + new drawinglayer::primitive2d::InvertPrimitive2D( + aRetval)); - switch(mePaintType) - { - case SC_OVERLAY_INVERT : - { - rOutputDevice.DrawRect( aRectangle ); - break; - } - case SC_OVERLAY_SOLID : - { - rOutputDevice.DrawRect(aRectangle); - break; - } - default: - { - // SC_OVERLAY_BORDER_TRANSPARENT is handled separately - } - } + aRetval = drawinglayer::primitive2d::Primitive2DSequence(&aInvert, 1); } - - if ( mePaintType == SC_OVERLAY_INVERT ) + else if(bIsTransparent) { - rOutputDevice.Pop(); + // embed all rectangles in 75% transparent paint + const drawinglayer::primitive2d::Primitive2DReference aUnifiedAlpha( + new drawinglayer::primitive2d::UnifiedAlphaPrimitive2D( + aRetval, + 0.75)); + + // prepare merged PolyPoygon selection outline + const basegfx::B2DPolyPolygon aPolyPolygon(impGetOverlayPolyPolygon()); + const drawinglayer::primitive2d::Primitive2DReference aSelectionOutline( + new drawinglayer::primitive2d::PolyPolygonHairlinePrimitive2D( + aPolyPolygon, + aRGBColor)); + + // add both to result + aRetval.realloc(2); + aRetval[0] = aUnifiedAlpha; + aRetval[1] = aSelectionOutline; } } - // restore original AA - rOutputDevice.SetAntialiasing(nOriginalAA); + return aRetval; } - void OverlayObjectCell::createBaseRange(OutputDevice& /* rOutputDevice */) + basegfx::B2DPolyPolygon OverlayObjectCell::impGetOverlayPolyPolygon() const { - maBaseRange.reset(); + PolyPolygon aPolyPoly; + const sal_uInt32 nRectCount(maRectangles.size()); - for(sal_uInt32 a(0L); a < maRectangles.size(); a++) + for(sal_uInt32 nRect(0); nRect < nRectCount; ++nRect) { - maBaseRange.expand(maRectangles[a]); - } - } + const basegfx::B2DRange& rRange(maRectangles[nRect]); + const Rectangle aRectangle( + FRound(rRange.getMinX()), FRound(rRange.getMinY()), + FRound(rRange.getMaxX()), FRound(rRange.getMaxY())); - void OverlayObjectCell::transform(const basegfx::B2DHomMatrix& rMatrix) - { - for(sal_uInt32 a(0L); a < maRectangles.size(); a++) - { - maRectangles[a].transform(rMatrix); + if ( nRectCount == 1 || nRect+1 < nRectCount ) + { + // simply add for all except the last rect + aPolyPoly.Insert( Polygon( aRectangle ) ); + } + else + { + PolyPolygon aTemp( aPolyPoly ); + aTemp.GetUnion( PolyPolygon( Polygon( aRectangle ) ), aPolyPoly ); + } } - } + return aPolyPoly.getB2DPolyPolygon(); + } } // end of namespace overlay } // end of namespace sdr diff --git a/sc/source/ui/view/gridwin5.cxx b/sc/source/ui/view/gridwin5.cxx index 8739ee2b0b91..f3d5b2781607 100644 --- a/sc/source/ui/view/gridwin5.cxx +++ b/sc/source/ui/view/gridwin5.cxx @@ -338,12 +338,12 @@ void ScGridWindow::RequestHelp(const HelpEvent& rHEvt) SdrObject* pObj = 0; SdrPageView* pPV = 0; Point aMDPos = PixelToLogic( aPosPixel ); - if ( pDrView->PickObj(aMDPos, pObj, pPV, SDRSEARCH_ALSOONMASTER) ) + if ( pDrView->PickObj(aMDPos, pDrView->getHitTolLog(), pObj, pPV, SDRSEARCH_ALSOONMASTER) ) { if ( pObj->IsGroupObject() ) { SdrObject* pHit = 0; - if ( pDrView->PickObj(aMDPos, pHit, pPV, SDRSEARCH_DEEP ) ) + if ( pDrView->PickObj(aMDPos, pDrView->getHitTolLog(), pHit, pPV, SDRSEARCH_DEEP ) ) pObj = pHit; } #ifdef ISSUE66550_HLINK_FOR_SHAPES diff --git a/sc/source/ui/view/output2.cxx b/sc/source/ui/view/output2.cxx index dd76058756a1..e41bd4941d9c 100644 --- a/sc/source/ui/view/output2.cxx +++ b/sc/source/ui/view/output2.cxx @@ -1358,13 +1358,11 @@ void ScOutputData::DrawStrings( BOOL bPixelToLogic ) } if (bDoCell && !bNeedEdit) { - BOOL bFormulaCell = (pCell->GetCellType() == CELLTYPE_FORMULA ); - if ( bFormulaCell ) + if ( pCell->GetCellType() == CELLTYPE_FORMULA ) lcl_CreateInterpretProgress( bProgress, pDoc, (ScFormulaCell*)pCell ); if ( aVars.SetText(pCell) ) pOldPattern = NULL; - bNeedEdit = aVars.HasEditCharacters() || - (bFormulaCell && ((ScFormulaCell*)pCell)->IsMultilineResult()); + bNeedEdit = aVars.HasEditCharacters(); } if (bDoCell && !bNeedEdit) { diff --git a/sc/source/ui/view/preview.cxx b/sc/source/ui/view/preview.cxx index 2906440d7e5a..b94837fc1793 100644 --- a/sc/source/ui/view/preview.cxx +++ b/sc/source/ui/view/preview.cxx @@ -244,6 +244,10 @@ void ScPreview::CalcPages( SCTAB /*nToWhichTab*/ ) nTabsTested = 0; } + // update all pending row heights with a single progress bar, + // instead of a separate progress for each sheet from ScPrintFunc + pDocShell->UpdatePendingRowHeights( nAnz-1, true ); + // PrintOptions is passed to PrintFunc for SkipEmpty flag, // but always all sheets are used (there is no selected sheet) ScPrintOptions aOptions = SC_MOD()->GetPrintOptions(); diff --git a/sc/source/ui/view/printfun.cxx b/sc/source/ui/view/printfun.cxx index 4324b610dd0b..b7b8b9fbadf6 100644 --- a/sc/source/ui/view/printfun.cxx +++ b/sc/source/ui/view/printfun.cxx @@ -185,6 +185,7 @@ long lcl_LineTotal(const SvxBorderLine* pLine) void ScPrintFunc::Construct( const ScPrintOptions* pOptions ) { + pDocShell->UpdatePendingRowHeights( nPrintTab ); pDoc = pDocShell->GetDocument(); SfxPrinter* pDocPrinter = pDoc->GetPrinter(); // auch fuer Preview den Drucker nehmen @@ -886,7 +887,7 @@ void ScPrintFunc::InitParam( const ScPrintOptions* pOptions ) if ( !aPageSize.Width() || !aPageSize.Height() ) { DBG_ERROR("PageSize Null ?!?!?"); - aPageSize = SvxPaperInfo::GetPaperSize( SVX_PAPER_A4 ); + aPageSize = SvxPaperInfo::GetPaperSize( PAPER_A4 ); } pBorderItem = (const SvxBoxItem*) &pParamSet->Get(ATTR_BORDER); @@ -2677,7 +2678,7 @@ void ScPrintFunc::ApplyPrintSettings() aEnumSize.Width() = aEnumSize.Height(); aEnumSize.Height() = nTemp; } - Paper ePaper = SvxPaperInfo::GetSvPaper( aEnumSize, MAP_TWIP, TRUE ); + Paper ePaper = SvxPaperInfo::GetSvxPaper( aEnumSize, MAP_TWIP, TRUE ); USHORT nPaperBin = ((const SvxPaperBinItem&)pParamSet->Get(ATTR_PAGE_PAPERBIN)).GetValue(); pPrinter->SetPaper( ePaper ); diff --git a/sc/source/ui/view/scextopt.cxx b/sc/source/ui/view/scextopt.cxx index 15b4329fb00e..e6b4a3d0c20e 100644 --- a/sc/source/ui/view/scextopt.cxx +++ b/sc/source/ui/view/scextopt.cxx @@ -42,9 +42,7 @@ ScExtDocSettings::ScExtDocSettings() : maOleSize( ScAddress::INITIALIZE_INVALID ), mfTabBarWidth( -1.0 ), mnLinkCnt( 0 ), - mnDisplTab( 0 ), - mbWinProtected( false ), - mbEncrypted( false ) + mnDisplTab( 0 ) { } diff --git a/sc/source/ui/view/select.cxx b/sc/source/ui/view/select.cxx index 288b50daed19..b8d0da840db7 100644 --- a/sc/source/ui/view/select.cxx +++ b/sc/source/ui/view/select.cxx @@ -47,6 +47,7 @@ //#include "dataobj.hxx" #include "transobj.hxx" #include "docsh.hxx" +#include "tabprotection.hxx" extern USHORT nScFillModeMouseModifier; // global.cxx @@ -322,6 +323,26 @@ BOOL ScViewFunctionSet::SetCursorAtCell( SCsCOL nPosX, SCsROW nPosY, BOOL bScrol { ScTabView* pView = pViewData->GetView(); SCTAB nTab = pViewData->GetTabNo(); + ScDocument* pDoc = pViewData->GetDocument(); + + if ( pDoc->IsTabProtected(nTab) ) + { + if (nPosX < 0 || nPosY < 0) + return false; + + ScTableProtection* pProtect = pDoc->GetTabProtection(nTab); + bool bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS); + bool bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS); + + if ( bSkipProtected && bSkipUnprotected ) + return FALSE; + + bool bCellProtected = pDoc->HasAttrib(nPosX, nPosY, nTab, nPosX, nPosY, nTab, HASATTR_PROTECTED); + if ( (bCellProtected && bSkipProtected) || (!bCellProtected && bSkipUnprotected) ) + // Don't select this cell! + return FALSE; + } + ScModule* pScMod = SC_MOD(); ScTabViewShell* pViewShell = pViewData->GetViewShell(); bool bRefMode = ( pViewShell ? pViewShell->IsRefInputMode() : false ); @@ -375,7 +396,6 @@ BOOL ScViewFunctionSet::SetCursorAtCell( SCsCOL nPosX, SCsROW nPosY, BOOL bScrol ScRange aDelRange; BOOL bOldDelMark = pViewData->GetDelMark( aDelRange ); - ScDocument* pDoc = pViewData->GetDocument(); if ( nPosX+1 >= (SCsCOL) nStartX && nPosX <= (SCsCOL) nEndX && nPosY+1 >= (SCsROW) nStartY && nPosY <= (SCsROW) nEndY && @@ -511,7 +531,6 @@ BOOL ScViewFunctionSet::SetCursorAtCell( SCsCOL nPosX, SCsROW nPosY, BOOL bScrol BYTE nMode = pViewData->GetFillMode(); if ( nMode == SC_FILL_EMBED_LT || nMode == SC_FILL_EMBED_RB ) { - ScDocument* pDoc = pViewData->GetDocument(); DBG_ASSERT( pDoc->IsEmbedded(), "!pDoc->IsEmbedded()" ); ScRange aRange; pDoc->GetEmbedded( aRange); diff --git a/sc/source/ui/view/tabview3.cxx b/sc/source/ui/view/tabview3.cxx index 1be33a37cd26..608658024d2b 100644 --- a/sc/source/ui/view/tabview3.cxx +++ b/sc/source/ui/view/tabview3.cxx @@ -79,6 +79,7 @@ #include "AccessibilityHints.hxx" #include "rangeutl.hxx" #include "client.hxx" +#include "tabprotection.hxx" #include <com/sun/star/chart2/data/HighlightedRange.hpp> @@ -946,6 +947,17 @@ void ScTabView::MoveCursorRel( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, ScDocument* pDoc = aViewData.GetDocument(); SCTAB nTab = aViewData.GetTabNo(); + bool bSkipProtected = false, bSkipUnprotected = false; + ScTableProtection* pProtect = pDoc->GetTabProtection(nTab); + if ( pProtect && pProtect->isProtected() ) + { + bSkipProtected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_LOCKED_CELLS); + bSkipUnprotected = !pProtect->isOptionEnabled(ScTableProtection::SELECT_UNLOCKED_CELLS); + } + + if ( bSkipProtected && bSkipUnprotected ) + return; + SCsCOL nOldX; SCsROW nOldY; SCsCOL nCurX; @@ -965,7 +977,7 @@ void ScTabView::MoveCursorRel( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, nCurY = (nMovY != 0) ? nOldY+nMovY : (SCsROW) aViewData.GetOldCurY(); } - BOOL bHidden; + BOOL bSkipCell = FALSE; aViewData.ResetOldCursor(); if (nMovX != 0 && VALIDCOLROW(nCurX,nCurY)) @@ -974,15 +986,20 @@ void ScTabView::MoveCursorRel( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, do { BYTE nColFlags = pDoc->GetColFlags( nCurX, nTab ); - bHidden = (nColFlags & CR_HIDDEN) || pDoc->IsHorOverlapped( nCurX, nCurY, nTab ); - if (bHidden) + bSkipCell = (nColFlags & CR_HIDDEN) || pDoc->IsHorOverlapped( nCurX, nCurY, nTab ); + if (bSkipProtected && !bSkipCell) + bSkipCell = pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED); + if (bSkipUnprotected && !bSkipCell) + bSkipCell = !pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED); + + if (bSkipCell) { if ( nCurX<=0 || nCurX>=MAXCOL ) { if (bHFlip) { nCurX = nOldX; - bHidden = FALSE; + bSkipCell = FALSE; } else { @@ -995,7 +1012,8 @@ void ScTabView::MoveCursorRel( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, if (nMovX > 0) ++nCurX; else --nCurX; } } - while (bHidden); + while (bSkipCell); + if (pDoc->IsVerOverlapped( nCurX, nCurY, nTab )) { aViewData.SetOldCursor( nCurX,nCurY ); @@ -1010,15 +1028,20 @@ void ScTabView::MoveCursorRel( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, do { BYTE nRowFlags = pDoc->GetRowFlags( nCurY, nTab ); - bHidden = (nRowFlags & CR_HIDDEN) || pDoc->IsVerOverlapped( nCurX, nCurY, nTab ); - if (bHidden) + bSkipCell = (nRowFlags & CR_HIDDEN) || pDoc->IsVerOverlapped( nCurX, nCurY, nTab ); + if (bSkipProtected && !bSkipCell) + bSkipCell = pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED); + if (bSkipUnprotected && !bSkipCell) + bSkipCell = !pDoc->HasAttrib(nCurX, nCurY, nTab, nCurX, nCurY, nTab, HASATTR_PROTECTED); + + if (bSkipCell) { if ( nCurY<=0 || nCurY>=MAXROW ) { if (bVFlip) { nCurY = nOldY; - bHidden = FALSE; + bSkipCell = FALSE; } else { @@ -1031,7 +1054,8 @@ void ScTabView::MoveCursorRel( SCsCOL nMovX, SCsROW nMovY, ScFollowMode eMode, if (nMovY > 0) ++nCurY; else --nCurY; } } - while (bHidden); + while (bSkipCell); + if (pDoc->IsHorOverlapped( nCurX, nCurY, nTab )) { aViewData.SetOldCursor( nCurX,nCurY ); @@ -1571,6 +1595,10 @@ void ScTabView::SetTabNo( SCTAB nTab, BOOL bNew, BOOL bExtendSelection ) ScDocument* pDoc = aViewData.GetDocument(); pDoc->MakeTable( nTab ); + // Update pending row heights before switching the sheet, so Reschedule from the progress bar + // doesn't paint the new sheet with old heights + aViewData.GetDocShell()->UpdatePendingRowHeights( nTab ); + SCTAB nTabCount = pDoc->GetTableCount(); SCTAB nOldPos = nTab; while (!pDoc->IsVisible(nTab)) // naechste sichtbare suchen diff --git a/sc/source/ui/view/tabvwsh3.cxx b/sc/source/ui/view/tabvwsh3.cxx index 7461d884c5b2..525ea1f14578 100644 --- a/sc/source/ui/view/tabvwsh3.cxx +++ b/sc/source/ui/view/tabvwsh3.cxx @@ -75,6 +75,8 @@ #include "autofmt.hxx" #include "dwfunctr.hxx" #include "shtabdlg.hxx" +#include "tabprotection.hxx" +#include "protectiondlg.hxx" #include <svtools/ilstitem.hxx> #define _SVSTDARR_ULONGS @@ -85,6 +87,10 @@ #include <svx/dialogs.hrc> //CHINA001 #include "scabstdlg.hxx" //CHINA001 +#include <memory> + +using ::std::auto_ptr; + #define IS_EDITMODE() GetViewData()->HasEditView( GetViewData()->GetActivePart() ) #define IS_AVAILABLE(WhichId,ppItem) \ (pReqArgs->GetItemState((WhichId), TRUE, ppItem ) == SFX_ITEM_SET) @@ -985,14 +991,6 @@ void ScTabViewShell::Execute( SfxRequest& rReq ) } break; - case SID_STATUS_DOCPOS: - { - //! Navigator an-/ausschalten (wie im Writer) ??? - //!GetViewData()->GetDispatcher().Execute( SID_NAVIGATOR, - //! SFX_CALLMODE_SYNCHRON|SFX_CALLMODE_RECORD ); - } - break; - case FID_PROTECT_DOC: { ScDocument* pDoc = GetViewData()->GetDocument(); @@ -1009,12 +1007,13 @@ void ScTabViewShell::Execute( SfxRequest& rReq ) } } - if (pDoc->IsDocProtected()) + ScDocProtection* pProtect = pDoc->GetDocProtection(); + if (pProtect && pProtect->isProtected()) { BOOL bCancel = FALSE; String aPassword; - if (pDoc->GetDocPassword().getLength()) + if (pProtect->isProtectedWithPass()) { String aText( ScResId(SCSTR_PASSWORD) ); @@ -1064,89 +1063,164 @@ void ScTabViewShell::Execute( SfxRequest& rReq ) case FID_PROTECT_TABLE: + { + ScDocument* pDoc = GetViewData()->GetDocument(); + SCTAB nTab = GetViewData()->GetTabNo(); + bool bOldProtection = pDoc->IsTabProtected(nTab); + +#if ENABLE_SHEET_PROTECTION + + if( pReqArgs ) { - ScDocument* pDoc = GetViewData()->GetDocument(); - SCTAB nTab = GetViewData()->GetTabNo(); - SfxPasswordDialog* pDlg; - String aPassword; - BOOL bCancel = FALSE; - BOOL bOldProtection = pDoc->IsTabProtected(nTab); - BOOL bNewProtection = ! bOldProtection; + const SfxPoolItem* pItem; + bool bNewProtection = !bOldProtection; + if( IS_AVAILABLE( FID_PROTECT_TABLE, &pItem ) ) + bNewProtection = ((const SfxBoolItem*)pItem)->GetValue(); + if( bNewProtection == bOldProtection ) + { + rReq.Ignore(); + break; + } + } - if( pReqArgs ) + if (bOldProtection) + { + // Unprotect a protected sheet. + + ScTableProtection* pProtect = pDoc->GetTabProtection(nTab); + if (pProtect && pProtect->isProtectedWithPass()) { - const SfxPoolItem* pItem; - if( IS_AVAILABLE( FID_PROTECT_TABLE, &pItem ) ) - bNewProtection = ((const SfxBoolItem*)pItem)->GetValue(); - if( bNewProtection == bOldProtection ) + String aText( ScResId(SCSTR_PASSWORDOPT) ); + auto_ptr<SfxPasswordDialog> pDlg(new SfxPasswordDialog(GetDialogParent(), &aText)); + pDlg->SetText( ScResId(SCSTR_UNPROTECTTAB) ); + pDlg->SetMinLen( 0 ); + pDlg->SetHelpId( FID_PROTECT_TABLE ); + pDlg->SetEditHelpId( HID_PASSWD_TABLE ); + + if (pDlg->Execute() == RET_OK) { - rReq.Ignore(); - break; + String aPassword = pDlg->GetPassword(); + Unprotect(nTab, aPassword); } } + else + // this sheet is not password-protected. + Unprotect(nTab, String()); - if ( bOldProtection) - { - if (pDoc->GetTabPassword(nTab).getLength()) - { - String aText( ScResId(SCSTR_PASSWORD) ); + if (!pReqArgs) + { + rReq.AppendItem( SfxBoolItem(FID_PROTECT_TABLE, false) ); + rReq.Done(); + } + } + else + { + // Protect a current sheet. - pDlg = new SfxPasswordDialog( GetDialogParent(), &aText ); - pDlg->SetText( ScResId(SCSTR_UNPROTECTTAB) ); - pDlg->SetMinLen( 0 ); - pDlg->SetHelpId( FID_PROTECT_TABLE ); - pDlg->SetEditHelpId( HID_PASSWD_TABLE ); + auto_ptr<ScTableProtectionDlg> pDlg(new ScTableProtectionDlg(GetDialogParent())); - if (pDlg->Execute() == RET_OK) - aPassword = pDlg->GetPassword(); - else - bCancel = TRUE; + ScTableProtection* pProtect = pDoc->GetTabProtection(nTab); + if (pProtect) + pDlg->SetDialogData(*pProtect); - delete pDlg; - } - } - else - { - String aText( ScResId(SCSTR_PASSWORDOPT) ); + if (pDlg->Execute() == RET_OK) + { + pScMod->InputEnterHandler(); - pDlg = new SfxPasswordDialog( GetDialogParent(), &aText ); - pDlg->SetText( ScResId(SCSTR_PROTECTTAB) ); - pDlg->SetMinLen( 0 ); - pDlg->SetHelpId( FID_PROTECT_TABLE ); - pDlg->SetEditHelpId( HID_PASSWD_TABLE ); - pDlg->ShowExtras( SHOWEXTRAS_CONFIRM ); + ScTableProtection aNewProtect; + pDlg->WriteData(aNewProtect); + ProtectSheet(nTab, aNewProtect); + if (!pReqArgs) + { + rReq.AppendItem( SfxBoolItem(FID_PROTECT_TABLE, true) ); + rReq.Done(); + } + } + } +#else + auto_ptr<SfxPasswordDialog> pDlg; + String aPassword; + BOOL bCancel = FALSE; + bool bNewProtection = ! bOldProtection; - if (pDlg->Execute() == RET_OK) - aPassword = pDlg->GetPassword(); - else - bCancel = TRUE; + if( pReqArgs ) + { + const SfxPoolItem* pItem; + if( IS_AVAILABLE( FID_PROTECT_TABLE, &pItem ) ) + bNewProtection = ((const SfxBoolItem*)pItem)->GetValue(); + if( bNewProtection == bOldProtection ) + { + rReq.Ignore(); + break; + } + } - delete pDlg; - } + if ( bOldProtection) + { + // Unprotect a protected sheet. - if( !bCancel ) + ScTableProtection* pProtect = pDoc->GetTabProtection(nTab); + if (pProtect && pProtect->isProtectedWithPass()) { - if ( bOldProtection ) - Unprotect( nTab, aPassword ); + String aText( ScResId(SCSTR_PASSWORDOPT) ); + pDlg.reset(new SfxPasswordDialog(GetDialogParent(), &aText)); + pDlg->SetText( ScResId(SCSTR_UNPROTECTTAB) ); + pDlg->SetMinLen( 0 ); + pDlg->SetHelpId( FID_PROTECT_TABLE ); + pDlg->SetEditHelpId( HID_PASSWD_TABLE ); + + if (pDlg->Execute() == RET_OK) + aPassword = pDlg->GetPassword(); else - { - pScMod->InputEnterHandler(); + bCancel = TRUE; + } - Protect( nTab, aPassword ); - } + if (!pReqArgs) + { + rReq.AppendItem( SfxBoolItem(FID_PROTECT_TABLE, false) ); + rReq.Done(); + } + } + else + { + String aText( ScResId(SCSTR_PASSWORDOPT) ); - if( !pReqArgs ) - { - rReq.AppendItem( SfxBoolItem( FID_PROTECT_TABLE, bNewProtection ) ); - rReq.Done(); - } + pDlg.reset(new SfxPasswordDialog(GetDialogParent(), &aText)); + pDlg->SetText( ScResId(SCSTR_PROTECTTAB) ); + pDlg->SetMinLen( 0 ); + pDlg->SetHelpId( FID_PROTECT_TABLE ); + pDlg->SetEditHelpId( HID_PASSWD_TABLE ); + pDlg->ShowExtras( SHOWEXTRAS_CONFIRM ); + + if (pDlg->Execute() == RET_OK) + aPassword = pDlg->GetPassword(); + else + bCancel = TRUE; + } + + if( !bCancel ) + { + if ( bOldProtection ) + Unprotect( nTab, aPassword ); + else + { + pScMod->InputEnterHandler(); + + Protect( nTab, aPassword ); } - TabChanged(); - UpdateInputHandler(TRUE); // damit sofort wieder eingegeben werden kann - SelectionChanged(); + if( !pReqArgs ) + { + rReq.AppendItem( SfxBoolItem( FID_PROTECT_TABLE, bNewProtection ) ); + rReq.Done(); + } } - break; +#endif + TabChanged(); + UpdateInputHandler(true); // damit sofort wieder eingegeben werden kann + SelectionChanged(); + } + break; case SID_OPT_LOCALE_CHANGED : { // locale changed, SYSTEM number formats changed => repaint cell contents diff --git a/sc/source/ui/view/tabvwsh4.cxx b/sc/source/ui/view/tabvwsh4.cxx index 2b9ef68b1f8a..d8449ebc3699 100644 --- a/sc/source/ui/view/tabvwsh4.cxx +++ b/sc/source/ui/view/tabvwsh4.cxx @@ -1190,6 +1190,10 @@ PrintDialog* __EXPORT ScTabViewShell::CreatePrintDialog( Window *pParent ) bool bAllTabs = SC_MOD()->GetPrintOptions().GetAllSheets(); pDlg->CheckSheetRange( bAllTabs ? PRINTSHEETS_ALL : PRINTSHEETS_SELECTED_SHEETS ); + // update all pending row heights with a single progress bar, + // instead of a separate progress for each sheet from ScPrintFunc + pDocShell->UpdatePendingRowHeights( MAXTAB, true ); + for ( SCTAB i=0; i<nTabCount; i++ ) { ScPrintFunc aPrintFunc( pDocShell, pPrinter, i ); diff --git a/sc/source/ui/view/tabvwsh5.cxx b/sc/source/ui/view/tabvwsh5.cxx index 36c0c0694d18..92cf03cdf5d6 100644 --- a/sc/source/ui/view/tabvwsh5.cxx +++ b/sc/source/ui/view/tabvwsh5.cxx @@ -47,6 +47,7 @@ #include "tabvwsh.hxx" #include "sc.hrc" #include "global.hxx" +#include "docsh.hxx" #include "document.hxx" #include "cell.hxx" #include "globstr.hrc" @@ -160,6 +161,10 @@ void __EXPORT ScTabViewShell::Notify( SfxBroadcaster& rBC, const SfxHint& rHint if (PaintExtras()) nParts = PAINT_ALL; + // if the current sheet has pending row height updates (sheet links refreshed), + // execute them before invalidating the window + GetViewData()->GetDocShell()->UpdatePendingRowHeights( GetViewData()->GetTabNo() ); + if (nParts & PAINT_SIZE) RepeatResize(); //! InvalidateBorder ??? if (nParts & PAINT_GRID) diff --git a/sc/source/ui/view/tabvwshh.cxx b/sc/source/ui/view/tabvwshh.cxx index 5c6ca6843833..7526a3de19bd 100644 --- a/sc/source/ui/view/tabvwshh.cxx +++ b/sc/source/ui/view/tabvwshh.cxx @@ -43,6 +43,7 @@ #include <sfx2/request.hxx> #include <basic/sbxcore.hxx> #include <svtools/whiter.hxx> +#include <vcl/msgbox.hxx> #include "tabvwsh.hxx" #include "client.hxx" @@ -50,6 +51,10 @@ #include "docsh.hxx" #include "sc.hrc" #include "drwlayer.hxx" // GetVisibleName +#include "retypepassdlg.hxx" +#include "tabprotection.hxx" + +#include <memory> using namespace com::sun::star; @@ -270,6 +275,22 @@ BOOL ScTabViewShell::HasAccessibilityObjects() return pAccessibilityBroadcaster != NULL; } +bool ScTabViewShell::ExecuteRetypePassDlg(ScPasswordHash eDesiredHash) +{ + using ::std::auto_ptr; + + ScDocument* pDoc = GetViewData()->GetDocument(); + + auto_ptr<ScRetypePassDlg> pDlg(new ScRetypePassDlg(GetDialogParent())); + pDlg->SetDataFromDocument(*pDoc); + pDlg->SetDesiredHash(eDesiredHash); + if (pDlg->Execute() != RET_OK) + return false; + + pDlg->WriteNewDataToDocument(*pDoc); + return true; +} + diff --git a/sc/source/ui/view/viewfun2.cxx b/sc/source/ui/view/viewfun2.cxx index a7b2f634bd6c..50ede74ab06b 100644 --- a/sc/source/ui/view/viewfun2.cxx +++ b/sc/source/ui/view/viewfun2.cxx @@ -2197,7 +2197,7 @@ BOOL ScViewFunc::DeleteTables(const SvShorts &TheTabs, BOOL bRecord ) pUndoDoc->SetVisible( nTab, pDoc->IsVisible( nTab ) ); if ( pDoc->IsTabProtected( nTab ) ) - pUndoDoc->SetTabProtection( nTab, TRUE, pDoc->GetTabPassword( nTab ) ); + pUndoDoc->SetTabProtection(nTab, pDoc->GetTabProtection(nTab)); // Drawing-Layer muss sein Undo selbst in der Hand behalten !!! // pUndoDoc->TransferDrawPage(pDoc, nTab,nTab); @@ -2612,7 +2612,7 @@ void ScViewFunc::MoveTable( USHORT nDestDocNo, SCTAB nDestTab, BOOL bCopy ) } if ( nErrVal > 0 && pDoc->IsTabProtected( TheTabs[i] ) ) - pDestDoc->SetTabProtection( nDestTab1, TRUE, pDoc->GetTabPassword( TheTabs[i] ) ); + pDestDoc->SetTabProtection(nDestTab1, pDoc->GetTabProtection(TheTabs[i])); nDestTab1++; } diff --git a/sc/source/ui/view/viewfun4.cxx b/sc/source/ui/view/viewfun4.cxx index 57fef68c5f83..0f3a1c812802 100644 --- a/sc/source/ui/view/viewfun4.cxx +++ b/sc/source/ui/view/viewfun4.cxx @@ -81,6 +81,9 @@ #include "impex.hxx" #include "editutil.hxx" #include "editable.hxx" +#include "dociter.hxx" +#include "reffind.hxx" +#include "compiler.hxx" using namespace com::sun::star; @@ -187,7 +190,128 @@ void ScViewFunc::PasteRTF( SCCOL nStartCol, SCROW nStartRow, ShowAllCursors(); } } +void ScViewFunc::DoRefConversion( BOOL bRecord ) +{ + ScDocument* pDoc = GetViewData()->GetDocument(); + ScMarkData& rMark = GetViewData()->GetMarkData(); + SCTAB nTabCount = pDoc->GetTableCount(); + if (bRecord && !pDoc->IsUndoEnabled()) + bRecord = FALSE; + ScRange aMarkRange; + rMark.MarkToSimple(); + BOOL bMulti = rMark.IsMultiMarked(); + if (bMulti) + rMark.GetMultiMarkArea( aMarkRange ); + else if (rMark.IsMarked()) + rMark.GetMarkArea( aMarkRange ); + else + { + aMarkRange = ScRange( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); + } + ScEditableTester aTester( pDoc, aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), + aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(),rMark ); + if (!aTester.IsEditable()) + { + ErrorMessage(aTester.GetMessageId()); + return; + } + + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + BOOL bOk = FALSE; + + ScDocument* pUndoDoc = NULL; + if (bRecord) + { + pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + SCTAB nTab = aMarkRange.aStart.Tab(); + pUndoDoc->InitUndo( pDoc, nTab, nTab ); + + if ( rMark.GetSelectCount() > 1 ) + { + for (SCTAB i=0; i<nTabCount; i++) + if ( rMark.GetTableSelect(i) && i != nTab ) + pUndoDoc->AddUndoTab( i, i ); + } + ScRange aCopyRange = aMarkRange; + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount-1); + pDoc->CopyToDocument( aCopyRange, IDF_ALL, bMulti, pUndoDoc, &rMark ); + } + + ScRangeListRef xRanges; + GetViewData()->GetMultiArea( xRanges ); + ULONG nCount = xRanges->Count(); + + for (SCTAB i=0; i<nTabCount; i++) + { + if (rMark.GetTableSelect(i)) + { + for (ULONG j=0; j<nCount; j++) + { + ScRange aRange = *xRanges->GetObject(j); + aRange.aStart.SetTab(i); + aRange.aEnd.SetTab(i); + ScCellIterator aIter( pDoc, aRange ); + ScBaseCell* pCell = aIter.GetFirst(); + while ( pCell ) + { + if (pCell->GetCellType() == CELLTYPE_FORMULA) + { + String aOld; + ((ScFormulaCell*)pCell)->GetFormula(aOld); + xub_StrLen nLen = aOld.Len(); + ScRefFinder aFinder( aOld, pDoc ); + aFinder.ToggleRel( 0, nLen ); + if (aFinder.GetFound()) + { + ScAddress aPos = ((ScFormulaCell*)pCell)->aPos; + String aNew = aFinder.GetText(); + ScCompiler aComp( pDoc, aPos); + aComp.SetGrammar(pDoc->GetGrammar()); + ScTokenArray* pArr = aComp.CompileString( aNew ); + ScFormulaCell* pNewCell = new ScFormulaCell( pDoc, aPos, + pArr,formula::FormulaGrammar::GRAM_DEFAULT, MM_NONE ); + pDoc->PutCell( aPos, pNewCell ); + bOk = TRUE; + } + } + pCell = aIter.GetNext(); + } + } + } + } + if (bRecord) + { + ScDocument* pRedoDoc = new ScDocument( SCDOCMODE_UNDO ); + SCTAB nTab = aMarkRange.aStart.Tab(); + pRedoDoc->InitUndo( pDoc, nTab, nTab ); + + if ( rMark.GetSelectCount() > 1 ) + { + for (SCTAB i=0; i<nTabCount; i++) + if ( rMark.GetTableSelect(i) && i != nTab ) + pRedoDoc->AddUndoTab( i, i ); + } + ScRange aCopyRange = aMarkRange; + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount-1); + pDoc->CopyToDocument( aCopyRange, IDF_ALL, bMulti, pRedoDoc, &rMark ); + + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoRefConversion( pDocSh, + aMarkRange, rMark, pUndoDoc, pRedoDoc, bMulti, IDF_ALL) ); + } + + pDocSh->PostPaint( aMarkRange, PAINT_GRID ); + pDocSh->UpdateOle(GetViewData()); + pDocSh->SetDocumentModified(); + CellContentChanged(); + + if (!bOk) + ErrorMessage(STR_ERR_NOREF); +} // Thesaurus - Undo ok void ScViewFunc::DoThesaurus( BOOL bRecord ) { @@ -537,11 +661,13 @@ BOOL ScViewFunc::PasteFile( const Point& rPos, const String& rFile, BOOL bLink ) SfxDispatcher &rDispatcher = GetViewData()->GetDispatcher(); SfxStringItem aFileNameItem( SID_FILE_NAME, aStrURL ); SfxStringItem aFilterItem( SID_FILTER_NAME, pFlt->GetName() ); + // #i69524# add target, as in SfxApplication when the Open dialog is used + SfxStringItem aTargetItem( SID_TARGETNAME, String::CreateFromAscii("_default") ); // Asynchron oeffnen, kann naemlich auch aus D&D heraus passieren // und das bekommt dem MAC nicht so gut ... return BOOL( 0 != rDispatcher.Execute( SID_OPENDOC, - SFX_CALLMODE_ASYNCHRON, &aFileNameItem, &aFilterItem, 0L) ); + SFX_CALLMODE_ASYNCHRON, &aFileNameItem, &aFilterItem, &aTargetItem, 0L) ); } } diff --git a/sc/source/ui/view/viewfun6.cxx b/sc/source/ui/view/viewfun6.cxx index cb9d4eb0da72..ceb852354c7e 100644 --- a/sc/source/ui/view/viewfun6.cxx +++ b/sc/source/ui/view/viewfun6.cxx @@ -175,9 +175,11 @@ void ScViewFunc::EditNote() // hide temporary note caption HideNoteMarker(); // show caption object without changing internal visibility state - pNote->ShowCaptionTemp(); + pNote->ShowCaptionTemp( aPos ); - // drawing object has been created in ScDocument::GetOrCreateNote + /* Drawing object has been created in ScDocument::GetOrCreateNote() or + in ScPostIt::ShowCaptionTemp(), so ScPostIt::GetCaption() should + return a caption object. */ if( SdrCaptionObj* pCaption = pNote->GetCaption() ) { // #i33764# enable the resize handles before starting edit mode diff --git a/sc/source/ui/view/viewfunc.cxx b/sc/source/ui/view/viewfunc.cxx index 9df9dc5f5246..79343c31f85b 100644 --- a/sc/source/ui/view/viewfunc.cxx +++ b/sc/source/ui/view/viewfunc.cxx @@ -599,6 +599,7 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const String& rS } else { + DELETEZ(pUndoData); ScFormulaCell* pCell = new ScFormulaCell( aCell, *pDoc, aPos ); if ( nError ) { @@ -751,12 +752,13 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const EditTextOb ScPatternAttr* pCellAttrs = NULL; EditTextObject* pNewData = NULL; String aString; + + const ScPatternAttr* pOldPattern = pDoc->GetPattern( nCol, nRow, nTab ); + ScTabEditEngine aEngine( *pOldPattern, pDoc->GetEnginePool() ); + aEngine.SetText(*pData); + if (bTestSimple) // Testen, ob einfacher String ohne Attribute { - const ScPatternAttr* pOldPattern = pDoc->GetPattern( nCol, nRow, nTab ); - ScTabEditEngine aEngine( *pOldPattern, pDoc->GetEnginePool() ); - aEngine.SetText(*pData); - ScEditAttrTester aAttrTester( &aEngine ); bSimple = !aAttrTester.NeedsObject(); bCommon = aAttrTester.NeedsCellAttr(); @@ -777,11 +779,11 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const EditTextOb pCellAttrs->GetFromEditItemSet( &aAttrTester.GetAttribs() ); //! remove common attributes from EditEngine? } - - if (bSimple) - aString = aEngine.GetText(); } + // #i97726# always get text for "repeat" of undo action + aString = ScEditUtil::GetSpaceDelimitedString(aEngine); + // // Undo // @@ -838,7 +840,7 @@ void ScViewFunc::EnterData( SCCOL nCol, SCROW nRow, SCTAB nTab, const EditTextOb { // wg. ChangeTrack erst jetzt pDocSh->GetUndoManager()->AddUndoAction( new ScUndoEnterData( pDocSh, nCol, nRow, nTab, nPos, pTabs, - ppOldCells, NULL, NULL, String(), + ppOldCells, NULL, NULL, aString, pUndoData ) ); } @@ -924,7 +926,7 @@ void ScViewFunc::EnterMatrix( const String& rString ) if (pData->GetSimpleArea(aRange) == SC_MARK_SIMPLE) { ScDocShell* pDocSh = pData->GetDocShell(); - BOOL bSuccess = pDocSh->GetDocFunc().EnterMatrix( aRange, &rMark, NULL, rString, FALSE, FALSE,formula::FormulaGrammar::GRAM_DEFAULT ); + BOOL bSuccess = pDocSh->GetDocFunc().EnterMatrix( aRange, &rMark, NULL, rString, FALSE, FALSE, EMPTY_STRING, formula::FormulaGrammar::GRAM_DEFAULT ); if (bSuccess) pDocSh->UpdateOle(GetViewData()); } @@ -1179,103 +1181,69 @@ void ScViewFunc::ApplyPatternLines( const ScPatternAttr& rAttr, const SvxBoxItem const SvxBoxInfoItem* pNewInner, BOOL bRecord ) { ScDocument* pDoc = GetViewData()->GetDocument(); - ScMarkData& rMark = GetViewData()->GetMarkData(); + ScMarkData aFuncMark( GetViewData()->GetMarkData() ); // local copy for UnmarkFiltered + ScViewUtil::UnmarkFiltered( aFuncMark, pDoc ); if (bRecord && !pDoc->IsUndoEnabled()) bRecord = FALSE; - SCCOL nStartCol; - SCROW nStartRow; - SCTAB nStartTab; - SCCOL nEndCol; - SCROW nEndRow; - SCTAB nEndTab; - - ScMarkType eMarkType = GetViewData()->GetSimpleArea( nStartCol, nStartRow, - nStartTab, nEndCol, nEndRow, nEndTab); - if (eMarkType == SC_MARK_SIMPLE || eMarkType == SC_MARK_SIMPLE_FILTERED) + ScRange aMarkRange; + aFuncMark.MarkToSimple(); + BOOL bMulti = aFuncMark.IsMultiMarked(); + if (bMulti) + aFuncMark.GetMultiMarkArea( aMarkRange ); + else if (aFuncMark.IsMarked()) + aFuncMark.GetMarkArea( aMarkRange ); + else { - bool bChangeSelection = false; - ScRange aMarkRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ); - if ( eMarkType == SC_MARK_SIMPLE_FILTERED ) - { - ScMarkData aVisibleMark( rMark ); - ScViewUtil::UnmarkFiltered( aVisibleMark, pDoc ); - ScRangeList aRangeList; - aVisibleMark.FillRangeListWithMarks( &aRangeList, FALSE ); - if ( aRangeList.Count() > 0 ) - { - // use the first range of visible cells - // (might also show an error message instead, or, later, allow multiple ranges) - - aMarkRange = *aRangeList.GetObject(0); - } - else // all hidden -> cursor position - { - aMarkRange.aStart.SetCol(GetViewData()->GetCurX()); - aMarkRange.aStart.SetRow(GetViewData()->GetCurY()); - aMarkRange.aStart.SetTab(GetViewData()->GetTabNo()); - aMarkRange.aEnd = aMarkRange.aStart; - } - aMarkRange.GetVars( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ); - bChangeSelection = true; // change the selection to only the affected cells - } - - rMark.MarkToSimple(); // not done by GetSimpleArea anymore + aMarkRange = ScRange( GetViewData()->GetCurX(), + GetViewData()->GetCurY(), GetViewData()->GetTabNo() ); + DoneBlockMode(); + InitOwnBlockMode(); + aFuncMark.SetMarkArea(aMarkRange); + MarkDataChanged(); + } - ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); - ScDocShellModificator aModificator( *pDocSh ); + ScDocShellModificator aModificator( *pDocSh ); - if (!rMark.IsMarked() || bChangeSelection) - { - DoneBlockMode(); - InitOwnBlockMode(); - rMark.SetMarkArea( ScRange( nStartCol, nStartRow, nStartTab, nEndCol, nEndRow, nEndTab ) ); - MarkDataChanged(); - } + if (bRecord) + { + ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); + SCTAB nStartTab = aMarkRange.aStart.Tab(); + SCTAB nTabCount = pDoc->GetTableCount(); + pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab ); + for (SCTAB i=0; i<nTabCount; i++) + if (i != nStartTab && aFuncMark.GetTableSelect(i)) + pUndoDoc->AddUndoTab( i, i ); - if (bRecord) - { - SCTAB nTabCount = pDoc->GetTableCount(); - ScDocument* pUndoDoc = new ScDocument( SCDOCMODE_UNDO ); - pUndoDoc->InitUndo( pDoc, nStartTab, nStartTab ); - for (SCTAB i=0; i<nTabCount; i++) - if (i != nStartTab && rMark.GetTableSelect(i)) - pUndoDoc->AddUndoTab( i, i ); - pDoc->CopyToDocument( nStartCol, nStartRow, 0, nEndCol, nEndRow, nTabCount-1, - IDF_ATTRIB, FALSE, pUndoDoc ); + ScRange aCopyRange = aMarkRange; + aCopyRange.aStart.SetTab(0); + aCopyRange.aEnd.SetTab(nTabCount-1); + pDoc->CopyToDocument( aCopyRange, IDF_ATTRIB, bMulti, pUndoDoc, &aFuncMark ); - pDocSh->GetUndoManager()->AddUndoAction( - new ScUndoSelectionAttr( pDocSh, rMark, - nStartCol, nStartRow, nStartTab, - nEndCol, nEndRow, nEndTab, - pUndoDoc, FALSE, &rAttr, pNewOuter, pNewInner ) ); - } + pDocSh->GetUndoManager()->AddUndoAction( + new ScUndoSelectionAttr( + pDocSh, aFuncMark, + aMarkRange.aStart.Col(), aMarkRange.aStart.Row(), aMarkRange.aStart.Tab(), + aMarkRange.aEnd.Col(), aMarkRange.aEnd.Row(), aMarkRange.aEnd.Tab(), + pUndoDoc, bMulti, &rAttr, pNewOuter, pNewInner ) ); + } - USHORT nExt = SC_PF_TESTMERGE; - pDocSh->UpdatePaintExt( nExt, nStartCol, nStartRow, nStartTab, - nEndCol, nEndRow, nEndTab ); // content before the change + USHORT nExt = SC_PF_TESTMERGE; + pDocSh->UpdatePaintExt( nExt, aMarkRange ); // content before the change - pDoc->ApplySelectionFrame( rMark, pNewOuter, pNewInner ); + pDoc->ApplySelectionFrame( aFuncMark, pNewOuter, pNewInner ); - pDocSh->UpdatePaintExt( nExt, nStartCol, nStartRow, nStartTab, - nEndCol, nEndRow, nEndTab ); // content after the change + pDocSh->UpdatePaintExt( nExt, aMarkRange ); // content after the change - rMark.MarkToMulti(); - pDoc->ApplySelectionPattern( rAttr, rMark ); + aFuncMark.MarkToMulti(); + pDoc->ApplySelectionPattern( rAttr, aFuncMark ); - pDocSh->PostPaint( nStartCol, nStartRow, nStartTab, - nEndCol, nEndRow, nEndTab, - PAINT_GRID, nExt ); - pDocSh->UpdateOle(GetViewData()); - aModificator.SetDocumentModified(); - CellContentChanged(); - rMark.MarkToSimple(); - } - else - { // "Rahmen nicht auf Mehrfachselektion" - ErrorMessage(STR_MSSG_APPLYPATTLINES_0); - } + pDocSh->PostPaint( aMarkRange, PAINT_GRID, nExt ); + pDocSh->UpdateOle(GetViewData()); + aModificator.SetDocumentModified(); + CellContentChanged(); StartFormatArea(); } @@ -2215,6 +2183,7 @@ void ScViewFunc::SetWidthOrHeight( BOOL bWidth, SCCOLROW nRangeCnt, SCCOLROW* pR const SCCOLROW* pTabRanges = pRanges; pDoc->IncSizeRecalcLevel( nTab ); // nicht fuer jede Spalte einzeln + pDoc->InitializeNoteCaptions( nTab ); for (SCCOLROW nRangeNo=0; nRangeNo<nRangeCnt; nRangeNo++) { SCCOLROW nStartNo = *(pTabRanges++); @@ -2580,6 +2549,36 @@ void ScViewFunc::ModifyCellSize( ScDirection eDir, BOOL bOptimal ) ShowAllCursors(); } +void ScViewFunc::ProtectSheet( SCTAB nTab, const ScTableProtection& rProtect ) +{ + if (nTab == TABLEID_DOC) + return; + + ScMarkData& rMark = GetViewData()->GetMarkData(); + ScDocShell* pDocSh = GetViewData()->GetDocShell(); + ScDocument* pDoc = pDocSh->GetDocument(); + ScDocFunc aFunc(*pDocSh); + bool bUndo(pDoc->IsUndoEnabled()); + + // modifying several tables is handled here + + if (bUndo) + { + String aUndo = ScGlobal::GetRscString( STR_UNDO_PROTECT_TAB ); + pDocSh->GetUndoManager()->EnterListAction( aUndo, aUndo ); + } + + SCTAB nCount = pDocSh->GetDocument()->GetTableCount(); + for ( SCTAB i=0; i<nCount; i++ ) + if ( rMark.GetTableSelect(i) ) + aFunc.ProtectSheet(i, rProtect); + + if (bUndo) + pDocSh->GetUndoManager()->LeaveListAction(); + + UpdateLayerLocks(); //! broadcast to all views +} + void ScViewFunc::Protect( SCTAB nTab, const String& rPassword ) { ScMarkData& rMark = GetViewData()->GetMarkData(); diff --git a/sc/util/makefile.mk b/sc/util/makefile.mk index fe2bf6bc636d..3fc0712cd996 100644 --- a/sc/util/makefile.mk +++ b/sc/util/makefile.mk @@ -85,6 +85,7 @@ SHL1STDLIBS= \ $(SVXLIB) \ $(GOODIESLIB) \ $(BASEGFXLIB) \ + $(DRAWINGLAYERLIB) \ $(VCLLIB) \ $(CPPULIB) \ $(CPPUHELPERLIB) \ @@ -189,6 +190,7 @@ SHL6STDLIBS= \ $(SVLLIB) \ $(SVXLIB) \ $(BASEGFXLIB) \ + $(DRAWINGLAYERLIB) \ $(VCLLIB) \ $(CPPULIB) \ $(CPPUHELPERLIB) \ diff --git a/scaddins/prj/build.lst b/scaddins/prj/build.lst index fd2fc4e80ccc..c2ade63c0b5d 100644 --- a/scaddins/prj/build.lst +++ b/scaddins/prj/build.lst @@ -1,4 +1,4 @@ -ca scaddins : vcl NULL +ca scaddins : l10n vcl NULL ca scaddins usr1 - all sc_mkout NULL ca scaddins\source\datefunc nmake - all sc_dfunc NULL ca scaddins\source\analysis nmake - all sc_analysis NULL diff --git a/sccomp/prj/build.lst b/sccomp/prj/build.lst index e2b7202ce7bf..8e1e0d0181cb 100644 --- a/sccomp/prj/build.lst +++ b/sccomp/prj/build.lst @@ -1,4 +1,4 @@ -scc sccomp : offuh comphelper LPSOLVE:lpsolve tools transex3 rsc NULL +scc sccomp : l10n offuh comphelper LPSOLVE:lpsolve tools rsc NULL scc sccomp usr1 - all scc_mkout NULL scc sccomp\prj get - all scc_prj NULL scc sccomp\source\solver nmake - all scc_solver NULL |